Fixes 'leo build' to compile programs again. Updates tests to run on new model

This commit is contained in:
howardwu 2020-05-16 22:05:26 -07:00
parent 45710a775d
commit 33f518d1d4
6 changed files with 83 additions and 57 deletions

View File

@ -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<F: Field + PrimeField, G: Group> {
}
impl<F: Field + PrimeField, G: Group> Compiler<F, G> {
pub fn init(package_name: String, main_file_path: PathBuf) -> Self {
Self {
pub fn init(package_name: String, main_file_path: PathBuf) -> Result<Self, CompilerError> {
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<String, CompilerError> {
@ -52,6 +57,17 @@ impl<F: Field + PrimeField, G: Group> Compiler<F, G> {
Ok(hex::encode(hash))
}
pub fn compile_constraints<CS: ConstraintSystem<F>>(
self,
cs: &mut CS,
) -> Result<ConstrainedValue<F, G>, 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<ast::File, 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()))?;
@ -66,7 +82,7 @@ impl<F: Field + PrimeField, G: Group> Compiler<F, G> {
// Ok(syntax_tree)
// }
pub fn evaluate_program<CS: ConstraintSystem<F>>(&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<F: Field + PrimeField, G: Group> Compiler<F, G> {
self.program = Program::<F, G>::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<F: Field + PrimeField, G: Group> ConstraintSynthesizer<F> for Compiler<F, G
self,
cs: &mut CS,
) -> 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

View File

@ -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),

View File

@ -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<Fr> {
let path = current_dir().unwrap();
fn compile_program(directory_name: &str, file_name: &str) -> Result<Compiler<Fr, EdwardsProjective>, 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<Fr> {
println!("Compiling file - {:?}", main_file_path);
// Compile from the main file path
let program = Compiler::<Fr>::init(file_name.to_string(), main_file_path);
program
Compiler::<Fr, EdwardsProjective>::init(file_name.to_string(), main_file_path)
}
#[test]
fn test_zero() {
let mut cs = TestConstraintSystem::<Fr>::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::<Fr>::Return(vec![ConstrainedValue::<Fr>::Integer(UInt32::constant(0))]),
ConstrainedValue::<Fr, EdwardsProjective>::Return(vec![ConstrainedValue::Integer(Integer::U32(UInt32::constant(0)))]),
output
);
println!("{}", output);
}
#[test]
fn test_one() {
let mut cs = TestConstraintSystem::<Fr>::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::<Fr>::Return(vec![ConstrainedValue::<Fr>::Integer(UInt32::constant(1))]),
ConstrainedValue::<Fr, EdwardsProjective>::Return(vec![ConstrainedValue::Integer(Integer::U32(UInt32::constant(1)))]),
output
);
println!("{}", output);
}
#[test]
fn test_1_plus_1() {
let mut cs = TestConstraintSystem::<Fr>::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::<Fr>::Return(vec![ConstrainedValue::<Fr>::Integer(UInt32::constant(2))]),
ConstrainedValue::<Fr, EdwardsProjective>::Return(vec![ConstrainedValue::Integer(Integer::U32(UInt32::constant(2)))]),
output
);
println!("{}", output);
}
#[test]
fn test_1_minus_1() {
let mut cs = TestConstraintSystem::<Fr>::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::<Fr>::Return(vec![ConstrainedValue::<Fr>::Integer(UInt32::constant(0))]),
ConstrainedValue::<Fr, EdwardsProjective>::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::<Fr>::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());
}

View File

@ -1,5 +1,5 @@
// The 'pedersen_hash' main function.
function main() -> u32 {
let a = 1 + 1;
let a = 1 / 0;
return a
}

View File

@ -63,14 +63,29 @@ impl CLI for BuildCommand {
main_file_path.push(MAIN_FILE_NAME);
// Compute the current program checksum
let mut program = Compiler::<Fr, EdwardsProjective>::init(package_name.clone(), main_file_path.clone());
let checksum = program.checksum()?;
let program = Compiler::<Fr, EdwardsProjective>::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::<Bls12_377> {
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::<Bls12_377> {
// 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::<KeypairAssembly::<Bls12_377>>()?;
log::info!("Compiled program in {:?}", main_file_path);

View File

@ -138,6 +138,12 @@ impl From<leo_compiler::errors::CompilerError> for CLIError {
}
}
impl From<snarkos_errors::gadgets::SynthesisError> for CLIError {
fn from(error: snarkos_errors::gadgets::SynthesisError) -> Self {
CLIError::Crate("snarkos_errors", format!("{}", error))
}
}
impl From<serde_json::error::Error> for CLIError {
fn from(error: serde_json::error::Error) -> Self {
CLIError::Crate("serde_json", format!("{}", error))