diff --git a/compiler/src/output/circuit_bytes.rs b/compiler/src/output/circuit_bytes.rs new file mode 100644 index 0000000000..fced82510b --- /dev/null +++ b/compiler/src/output/circuit_bytes.rs @@ -0,0 +1,100 @@ +// use snarkos_utilities::serialize::*; +// use snarkos_algorithms::snark::groth16::KeypairAssembly; +// +// +// pub struct CircuitBytes { +// assembly: KeypairAssembly +// } + +// impl CanonicalSerialize for CircuitBytes { + +// } + +// impl CircuitBytes { +// use snarkos_utilities::serialize::*; +// fn serialize_constraints(assembly: KeypairAssembly) { +// let mut writer = Vec::new(); +// // println!("{}", assembly.num_constraints); +// +// let fr_size = ::SERIALIZED_SIZE; +// let index_size = ::SERIALIZED_SIZE; +// let tuple_size = fr_size + index_size; +// println!("tuple size {}", tuple_size); +// +// let mut total_size_bytes = 0; +// // serialize each constraint +// for i in 0..assembly.num_constraints { +// // serialize each linear combination +// // println!("a len {}", a_len); +// // println!("b len {}", assembly.bt[i].len()); +// // println!("c len {}", assembly.ct[i].len()); +// +// // Serialize the at[i] vector of tuples Vec<(Fr, Index)> +// +// let a_len = assembly.at[i].len(); +// CanonicalSerialize::serialize(&(a_len as u8), &mut writer).unwrap(); +// total_size_bytes += 1; +// +// total_size_bytes += a_len * tuple_size; +// +// for &(ref coeff, index) in assembly.at[i].iter() { +// // println!("a({:?}, {:?})", coeff, index); +// CanonicalSerialize::serialize(coeff, &mut writer).unwrap(); +// CanonicalSerialize::serialize(&index, &mut writer).unwrap(); +// } +// +// // Serialize the bt[i] vector of tuples Vec<(Fr, Index)> +// +// let b_len = assembly.bt[i].len(); +// CanonicalSerialize::serialize(&(b_len as u8), &mut writer).unwrap(); +// total_size_bytes += 1; +// +// total_size_bytes += b_len * tuple_size; +// +// for &(ref coeff, index) in assembly.bt[i].iter() { +// // println!("b({:?}, {:?})", coeff, index); +// CanonicalSerialize::serialize(coeff, &mut writer).unwrap(); +// CanonicalSerialize::serialize(&index, &mut writer).unwrap(); +// } +// +// // Serialize the ct[i] vector of tuples Vec<(Fr, Index)> +// +// let c_len = assembly.ct[i].len(); +// CanonicalSerialize::serialize(&(c_len as u8), &mut writer).unwrap(); +// total_size_bytes += 1; +// +// total_size_bytes += c_len * tuple_size; +// +// for &(ref coeff, index) in assembly.ct[i].iter() { +// // println!("c({:?}, {:?})", coeff, index); +// CanonicalSerialize::serialize(coeff, &mut writer).unwrap(); +// CanonicalSerialize::serialize(&index, &mut writer).unwrap(); +// } +// } +// println!("expected size bytes {:?}", total_size_bytes); +// println!("actual size bytes {:?}", writer.len()); +// } +// +// +// let mut cs = KeypairAssembly:: { +// num_inputs: 0, +// num_aux: 0, +// num_constraints: 0, +// at: vec![], +// bt: vec![], +// ct: vec![], +// }; +// let temporary_program = program.clone(); +// let output = temporary_program.compile_constraints(&mut cs)?; +// log::debug!("Compiled constraints - {:#?}", output); +// log::debug!("Number of constraints - {:#?}", cs.num_constraints()); +// +// serialize_constraints(cs); +// +// // println!("{}", std::mem::size_of::()); +// // println!("{}", std::mem::size_of::()); +// // println!("{}", ::SERIALIZED_SIZE); +// // println!("{}", ::SERIALIZED_SIZE); +// +// // println!("{}", std::mem::size_of::()); +// } diff --git a/compiler/src/output/mod.rs b/compiler/src/output/mod.rs index f112f0a02b..6948b1bc86 100644 --- a/compiler/src/output/mod.rs +++ b/compiler/src/output/mod.rs @@ -1,3 +1,6 @@ +pub mod circuit_bytes; +pub use self::circuit_bytes::*; + pub mod output_file; pub use self::output_file::*; diff --git a/leo/commands/build.rs b/leo/commands/build.rs index 32f48db04a..38916d0e63 100644 --- a/leo/commands/build.rs +++ b/leo/commands/build.rs @@ -2,18 +2,19 @@ use crate::{cli::*, cli_types::*, errors::CLIError}; use leo_compiler::{compiler::Compiler, group::targets::edwards_bls12::EdwardsGroupType}; use leo_package::{ inputs::*, - outputs::{ChecksumFile, OutputsDirectory, OUTPUTS_DIRECTORY_NAME}, + outputs::{ChecksumFile, CircuitFile, OutputsDirectory, OUTPUTS_DIRECTORY_NAME}, root::Manifest, source::{LibFile, MainFile, LIB_FILE_NAME, MAIN_FILE_NAME, SOURCE_DIRECTORY_NAME}, }; use snarkos_algorithms::snark::groth16::KeypairAssembly; use snarkos_curves::{bls12_377::Bls12_377, edwards_bls12::Fq}; -use snarkos_models::gadgets::r1cs::ConstraintSystem; +use snarkos_models::{ + curves::PairingEngine, + gadgets::r1cs::{ConstraintSystem, Index}, +}; use clap::ArgMatches; -use serde::Serialize; -use snarkos_models::curves::{PairingEngine, PrimeField}; use std::{convert::TryFrom, env::current_dir}; #[derive(Debug)] @@ -100,6 +101,146 @@ impl CLI for BuildCommand { // Generate the program on the constraint system and verify correctness { + use snarkos_utilities::serialize::*; + fn serialize_circuit(assembly: KeypairAssembly, writer: &mut W) { + let fr_size = <::Fr as ConstantSerializedSize>::SERIALIZED_SIZE; + let index_size = ::SERIALIZED_SIZE; + let tuple_size = fr_size + index_size; + println!("tuple size {}", tuple_size); + + let mut total_size_bytes = 0; + + let num_inputs = assembly.num_inputs; + CanonicalSerialize::serialize(&(num_inputs as u8), writer).unwrap(); + total_size_bytes += 1; + + let num_aux = assembly.num_aux; + CanonicalSerialize::serialize(&(num_aux as u8), writer).unwrap(); + total_size_bytes += 1; + + let num_constraints = assembly.num_constraints; + CanonicalSerialize::serialize(&(num_constraints as u8), writer).unwrap(); + total_size_bytes += 1; + + // println!("{}", assembly.num_constraints); + // serialize each constraint + for i in 0..num_constraints { + // Serialize the at[i] vector of tuples Vec<(Fr, Index)> + + let a_len = assembly.at[i].len(); + CanonicalSerialize::serialize(&(a_len as u8), writer).unwrap(); + + total_size_bytes += 1; + total_size_bytes += a_len * tuple_size; + + for &(ref coeff, index) in assembly.at[i].iter() { + // println!("a({:?}, {:?})", coeff, index); + CanonicalSerialize::serialize(coeff, writer).unwrap(); + CanonicalSerialize::serialize(&index, writer).unwrap(); + } + + // Serialize the bt[i] vector of tuples Vec<(Fr, Index)> + + let b_len = assembly.bt[i].len(); + CanonicalSerialize::serialize(&(b_len as u8), writer).unwrap(); + + total_size_bytes += 1; + total_size_bytes += b_len * tuple_size; + + for &(ref coeff, index) in assembly.bt[i].iter() { + // println!("b({:?}, {:?})", coeff, index); + CanonicalSerialize::serialize(coeff, writer).unwrap(); + CanonicalSerialize::serialize(&index, writer).unwrap(); + } + + // Serialize the ct[i] vector of tuples Vec<(Fr, Index)> + + let c_len = assembly.ct[i].len(); + CanonicalSerialize::serialize(&(c_len as u8), writer).unwrap(); + + total_size_bytes += 1; + total_size_bytes += c_len * tuple_size; + + for &(ref coeff, index) in assembly.ct[i].iter() { + // println!("c({:?}, {:?})", coeff, index); + CanonicalSerialize::serialize(coeff, writer).unwrap(); + CanonicalSerialize::serialize(&index, writer).unwrap(); + } + } + + println!("expected size bytes {:?}", total_size_bytes); + // println!("actual size bytes {:?}", writer.len()); + } + + fn deserialize_circuit(reader: &mut R) -> KeypairAssembly { + let fr_size = <::Fr as ConstantSerializedSize>::SERIALIZED_SIZE; + let index_size = ::SERIALIZED_SIZE; + let tuple_size = fr_size + index_size; + println!("tuple size {}", tuple_size); + + let num_inputs = ::deserialize(reader).unwrap() as usize; + let num_aux = ::deserialize(reader).unwrap() as usize; + let num_constraints = ::deserialize(reader).unwrap() as usize; + + let mut assembly = KeypairAssembly:: { + num_inputs, + num_aux, + num_constraints, + at: vec![], + bt: vec![], + ct: vec![], + }; + + for _ in 0..num_constraints { + // deserialize each at[i] vector + + let a_len = ::deserialize(reader).unwrap() as usize; + let mut a_lc = vec![]; + + for _ in 0..a_len { + let fr = <::Fr as CanonicalDeserialize>::deserialize(reader).unwrap(); + let index = ::deserialize(reader).unwrap(); + let tuple = (fr, index); + + a_lc.push(tuple); + } + + assembly.at.push(a_lc); + + // deserialize each bt[i] vector + + let b_len = ::deserialize(reader).unwrap() as usize; + let mut b_lc = vec![]; + + for _ in 0..b_len { + let fr = <::Fr as CanonicalDeserialize>::deserialize(reader).unwrap(); + let index = ::deserialize(reader).unwrap(); + let tuple = (fr, index); + + b_lc.push(tuple); + } + + assembly.at.push(b_lc); + + // deserialize each ct[i] vector + + let c_len = ::deserialize(reader).unwrap() as usize; + let mut c_lc = vec![]; + + for _ in 0..c_len { + let fr = <::Fr as CanonicalDeserialize>::deserialize(reader).unwrap(); + let index = ::deserialize(reader).unwrap(); + let tuple = (fr, index); + + c_lc.push(tuple); + } + + assembly.at.push(c_lc); + } + + assembly + } + let mut cs = KeypairAssembly:: { num_inputs: 0, num_aux: 0, @@ -112,6 +253,31 @@ impl CLI for BuildCommand { let output = temporary_program.compile_constraints(&mut cs)?; log::debug!("Compiled constraints - {:#?}", output); log::debug!("Number of constraints - {:#?}", cs.num_constraints()); + + // Serialize circuit + let mut writer = Vec::new(); + serialize_circuit(cs, &mut writer); + println!("actual size bytes {:?}", writer.len()); + + // Write serialized circuit to circuit `.bytes` file. + let circuit_file = CircuitFile::new(&package_name); + circuit_file.write_to(&path, &writer[..])?; + + // Read serialized circuit file + let serialized = circuit_file.read_from(&package_path)?; + let same = writer == serialized; + println!("same {}", same); + + let deserialized = deserialize_circuit::(&mut &serialized[..]); + + println!("deserialized {:?}", deserialized.num_constraints); + + // println!("{}", std::mem::size_of::()); + // println!("{}", std::mem::size_of::()); + // println!("{}", ::SERIALIZED_SIZE); + // println!("{}", ::SERIALIZED_SIZE); + + // println!("{}", std::mem::size_of::()); } // If a checksum file exists, check if it differs from the new checksum diff --git a/leo/errors/cli.rs b/leo/errors/cli.rs index 56b906630d..b474c48794 100644 --- a/leo/errors/cli.rs +++ b/leo/errors/cli.rs @@ -9,12 +9,15 @@ pub enum CLIError { #[error("{}", _0)] BytesFileError(ZipFileError), - #[error("{}: {}", _0, _1)] - Crate(&'static str, String), - #[error("{}", _0)] ChecksumFileError(ChecksumFileError), + #[error("{}", _0)] + CircuitFileError(CircuitFileError), + + #[error("{}: {}", _0, _1)] + Crate(&'static str, String), + #[error("{}", _0)] GitignoreError(GitignoreError), @@ -88,6 +91,13 @@ impl From for CLIError { } } +impl From for CLIError { + fn from(error: CircuitFileError) -> Self { + log::error!("{}\n", error); + CLIError::CircuitFileError(error) + } +} + impl From for CLIError { fn from(error: GitignoreError) -> Self { log::error!("{}\n", error);