From 33f518d1d4e63d320c1ea14a6f1d6dde955b9241 Mon Sep 17 00:00:00 2001 From: howardwu Date: Sat, 16 May 2020 22:05:26 -0700 Subject: [PATCH] Fixes 'leo build' to compile programs again. Updates tests to run on new model --- compiler/src/compiler.rs | 30 +++++++++---- compiler/src/errors/compiler.rs | 3 ++ compiler/tests/u32/mod.rs | 65 ++++++++++++++--------------- examples/pedersen_hash/src/main.leo | 2 +- leo/commands/build.rs | 34 ++++++++------- leo/errors/cli.rs | 6 +++ 6 files changed, 83 insertions(+), 57 deletions(-) diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index 9c52d69cb2..33b4a6ddc6 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -4,7 +4,7 @@ use crate::{ ast, constraints::{generate_constraints, ConstrainedValue}, errors::CompilerError, - InputValue, Program, + InputValue, Program }; use snarkos_errors::gadgets::SynthesisError; @@ -28,15 +28,20 @@ pub struct Compiler { } impl Compiler { - pub fn init(package_name: String, main_file_path: PathBuf) -> Self { - Self { + pub fn init(package_name: String, main_file_path: PathBuf) -> Result { + let mut program = Self { package_name, main_file_path, program: Program::new(), program_inputs: vec![], output: None, _engine: PhantomData, - } + }; + + // Generate the abstract syntax tree and assemble the program + program.parse_program()?; + + Ok(program) } pub fn checksum(&self) -> Result { @@ -52,6 +57,17 @@ impl Compiler { Ok(hex::encode(hash)) } + pub fn compile_constraints>( + self, + cs: &mut CS, + ) -> Result, SynthesisError> { + let result = generate_constraints(cs, self.program, self.program_inputs).unwrap(); + + // Write results to file or something + + Ok(result) + } + // pub fn compile(&self) -> Result { // // Read in the main file as string // let unparsed_file = fs::read_to_string(&self.main_file_path).map_err(|_| CompilerError::FileReadError(self.main_file_path.clone()))?; @@ -66,7 +82,7 @@ impl Compiler { // Ok(syntax_tree) // } - pub fn evaluate_program>(&mut self) -> Result<(), CompilerError> { + fn parse_program(&mut self) -> Result<(), CompilerError> { // Read in the main file as string let unparsed_file = fs::read_to_string(&self.main_file_path) .map_err(|_| CompilerError::FileReadError(self.main_file_path.clone()))?; @@ -85,7 +101,7 @@ impl Compiler { self.program = Program::::from(syntax_tree, package_name); self.program_inputs = vec![None; self.program.num_parameters]; - log::debug!("Compilation complete\n{:#?}", self.program); + log::debug!("Program parsing complete\n{:#?}", self.program); Ok(()) } @@ -96,7 +112,7 @@ impl ConstraintSynthesizer for Compiler Result<(), SynthesisError> { - let _res = generate_constraints(cs, self.program, self.program_inputs).unwrap(); + let _result = generate_constraints(cs, self.program, self.program_inputs).unwrap(); // Write results to file or something diff --git a/compiler/src/errors/compiler.rs b/compiler/src/errors/compiler.rs index df888529ef..b064a2882a 100644 --- a/compiler/src/errors/compiler.rs +++ b/compiler/src/errors/compiler.rs @@ -8,6 +8,9 @@ pub enum CompilerError { #[error("creating: {}", _0)] Creating(io::Error), + #[error("Attempt to access current directory failed - {:?}", _0)] + DirectoryError(io::Error), + #[error("{}", _0)] ImportError(ImportError), diff --git a/compiler/tests/u32/mod.rs b/compiler/tests/u32/mod.rs index 78b0e719c8..be3789032c 100644 --- a/compiler/tests/u32/mod.rs +++ b/compiler/tests/u32/mod.rs @@ -1,15 +1,18 @@ -use leo_compiler::{compiler::Compiler, ConstrainedValue}; - -use snarkos_curves::bls12_377::Fr; +use leo_compiler::{compiler::Compiler, errors::CompilerError, types::Integer, ConstrainedValue}; +use snarkos_curves::{ + bls12_377::{Bls12_377, Fr}, + edwards_bls12::EdwardsProjective +}; use snarkos_models::gadgets::r1cs::{ConstraintSynthesizer, TestConstraintSystem}; use snarkos_models::gadgets::utilities::uint32::UInt32; + use std::env::current_dir; const DIRECTORY_NAME: &str = "tests/u32/"; -fn compile_program(directory_name: &str, file_name: &str) -> Compiler { - let path = current_dir().unwrap(); +fn compile_program(directory_name: &str, file_name: &str) -> Result, CompilerError> { + let path = current_dir().map_err(|error| CompilerError::DirectoryError(error))?; // Sanitize the package path to the test directory let mut package_path = path.clone(); @@ -25,69 +28,63 @@ fn compile_program(directory_name: &str, file_name: &str) -> Compiler { println!("Compiling file - {:?}", main_file_path); // Compile from the main file path - let program = Compiler::::init(file_name.to_string(), main_file_path); - - program + Compiler::::init(file_name.to_string(), main_file_path) } #[test] fn test_zero() { let mut cs = TestConstraintSystem::::new(); - let program = compile_program(DIRECTORY_NAME, "zero.leo"); - let output = program.evaluate_program(&mut cs); - assert!(cs.is_satisfied()); + let program = compile_program(DIRECTORY_NAME, "zero.leo").unwrap(); + let output = program.compile_constraints(&mut cs).unwrap(); + println!("{}", output); - let output = output.unwrap(); + assert!(cs.is_satisfied()); assert_eq!( - ConstrainedValue::::Return(vec![ConstrainedValue::::Integer(UInt32::constant(0))]), + ConstrainedValue::::Return(vec![ConstrainedValue::Integer(Integer::U32(UInt32::constant(0)))]), output ); - println!("{}", output); } #[test] fn test_one() { let mut cs = TestConstraintSystem::::new(); - let program = compile_program(DIRECTORY_NAME, "one.leo"); - let output = program.evaluate_program(&mut cs); - assert!(cs.is_satisfied()); + let program = compile_program(DIRECTORY_NAME, "one.leo").unwrap(); + let output = program.compile_constraints(&mut cs).unwrap(); + println!("{}", output); - let output = output.unwrap(); + assert!(cs.is_satisfied()); assert_eq!( - ConstrainedValue::::Return(vec![ConstrainedValue::::Integer(UInt32::constant(1))]), + ConstrainedValue::::Return(vec![ConstrainedValue::Integer(Integer::U32(UInt32::constant(1)))]), output ); - println!("{}", output); } #[test] fn test_1_plus_1() { let mut cs = TestConstraintSystem::::new(); - let program = compile_program(DIRECTORY_NAME, "1+1.leo"); - let output = program.evaluate_program(&mut cs); - assert!(cs.is_satisfied()); + let program = compile_program(DIRECTORY_NAME, "1+1.leo").unwrap(); + let output = program.compile_constraints(&mut cs).unwrap(); + println!("{}", output); - let output = output.unwrap(); + assert!(cs.is_satisfied()); assert_eq!( - ConstrainedValue::::Return(vec![ConstrainedValue::::Integer(UInt32::constant(2))]), + ConstrainedValue::::Return(vec![ConstrainedValue::Integer(Integer::U32(UInt32::constant(2)))]), output ); - println!("{}", output); } #[test] fn test_1_minus_1() { let mut cs = TestConstraintSystem::::new(); - let program = compile_program(DIRECTORY_NAME, "1-1.leo"); - let output = program.evaluate_program(&mut cs); - assert!(cs.is_satisfied()); + let program = compile_program(DIRECTORY_NAME, "1-1.leo").unwrap(); + let output = program.compile_constraints(&mut cs).unwrap(); + println!("{}", output); - let output = output.unwrap(); + assert!(cs.is_satisfied()); assert_eq!( - ConstrainedValue::::Return(vec![ConstrainedValue::::Integer(UInt32::constant(0))]), + ConstrainedValue::::Return(vec![ConstrainedValue::Integer(Integer::U32(UInt32::constant(0)))]), output ); - println!("{}", output); } #[test] @@ -95,7 +92,7 @@ fn test_1_minus_2_should_fail() { // TODO (howardwu): Catch panic from subtraction overflow let mut cs = TestConstraintSystem::::new(); - let program = compile_program(DIRECTORY_NAME, "1-2.leo"); - let output = program.evaluate_program(&mut cs); + let program = compile_program(DIRECTORY_NAME, "1-2.leo").unwrap(); + let output = program.compile_constraints(&mut cs); assert!(output.is_err()); } diff --git a/examples/pedersen_hash/src/main.leo b/examples/pedersen_hash/src/main.leo index edc01e0599..91eee630c0 100644 --- a/examples/pedersen_hash/src/main.leo +++ b/examples/pedersen_hash/src/main.leo @@ -1,5 +1,5 @@ // The 'pedersen_hash' main function. function main() -> u32 { - let a = 1 + 1; + let a = 1 / 0; return a } diff --git a/leo/commands/build.rs b/leo/commands/build.rs index 9cdfba375a..db8cd89f6c 100644 --- a/leo/commands/build.rs +++ b/leo/commands/build.rs @@ -63,14 +63,29 @@ impl CLI for BuildCommand { main_file_path.push(MAIN_FILE_NAME); // Compute the current program checksum - let mut program = Compiler::::init(package_name.clone(), main_file_path.clone()); - let checksum = program.checksum()?; + let program = Compiler::::init(package_name.clone(), main_file_path.clone())?; + let program_checksum = program.checksum()?; + + // Generate the program on the constraint system and verify correctness + { + 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).unwrap(); + log::debug!("Compiled constraints - {:#?}", output); + } // If a checksum file exists, check if it differs from the new checksum let checksum_file = ChecksumFile::new(&package_name); let checksum_differs = if checksum_file.exists_at(&package_path) { let previous_checksum = checksum_file.read_from(&package_path)?; - checksum != previous_checksum + program_checksum != previous_checksum } else { // By default, the checksum differs if there is no checksum to compare against true @@ -79,19 +94,8 @@ impl CLI for BuildCommand { // If checksum differs, compile the program if checksum_differs { // Write the new checksum to the outputs directory - checksum_file.write_to(&path, checksum)?; - - // Generate the program on the constraint system and verify correctness - // let mut cs = KeypairAssembly:: { - // num_inputs: 0, - // num_aux: 0, - // num_constraints: 0, - // at: vec![], - // bt: vec![], - // ct: vec![], - // }; + checksum_file.write_to(&path, program_checksum)?; } - program.evaluate_program::>()?; log::info!("Compiled program in {:?}", main_file_path); diff --git a/leo/errors/cli.rs b/leo/errors/cli.rs index 34f85ae53d..1f36c8f092 100644 --- a/leo/errors/cli.rs +++ b/leo/errors/cli.rs @@ -138,6 +138,12 @@ impl From for CLIError { } } +impl From for CLIError { + fn from(error: snarkos_errors::gadgets::SynthesisError) -> Self { + CLIError::Crate("snarkos_errors", format!("{}", error)) + } +} + impl From for CLIError { fn from(error: serde_json::error::Error) -> Self { CLIError::Crate("serde_json", format!("{}", error))