diff --git a/circ_blocks/Cargo.toml b/circ_blocks/Cargo.toml index c48b45ec..bacaee0d 100644 --- a/circ_blocks/Cargo.toml +++ b/circ_blocks/Cargo.toml @@ -101,9 +101,6 @@ bellman = [ "rayon", ] -[[example]] -name = "circ" - [[example]] name = "zk" required-features = ["r1cs"] @@ -112,10 +109,6 @@ required-features = ["r1cs"] name = "cp" required-features = ["bellman", "poly"] -[[example]] -name = "zxi" -required-features = ["smt", "zok"] - [[example]] name = "zxc" required-features = ["r1cs", "smt", "zok"] diff --git a/circ_blocks/examples/circ.rs b/circ_blocks/examples/circ.rs deleted file mode 100644 index 126126db..00000000 --- a/circ_blocks/examples/circ.rs +++ /dev/null @@ -1,471 +0,0 @@ -#![allow(unused_imports)] -#![allow(clippy::vec_init_then_push)] -#[cfg(feature = "bellman")] -use bellman::{ - gadgets::test::TestConstraintSystem, - groth16::{ - create_random_proof, generate_parameters, generate_random_parameters, - prepare_verifying_key, verify_proof, Parameters, Proof, VerifyingKey, - }, - Circuit, -}; -#[cfg(feature = "bellman")] -use bls12_381::{Bls12, Scalar}; -use circ::cfg::{ - cfg, - clap::{self, Args, Parser, Subcommand, ValueEnum}, - CircOpt, -}; -#[cfg(feature = "c")] -use circ::front::c::{self, C}; -#[cfg(all(feature = "smt", feature = "datalog"))] -use circ::front::datalog::{self, Datalog}; -#[cfg(all(feature = "smt", feature = "zok"))] -use circ::front::zsharp::{self, ZSharpFE}; -use circ::front::{FrontEnd, Mode}; -use circ::ir::term::{Node, Op, BV_LSHR, BV_SHL}; -use circ::ir::{ - opt::{opt, Opt}, - term::{ - check, - text::{parse_value_map, serialize_value_map}, - }, -}; -#[cfg(feature = "aby")] -use circ::target::aby::trans::to_aby; -#[cfg(feature = "lp")] -use circ::target::ilp::{assignment_to_values, trans::to_ilp}; -#[cfg(feature = "spartan")] -use circ::target::r1cs::spartan::write_data; -#[cfg(feature = "bellman")] -use circ::target::r1cs::{ - bellman::Bellman, - mirage::Mirage, - proof::{CommitProofSystem, ProofSystem}, -}; -#[cfg(feature = "r1cs")] -use circ::target::r1cs::{opt::reduce_linearities, trans::to_r1cs}; -#[cfg(feature = "smt")] -use circ::target::smt::find_model; -use circ_fields::FieldT; -use fxhash::FxHashMap as HashMap; -#[cfg(feature = "lp")] -use good_lp::default_solver; -use log::trace; -use std::fs::File; -use std::io::Read; -use std::io::Write; -use std::path::{Path, PathBuf}; - -#[derive(Debug, Parser)] -#[command(name = "circ", about = "CirC: the circuit compiler")] -struct Options { - /// Input file - #[arg(name = "PATH")] - path: PathBuf, - - #[command(flatten)] - frontend: FrontendOptions, - - #[command(flatten)] - circ: CircOpt, - - /// Number of parties for an MPC. - #[arg(long, default_value = "2", name = "PARTIES")] - parties: u8, - - #[structopt(subcommand)] - backend: Backend, -} - -#[derive(Debug, Args)] -struct FrontendOptions { - /// Input language - #[arg(long, default_value = "auto", name = "LANG")] - language: Language, - - /// Value threshold - #[arg(long)] - value_threshold: Option, -} - -#[derive(Debug, Subcommand)] -enum Backend { - #[allow(dead_code)] - R1cs { - #[arg(long, default_value = "P")] - prover_key: PathBuf, - #[arg(long, default_value = "V")] - verifier_key: PathBuf, - #[arg(long, default_value = "50")] - /// linear combination constraints up to this size will be eliminated - lc_elimination_thresh: usize, - #[arg(long, default_value = "count")] - action: ProofAction, - #[arg(long, default_value = "groth16")] - proof_impl: ProofImpl, - }, - Smt {}, - Ilp {}, - Mpc { - #[arg(long, default_value = "hycc", name = "cost_model")] - cost_model: String, - #[arg(long, default_value = "lp", name = "selection_scheme")] - selection_scheme: String, - }, -} - -#[derive(PartialEq, Eq, Debug, Clone, ValueEnum)] -enum Language { - Zsharp, - Datalog, - C, - Auto, -} - -#[derive(PartialEq, Eq, Debug)] -pub enum DeterminedLanguage { - Zsharp, - Datalog, - C, -} - -#[derive(PartialEq, Eq, Debug)] -pub enum CostModelType { - Opa, - Hycc, -} - -#[derive(PartialEq, Eq, Debug, Clone, ValueEnum)] -enum ProofAction { - Count, - Setup, - CpSetup, - SpartanSetup, -} - -#[derive(PartialEq, Eq, Debug, Clone, ValueEnum)] -enum ProofImpl { - Groth16, - Mirage, -} - -fn determine_language(l: &Language, input_path: &Path) -> DeterminedLanguage { - match *l { - Language::Datalog => DeterminedLanguage::Datalog, - Language::Zsharp => DeterminedLanguage::Zsharp, - Language::C => DeterminedLanguage::C, - Language::Auto => { - let p = input_path.to_str().unwrap(); - if p.ends_with(".zok") { - DeterminedLanguage::Zsharp - } else if p.ends_with(".pl") { - DeterminedLanguage::Datalog - } else if p.ends_with(".c") || p.ends_with(".cpp") || p.ends_with(".cc") { - DeterminedLanguage::C - } else { - println!("Could not deduce the input language from path '{p}', please set the language manually"); - std::process::exit(2) - } - } - } -} - -#[allow(unused_variables, unreachable_code)] -fn main() { - env_logger::Builder::from_default_env() - .format_level(false) - .format_timestamp(None) - .init(); - let options = Options::parse(); - circ::cfg::set(&options.circ); - let path_buf = options.path.clone(); - println!("{options:?}"); - let mode = match options.backend { - Backend::R1cs { .. } => match options.frontend.value_threshold { - Some(t) => Mode::ProofOfHighValue(t), - None => Mode::Proof, - }, - Backend::Ilp { .. } => Mode::Opt, - Backend::Mpc { .. } => Mode::Mpc(options.parties), - Backend::Smt { .. } => Mode::Proof, - }; - let language = determine_language(&options.frontend.language, &options.path); - let cs = match language { - #[cfg(all(feature = "smt", feature = "zok"))] - DeterminedLanguage::Zsharp => { - let inputs = zsharp::Inputs { - file: options.path, - mode, - }; - ZSharpFE::gen(inputs) - } - #[cfg(not(all(feature = "smt", feature = "zok")))] - DeterminedLanguage::Zsharp => { - panic!("Missing feature: smt,zok"); - } - #[cfg(all(feature = "smt", feature = "datalog"))] - DeterminedLanguage::Datalog => { - let inputs = datalog::Inputs { file: options.path }; - Datalog::gen(inputs) - } - #[cfg(not(all(feature = "smt", feature = "datalog")))] - DeterminedLanguage::Datalog => { - panic!("Missing feature: smt,datalog"); - } - #[cfg(feature = "c")] - DeterminedLanguage::C => { - let inputs = c::Inputs { - file: options.path, - mode, - sv_functions: options.circ.c.sv_functions, - assert_no_ub: options.circ.c.assert_no_ub, - }; - C::gen(inputs) - } - #[cfg(not(feature = "c"))] - DeterminedLanguage::C => { - panic!("Missing feature: c"); - } - }; - let cs = match mode { - Mode::Opt => opt( - cs, - vec![Opt::ScalarizeVars, Opt::ConstantFold(Box::new([]))], - ), - Mode::Mpc(_) => { - let ignore = [BV_LSHR, BV_SHL]; - opt( - cs, - vec![ - Opt::ScalarizeVars, - Opt::Flatten, - Opt::Sha, - Opt::ConstantFold(Box::new(ignore.clone())), - Opt::Flatten, - // Function calls return tuples - Opt::Tuple, - Opt::Obliv, - // The obliv elim pass produces more tuples, that must be eliminated - Opt::Tuple, - Opt::LinearScan, - // The linear scan pass produces more tuples, that must be eliminated - Opt::Tuple, - Opt::ConstantFold(Box::new(ignore)), - // Binarize nary terms - Opt::Binarize, - ], - // vec![Opt::Sha, Opt::ConstantFold, Opt::Mem, Opt::ConstantFold], - ) - } - Mode::Proof | Mode::ProofOfHighValue(_) => { - let mut opts = Vec::new(); - - opts.push(Opt::DeskolemizeWitnesses); - opts.push(Opt::ScalarizeVars); - opts.push(Opt::Flatten); - opts.push(Opt::Sha); - opts.push(Opt::ConstantFold(Box::new([]))); - opts.push(Opt::ParseCondStores); - // Tuples must be eliminated before oblivious array elim - opts.push(Opt::ConstantFold(Box::new([]))); - opts.push(Opt::Obliv); - // The obliv elim pass produces more tuples, that must be eliminated - opts.push(Opt::SetMembership); - opts.push(Opt::PersistentRam); - opts.push(Opt::VolatileRam); - opts.push(Opt::SkolemizeChallenges); - opts.push(Opt::ScalarizeVars); - opts.push(Opt::ConstantFold(Box::new([]))); - opts.push(Opt::Obliv); - opts.push(Opt::LinearScan); - // The linear scan pass produces more tuples, that must be eliminated - opts.push(Opt::Tuple); - opts.push(Opt::Flatten); - opts.push(Opt::ConstantFold(Box::new([]))); - opt(cs, opts) - } - }; - println!("Done with IR optimization"); - - for (name, c) in &cs.comps { - println!("\n--\nName: {}", name); - println!("Pre-Comp:"); - for (inst, t) in c.precomputes.outputs() { - println!(" Inst: {}, Term: {}", inst, t); - } - println!("Party ID:"); - for (n, pid) in &c.metadata.party_ids { - println!(" Name: {}, ID: {}", n, pid); - } - println!("Party Visibility:"); - // for (i, (t, pid)) in &c.metadata.input_vis { - // println!(" Input: {}, Term: {}, Vis: {:?}", i, t, pid); - // } - println!("Output:"); - for t in &c.outputs { - println!(" {}", t); - } - } - - /* - match options.backend { - #[cfg(feature = "r1cs")] - Backend::R1cs { - action, - prover_key, - verifier_key, - proof_impl, - .. - } => { - println!("Converting to r1cs"); - let cs = cs.get("main"); - trace!("IR: {}", circ::ir::term::text::serialize_computation(cs)); - let mut r1cs = to_r1cs(cs, cfg()); - - println!("Pre-opt R1cs size: {}", r1cs.constraints().len()); - r1cs = reduce_linearities(r1cs, cfg()); - - println!("Final R1cs size: {}", r1cs.constraints().len()); - let (prover_data, verifier_data) = r1cs.finalize(cs); - match action { - ProofAction::Count => (), - #[cfg(feature = "bellman")] - ProofAction::Setup => { - println!("Generating Parameters"); - match proof_impl { - ProofImpl::Groth16 => Bellman::::setup_fs( - prover_data, - verifier_data, - prover_key, - verifier_key, - ) - .unwrap(), - ProofImpl::Mirage => Mirage::::setup_fs( - prover_data, - verifier_data, - prover_key, - verifier_key, - ) - .unwrap(), - }; - } - #[cfg(not(feature = "bellman"))] - ProofAction::Setup => panic!("Missing feature: bellman"), - #[cfg(feature = "bellman")] - ProofAction::CpSetup => { - println!("Generating Parameters"); - match proof_impl { - ProofImpl::Groth16 => panic!("Groth16 is not CP"), - ProofImpl::Mirage => Mirage::::cp_setup_fs( - prover_data, - verifier_data, - prover_key, - verifier_key, - ) - .unwrap(), - }; - } - #[cfg(not(feature = "bellman"))] - ProofAction::CpSetup => panic!("Missing feature: bellman"), - #[cfg(feature = "spartan")] - ProofAction::SpartanSetup => { - write_data::<_, _>(prover_key, verifier_key, &prover_data, &verifier_data) - .unwrap(); - } - #[cfg(not(feature = "spartan"))] - ProofAction::SpartanSetup => panic!("Missing feature: spartan"), - } - } - #[cfg(not(feature = "r1cs"))] - Backend::R1cs { .. } => { - panic!("Missing feature: r1cs"); - } - #[cfg(feature = "aby")] - Backend::Mpc { - cost_model, - selection_scheme, - } => { - println!("Converting to aby"); - let lang_str = match language { - DeterminedLanguage::C => "c".to_string(), - DeterminedLanguage::Zsharp => "zok".to_string(), - _ => panic!("Language isn't supported by MPC backend: {:#?}", language), - }; - println!("Cost model: {cost_model}"); - println!("Selection scheme: {selection_scheme}"); - to_aby(cs, &path_buf, &lang_str, &cost_model, &selection_scheme); - } - #[cfg(not(feature = "aby"))] - Backend::Mpc { .. } => { - panic!("Missing feature: aby"); - } - #[cfg(feature = "lp")] - Backend::Ilp { .. } => { - println!("Converting to ilp"); - let inputs_and_sorts: HashMap<_, _> = cs - .get("main") - .clone() - .metadata - .ordered_inputs() - .iter() - .map(|term| match term.op() { - Op::Var(n, s) => (n.clone(), s.clone()), - _ => unreachable!(), - }) - .collect(); - let ilp = to_ilp(cs.get("main").clone()); - let solver_result = ilp.solve(default_solver); - let (max, vars) = solver_result.expect("ILP could not be solved"); - println!("Max value: {}", max.round() as u64); - println!("Assignment:"); - for (var, val) in &vars { - println!(" {}: {}", var, val.round() as u64); - } - let values = assignment_to_values(&vars, &inputs_and_sorts); - let values_as_str = serialize_value_map(&values); - std::fs::write("assignment.txt", values_as_str).unwrap(); - } - #[cfg(not(feature = "lp"))] - Backend::Ilp { .. } => { - panic!("Missing feature: lp"); - } - #[cfg(feature = "smt")] - Backend::Smt { .. } => { - let main_comp = cs.get("main").clone(); - assert_eq!(main_comp.outputs.len(), 1); - let model = find_model(&main_comp.outputs[0]); - if options.circ.datalog.lint_prim_rec { - match model { - Some(m) => { - println!("Not primitive recursive!"); - for (var, val) in m { - println!("{var} -> {val}"); - } - std::process::exit(1) - } - None => { - println!("Primitive recursive"); - } - } - } else { - match model { - Some(m) => { - println!("Property does not hold!\nCounterexample:"); - for (var, val) in m { - println!("{var} -> {val}"); - } - std::process::exit(1) - } - None => { - println!("Property holds"); - } - } - } - } - #[cfg(not(feature = "smt"))] - Backend::Smt { .. } => { - panic!("Missing feature: smt"); - } - }*/ -} diff --git a/circ_blocks/examples/zxi.rs b/circ_blocks/examples/zxi.rs deleted file mode 100644 index 7799076d..00000000 --- a/circ_blocks/examples/zxi.rs +++ /dev/null @@ -1,67 +0,0 @@ -use circ::front::zsharp::{Inputs, ZSharpFE}; -use circ::ir::term::text::parse_value_map; - -use circ::cfg::{ - clap::{self, Parser}, - CircOpt, -}; -use circ::front::Mode; -use rand_chacha::rand_core::block; -use std::path::PathBuf; - -use zokrates_pest_ast::*; -use rug::Integer; - -#[derive(Debug, Parser)] -#[command(name = "zxi", about = "The Z# interpreter")] -struct Options { - /// Input file - #[arg()] - zsharp_path: PathBuf, - - /// Scalar input values - #[arg()] - inputs_path: Option, - - #[command(flatten)] - /// CirC options - circ: CircOpt, -} - -fn main() { - let func_inputs: Vec = vec![]; - - env_logger::Builder::from_default_env() - .format_level(false) - .format_timestamp(None) - .init(); - let mut options = Options::parse(); - options.circ.ir.field_to_bv = circ_opt::FieldToBv::Panic; - circ::cfg::set(&options.circ); - let inputs = Inputs { - file: options.zsharp_path, - mode: Mode::Proof - }; - let entry_regs: Vec = func_inputs.iter().map(|i| Integer::from(*i)).collect(); - let (cs, block_id_list, _, block_inputs_list, mem_list) = ZSharpFE::interpret(inputs, &entry_regs); - print!("\n\nReturn value: "); - cs.pretty(&mut std::io::stdout().lock()) - .expect("error pretty-printing value"); - println!(); - for i in 0..block_id_list.len() { - println!("BLOCK ID: {}", block_id_list[i]); - let mut str_list = Vec::new(); - for (name, val) in &block_inputs_list[i] { - str_list.push(format!("{}: {:?}", name, val)); - } - str_list.sort(); - for s in str_list { - println!("{}", s); - } - } - println!("MEM"); - for (addr, data) in mem_list { - println!("ADDR: {:?}", addr); - println!("DATA: {:?}", data); - } -} diff --git a/spartan_parallel/Cargo.toml b/spartan_parallel/Cargo.toml index 0f13d883..2536c43b 100644 --- a/spartan_parallel/Cargo.toml +++ b/spartan_parallel/Cargo.toml @@ -40,26 +40,6 @@ curve25519-dalek = { git = "https://github.com/Jiangkm3/curve25519-dalek.git", b name = "libspartan" path = "src/lib.rs" -[[bin]] -name = "snark" -path = "profiler/snark.rs" -required-features = ["std"] - -[[bin]] -name = "nizk" -path = "profiler/nizk.rs" -required-features = ["std"] - -[[bench]] -name = "snark" -harness = false -required-features = ["std"] - -[[bench]] -name = "nizk" -harness = false -required-features = ["std"] - [features] default = ["std", "simd_backend"] std = [ diff --git a/spartan_parallel/benches/nizk.rs b/spartan_parallel/benches/nizk.rs deleted file mode 100644 index 982c4670..00000000 --- a/spartan_parallel/benches/nizk.rs +++ /dev/null @@ -1,92 +0,0 @@ -#![allow(clippy::assertions_on_result_states)] -extern crate byteorder; -extern crate core; -extern crate criterion; -extern crate digest; -extern crate libspartan; -extern crate merlin; -extern crate rand; -extern crate sha3; - -use libspartan::{Instance, NIZKGens, NIZK}; -use merlin::Transcript; - -use criterion::*; - -fn nizk_prove_benchmark(c: &mut Criterion) { - for &s in [10, 12, 16].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("NIZK_prove_benchmark"); - group.plot_config(plot_config); - - let num_vars = (2_usize).pow(s as u32); - let num_cons = num_vars; - let num_inputs = 10; - - let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - - let gens = NIZKGens::new(num_cons, num_vars, num_inputs); - - let name = format!("NIZK_prove_{num_vars}"); - group.bench_function(&name, move |b| { - b.iter(|| { - let mut prover_transcript = Transcript::new(b"example"); - NIZK::prove( - black_box(&inst), - black_box(vars.clone()), - black_box(&inputs), - black_box(&gens), - black_box(&mut prover_transcript), - ); - }); - }); - group.finish(); - } -} - -fn nizk_verify_benchmark(c: &mut Criterion) { - for &s in [10, 12, 16].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("NIZK_verify_benchmark"); - group.plot_config(plot_config); - - let num_vars = (2_usize).pow(s as u32); - let num_cons = num_vars; - let num_inputs = 10; - let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - - let gens = NIZKGens::new(num_cons, num_vars, num_inputs); - - // produce a proof of satisfiability - let mut prover_transcript = Transcript::new(b"example"); - let proof = NIZK::prove(&inst, vars, &inputs, &gens, &mut prover_transcript); - - let name = format!("NIZK_verify_{num_cons}"); - group.bench_function(&name, move |b| { - b.iter(|| { - let mut verifier_transcript = Transcript::new(b"example"); - assert!(proof - .verify( - black_box(&inst), - black_box(&inputs), - black_box(&mut verifier_transcript), - black_box(&gens) - ) - .is_ok()); - }); - }); - group.finish(); - } -} - -fn set_duration() -> Criterion { - Criterion::default().sample_size(10) -} - -criterion_group! { -name = benches_nizk; -config = set_duration(); -targets = nizk_prove_benchmark, nizk_verify_benchmark -} - -criterion_main!(benches_nizk); diff --git a/spartan_parallel/benches/snark.rs b/spartan_parallel/benches/snark.rs deleted file mode 100644 index 5b4e3d35..00000000 --- a/spartan_parallel/benches/snark.rs +++ /dev/null @@ -1,131 +0,0 @@ -#![allow(clippy::assertions_on_result_states)] -extern crate libspartan; -extern crate merlin; - -use libspartan::{Instance, SNARKGens, SNARK}; -use merlin::Transcript; - -use criterion::*; - -fn snark_encode_benchmark(c: &mut Criterion) { - for &s in [10, 12, 16].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("SNARK_encode_benchmark"); - group.plot_config(plot_config); - - let num_vars = (2_usize).pow(s as u32); - let num_cons = num_vars; - let num_inputs = 10; - let (inst, _vars, _inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - - // produce public parameters - let gens = SNARKGens::new(num_cons, num_vars, num_inputs, num_cons); - - // produce a commitment to R1CS instance - let name = format!("SNARK_encode_{num_cons}"); - group.bench_function(&name, move |b| { - b.iter(|| { - SNARK::encode(black_box(&inst), black_box(&gens)); - }); - }); - group.finish(); - } -} - -fn snark_prove_benchmark(c: &mut Criterion) { - for &s in [10, 12, 16].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("SNARK_prove_benchmark"); - group.plot_config(plot_config); - - let num_vars = (2_usize).pow(s as u32); - let num_cons = num_vars; - let num_inputs = 10; - - let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - - // produce public parameters - let gens = SNARKGens::new(num_cons, num_vars, num_inputs, num_cons); - - // produce a commitment to R1CS instance - let (comm, decomm) = SNARK::encode(&inst, &gens); - - // produce a proof - let name = format!("SNARK_prove_{num_cons}"); - group.bench_function(&name, move |b| { - b.iter(|| { - let mut prover_transcript = Transcript::new(b"example"); - SNARK::prove( - black_box(&inst), - black_box(&comm), - black_box(&decomm), - black_box(vars.clone()), - black_box(&inputs), - black_box(&gens), - black_box(&mut prover_transcript), - ); - }); - }); - group.finish(); - } -} - -fn snark_verify_benchmark(c: &mut Criterion) { - for &s in [10, 12, 16].iter() { - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - let mut group = c.benchmark_group("SNARK_verify_benchmark"); - group.plot_config(plot_config); - - let num_vars = (2_usize).pow(s as u32); - let num_cons = num_vars; - let num_inputs = 10; - let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - - // produce public parameters - let gens = SNARKGens::new(num_cons, num_vars, num_inputs, num_cons); - - // produce a commitment to R1CS instance - let (comm, decomm) = SNARK::encode(&inst, &gens); - - // produce a proof of satisfiability - let mut prover_transcript = Transcript::new(b"example"); - let proof = SNARK::prove( - &inst, - &comm, - &decomm, - vars, - &inputs, - &gens, - &mut prover_transcript, - ); - - // verify the proof - let name = format!("SNARK_verify_{num_cons}"); - group.bench_function(&name, move |b| { - b.iter(|| { - let mut verifier_transcript = Transcript::new(b"example"); - assert!(proof - .verify( - black_box(&comm), - black_box(&inputs), - black_box(&mut verifier_transcript), - black_box(&gens) - ) - .is_ok()); - }); - }); - group.finish(); - } -} - -fn set_duration() -> Criterion { - Criterion::default().sample_size(10) -} - -criterion_group! { -name = benches_snark; -config = set_duration(); -targets = snark_encode_benchmark, snark_prove_benchmark, snark_verify_benchmark -} - -criterion_main!(benches_snark); diff --git a/spartan_parallel/examples/accumulator.rs b/spartan_parallel/examples/accumulator.rs deleted file mode 100644 index 3ff4f237..00000000 --- a/spartan_parallel/examples/accumulator.rs +++ /dev/null @@ -1,951 +0,0 @@ -//! An accumulator: s = 1 + 2 + 3 computed with loops -//! The pseudocode is: -//! i = 0 -//! s = 0 -//! while i != 4: -//! s = s + i -//! i = i + 1 -//! Which, when converted to blocks, is: -//! Block 1: Block 2: -//! assert b == 0 assert b == 1 -//! i = 0 s = s + i -//! s = 0 i = i + 1 -//! if i != 4: if i != 4: -//! b = 1 b = 1 -//! else: else: -//! b = 2 b = 2 -//! -//! Converting each block to constraints: -//! Block 1: Block 2: -//! b0 = b_in b0 = b_in -//! i0 = i_in i0 = i_in -//! s0 = s_in s0 = s_in -//! 0 = b0 1 = b0 -//! 0 = i0 i0 = s1 - s0 -//! 0 = s0 1 = i1 - i0 -//! Z1 = (i0 - 4) * Z0 Z1 = (i1 - 4) * Z0 -//! 0 = B0 * (Z1 - 1) 0 = B0 * (Z1 - 1) -//! 0 = B0 * (b1 - 1) 0 = B0 * (b1 - 1) -//! 0 = (1 - B0) * (i0 - 4) 0 = (1 - B0) * (i1 - 4) -//! 0 = (1 - B0) * (b1 - 2) 0 = (1 - B0) * (b1 - 2) -//! b_out = b1 b_out = b1 -//! i_out = i0 i_out = i1 -//! s_out = s0 s_out = s1 -//! -//! Finally, consistency check: -//! Permutation on (b_in, i_in, s_in, b_out, i_out, s_out) -//! Consistency check on (b_in, i_in, s_in, b_out, i_out, s_out) -//! -#![allow(clippy::assertions_on_result_states)] -use std::ops::Neg; - -use curve25519_dalek::scalar::Scalar; -use libspartan::{Instance, SNARKGens, VarsAssignment, SNARK, InputsAssignment}; -use merlin::Transcript; - -#[allow(non_snake_case)] -fn produce_r1cs() -> ( - usize, - usize, - Vec<[u8; 32]>, - Vec<[u8; 32]>, - usize, - - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - Vec, - Instance, - usize, - usize, - usize, - Instance, - usize, - usize, - Instance, - usize, - usize, - Instance, - usize, - usize, - Instance, - usize, - usize, - usize, - [Instance; 2], - Vec>, - Vec>, - Vec -) { - // bad test cases for debugging - // set them to unreachable values to prevent bad tests - // let bad_instance = 3; - // let bad_proof = 1; - - // Separate instances into three lists: - // BLOCK: correctness within a block - // CONSIS: consistency between blocks - // PERM: permutation between two orderings - // - // Separate inputs into two lists: - // BLOCK_ORDER - // EXEC_ORDER - // - // Separate vars into three lists - // BLOCK, CONSIS, PERM - - let zero = Scalar::zero().to_bytes(); - let one = Scalar::one().to_bytes(); - let two = Scalar::from(2u32).to_bytes(); - let three = Scalar::from(3u32).to_bytes(); - let four = Scalar::from(4u32).to_bytes(); - let six = Scalar::from(6u32).to_bytes(); - - // args are in (variable, constant) pairs - fn gen_constr( - mut A: Vec<(usize, usize, [u8; 32])>, mut B: Vec<(usize, usize, [u8; 32])>, mut C: Vec<(usize, usize, [u8; 32])>, V_cnst: usize, - i: usize, args_A: Vec<(usize, isize)>, args_B: Vec<(usize, isize)>, args_C: Vec<(usize, isize)>) -> ( - Vec<(usize, usize, [u8; 32])>, Vec<(usize, usize, [u8; 32])>, Vec<(usize, usize, [u8; 32])> - ) { - let zero = Scalar::zero().to_bytes(); - let one = Scalar::one().to_bytes(); - let two = Scalar::from(2u32).to_bytes(); - let minus_one = Scalar::one().neg().to_bytes(); - let minus_two = Scalar::from(2u32).neg().to_bytes(); - let minus_four = Scalar::from(4u32).neg().to_bytes(); - let int_to_scalar = |i| { - match i { - 0 => zero, - 1 => one, - 2 => two, - -1 => minus_one, - -2 => minus_two, - -4 => minus_four, - _ => panic!("Unsupported constant!") - } - }; - for vars in &args_A { - let sc = int_to_scalar(vars.1); - A.push((i, vars.0, sc)); - } - if args_B.len() == 0 { - B.push((i, V_cnst, one)); - } - for vars in &args_B { - let sc = int_to_scalar(vars.1); - B.push((i, vars.0, sc)); - } - for vars in &args_C { - let sc = int_to_scalar(vars.1); - C.push((i, vars.0, sc)); - } - (A, B, C) - } - - // -- - // COMPILE TIME KNOWLEDGE - // -- - - // num_vars should be consistent accross the instances - // everything else is instance-specific - // Divide inputs into (1, input, 1, output) - // So num_inputs = num_outputs = input_output_cutoff - 1 - let num_vars = 16; - let input_output_cutoff = 4; - - // Number of proofs of each R1CS instance - // OBTAINED DURING COMPILE TIME - let total_num_proofs_bound = 16; - let block_max_num_proofs_bound = 8; - - // What is the input and output block? - // Note: the assumption is that during a normal execution, the input block and the output block will only be reached once - let input_block_num = 0; - let output_block_num = 2; - - // -- - // BLOCK Instances - // -- - - // parameters of the BLOCK instance - // maximum value among the R1CS instances - let block_num_cons = 16; - let block_num_non_zero_entries = 19; - // Number of R1CS instances - let block_num_instances = 2; - - // 0 1 2 3 4 5 6 7 8 - // variable orders: b0 i0 s0 b1 i1 s1 Z0 Z1 B0 - // input orders: valid b_i i_i s_i 1 b_o i_o s_o - let V_b0 = 0; - let V_i0 = 1; - let V_s0 = 2; - let V_b1 = 3; - let V_i1 = 4; - let V_s1 = 5; - let V_Z0 = 6; - let V_Z1 = 7; - let V_B0 = 8; - let V_valid = num_vars; - let V_bi = num_vars + 1; - let V_ii = num_vars + 2; - let V_si = num_vars + 3; - let V_cnst = V_valid; - let V_bo = num_vars + 5; - let V_io = num_vars + 6; - let V_so = num_vars + 7; - - let block_inst = { - let mut A_list = Vec::new(); - let mut B_list = Vec::new(); - let mut C_list = Vec::new(); - - // Instance 0: block 1 - // Instances need to be sorted in reverse # of proofs order - let (A, B, C) = { - let mut A: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut B: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut C: Vec<(usize, usize, [u8; 32])> = Vec::new(); - - // R1CS: - // b0 = b_in - (A, B, C) = gen_constr(A, B, C, V_cnst, - 0, vec![(V_b0, 1)], vec![], vec![(V_bi, 1)]); - // i0 = i_in - (A, B, C) = gen_constr(A, B, C, V_cnst, - 1, vec![(V_i0, 1)], vec![], vec![(V_ii, 1)]); - // s0 = s_in - (A, B, C) = gen_constr(A, B, C, V_cnst, - 2, vec![(V_s0, 1)], vec![], vec![(V_si, 1)]); - // b0 = 1 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 3, vec![(V_b0, 1)], vec![], vec![(V_cnst, 1)]); - // s1 - s0 = i0 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 4, vec![(V_s1, 1), (V_s0, -1)], vec![], vec![(V_i0, 1)]); - // i1 - i0 = 1 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 5, vec![(V_i1, 1), (V_i0, -1)], vec![], vec![(V_cnst, 1)]); - // (i1 - 4) * Z0 = Z1 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 6, vec![(V_i1, 1), (V_cnst, -4)], vec![(V_Z0, 1)], vec![(V_Z1, 1)]); - // B0 * (Z1 - 1) = 0 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 7, vec![(V_B0, 1)], vec![(V_Z1, 1), (V_cnst, -1)], vec![]); - // B0 * (b1 - 1) = 0 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 8, vec![(V_B0, 1)], vec![(V_b1, 1), (V_cnst, -1)], vec![]); - // (1 - B0) * (i1 - 4) = 0 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 9, vec![(V_cnst, 1), (V_B0, -1)], vec![(V_i1, 1), (V_cnst, -4)], vec![]); - // (1 - B0) * (b1 - 2) = 0 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 10, vec![(V_cnst, 1), (V_B0, -1)], vec![(V_b1, 1), (V_cnst, -2)], vec![]); - // b_out = b1 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 11, vec![(V_bo, 1)], vec![], vec![(V_b1, 1)]); - // i_out = i1 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 12, vec![(V_io, 1)], vec![], vec![(V_i1, 1)]); - // s_out = s1 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 13, vec![(V_so, 1)], vec![], vec![(V_s1, 1)]); - - (A, B, C) - }; - A_list.push(A); - B_list.push(B); - C_list.push(C); - - // Instance 1: block 0 - let (A, B, C) = { - let mut A: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut B: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut C: Vec<(usize, usize, [u8; 32])> = Vec::new(); - - // R1CS: - // b0 = b_in - (A, B, C) = gen_constr(A, B, C, V_cnst, - 0, vec![(V_b0, 1)], vec![], vec![(V_bi, 1)]); - // i0 = i_in - (A, B, C) = gen_constr(A, B, C, V_cnst, - 1, vec![(V_i0, 1)], vec![], vec![(V_ii, 1)]); - // s0 = s_in - (A, B, C) = gen_constr(A, B, C, V_cnst, - 2, vec![(V_s0, 1)], vec![], vec![(V_si, 1)]); - // b0 = 0 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 3, vec![(V_b0, 1)], vec![], vec![]); - // i0 = 0 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 4, vec![(V_i0, 1)], vec![], vec![]); - // s0 = 0 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 5, vec![(V_s0, 1)], vec![], vec![]); - // (i0 - 4) * Z0 = Z1 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 6, vec![(V_i0, 1), (V_cnst, -4)], vec![(V_Z0, 1)], vec![(V_Z1, 1)]); - // B0 * (Z1 - 1) = 0 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 7, vec![(V_B0, 1)], vec![(V_Z1, 1), (V_cnst, -1)], vec![]); - // B0 * (b1 - 1) = 0 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 8, vec![(V_B0, 1)], vec![(V_b1, 1), (V_cnst, -1)], vec![]); - // (1 - B0) * (i0 - 4) = 0 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 9, vec![(V_cnst, 1), (V_B0, -1)], vec![(V_i0, 1), (V_cnst, -4)], vec![]); - // (1 - B0) * (b1 - 2) = 0 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 10, vec![(V_cnst, 1), (V_B0, -1)], vec![(V_b1, 1), (V_cnst, -2)], vec![]); - // b_out = b1 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 11, vec![(V_bo, 1)], vec![], vec![(V_b1, 1)]); - // i_out = i0 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 12, vec![(V_io, 1)], vec![], vec![(V_i0, 1)]); - // s_out = s0 - (A, B, C) = gen_constr(A, B, C, V_cnst, - 13, vec![(V_so, 1)], vec![], vec![(V_s0, 1)]); - - (A, B, C) - }; - A_list.push(A); - B_list.push(B); - C_list.push(C); - - let block_inst = Instance::new(block_num_instances, block_num_cons, 2 * num_vars, &A_list, &B_list, &C_list).unwrap(); - - block_inst - }; - - // -- - // CONSIS INSTANCES - // -- - // CONSIS is consisted of two instances - // CONSIS_COMB performs random linear combination on inputs and outputs to a single value - // It is parallelized for consis_num_proofs copies - // CONSIS_CHECK checks that these values indeed matches - // There is only one copy for CONSIS_CHECK - - // CONSIS_COMB - // CONSIS_COMB takes in 4 witness lists as inputs: - // - perm_w0: , see PERM_PRELIM below - // - exec_inputs: - // - consis_w2: <0, i0 * r, i1 * r^2, ..., 0, o0 * r, o1 * r^2, ...> - // - consis_w3: - // Note: if v is 1, it is almost impossible to have consis_w3[1] = 0 - let consis_comb_num_cons = 2 * input_output_cutoff + 1; - let consis_comb_num_non_zero_entries = 4 * input_output_cutoff - 1; - - let V_valid = num_vars; - let V_cnst = V_valid; - - let consis_comb_inst = { - let mut A_list = Vec::new(); - let mut B_list = Vec::new(); - let mut C_list = Vec::new(); - - let (A, B, C) = { - let mut A: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut B: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut C: Vec<(usize, usize, [u8; 32])> = Vec::new(); - - let mut constraint_count = 0; - - // R1CS: - // For w2 - for i in 1..input_output_cutoff { - // Dot product for inputs - (A, B, C) = gen_constr(A, B, C, V_cnst, - constraint_count, vec![(i, 1)], vec![(num_vars + i, 1)], vec![(2 * num_vars + i, 1)]); - constraint_count += 1; - // Dot product for outputs - (A, B, C) = gen_constr(A, B, C, V_cnst, - constraint_count, vec![(i, 1)], vec![(num_vars + input_output_cutoff + i, 1)], vec![(2 * num_vars + input_output_cutoff + i, 1)]); - constraint_count += 1; - } - // For w3 - (A, B, C) = gen_constr(A, B, C, V_cnst, // w3[0] - constraint_count, vec![(V_valid, 1)], vec![], vec![(3 * num_vars, 1)]); - constraint_count += 1; - (A, B, C) = gen_constr(A, B, C, V_cnst, // w3[1] - constraint_count, - vec![(V_valid, 1)], - [vec![(V_cnst, 1)], (1..input_output_cutoff).map(|i| (2 * num_vars + i, 1)).collect()].concat(), - vec![(3 * num_vars + 1, 1)] - ); - constraint_count += 1; - (A, B, C) = gen_constr(A, B, C, V_cnst, // w3[2] - constraint_count, - vec![(V_valid, 1)], - [vec![(V_cnst, 1)], (1..input_output_cutoff).map(|i| (2 * num_vars + input_output_cutoff + i, 1)).collect()].concat(), - vec![(3 * num_vars + 2, 1)] - ); - - (A, B, C) - }; - A_list.push(A); - B_list.push(B); - C_list.push(C); - - let consis_comb_inst = Instance::new(1, consis_comb_num_cons, 4 * num_vars, &A_list, &B_list, &C_list).unwrap(); - - consis_comb_inst - }; - - // CONSIS_CHECK - // CONSIS_CHECK takes in consis_w3 = - // and verifies (o[k] - i[k + 1]) * v[k + 1] = 0 for all k - let consis_check_num_cons_base = 1; - let consis_check_num_non_zero_entries = 2 * total_num_proofs_bound; - let consis_check_num_cons = consis_check_num_cons_base * total_num_proofs_bound; - - let V_valid = 0; - let V_i = 1; - let V_o = 2; - let consis_check_inst = { - let mut A_list = Vec::new(); - let mut B_list = Vec::new(); - let mut C_list = Vec::new(); - - // Check output of the last block is the input of the next block - let (A, B, C) = { - let mut A: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut B: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut C: Vec<(usize, usize, [u8; 32])> = Vec::new(); - - // R1CS: - for i in 0..total_num_proofs_bound - 1 { - // Output matches input - (A, B, C) = gen_constr(A, B, C, 0, - i, vec![(i * num_vars + V_o, 1), ((i + 1) * num_vars + V_i, -1)], vec![((i + 1) * num_vars + V_valid, 1)], vec![]); - } - (A, B, C) - }; - A_list.push(A); - B_list.push(B); - C_list.push(C); - - let consis_check_inst = Instance::new(1, consis_check_num_cons, total_num_proofs_bound * num_vars, &A_list, &B_list, &C_list).unwrap(); - - consis_check_inst - }; - - // -- - // PERM Instances - // -- - // PERM is consisted of four instances - // PERM_PRELIM checks the correctness of (r, r^2, ...) - // PERM_ROOT and PERM_BLOCK_POLY compute the polynomial defined by block_inputs - // PERM_ROOT and PERM_EXEC_POLY compute the polynomial defined by exec_inputs - // Finally, the verifier checks that the two products are the same - // The product is defined by PROD = \prod(\tau - (\sum_i a_i * r^{i-1})) - // There is only one proof - - // PERM_PRELIM - let perm_prelim_num_cons = num_vars - 2; - let perm_prelim_num_non_zero_entries = num_vars - 2; - let perm_prelim_inst = { - let mut A_list = Vec::new(); - let mut B_list = Vec::new(); - let mut C_list = Vec::new(); - - let (A, B, C) = { - let mut A: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut B: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut C: Vec<(usize, usize, [u8; 32])> = Vec::new(); - - let V_r = 1; - - for i in 2..num_vars { - (A, B, C) = gen_constr(A, B, C, V_cnst, - i - 2, vec![(i - 1, 1)], vec![(V_r, 1)], vec![(i, 1)]); - } - (A, B, C) - }; - - A_list.push(A); - B_list.push(B); - C_list.push(C); - - let perm_block_inst = Instance::new(1, perm_prelim_num_cons, num_vars, &A_list, &B_list, &C_list).unwrap(); - perm_block_inst - }; - - // PERM_ROOT - let perm_root_num_cons = num_vars + 2; - let perm_root_num_non_zero_entries = 2 * num_vars + 2; - let perm_root_inst = { - let (A, B, C) = { - let mut A: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut B: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut C: Vec<(usize, usize, [u8; 32])> = Vec::new(); - - // Witnesses of PERM_ROOT is consisted of [w0, w1, w2, w3], each of size num_vars - // w0: tau, r, r^2, ... - // w1: one block_inputs entry: i0, i1, ... - // w2: one block_inputs entry dot product : i0, i1 * r, i2 * r^2, i3 * r^3, ... - // w3[0]: valid bit, should match block_inputs[0] - // w3[1]: one root of the polynomial: (tau - (i0 + i1 * r + i2 * r^2 - ...)), 0 if invalid - let V_tau = 0; - // The best way to find a CONSTANT ONE is to peak into the constant term of the first input, which is guaranteed to be valid - let V_cnst = num_vars; - - let mut constraint_count = 0; - - // correctness of w2 - (A, B, C) = gen_constr(A, B, C, V_cnst, // for i0 - constraint_count, vec![(num_vars, 1)], vec![], vec![(2 * num_vars, 1)]); - constraint_count += 1; - for i in 1..num_vars { - (A, B, C) = gen_constr(A, B, C, V_cnst, // for i1.. - constraint_count, vec![(num_vars + i, 1)], vec![(i, 1)], vec![(2 * num_vars + i, 1)]); - constraint_count += 1; - } - // correctness of w3[0] - (A, B, C) = gen_constr(A, B, C, V_cnst, - constraint_count, vec![(num_vars, 1)], vec![], vec![(3 * num_vars, 1)]); - constraint_count += 1; - // correctness of w3[1] - (A, B, C) = gen_constr(A, B, C, V_cnst, constraint_count, - [vec![(V_tau, 1)], (0..num_vars).map(|i| (2 * num_vars + i, -1)).collect()].concat(), - vec![(num_vars, 1)], - vec![(3 * num_vars + 1, 1)]); - - (A, B, C) - }; - - let A_list = vec![A.clone()]; - let B_list = vec![B.clone()]; - let C_list = vec![C.clone()]; - - let perm_root_inst = Instance::new(1, perm_root_num_cons, 4 * num_vars, &A_list, &B_list, &C_list).unwrap(); - - perm_root_inst - }; - - // PERM_BLOCK_POLY and PERM_EXEC_POLY - // The strategy is to compute the local polynomials (evaluated on tau) for each block instance - // Each w3[p][2] (i.e. w3[p][0][2]) stores the product pi for instance P. The verifier obtains all P of them and multiply them together. - // The correct formular is pi = v[k] * x[k] * (pi[k+1] + (1 - v[k+1]))) - // To do this, think of each entry of w3[k] (w3[p][k]) as a tuple (v, x, pi, D) - // v[k] <- whether the entry is valid - // x[k] <- \tau - (\sum_i a_i * r^{i-1}) - // pi[k] <- v[k] * D2[k] - // D[k] <- x[k] * (pi[k + 1] + (1 - v[k + 1])) - // PERM_EXEC_POLY looks like PERM_BLOCK_POLY except number of variables is now total_num_proofs_bound - let perm_poly_num_cons_base = 2; - let perm_block_poly_num_non_zero_entries = 4 * block_max_num_proofs_bound; - let perm_exec_poly_num_non_zero_entries = 4 * total_num_proofs_bound; - - let perm_poly_inst = [block_max_num_proofs_bound, total_num_proofs_bound].map(|entry_size| { - let perm_poly_num_cons = perm_poly_num_cons_base * entry_size; - let perm_poly_inst = { - let (A, B, C) = { - let mut A: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut B: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut C: Vec<(usize, usize, [u8; 32])> = Vec::new(); - - let V_valid = 0; - let V_cnst = V_valid; - let V_x = 1; - let V_pi = 2; - let V_d = 3; - - let mut constraint_count = 0; - - // Need to order the constraints so that they solve the inputs in the front first - // This way Az, Bz, Cz will have all non-zero entries concentrated in the front - for i in 0..entry_size - 1 { - // D - (A, B, C) = gen_constr(A, B, C, i * num_vars + V_cnst, - constraint_count, - vec![(i * num_vars + V_x, 1)], - vec![((i + 1) * num_vars + V_pi, 1), (i * num_vars + V_cnst, 1), ((i + 1) * num_vars + V_valid, -1)], - vec![(i * num_vars + V_d, 1)]); - constraint_count += 1; - // pi - (A, B, C) = gen_constr(A, B, C, i * num_vars + V_cnst, - constraint_count, vec![(i * num_vars + V_valid, 1)], vec![(i * num_vars + V_d, 1)], vec![(i * num_vars + V_pi, 1)]); - // Pad base constraint size to 2 - constraint_count += 1; - } - // Last Entry - let i = entry_size - 1; - // last D is x[k] * 1 - (A, B, C) = gen_constr(A, B, C, i * num_vars + V_cnst, - constraint_count, vec![(i * num_vars + V_x, 1)], vec![], vec![(i * num_vars + V_d, 1)]); - constraint_count += 1; - // last pi is just usual - (A, B, C) = gen_constr(A, B, C, i * num_vars + V_cnst, - constraint_count, vec![(i * num_vars + V_valid, 1)], vec![(i * num_vars + V_d, 1)], vec![(i * num_vars + V_pi, 1)]); - - (A, B, C) - }; - - let A_list = vec![A.clone()]; - let B_list = vec![B.clone()]; - let C_list = vec![C.clone()]; - - let perm_poly_inst = Instance::new(1, perm_poly_num_cons, entry_size * num_vars, &A_list, &B_list, &C_list).unwrap(); - - perm_poly_inst - }; - perm_poly_inst - }); - - // -- - // End Instances - // -- - - // -- - // RUNTIME KNOWLEDGE - // -- - let block_max_num_proofs = 4; - let block_num_proofs = vec![4, 1]; - let consis_num_proofs: usize = 8; - // What is the input and the output? - let input = vec![zero, zero]; - let output = vec![four, six]; - // Which block in the execution order is the output block? - let output_block_index = 4; - - // -- - // Begin Assignments - // -- - - let (block_vars_matrix, block_inputs_matrix, exec_inputs) = { - - let mut block_vars_matrix = Vec::new(); - let mut block_inputs_matrix = Vec::new(); - let mut exec_inputs = Vec::new(); - - // Block 1 - let (assignment_vars, assignment_inputs) = { - let mut assignment_vars = Vec::new(); - let mut assignment_inputs = Vec::new(); - // 0 1 2 3 4 5 6 7 8 - // variable orders: b0 i0 s0 b1 i1 s1 Z0 Z1 B0 - // input orders: valid b_i i_i s_i 1 b_o i_o s_o - // Iteration i = 1 - let mut vars = vec![one, zero, zero, one, one, zero, Scalar::from(3u32).neg().invert().to_bytes(), one, one]; - let mut inputs = vec![one, one, zero, zero, one, one, one, zero]; - vars.extend(vec![zero; 7]); - inputs.extend(vec![zero; 8]); - let next_block_assignment_vars = VarsAssignment::new(&vars).unwrap(); - let next_block_assignment_inputs = InputsAssignment::new(&inputs).unwrap(); - assignment_vars.push(next_block_assignment_vars); - assignment_inputs.push(next_block_assignment_inputs.clone()); - exec_inputs.push(next_block_assignment_inputs); - // Iteration i = 2 - let mut vars = vec![one, one, zero, one, two, one, Scalar::from(2u32).neg().invert().to_bytes(), one, one]; - let mut inputs = vec![one, one, one, zero, one, one, two, one]; - vars.extend(vec![zero; 7]); - inputs.extend(vec![zero; 8]); - let next_block_assignment_vars = VarsAssignment::new(&vars).unwrap(); - let next_block_assignment_inputs = InputsAssignment::new(&inputs).unwrap(); - assignment_vars.push(next_block_assignment_vars); - assignment_inputs.push(next_block_assignment_inputs.clone()); - exec_inputs.push(next_block_assignment_inputs); - // Iteration i = 3 - let mut vars = vec![one, two, one, one, three, three, Scalar::from(1u32).neg().invert().to_bytes(), one, one]; - let mut inputs = vec![one, one, two, one, one, one, three, three]; - vars.extend(vec![zero; 7]); - inputs.extend(vec![zero; 8]); - let next_block_assignment_vars = VarsAssignment::new(&vars).unwrap(); - let next_block_assignment_inputs = InputsAssignment::new(&inputs).unwrap(); - assignment_vars.push(next_block_assignment_vars); - assignment_inputs.push(next_block_assignment_inputs.clone()); - exec_inputs.push(next_block_assignment_inputs); - // Iteration i = 4 - let mut vars = vec![one, three, three, two, four, six, zero, zero, zero]; - let mut inputs = vec![one, one, three, three, one, two, four, six]; - vars.extend(vec![zero; 7]); - inputs.extend(vec![zero; 8]); - let next_block_assignment_vars = VarsAssignment::new(&vars).unwrap(); - let next_block_assignment_inputs = InputsAssignment::new(&inputs).unwrap(); - assignment_vars.push(next_block_assignment_vars); - assignment_inputs.push(next_block_assignment_inputs.clone()); - exec_inputs.push(next_block_assignment_inputs); - - (assignment_vars, assignment_inputs) - }; - block_vars_matrix.push(assignment_vars); - block_inputs_matrix.push(assignment_inputs); - - // Block 0 - let (assignment_vars, assignment_inputs) = { - let mut assignment_vars = Vec::new(); - let mut assignment_inputs = Vec::new(); - // 0 1 2 3 4 5 6 7 8 - // variable orders: b0 i0 s0 b1 i1 s1 Z0 Z1 B0 - // input orders: valid b_i i_i s_i 1 b_o i_o s_o - let mut vars = vec![zero, zero, zero, one, zero, zero, Scalar::from(4u32).neg().invert().to_bytes(), one, one]; - let mut inputs = vec![one, zero, zero, zero, one, one, zero, zero]; - vars.extend(vec![zero; 7]); - inputs.extend(vec![zero; 8]); - let next_block_assignment_vars = VarsAssignment::new(&vars).unwrap(); - let next_block_assignment_inputs = InputsAssignment::new(&inputs).unwrap(); - assignment_vars.push(next_block_assignment_vars); - assignment_inputs.push(next_block_assignment_inputs.clone()); - exec_inputs.insert(0, next_block_assignment_inputs); - - (assignment_vars, assignment_inputs) - }; - block_vars_matrix.push(assignment_vars); - block_inputs_matrix.push(assignment_inputs); - - // Pad exec_inputs with 0 - assert!(consis_num_proofs >= exec_inputs.len()); - let pad_size = consis_num_proofs - exec_inputs.len(); - for _ in 0..pad_size { - exec_inputs.push(VarsAssignment::new(&vec![zero; num_vars]).unwrap()); - } - - // Witnesses for permutation cannot be generated until tau and r are generated - // Both can only be generated at proving time - - (block_vars_matrix, block_inputs_matrix, exec_inputs) - }; - - // -- - // End Assignments - // -- - - ( - input_block_num, - output_block_num, - input, - output, - output_block_index, - - num_vars, - input_output_cutoff, - total_num_proofs_bound, - block_max_num_proofs_bound, - - block_num_cons, - block_num_non_zero_entries, - block_num_instances, - block_max_num_proofs, - block_num_proofs, - block_inst, - - consis_comb_num_cons, - consis_comb_num_non_zero_entries, - consis_num_proofs, - consis_comb_inst, - - consis_check_num_cons_base, - consis_check_num_non_zero_entries, - consis_check_inst, - - perm_prelim_num_cons, - perm_prelim_num_non_zero_entries, - perm_prelim_inst, - - perm_root_num_cons, - perm_root_num_non_zero_entries, - perm_root_inst, - - perm_poly_num_cons_base, - perm_block_poly_num_non_zero_entries, - perm_exec_poly_num_non_zero_entries, - perm_poly_inst, - - block_vars_matrix, - block_inputs_matrix, - exec_inputs - ) -} - -fn main() { - // produce an R1CS instance - let ( - input_block_num, - output_block_num, - input, - output, - output_block_index, - - num_vars, - input_output_cutoff, - total_num_proofs_bound, - block_max_num_proofs_bound, - - block_num_cons, - block_num_non_zero_entries, - block_num_instances, - block_max_num_proofs, - block_num_proofs, - block_inst, - - consis_comb_num_cons, - consis_comb_num_non_zero_entries, - consis_num_proofs, - consis_comb_inst, - - consis_check_num_cons_base, - consis_check_num_non_zero_entries, - consis_check_inst, - - perm_prelim_num_cons, - perm_prelim_num_non_zero_entries, - perm_prelim_inst, - - perm_root_num_cons, - perm_root_num_non_zero_entries, - perm_root_inst, - - perm_poly_num_cons_base, - perm_block_poly_num_non_zero_entries, - perm_exec_poly_num_non_zero_entries, - perm_poly_inst, - - block_vars_matrix, - block_inputs_matrix, - exec_inputs - ) = produce_r1cs(); - - let perm_block_poly_num_cons = perm_poly_num_cons_base * block_max_num_proofs_bound; - let perm_exec_poly_num_cons = perm_poly_num_cons_base * total_num_proofs_bound; - let consis_check_num_cons = consis_check_num_cons_base * total_num_proofs_bound; - - assert_eq!(block_num_instances, block_vars_matrix.len()); - assert_eq!(block_num_instances, block_inputs_matrix.len()); - for p in 0..block_num_instances { - assert_eq!(block_vars_matrix[p].len(), block_inputs_matrix[p].len()); - } - - // produce public parameters - let block_gens = SNARKGens::new(block_num_cons, num_vars, block_num_instances, block_num_non_zero_entries); - let consis_comb_gens = SNARKGens::new(consis_comb_num_cons, 4 * num_vars, 1, consis_comb_num_non_zero_entries); - let consis_check_gens = SNARKGens::new(consis_check_num_cons, total_num_proofs_bound * num_vars, 1, consis_check_num_non_zero_entries); - let perm_prelim_gens = SNARKGens::new(perm_prelim_num_cons, num_vars, 1, perm_prelim_num_non_zero_entries); - let perm_root_gens = SNARKGens::new(perm_root_num_cons, 4 * num_vars, 1, perm_root_num_non_zero_entries); - let perm_block_poly_gens = SNARKGens::new(perm_block_poly_num_cons, block_max_num_proofs_bound * num_vars, 1, perm_block_poly_num_non_zero_entries); - let perm_exec_poly_gens = SNARKGens::new(perm_exec_poly_num_cons, total_num_proofs_bound * num_vars, 1, perm_exec_poly_num_non_zero_entries); - // Only use one version of gens_r1cs_sat - // for size VAR - let vars_gens = SNARKGens::new(block_num_cons, num_vars, block_num_instances, block_num_non_zero_entries).gens_r1cs_sat; - // for size PROOF * VAR - let proofs_times_vars_gens = SNARKGens::new(block_num_cons, block_max_num_proofs_bound * num_vars, 1, block_num_non_zero_entries).gens_r1cs_sat; - // for size TOTAL_PROOF * VAR - let total_proofs_times_vars_gens = SNARKGens::new(block_num_cons, total_num_proofs_bound * num_vars, 1, block_num_non_zero_entries).gens_r1cs_sat; - - // create a commitment to the R1CS instance - // TODO: change to encoding all r1cs instances - let (block_comm, block_decomm) = SNARK::encode(&block_inst, &block_gens); - let (consis_comb_comm, consis_comb_decomm) = SNARK::encode(&consis_comb_inst, &consis_comb_gens); - let (consis_check_comm, consis_check_decomm) = SNARK::encode(&consis_check_inst, &consis_check_gens); - let (perm_prelim_comm, perm_prelim_decomm) = SNARK::encode(&perm_prelim_inst, &perm_prelim_gens); - let (perm_root_comm, perm_root_decomm) = SNARK::encode(&perm_root_inst, &perm_root_gens); - let (perm_block_poly_comm, perm_block_poly_decomm) = SNARK::encode(&perm_poly_inst[0], &perm_block_poly_gens); - let (perm_exec_poly_comm, perm_exec_poly_decomm) = SNARK::encode(&perm_poly_inst[1], &perm_exec_poly_gens); - - // produce a proof of satisfiability - let mut prover_transcript = Transcript::new(b"snark_example"); - let proof = SNARK::prove( - input_block_num, - output_block_num, - &input, - &output, - output_block_index, - - num_vars, - input_output_cutoff, - total_num_proofs_bound, - block_num_instances, - block_max_num_proofs_bound, - block_max_num_proofs, - &block_num_proofs, - &block_inst, - &block_comm, - &block_decomm, - &block_gens, - consis_num_proofs, - &consis_comb_inst, - &consis_comb_comm, - &consis_comb_decomm, - &consis_comb_gens, - consis_check_num_cons_base, - &consis_check_inst, - &consis_check_comm, - &consis_check_decomm, - &consis_check_gens, - &perm_prelim_inst, - &perm_prelim_comm, - &perm_prelim_decomm, - &perm_prelim_gens, - &perm_root_inst, - &perm_root_comm, - &perm_root_decomm, - &perm_root_gens, - perm_poly_num_cons_base, - &perm_poly_inst[0], - &perm_block_poly_comm, - &perm_block_poly_decomm, - &perm_block_poly_gens, - &perm_poly_inst[1], - &perm_exec_poly_comm, - &perm_exec_poly_decomm, - &perm_exec_poly_gens, - block_vars_matrix, - block_inputs_matrix, - exec_inputs, - &vars_gens, - &proofs_times_vars_gens, - &total_proofs_times_vars_gens, - &mut prover_transcript, - ); - - // verify the proof of satisfiability - let mut verifier_transcript = Transcript::new(b"snark_example"); - assert!(proof - .verify( - input_block_num, - output_block_num, - &input, - &output, - output_block_index, - - num_vars, - input_output_cutoff, - total_num_proofs_bound, - block_num_instances, - block_max_num_proofs_bound, - block_max_num_proofs, - &block_num_proofs, - block_num_cons, - &block_comm, - &block_gens, - consis_num_proofs, - consis_comb_num_cons, - &consis_comb_comm, - &consis_comb_gens, - consis_check_num_cons_base, - &consis_check_comm, - &consis_check_gens, - perm_prelim_num_cons, - &perm_prelim_comm, - &perm_prelim_gens, - perm_root_num_cons, - &perm_root_comm, - &perm_root_gens, - perm_poly_num_cons_base, - &perm_block_poly_comm, - &perm_block_poly_gens, - &perm_exec_poly_comm, - &perm_exec_poly_gens, - &vars_gens, - &proofs_times_vars_gens, - &total_proofs_times_vars_gens, - &mut verifier_transcript - ).is_ok()); - println!("proof verification successful!"); -} diff --git a/spartan_parallel/examples/cubic.rs b/spartan_parallel/examples/cubic.rs deleted file mode 100644 index 91e3cae9..00000000 --- a/spartan_parallel/examples/cubic.rs +++ /dev/null @@ -1,299 +0,0 @@ -//! Demonstrates how to produces a proof for canonical cubic equation: `x^3 + x + 5 = y`. -//! The example is described in detail [here]. -//! -//! The R1CS for this problem is: -//! Instance 1: -//! `Z0 * Z0 - Z1 = 0` -//! `Z1 * Z0 - Z2 = 0` -//! `(Z2 + Z0) * 1 - Z3 = 0` -//! `(Z3 + 5) * 1 - Z4 = 0` -//! Instance 2: -//! `Z0 * 2 - Z1 = 0` -//! `Z1 * Z0 - 2 * Z2 = 0` -//! `(Z2 + Z1 + Z0) * 4 - Z3 = 0` -//! `(Z3 + Z1 + 5) * 2 - Z4 = 0` -//! -//! [here]: https://medium.com/@VitalikButerin/quadratic-arithmetic-programs-from-zero-to-hero-f6d558cea649 -#![allow(clippy::assertions_on_result_states)] -use curve25519_dalek::scalar::Scalar; -use libspartan::{Instance, SNARKGens, VarsAssignment, SNARK, InputsAssignment}; -use merlin::Transcript; -use rand::rngs::OsRng; - -#[allow(non_snake_case)] -fn produce_r1cs() -> ( - usize, - usize, - usize, - usize, - usize, - Vec, - Instance, - Vec>, - Vec>, -) { - // bad test cases - // set them to unreachable values to prevent bad tests - let bad_instance = 3; - let bad_proof = 1; - // parameters of the R1CS instance - // maximum value among the R1CS instances - let num_cons = 4; - // num_vars = num_inputs - // Divide inputs into (1, input, 1, output) - let num_vars = 4; - let num_inputs = num_vars; - let num_non_zero_entries = 8; - // Number of R1CS instances - let num_instances = 2; - // Number of proofs of each R1CS instance - let max_num_proofs = 4; - let num_proofs = vec![4, 2]; - - let one = Scalar::one().to_bytes(); - let two = Scalar::from(2u32).to_bytes(); - let mut assignment_vars_matrix = Vec::new(); - let mut assignment_inputs_matrix = Vec::new(); - - let mut A_list = Vec::new(); - let mut B_list = Vec::new(); - let mut C_list = Vec::new(); - - // -- - // Instance 0 - // -- - let instance = 0; - // We will encode the above constraints into three matrices, where - // the coefficients in the matrix are in the little-endian byte order - let mut A: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut B: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut C: Vec<(usize, usize, [u8; 32])> = Vec::new(); - - // R1CS is a set of three sparse matrices A B C, where is a row for every - // constraint and a column for every entry in z = (vars, 1, inputs) - // An R1CS instance is satisfiable iff: - // Az \circ Bz = Cz, where z = (vars, 1, inputs) - - // constraint 0 entries in (A,B,C) - // constraint 0 is Z0 * Z0 - Z1 = 0. - A.push((0, 0, one)); - B.push((0, 0, one)); - C.push((0, 1, one)); - - // constraint 1 entries in (A,B,C) - // constraint 1 is Z1 * Z0 - Z2 = 0. - A.push((1, 1, one)); - B.push((1, 0, one)); - C.push((1, 2, one)); - - // constraint 2 entries in (A,B,C) - // constraint 2 is (Z2 + Z0) * 1 - Z3 = 0. - A.push((2, 2, one)); - A.push((2, 0, one)); - B.push((2, num_vars, one)); - C.push((2, 3, one)); - - // constraint 3 entries in (A,B,C) - // constraint 3 is (Z3 + 5) * 1 - I0 = 0. - A.push((3, 3, one)); - A.push((3, num_vars, Scalar::from(5u32).to_bytes())); - B.push((3, num_vars, one)); - C.push((3, num_vars + 1, one)); - - A_list.push(A); - B_list.push(B); - C_list.push(C); - - let mut assignment_vars = Vec::new(); - let mut assignment_inputs = Vec::new(); - - for proof in 0..num_proofs[instance] { - // compute a satisfying assignment - let mut csprng: OsRng = OsRng; - let z0 = Scalar::random(&mut csprng); - let z1 = z0 * z0; // constraint 0 - let z2 = z1 * z0; // constraint 1 - // let z3 = z2 + z0; // constraint 2 - let z3 = if instance == bad_instance && proof == bad_proof {z2 - z0} else {z2 + z0}; - let i0 = z3 + Scalar::from(5u32); // constraint 3 - - // create a VarsAssignment - let mut vars = vec![Scalar::zero().to_bytes(); num_vars]; - vars[0] = z0.to_bytes(); - vars[1] = z1.to_bytes(); - vars[2] = z2.to_bytes(); - vars[3] = z3.to_bytes(); - let next_assignment_vars = VarsAssignment::new(&vars).unwrap(); - - // create an InputsAssignment (1, input, 1, output) - let mut inputs = vec![Scalar::zero().to_bytes(); num_inputs]; - inputs[0] = Scalar::one().to_bytes(); - inputs[1] = i0.to_bytes(); - inputs[num_inputs / 2] = Scalar::one().to_bytes(); - let next_assignment_inputs = InputsAssignment::new(&inputs).unwrap(); - - // check if the instance we created is satisfiable - // let res = inst.is_sat(&next_assignment_vars, &next_assignment_inputs); - // assert!(res.unwrap(), "should be satisfied"); - - assignment_vars.push(next_assignment_vars); - assignment_inputs.push(next_assignment_inputs); - } - - assignment_vars_matrix.push(assignment_vars); - assignment_inputs_matrix.push(assignment_inputs); - - // -- - // Instance 1 - // -- - let instance = 1; - // We will encode the above constraints into three matrices, where - // the coefficients in the matrix are in the little-endian byte order - let mut A: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut B: Vec<(usize, usize, [u8; 32])> = Vec::new(); - let mut C: Vec<(usize, usize, [u8; 32])> = Vec::new(); - - // R1CS is a set of three sparse matrices A B C, where is a row for every - // constraint and a column for every entry in z = (vars, 1, inputs) - // An R1CS instance is satisfiable iff: - // Az \circ Bz = Cz, where z = (vars, 1, inputs) - - // constraint 0 entries in (A,B,C) - // constraint 0 is Z0 * 2 - Z1 = 0 - A.push((0, 0, one)); - B.push((0, num_vars, two)); - C.push((0, 1, one)); - - // constraint 1 entries in (A,B,C) - // constraint 1 is Z1 * Z0 - Z2 = 0. - A.push((1, 1, one)); - B.push((1, 0, one)); - C.push((1, 2, one)); - - // constraint 2 entries in (A,B,C) - // constraint 2 is (Z2 + Z1 + Z0) * 4 - Z3 = 0. - A.push((2, 2, one)); - A.push((2, 1, one)); - A.push((2, 0, one)); - B.push((2, num_vars, two)); - C.push((2, 3, one)); - - // constraint 3 entries in (A,B,C) - // constraint 3 is (Z3 + Z1 + 5) * 2 - I0 = 0. - A.push((3, 3, one)); - A.push((3, 1, one)); - A.push((3, num_vars, Scalar::from(5u32).to_bytes())); - B.push((3, num_vars, two)); - C.push((3, num_vars + 1, one)); - - A_list.push(A); - B_list.push(B); - C_list.push(C); - - let mut assignment_vars = Vec::new(); - let mut assignment_inputs = Vec::new(); - - for proof in 0..num_proofs[instance] { - // compute a satisfying assignment - let mut csprng: OsRng = OsRng; - let z0 = Scalar::random(&mut csprng); - let z1 = z0 + z0; // constraint 0 - let z2 = z1 * z0; // constraint 1 - // let z3 = z2 + z1 + z0 + z2 + z1 + z0; // constraint 2 - let z3 = if instance == bad_instance && proof == bad_proof {z2} else {z2 + z1 + z0 + z2 + z1 + z0}; - let i0 = z3 + z1 + Scalar::from(5u32) + z3 + z1 + Scalar::from(5u32); // constraint 3 - - // create a VarsAssignment - let mut vars = vec![Scalar::zero().to_bytes(); num_vars]; - vars[0] = z0.to_bytes(); - vars[1] = z1.to_bytes(); - vars[2] = z2.to_bytes(); - vars[3] = z3.to_bytes(); - let next_assignment_vars = VarsAssignment::new(&vars).unwrap(); - - // create an InputsAssignment (1, input, 1, output) - let mut inputs = vec![Scalar::zero().to_bytes(); num_inputs]; - inputs[0] = Scalar::one().to_bytes(); - inputs[1] = i0.to_bytes(); - inputs[num_inputs / 2] = Scalar::one().to_bytes(); - let next_assignment_inputs = InputsAssignment::new(&inputs).unwrap(); - - // check if the instance we created is satisfiable - // let res = inst.is_sat(&next_assignment_vars, &next_assignment_inputs); - // assert!(res.unwrap(), "should be satisfied"); - - assignment_vars.push(next_assignment_vars); - assignment_inputs.push(next_assignment_inputs); - } - - assignment_vars_matrix.push(assignment_vars); - assignment_inputs_matrix.push(assignment_inputs); - - // -- - // End Instances - // -- - - let inst = Instance::new(num_instances, num_cons, 2 * num_vars, &A_list, &B_list, &C_list).unwrap(); - - ( - num_cons, - num_vars, - num_non_zero_entries, - num_instances, - max_num_proofs, - num_proofs, - inst, - assignment_vars_matrix, - assignment_inputs_matrix, - ) -} - -fn main() { - // produce an R1CS instance - let ( - num_cons, - // num_inputs == num_vars - num_vars, - num_non_zero_entries, - num_instances, - max_num_proofs, - num_proofs, - inst, - assignment_vars_matrix, - assignment_inputs_matrix - ) = produce_r1cs(); - - assert_eq!(num_instances, assignment_vars_matrix.len()); - assert_eq!(num_instances, assignment_inputs_matrix.len()); - for p in 0..num_instances { - assert_eq!(assignment_vars_matrix[p].len(), assignment_inputs_matrix[p].len()); - } - - // produce public parameters - let gens = SNARKGens::new(num_cons, num_vars, num_instances, num_non_zero_entries); - - // create a commitment to the R1CS instance - // TODO: change to encoding all r1cs instances - let (comm, decomm) = SNARK::encode(&inst, &gens); - - // produce a proof of satisfiability - let mut prover_transcript = Transcript::new(b"snark_example"); - let proof = SNARK::prove( - max_num_proofs, - &num_proofs, - &inst, - &comm, - &decomm, - assignment_vars_matrix, - assignment_inputs_matrix, - &gens, - &mut prover_transcript, - ); - - // verify the proof of satisfiability - let mut verifier_transcript = Transcript::new(b"snark_example"); - assert!(proof - .verify(num_instances, max_num_proofs, &num_proofs, num_cons, &comm, &mut verifier_transcript, &gens) - .is_ok()); - println!("proof verification successful!"); -} diff --git a/spartan_parallel/examples/mem.rs b/spartan_parallel/examples/mem.rs deleted file mode 100644 index 83beef42..00000000 --- a/spartan_parallel/examples/mem.rs +++ /dev/null @@ -1,671 +0,0 @@ -//! An simple program with some memory operations -//! The pseudocode is: -//! a[0] = 1 -//! a[1] = 2 -//! s = 0 -//! i = 0 -//! while i != 3: -//! i = i + a[0] -//! s = s + a[1] -//! Which, when converted to blocks, is: -//! Block 0: Block 1: -//! assert v * v = v assert v * v = v -//! if (v == 1) { if (v == 1) { -//! assert b == 0 assert b == 1 -//! assert A0 == 0 assert A0 == 0 -//! assert V0 == 1 LOAD(A0, V0) -//! STORE(A0, V0) assert A1 == 1 -//! assert A1 == 1 LOAD(A1, V1) -//! assert V1 == 2 i = i + V0 -//! STORE(A1, V1) s = s + V1 -//! s = 0 if i != 3: -//! i = 1 b = 1 -//! if i != 3: else: -//! b = 1 b = 2 -//! else: } -//! b = 2 -//! } -//! Note: take caution when translating STORE(0, 1) into constraints. If an execution of the block is invalid, this could cause a problem! -//! -//! Converting each block to constraints: -//! Block 0: Block 1: -//! 0 v = v * v v = v * v -//! 1 0 = w - v 0 = w - v -//! 2 0 = b0 0 = b0 - 1 -//! 3 0 = i0 0 = A0 -//! 4 0 = s0 0 = A1 - 1 -//! 5 Z1 = (i0 - 3) * Z0 0 = i1 - i0 - V0 -//! 6 0 = A0 0 = s1 - s0 - V1 -//! 7 0 = V0 - 1 Z1 = (i1 - 3) * Z0 -//! 8 0 = A1 - 1 0 = B0 * (Z1 - 1) -//! 9 0 = V1 - 2 0 = B0 * (b1 - 1) -//! 10 0 = B0 * (Z1 - 1) 0 = (1 - B0) * (i1 - 3) -//! 11 0 = B0 * (b1 - 1) 0 = (1 - B0) * (b1 - 2) -//! 12 0 = (1 - B0) * (i0 - 3) -//! 13 0 = (1 - B0) * (b1 - 2) -//! 14 i1 = i0 -//! 15 s1 = s0 -//! -//! Program States -//! The first entry of the witness is a copy of the valid bit, followed by a list of addresses and then a list of values -//! Put all memory states at the front of the witnesses -//! 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 -//! Exec: v | b0 i0 s0 | _ | b1 i1 s1 | w A0 A1 V0 V1 Z0 Z1 B0 -//! 0 1 0 0 0 0 1 0 0 1 0 1 1 2 -3i 1 1 -//! 1 1 1 0 0 0 1 1 2 1 0 1 1 2 -2i 1 1 -//! 2 1 1 1 2 0 1 2 4 1 0 1 1 2 -1i 1 1 -//! 3 1 1 2 4 0 2 3 6 1 0 1 1 2 0 0 0 -//! 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -//! -#![allow(clippy::assertions_on_result_states)] -use std::{ops::Neg, cmp::max}; - -use curve25519_dalek::scalar::Scalar; -use libspartan::{instance::Instance, SNARKGens, VarsAssignment, SNARK, InputsAssignment, MemsAssignment}; -use merlin::Transcript; - -// Everything provided by the frontend -struct CompileTimeKnowledge { - block_num_instances: usize, - num_vars: usize, - num_inputs_unpadded: usize, - total_num_proofs_bound: usize, - block_num_mem_accesses: Vec, - total_num_mem_accesses_bound: usize, - - args: Vec, Vec<(usize, [u8; 32])>, Vec<(usize, [u8; 32])>)>>, - - func_input_width: usize, - input_offset: usize, - input_block_num: usize, - output_offset: usize, - output_block_num: usize -} - -// Everything provided by the prover -struct RunTimeKnowledge { - block_max_num_proofs: usize, - block_num_proofs: Vec, - consis_num_proofs: usize, - total_num_mem_accesses: usize, - - block_vars_matrix: Vec>, - block_inputs_matrix: Vec>, - exec_inputs: Vec, - addr_mems_list: Vec, - - input: Vec<[u8; 32]>, - output: [u8; 32], - output_exec_num: usize -} - -#[allow(non_snake_case)] -fn produce_r1cs() -> ( - CompileTimeKnowledge, - RunTimeKnowledge -) { - // Separate instances into three lists: - // BLOCK: correctness within a block - // CONSIS: consistency between blocks - // PERM: permutation between two orderings - // - // Separate inputs into two lists: - // BLOCK_ORDER - // EXEC_ORDER - // - // Separate vars into three lists - // BLOCK, CONSIS, PERM - - let minus_three = Scalar::from(3u32).neg().to_bytes(); - let minus_two = Scalar::from(2u32).neg().to_bytes(); - let minus_one = Scalar::from(1u32).neg().to_bytes(); - let zero = Scalar::zero().to_bytes(); - let one = Scalar::one().to_bytes(); - let two = Scalar::from(2u32).to_bytes(); - let three = Scalar::from(3u32).to_bytes(); - let four = Scalar::from(4u32).to_bytes(); - let six = Scalar::from(6u32).to_bytes(); - - // -- - // COMPILE TIME KNOWLEDGE - // -- - - // num_vars should be consistent accross the instances - // everything else is instance-specific - // Divide inputs into (1, input, 1, output) - // So num_inputs = num_outputs = num_vars / 2 - 1 - let num_vars = 16; - // How many non-dummy inputs do we have? - let num_inputs_unpadded = 4; - - // Number of proofs of each R1CS instance - // Total for all blocks and one block - // OBTAINED DURING COMPILE TIME - let total_num_proofs_bound = 16; - // Bound on total number of memory accesses - let total_num_mem_accesses_bound = 16; - - // What is the input and output block? - // Note: the assumption is that during a normal execution, the input block and the output block will only be reached once - let input_block_num = 0; - let output_block_num = 2; - - // -- - // BLOCK Instances - // -- - - // Number of R1CS instances - let block_num_instances = 2; - - // Program States - // Put all memory states at the front of the witnesses - // 0 1 2 3 4 5 6 7 0 2 3 4 5 6 7 8 - // Exec: v | b0 i0 s0 | _ | b1 i1 s1 | w A0 V0 A1 V1 Z0 Z1 B0 - let args = { - let V_valid = 0; - let V_cnst = V_valid; - let V_b0 = 1; - let V_i0 = 2; - let V_s0 = 3; - let V_b1 = num_inputs_unpadded + 1; - let V_i1 = num_inputs_unpadded + 2; - let V_s1 = num_inputs_unpadded + 3; - let V_w = num_vars; - let V_A0 = num_vars + 1; - let V_V0 = num_vars + 2; - let V_A1 = num_vars + 3; - let V_V1 = num_vars + 4; - let V_Z0 = num_vars + 5; - let V_Z1 = num_vars + 6; - let V_B0 = num_vars + 7; - - let mut args = Vec::new(); - // Block 0 - let arg = vec![ - // 0: v * v = v - (vec![(V_valid, one)], vec![(V_valid, one)], vec![(V_valid, one)]), - // 1: 0 = w - v - (vec![], vec![], vec![(V_w, one), (V_valid, minus_one)]), - // 2: 0 = b0 - (vec![], vec![], vec![(V_b0, one)]), - // 3: 0 = i0 - (vec![], vec![], vec![(V_i0, one)]), - // 4: 0 = s0 - (vec![], vec![], vec![(V_s0, one)]), - // 5: (i0 - 3) * Z0 = Z1 - (vec![(V_i0, one), (V_cnst, minus_three)], vec![(V_Z0, one)], vec![(V_Z1, one)]), - // 6: 0 = A0 - (vec![], vec![], vec![(V_A0, one)]), - // 7: 0 = V0 - 1 - (vec![], vec![], vec![(V_V0, one), (V_cnst, minus_one)]), - // 8: 0 = A1 - 1 - (vec![], vec![], vec![(V_A1, one), (V_cnst, minus_one)]), - // 9: 0 = V1 - 2 - (vec![], vec![], vec![(V_V1, one), (V_cnst, minus_two)]), - // 10: B0 * (Z1 - 1) = 0 - (vec![(V_B0, one)], vec![(V_Z1, one), (V_cnst, minus_one)], vec![]), - // 11: B0 * (b1 - 1) = 0 - (vec![(V_B0, one)], vec![(V_b1, one), (V_cnst, minus_one)], vec![]), - // 12: (1 - B0) * (i1 - 3) = 0 - (vec![(V_cnst, one), (V_B0, minus_one)], vec![(V_i1, one), (V_cnst, minus_three)], vec![]), - // 13: (1 - B0) * (b1 - 2) = 0 - (vec![(V_cnst, one), (V_B0, minus_one)], vec![(V_b1, one), (V_cnst, minus_two)], vec![]), - // 14: 0 = i1 - i0 - (vec![], vec![], vec![(V_i1, one), (V_i0, minus_one)]), - // 15: 0 = s1 - s0 - (vec![], vec![], vec![(V_s1, one), (V_s0, minus_one)]), - ]; - args.push(arg); - - // Block 1 - let arg = vec![ - // 0: v * v = v - (vec![(V_valid, one)], vec![(V_valid, one)], vec![(V_valid, one)]), - // 1: 0 = w - v - (vec![], vec![], vec![(V_w, one), (V_valid, minus_one)]), - // 2: 0 = b0 - 1 - (vec![], vec![], vec![(V_b0, one), (V_cnst, minus_one)]), - // 3: 0 = A0 - (vec![], vec![], vec![(V_A0, one)]), - // 4: 0 = A1 - 1 - (vec![], vec![], vec![(V_A1, one), (V_cnst, minus_one)]), - // 5: 0 = i1 - i0 - V0 - (vec![], vec![], vec![(V_i1, one), (V_i0, minus_one), (V_V0, minus_one)]), - // 6: 0 = s1 - s0 - V1 - (vec![], vec![], vec![(V_s1, one), (V_s0, minus_one), (V_V1, minus_one)]), - // 7: (i1 - 3) * Z0 = Z1 - (vec![(V_i1, one), (V_cnst, minus_three)], vec![(V_Z0, one)], vec![(V_Z1, one)]), - // 8: B0 * (Z1 - 1) = 0 - (vec![(V_B0, one)], vec![(V_Z1, one), (V_cnst, minus_one)], vec![]), - // 9: B0 * (b1 - 1) = 0 - (vec![(V_B0, one)], vec![(V_b1, one), (V_cnst, minus_one)], vec![]), - // 10: (1 - B0) * (i1 - 3) = 0 - (vec![(V_cnst, one), (V_B0, minus_one)], vec![(V_i1, one), (V_cnst, minus_three)], vec![]), - // 11: (1 - B0) * (b1 - 2) = 0 - (vec![(V_cnst, one), (V_B0, minus_one)], vec![(V_b1, one), (V_cnst, minus_two)], vec![]) - ]; - args.push(arg); - - args - }; - - // -- - // End Instances - // -- - - // -- - // RUNTIME KNOWLEDGE - // -- - let block_max_num_proofs = 4; - let block_num_proofs = vec![1, 4]; - let consis_num_proofs: usize = 5; - // What is the input and the output? - let input = vec![zero, zero]; - let output = three; - // Which block in the execution order is the output block? - let output_exec_num = 3; - // How many memory accesses per block? - let block_num_mem_accesses = vec![2, 2]; - // How many memory accesses are there? - let total_num_mem_accesses = 8; - - // -- - // Begin Assignments - // -- - - let ( - block_vars_matrix, - block_inputs_matrix, - exec_inputs, - addr_mems_list - ) = { - - let mut block_vars_matrix = Vec::new(); - let mut block_inputs_matrix = Vec::new(); - let mut exec_inputs = Vec::new(); - let mut addr_mems_list = Vec::new(); - - // Assignment needs to be sorted by # of executions per block, so assignment[0] corresponds to block 1, assignment[1] is block 0 - // Block 1 - // Exec: v | b0 i0 s0 | _ | b1 i1 s1 | w A0 V0 A1 V1 Z0 Z1 B0 - // 0 1 1 0 0 0 1 1 2 1 0 1 1 2 -2i 1 1 - // 1 1 1 1 2 0 1 2 4 1 0 1 1 2 -1i 1 1 - // 2 1 1 2 4 0 2 3 6 1 0 1 1 2 0 0 0 - // 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - let (assignment_vars, assignment_inputs) = { - let mut assignment_vars = Vec::new(); - let mut assignment_inputs = Vec::new(); - // Iteration i = 1 - let inputs: Vec<[u8; 32]> = [vec![one, one, zero, zero], vec![zero, one, one, two]].concat(); - let vars: Vec<[u8; 32]> = [vec![one, zero, one, one, two, Scalar::from(2u32).neg().invert().to_bytes(), one, one], vec![zero; 8]].concat(); - let next_block_assignment_vars = VarsAssignment::new(&vars).unwrap(); - let next_block_assignment_inputs = InputsAssignment::new(&inputs).unwrap(); - assignment_vars.push(next_block_assignment_vars); - assignment_inputs.push(next_block_assignment_inputs.clone()); - exec_inputs.push(next_block_assignment_inputs); - // Iteration i = 2 - let inputs: Vec<[u8; 32]> = [vec![one, one, one, two], vec![zero, one, two, four]].concat(); - let vars: Vec<[u8; 32]> = [vec![one, zero, one, one, two, Scalar::from(1u32).neg().invert().to_bytes(), one, one], vec![zero; 8]].concat(); - let next_block_assignment_vars = VarsAssignment::new(&vars).unwrap(); - let next_block_assignment_inputs = InputsAssignment::new(&inputs).unwrap(); - assignment_vars.push(next_block_assignment_vars); - assignment_inputs.push(next_block_assignment_inputs.clone()); - exec_inputs.push(next_block_assignment_inputs); - // Iteration i = 3 - let inputs: Vec<[u8; 32]> = [vec![one, one, two, four], vec![zero, two, three, six]].concat(); - let vars: Vec<[u8; 32]> = [vec![one, zero, one, one, two, zero, zero, zero], vec![zero; 8]].concat(); - let next_block_assignment_vars = VarsAssignment::new(&vars).unwrap(); - let next_block_assignment_inputs = InputsAssignment::new(&inputs).unwrap(); - assignment_vars.push(next_block_assignment_vars); - assignment_inputs.push(next_block_assignment_inputs.clone()); - exec_inputs.push(next_block_assignment_inputs); - // Iteration i = 4 - let inputs: Vec<[u8; 32]> = vec![zero; 8]; - let vars: Vec<[u8; 32]> = vec![zero; 16]; - let next_block_assignment_vars = VarsAssignment::new(&vars).unwrap(); - let next_block_assignment_inputs = InputsAssignment::new(&inputs).unwrap(); - assignment_vars.push(next_block_assignment_vars); - assignment_inputs.push(next_block_assignment_inputs.clone()); - exec_inputs.push(next_block_assignment_inputs); - - (assignment_vars, assignment_inputs) - }; - block_vars_matrix.push(assignment_vars); - block_inputs_matrix.push(assignment_inputs); - - // Block 0 - // Exec: v | b0 i0 s0 | _ | b1 i1 s1 | w L A0 A1 V0 V1 Z0 Z1 B0 - // 0 1 0 0 0 0 1 0 0 1 2 0 1 1 2 -3i 1 1 - let (assignment_vars, assignment_inputs) = { - let mut assignment_vars = Vec::new(); - let mut assignment_inputs = Vec::new(); - let inputs = [vec![one, zero, zero, zero], vec![zero, one, zero, zero]].concat(); - let vars = [vec![one, zero, one, one, two, Scalar::from(3u32).neg().invert().to_bytes(), one, one], vec![zero; 8]].concat(); - let next_block_assignment_vars = VarsAssignment::new(&vars).unwrap(); - let next_block_assignment_inputs = InputsAssignment::new(&inputs).unwrap(); - assignment_vars.push(next_block_assignment_vars); - assignment_inputs.push(next_block_assignment_inputs.clone()); - exec_inputs.insert(0, next_block_assignment_inputs); - - (assignment_vars, assignment_inputs) - }; - block_vars_matrix.push(assignment_vars); - block_inputs_matrix.push(assignment_inputs); - - // Witnesses for permutation cannot be generated until tau and r are generated - // Both can only be generated at proving time - - // Memory accesses in address order: (v, addr, val, D) - // where D[k] = v[k + 1] * (1 - addr[k + 1] - addr[k]) - for _ in 0..3 { - addr_mems_list.push(VarsAssignment::new(&vec![one, zero, one, one]).unwrap()); - } - addr_mems_list.push(VarsAssignment::new(&vec![one, zero, one, zero]).unwrap()); - for _ in 0..3 { - addr_mems_list.push(VarsAssignment::new(&vec![one, one, two, one]).unwrap()); - } - addr_mems_list.push(VarsAssignment::new(&vec![one, one, two, zero]).unwrap()); - - (block_vars_matrix, block_inputs_matrix, exec_inputs, addr_mems_list) - }; - - // -- - // End Assignments - // -- - - ( - // COMPILE TIME KNOWLEDGE - CompileTimeKnowledge { - block_num_instances, - num_vars, - num_inputs_unpadded, - total_num_proofs_bound, - block_num_mem_accesses, - total_num_mem_accesses_bound, - - args, - - func_input_width: 2, - input_offset: 2, - input_block_num, - output_offset: 2, - output_block_num - }, - - // RUNTIME KNOWLEDGE - RunTimeKnowledge { - block_max_num_proofs, - block_num_proofs, - consis_num_proofs, - total_num_mem_accesses, - - block_vars_matrix, - block_inputs_matrix, - exec_inputs, - addr_mems_list, - - input, - output, - output_exec_num - } - ) -} - -fn main() { - // produce an R1CS instance - let (ctk, rtk) = produce_r1cs(); - let block_num_instances = ctk.block_num_instances; - let num_vars = ctk.num_vars; - let num_inputs_unpadded = ctk.num_inputs_unpadded; - let num_ios = (num_inputs_unpadded * 2).next_power_of_two(); - let total_num_proofs_bound = ctk.total_num_proofs_bound; - let block_num_mem_accesses = ctk.block_num_mem_accesses; - let total_num_mem_accesses_bound = ctk.total_num_mem_accesses_bound; - - let block_vars_matrix = rtk.block_vars_matrix; - let block_inputs_matrix = rtk.block_inputs_matrix; - - assert!(ctk.args.len() == block_num_instances); - assert!(block_num_mem_accesses.len() == block_num_instances); - for n in &block_num_mem_accesses { - assert!(3 * n <= num_vars - 4); - } - - // Generate all remaining instances - - // BLOCK INSTANCES - let (block_num_cons, block_num_non_zero_entries, mut block_inst) = Instance::gen_block_inst(block_num_instances, num_vars, &ctk.args); - - // CONSIS INSTANCES - // CONSIS is consisted of two instances - // CONSIS_COMB performs random linear combination on inputs and outputs to a single value - // It is parallelized for consis_num_proofs copies - // CONSIS_CHECK checks that these values indeed matches - // There is only one copy for CONSIS_CHECK - // CONSIS_COMB - let (consis_comb_num_cons, consis_comb_num_non_zero_entries, consis_comb_inst) = Instance::gen_consis_comb_inst(num_inputs_unpadded, num_ios); - // CONSIS_CHECK - let (consis_check_num_cons_base, consis_check_num_non_zero_entries, consis_check_inst) = Instance::gen_consis_check_inst(total_num_proofs_bound); - - // PERM INSTANCES - // PERM is consisted of four instances - // PERM_PRELIM checks the correctness of (r, r^2, ...) - // PERM_ROOT and PERM_BLOCK_POLY compute the polynomial defined by block_inputs - // PERM_ROOT and PERM_EXEC_POLY compute the polynomial defined by exec_inputs - // Finally, the verifier checks that the two products are the same - // The product is defined by PROD = \prod(\tau - (\sum_i a_i * r^{i-1})) - // There is only one proof - // PERM_PRELIM - let (perm_prelim_num_cons, perm_prelim_num_non_zero_entries, perm_prelim_inst) = Instance::gen_perm_prelim_inst(num_inputs_unpadded, num_ios); - // PERM_ROOT - let (perm_root_num_cons, perm_root_num_non_zero_entries, perm_root_inst) = Instance::gen_perm_root_inst(num_inputs_unpadded, num_ios); - // PERM_POLY for PERM_BLOCK_POLY, PERM_EXEC_POLY, & MEM_ADDR_POLY - let perm_size_bound = max(total_num_proofs_bound, total_num_mem_accesses_bound); - let (perm_poly_num_cons_base, perm_poly_num_non_zero_entries, perm_poly_inst) = Instance::gen_perm_poly_inst(perm_size_bound, 4); - - // MEM INSTANCES - // MEM_EXTRACT - let max_block_num_mem_accesses = *block_num_mem_accesses.iter().max().unwrap(); - let (mem_extract_num_cons, mem_extract_num_non_zero_entries, mem_extract_inst) = Instance::gen_mem_extract_inst(num_vars, max_block_num_mem_accesses); - // MEM_BLOCK_POLY - let (mem_block_poly_num_cons_base, mem_block_poly_num_non_zero_entries, mem_block_poly_inst) = Instance::gen_perm_poly_inst(total_num_proofs_bound, num_vars); - // MEM_COHERE - let (mem_cohere_num_cons_base, mem_cohere_num_non_zero_entries, mem_cohere_inst) = Instance::gen_mem_cohere_inst(total_num_mem_accesses_bound); - // MEM_ADDR_COMB - let (mem_addr_comb_num_cons, mem_addr_comb_num_non_zero_entries, mem_addr_comb_inst) = Instance::gen_mem_addr_comb_inst(); - - // -- - // INSTANCE PREPROCESSING - // -- - let consis_check_num_cons = consis_check_num_cons_base * total_num_proofs_bound; - let perm_poly_num_cons = perm_poly_num_cons_base * perm_size_bound; - let mem_block_poly_num_cons = mem_block_poly_num_cons_base * total_num_proofs_bound; - let mem_cohere_num_cons = mem_cohere_num_cons_base * total_num_mem_accesses_bound; - - // produce public parameters - let block_gens = SNARKGens::new(block_num_cons, 2 * num_vars, block_num_instances, block_num_non_zero_entries); - let consis_comb_gens = SNARKGens::new(consis_comb_num_cons, 4 * num_ios, 1, consis_comb_num_non_zero_entries); - let consis_check_gens = SNARKGens::new(consis_check_num_cons, total_num_proofs_bound * 4, 1, consis_check_num_non_zero_entries); - let perm_prelim_gens = SNARKGens::new(perm_prelim_num_cons, num_ios, 1, perm_prelim_num_non_zero_entries); - let perm_root_gens = SNARKGens::new(perm_root_num_cons, 4 * num_ios, 1, perm_root_num_non_zero_entries); - let perm_poly_gens = SNARKGens::new(perm_poly_num_cons, perm_size_bound * 4, 1, perm_poly_num_non_zero_entries); - let mem_extract_gens = SNARKGens::new(mem_extract_num_cons, 4 * num_vars, 1, mem_extract_num_non_zero_entries); - let mem_block_poly_gens = SNARKGens::new(mem_block_poly_num_cons, total_num_proofs_bound * num_vars, 1, mem_block_poly_num_non_zero_entries); - let mem_cohere_gens = SNARKGens::new(mem_cohere_num_cons, total_num_mem_accesses_bound * 4, 1, mem_cohere_num_non_zero_entries); - let mem_addr_comb_gens = SNARKGens::new(mem_addr_comb_num_cons, 4 * 4, 1, mem_addr_comb_num_non_zero_entries); - // Only use one version of gens_r1cs_sat - // for size VAR - let vars_gens = SNARKGens::new(block_num_cons, num_vars, block_num_instances, block_num_non_zero_entries).gens_r1cs_sat; - // for size PROOF * VAR - let proofs_times_vars_gens = SNARKGens::new(block_num_cons, max(total_num_proofs_bound, total_num_mem_accesses_bound) * num_vars, 1, block_num_non_zero_entries).gens_r1cs_sat; - - // create a commitment to the R1CS instance - // TODO: change to encoding all r1cs instances - let (block_comm, block_decomm) = SNARK::multi_encode(&block_inst, &block_gens); - let (consis_comb_comm, consis_comb_decomm) = SNARK::encode(&consis_comb_inst, &consis_comb_gens); - let (consis_check_comm, consis_check_decomm) = SNARK::encode(&consis_check_inst, &consis_check_gens); - let (perm_prelim_comm, perm_prelim_decomm) = SNARK::encode(&perm_prelim_inst, &perm_prelim_gens); - let (perm_root_comm, perm_root_decomm) = SNARK::encode(&perm_root_inst, &perm_root_gens); - let (perm_poly_comm, perm_poly_decomm) = SNARK::encode(&perm_poly_inst, &perm_poly_gens); - let (mem_extract_comm, mem_extract_decomm) = SNARK::encode(&mem_extract_inst, &mem_extract_gens); - let (mem_block_poly_comm, mem_block_poly_decomm) = SNARK::encode(&mem_block_poly_inst, &mem_block_poly_gens); - let (mem_cohere_comm, mem_cohere_decomm) = SNARK::encode(&mem_cohere_inst, &mem_cohere_gens); - let (mem_addr_comb_comm, mem_addr_comb_decomm) = SNARK::encode(&mem_addr_comb_inst, &mem_addr_comb_gens); - - // Mask vector for mem_extract - let (mem_block_mask, mem_block_poly_mask_list, mem_block_comm_mask_list) = - Instance::gen_mem_extract_mask(block_num_instances, max_block_num_mem_accesses.next_power_of_two(), &block_num_mem_accesses, &vars_gens); - - // produce a proof of satisfiability - let mut prover_transcript = Transcript::new(b"snark_example"); - let proof = SNARK::prove( - ctk.input_block_num, - ctk.output_block_num, - ctk.func_input_width, - ctk.input_offset, - ctk.output_offset, - &rtk.input, - &rtk.output, - rtk.output_exec_num, - - num_vars, - num_ios, - num_inputs_unpadded, - total_num_proofs_bound, - block_num_instances, - rtk.block_max_num_proofs, - &rtk.block_num_proofs, - &mut block_inst, - &block_comm, - &block_decomm, - &block_gens, - - rtk.consis_num_proofs, - &consis_comb_inst, - &consis_comb_comm, - &consis_comb_decomm, - &consis_comb_gens, - consis_check_num_cons_base, - &consis_check_inst, - &consis_check_comm, - &consis_check_decomm, - &consis_check_gens, - - &perm_prelim_inst, - &perm_prelim_comm, - &perm_prelim_decomm, - &perm_prelim_gens, - &perm_root_inst, - &perm_root_comm, - &perm_root_decomm, - &perm_root_gens, - perm_poly_num_cons_base, - &perm_poly_inst, - &perm_poly_comm, - &perm_poly_decomm, - &perm_poly_gens, - - max_block_num_mem_accesses, - &mem_extract_inst, - &mem_extract_comm, - &mem_extract_decomm, - &mem_extract_gens, - - mem_block_poly_num_cons_base, - &mem_block_poly_inst, - &mem_block_poly_comm, - &mem_block_poly_decomm, - &mem_block_poly_gens, - - total_num_mem_accesses_bound, - rtk.total_num_mem_accesses, - mem_cohere_num_cons_base, - &mem_cohere_inst, - &mem_cohere_comm, - &mem_cohere_decomm, - &mem_cohere_gens, - - &mem_addr_comb_inst, - &mem_addr_comb_comm, - &mem_addr_comb_decomm, - &mem_addr_comb_gens, - - block_vars_matrix, - block_inputs_matrix, - rtk.exec_inputs, - rtk.addr_mems_list, - - &mem_block_mask, - &mem_block_poly_mask_list, - &mem_block_comm_mask_list, - - &vars_gens, - &proofs_times_vars_gens, - &mut prover_transcript, - ); - - // verify the proof of satisfiability - let mut verifier_transcript = Transcript::new(b"snark_example"); - assert!(proof.verify( - ctk.input_block_num, - ctk.output_block_num, - ctk.func_input_width, - ctk.input_offset, - ctk.output_offset, - &rtk.input, - &rtk.output, - rtk.output_exec_num, - - num_vars, - num_ios, - num_inputs_unpadded, - total_num_proofs_bound, - block_num_instances, - rtk.block_max_num_proofs, - &rtk.block_num_proofs, - block_num_cons, - &block_comm, - &block_gens, - - rtk.consis_num_proofs, - consis_comb_num_cons, - &consis_comb_comm, - &consis_comb_gens, - consis_check_num_cons_base, - &consis_check_comm, - &consis_check_gens, - - perm_prelim_num_cons, - &perm_prelim_comm, - &perm_prelim_gens, - perm_root_num_cons, - &perm_root_comm, - &perm_root_gens, - perm_poly_num_cons_base, - &perm_poly_comm, - &perm_poly_gens, - - max_block_num_mem_accesses, - mem_extract_num_cons, - &mem_extract_comm, - &mem_extract_gens, - mem_block_poly_num_cons_base, - &mem_block_poly_comm, - &mem_block_poly_gens, - total_num_mem_accesses_bound, - rtk.total_num_mem_accesses, - mem_cohere_num_cons_base, - &mem_cohere_comm, - &mem_cohere_gens, - mem_addr_comb_num_cons, - &mem_addr_comb_comm, - &mem_addr_comb_gens, - - &mem_block_comm_mask_list, - - &vars_gens, - &proofs_times_vars_gens, - &mut verifier_transcript - ).is_ok()); - println!("proof verification successful!"); -} diff --git a/spartan_parallel/profiler/nizk.rs b/spartan_parallel/profiler/nizk.rs deleted file mode 100644 index e2d3a15b..00000000 --- a/spartan_parallel/profiler/nizk.rs +++ /dev/null @@ -1,52 +0,0 @@ -#![allow(non_snake_case)] -#![allow(clippy::assertions_on_result_states)] - -extern crate flate2; -extern crate libspartan; -extern crate merlin; -extern crate rand; - -use flate2::{write::ZlibEncoder, Compression}; -use libspartan::{Instance, NIZKGens, NIZK}; -use merlin::Transcript; - -fn print(msg: &str) { - let star = "* "; - println!("{:indent$}{}{}", "", star, msg, indent = 2); -} - -pub fn main() { - // the list of number of variables (and constraints) in an R1CS instance - let inst_sizes = vec![10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; - - println!("Profiler:: NIZK"); - for &s in inst_sizes.iter() { - let num_vars = (2_usize).pow(s as u32); - let num_cons = num_vars; - let num_inputs = 10; - - // produce a synthetic R1CSInstance - let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - - // produce public generators - let gens = NIZKGens::new(num_cons, num_vars, num_inputs); - - // produce a proof of satisfiability - let mut prover_transcript = Transcript::new(b"nizk_example"); - let proof = NIZK::prove(&inst, vars, &inputs, &gens, &mut prover_transcript); - - let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default()); - bincode::serialize_into(&mut encoder, &proof).unwrap(); - let proof_encoded = encoder.finish().unwrap(); - let msg_proof_len = format!("NIZK::proof_compressed_len {:?}", proof_encoded.len()); - print(&msg_proof_len); - - // verify the proof of satisfiability - let mut verifier_transcript = Transcript::new(b"nizk_example"); - assert!(proof - .verify(&inst, &inputs, &mut verifier_transcript, &gens) - .is_ok()); - - println!(); - } -} diff --git a/spartan_parallel/profiler/snark.rs b/spartan_parallel/profiler/snark.rs deleted file mode 100644 index b3474805..00000000 --- a/spartan_parallel/profiler/snark.rs +++ /dev/null @@ -1,62 +0,0 @@ -#![allow(non_snake_case)] -#![allow(clippy::assertions_on_result_states)] - -extern crate flate2; -extern crate libspartan; -extern crate merlin; - -use flate2::{write::ZlibEncoder, Compression}; -use libspartan::{Instance, SNARKGens, SNARK}; -use merlin::Transcript; - -fn print(msg: &str) { - let star = "* "; - println!("{:indent$}{}{}", "", star, msg, indent = 2); -} - -pub fn main() { - // the list of number of variables (and constraints) in an R1CS instance - let inst_sizes = vec![10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; - - println!("Profiler:: SNARK"); - for &s in inst_sizes.iter() { - let num_vars = (2_usize).pow(s as u32); - let num_cons = num_vars; - let num_inputs = 10; - - // produce a synthetic R1CSInstance - let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - - // produce public generators - let gens = SNARKGens::new(num_cons, num_vars, num_inputs, num_cons); - - // create a commitment to R1CSInstance - let (comm, decomm) = SNARK::encode(&inst, &gens); - - // produce a proof of satisfiability - let mut prover_transcript = Transcript::new(b"snark_example"); - let proof = SNARK::prove( - &inst, - &comm, - &decomm, - vars, - &inputs, - &gens, - &mut prover_transcript, - ); - - let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default()); - bincode::serialize_into(&mut encoder, &proof).unwrap(); - let proof_encoded = encoder.finish().unwrap(); - let msg_proof_len = format!("SNARK::proof_compressed_len {:?}", proof_encoded.len()); - print(&msg_proof_len); - - // verify the proof of satisfiability - let mut verifier_transcript = Transcript::new(b"snark_example"); - assert!(proof - .verify(&comm, &inputs, &mut verifier_transcript, &gens) - .is_ok()); - - println!(); - } -}