diff --git a/Cargo.lock b/Cargo.lock index ad123383f6..62851296f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -609,6 +609,7 @@ dependencies = [ "pest", "rand", "rand_xorshift", + "serde", "sha2", "snarkos-curves", "snarkos-dpc", diff --git a/ast/src/functions/function.rs b/ast/src/functions/function.rs index 4ddb1938b9..3cac5debd3 100644 --- a/ast/src/functions/function.rs +++ b/ast/src/functions/function.rs @@ -1,4 +1,4 @@ -use crate::{ast::Rule, common::Identifier, functions::FunctionInput, statements::Statement, types::Type, SpanDef}; +use crate::{ast::Rule, common::Identifier, functions::input::Input, statements::Statement, types::Type, SpanDef}; use pest::Span; use pest_ast::FromPest; @@ -8,7 +8,7 @@ use serde::Serialize; #[pest_ast(rule(Rule::function_definition))] pub struct Function<'ast> { pub function_name: Identifier<'ast>, - pub parameters: Vec>, + pub parameters: Vec>, pub returns: Vec>, pub statements: Vec>, #[pest_ast(outer())] diff --git a/ast/src/functions/function_input.rs b/ast/src/functions/inputs/function_input.rs similarity index 100% rename from ast/src/functions/function_input.rs rename to ast/src/functions/inputs/function_input.rs diff --git a/ast/src/functions/inputs/input.rs b/ast/src/functions/inputs/input.rs new file mode 100644 index 0000000000..a4fb066057 --- /dev/null +++ b/ast/src/functions/inputs/input.rs @@ -0,0 +1,17 @@ +use crate::{ + ast::Rule, + functions::{FunctionInput, Record, Registers, State, StateLeaf}, +}; + +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::input))] +pub enum Input<'ast> { + FunctionInput(FunctionInput<'ast>), + Record(Record<'ast>), + Registers(Registers<'ast>), + State(State<'ast>), + StateLeaf(StateLeaf<'ast>), +} diff --git a/ast/src/functions/inputs/mod.rs b/ast/src/functions/inputs/mod.rs new file mode 100644 index 0000000000..ec188dab11 --- /dev/null +++ b/ast/src/functions/inputs/mod.rs @@ -0,0 +1,17 @@ +pub mod function_input; +pub use function_input::*; + +pub mod input; +pub use input::*; + +pub mod record; +pub use record::*; + +pub mod registers; +pub use registers::*; + +pub mod state; +pub use state::*; + +pub mod state_leaf; +pub use state_leaf::*; diff --git a/ast/src/functions/inputs/record.rs b/ast/src/functions/inputs/record.rs new file mode 100644 index 0000000000..194ef9df01 --- /dev/null +++ b/ast/src/functions/inputs/record.rs @@ -0,0 +1,13 @@ +use crate::{ast::Rule, SpanDef}; + +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::record))] +pub struct Record<'ast> { + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, +} diff --git a/ast/src/functions/inputs/registers.rs b/ast/src/functions/inputs/registers.rs new file mode 100644 index 0000000000..a3786adb9c --- /dev/null +++ b/ast/src/functions/inputs/registers.rs @@ -0,0 +1,13 @@ +use crate::{ast::Rule, SpanDef}; + +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::registers))] +pub struct Registers<'ast> { + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, +} diff --git a/ast/src/functions/inputs/state.rs b/ast/src/functions/inputs/state.rs new file mode 100644 index 0000000000..0539087b1b --- /dev/null +++ b/ast/src/functions/inputs/state.rs @@ -0,0 +1,13 @@ +use crate::{ast::Rule, SpanDef}; + +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::state))] +pub struct State<'ast> { + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, +} diff --git a/ast/src/functions/inputs/state_leaf.rs b/ast/src/functions/inputs/state_leaf.rs new file mode 100644 index 0000000000..f8988a0891 --- /dev/null +++ b/ast/src/functions/inputs/state_leaf.rs @@ -0,0 +1,13 @@ +use crate::{ast::Rule, SpanDef}; + +use pest::Span; +use pest_ast::FromPest; +use serde::Serialize; + +#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] +#[pest_ast(rule(Rule::state_leaf))] +pub struct StateLeaf<'ast> { + #[pest_ast(outer())] + #[serde(with = "SpanDef")] + pub span: Span<'ast>, +} diff --git a/ast/src/functions/mod.rs b/ast/src/functions/mod.rs index fadb2897b1..7ae6a0a9fe 100644 --- a/ast/src/functions/mod.rs +++ b/ast/src/functions/mod.rs @@ -1,8 +1,8 @@ pub mod function; pub use function::*; -pub mod function_input; -pub use function_input::*; +pub mod inputs; +pub use inputs::*; pub mod test_function; pub use test_function::*; diff --git a/ast/src/leo.pest b/ast/src/leo.pest index e292ba698f..2177a06df4 100644 --- a/ast/src/leo.pest +++ b/ast/src/leo.pest @@ -335,11 +335,32 @@ statement_return = { "return " ~ return_} /// Functions // Declared in functions/function.rs -function_definition = { "function " ~ identifier ~ "(" ~ NEWLINE* ~ input_model_list ~ NEWLINE* ~ ")" ~ ("->" ~ (type_ | "(" ~ type_list ~ ")"))? ~ "{" ~ NEWLINE* ~ statement* ~ NEWLINE* ~ "}" ~ NEWLINE* } +function_definition = { "function " ~ identifier ~ "(" ~ NEWLINE* ~ input_list ~ NEWLINE* ~ ")" ~ ("->" ~ (type_ | "(" ~ type_list ~ ")"))? ~ "{" ~ NEWLINE* ~ statement* ~ NEWLINE* ~ "}" ~ NEWLINE* } -// Declared in functions/function_input.rs +// Declared in functions/inputs/function_input.rs function_input = { mutable? ~ identifier ~ ":" ~ type_ } -input_model_list = _{ (function_input ~ ("," ~ NEWLINE* ~ function_input)*)? } + +// Declared in functions/inputs/record.rs +record = { "record" } + +// Declared in functions/inputs/registers.rs +registers = { "registers" } + +// Declared in functions/inputs/state.rs +state = { "state" } + +// Declared in functions/inputs/state_leaf.rs +state_leaf = { "state_leaf" } + +// Declared in functions/inputs/input.rs +input = { + record + | registers + | state_leaf + | state + | function_input +} +input_list = _{ (input ~ ("," ~ NEWLINE* ~ input)*)? } // Declared in functions/test_function.rs test_function = { "test " ~ function_definition } diff --git a/compiler/Cargo.toml b/compiler/Cargo.toml index 0f09d3189d..a2a5a109b0 100644 --- a/compiler/Cargo.toml +++ b/compiler/Cargo.toml @@ -24,8 +24,9 @@ log = { version = "0.4" } pest = { version = "2.0" } rand = { version = "0.7" } rand_xorshift = { version = "0.2", default-features = false } +serde = { version = "1.0" } sha2 = { version = "0.9" } thiserror = { version = "1.0" } [dev-dependencies] -num-bigint = { version = "0.3" } +num-bigint = { version = "0.3" } \ No newline at end of file diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index 1006480e0f..af069a7dea 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -3,13 +3,14 @@ use crate::{ constraints::{generate_constraints, generate_test_constraints}, errors::CompilerError, - value::ConstrainedValue, GroupType, ImportParser, + OutputBytes, + OutputsFile, }; use leo_ast::LeoParser; use leo_inputs::LeoInputsParser; -use leo_types::{InputValue, Inputs, Program}; +use leo_types::{Inputs, MainInputs, Program}; use snarkos_errors::gadgets::SynthesisError; use snarkos_models::{ @@ -24,43 +25,98 @@ use std::{fs, marker::PhantomData, path::PathBuf}; pub struct Compiler> { package_name: String, main_file_path: PathBuf, + outputs_directory: PathBuf, program: Program, program_inputs: Inputs, imported_programs: ImportParser, - output: Option>, _engine: PhantomData, + _group: PhantomData, } impl> Compiler { - pub fn new(package_name: String) -> Self { + pub fn new(package_name: String, main_file_path: PathBuf, outputs_directory: PathBuf) -> Self { Self { package_name: package_name.clone(), - main_file_path: PathBuf::new(), + main_file_path, + outputs_directory, program: Program::new(package_name), program_inputs: Inputs::new(), imported_programs: ImportParser::new(), - output: None, _engine: PhantomData, + _group: PhantomData, } } - pub fn new_from_path(package_name: String, main_file_path: PathBuf) -> Result { - let mut compiler = Self::new(package_name); - compiler.set_path(main_file_path); + /// Parses program files. + /// Returns a compiler struct that stores the typed program abstract syntax trees (ast). + pub fn parse_program_without_inputs( + package_name: String, + main_file_path: PathBuf, + outputs_directory: PathBuf, + ) -> Result { + let mut compiler = Self::new(package_name, main_file_path, outputs_directory); - // Generate the abstract syntax tree and assemble the program let program_string = compiler.load_program()?; compiler.parse_program(&program_string)?; Ok(compiler) } - pub fn set_path(&mut self, main_file_path: PathBuf) { - self.main_file_path = main_file_path + /// Parses input, state, and program files. + /// Returns a compiler struct that stores the typed inputs and typed program abstract syntax trees (ast). + pub fn parse_program_with_inputs( + package_name: String, + main_file_path: PathBuf, + outputs_directory: PathBuf, + inputs_string: &str, + state_string: &str, + ) -> Result { + let mut compiler = Self::new(package_name, main_file_path, outputs_directory); + + compiler.parse_inputs(inputs_string, state_string)?; + + let program_string = compiler.load_program()?; + compiler.parse_program(&program_string)?; + + Ok(compiler) } - pub fn set_inputs(&mut self, program_inputs: Vec>) { - self.program_inputs.set_inputs(program_inputs); + /// Parse the input and state files. + /// Stores a typed ast of all inputs to the program. + pub fn parse_inputs(&mut self, inputs_string: &str, state_string: &str) -> Result<(), CompilerError> { + let inputs_syntax_tree = LeoInputsParser::parse_file(&inputs_string)?; + let state_syntax_tree = LeoInputsParser::parse_file(&state_string)?; + + self.program_inputs.parse_inputs(inputs_syntax_tree)?; + self.program_inputs.parse_state(state_syntax_tree)?; + + Ok(()) + } + + /// Parse the program file and all associated import files. + pub fn parse_program(&mut self, program_string: &str) -> Result<(), CompilerError> { + // Parse the program syntax tree + let syntax_tree = LeoParser::parse_file(&self.main_file_path, program_string)?; + + // Build program from syntax tree + let package_name = self.package_name.clone(); + + self.program = Program::from(syntax_tree, package_name); + self.imported_programs = ImportParser::parse(&self.program)?; + + log::debug!("Program parsing complete\n{:#?}", self.program); + + Ok(()) + } + + /// Loads the program file at `main_file_path`. + fn load_program(&mut self) -> Result { + Ok(LeoParser::load_file(&self.main_file_path)?) + } + + /// Manually sets main function inputs + pub fn set_main_inputs(&mut self, inputs: MainInputs) { + self.program_inputs.set_main_inputs(inputs); } pub fn checksum(&self) -> Result { @@ -76,53 +132,36 @@ impl> Compiler { Ok(hex::encode(hash)) } - pub fn compile_constraints>( - self, - cs: &mut CS, - ) -> Result, CompilerError> { + /// Synthesizes the circuit without program inputs to verify correctness. + pub fn compile_constraints>(self, cs: &mut CS) -> Result { let path = self.main_file_path; - let inputs = self.program_inputs.get_inputs(); + let inputs = self.program_inputs.empty(); - generate_constraints(cs, self.program, inputs, &self.imported_programs).map_err(|mut error| { + generate_constraints::(cs, self.program, inputs, &self.imported_programs).map_err(|mut error| { error.set_path(path); error }) } + /// Synthesizes the circuit for test functions with program inputs. pub fn compile_test_constraints(self, cs: &mut TestConstraintSystem) -> Result<(), CompilerError> { - generate_test_constraints::(cs, self.program, &self.imported_programs) + generate_test_constraints::(cs, self.program, self.program_inputs, &self.imported_programs) } - /// Loads the Leo code as a string from the given file path. - fn load_program(&mut self) -> Result { - Ok(LeoParser::load_file(&self.main_file_path)?) - } + /// Calls the internal generate_constraints method with arguments + pub fn generate_constraints_helper>( + self, + cs: &mut CS, + ) -> Result { + let path = self.main_file_path; + generate_constraints::<_, G, _>(cs, self.program, self.program_inputs, &self.imported_programs).map_err( + |mut error| { + error.set_path(path); - /// Parses the Leo program string, constructs a syntax tree, and generates a program. - pub fn parse_program(&mut self, program_string: &str) -> Result<(), CompilerError> { - // Parse the program syntax tree - let syntax_tree = LeoParser::parse_file(&self.main_file_path, program_string)?; - - // Build program from syntax tree - let package_name = self.package_name.clone(); - - self.program = Program::from(syntax_tree, package_name); - self.program_inputs.set_inputs_size(self.program.expected_inputs.len()); - self.imported_programs = ImportParser::parse(&self.program)?; - - log::debug!("Program parsing complete\n{:#?}", self.program); - - Ok(()) - } - - pub fn parse_inputs(&mut self, inputs_string: &str) -> Result<(), CompilerError> { - let syntax_tree = LeoInputsParser::parse_file(&inputs_string)?; - - // Check number/order of parameters here - self.program_inputs = Inputs::from_inputs_file(syntax_tree, self.program.expected_inputs.clone())?; - - Ok(()) + error + }, + ) } pub fn to_bytes(&self) -> Result, CompilerError> { @@ -131,37 +170,36 @@ impl> Compiler { pub fn from_bytes(bytes: &[u8]) -> Result { let program: Program = bincode::deserialize(bytes)?; - let mut program_inputs = Inputs::new(); - - program_inputs.set_inputs_size(program.expected_inputs.len()); + let program_inputs = Inputs::new(); Ok(Self { package_name: program.name.clone(), main_file_path: PathBuf::new(), + outputs_directory: PathBuf::new(), program, program_inputs, imported_programs: ImportParser::new(), - output: None, _engine: PhantomData, + _group: PhantomData, }) } } impl> ConstraintSynthesizer for Compiler { + /// Synthesizes the circuit with program inputs. fn generate_constraints>(self, cs: &mut CS) -> Result<(), SynthesisError> { - let result = generate_constraints::<_, G, _>( - cs, - self.program, - self.program_inputs.get_inputs(), - &self.imported_programs, - ) - .map_err(|e| { + let outputs_directory = self.outputs_directory.clone(); + let package_name = self.package_name.clone(); + let result = self.generate_constraints_helper(cs).map_err(|e| { log::error!("{}", e); SynthesisError::Unsatisfiable })?; - // Write results to file or something - log::info!("{}", result); + log::info!("Program circuit successfully synthesized!"); + + // Write results to file + let outputs_file = OutputsFile::new(&package_name); + outputs_file.write(&outputs_directory, result.bytes()).unwrap(); Ok(()) } diff --git a/compiler/src/constraints/constraints.rs b/compiler/src/constraints/constraints.rs index a732de9099..9073e7f977 100644 --- a/compiler/src/constraints/constraints.rs +++ b/compiler/src/constraints/constraints.rs @@ -1,7 +1,15 @@ //! Generates R1CS constraints for a compiled Leo program. -use crate::{errors::CompilerError, new_scope, ConstrainedProgram, ConstrainedValue, GroupType, ImportParser}; -use leo_types::{InputValue, Program}; +use crate::{ + errors::CompilerError, + new_scope, + ConstrainedProgram, + ConstrainedValue, + GroupType, + ImportParser, + OutputBytes, +}; +use leo_types::{Inputs, Program}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -11,10 +19,10 @@ use snarkos_models::{ pub fn generate_constraints, CS: ConstraintSystem>( cs: &mut CS, program: Program, - parameters: Vec>, + inputs: Inputs, imported_programs: &ImportParser, -) -> Result, CompilerError> { - let mut resolved_program = ConstrainedProgram::new(); +) -> Result { + let mut resolved_program = ConstrainedProgram::::new(); let program_name = program.get_name(); let main_function_name = new_scope(program_name.clone(), "main".into()); @@ -26,7 +34,7 @@ pub fn generate_constraints, CS: Constrai match main.clone() { ConstrainedValue::Function(_circuit_identifier, function) => { - let result = resolved_program.enforce_main_function(cs, program_name, function, parameters)?; + let result = resolved_program.enforce_main_function(cs, program_name, function, inputs)?; Ok(result) } _ => Err(CompilerError::NoMainFunction), @@ -36,6 +44,7 @@ pub fn generate_constraints, CS: Constrai pub fn generate_test_constraints>( cs: &mut TestConstraintSystem, program: Program, + inputs: Inputs, imported_programs: &ImportParser, ) -> Result<(), CompilerError> { let mut resolved_program = ConstrainedProgram::::new(); @@ -54,7 +63,7 @@ pub fn generate_test_constraints>( cs, program_name.clone(), test_function.0, - vec![], // test functions should not take any inputs + inputs.clone(), // pass program inputs into every test ); if result.is_ok() { diff --git a/compiler/src/errors/compiler.rs b/compiler/src/errors/compiler.rs index 9f086b6b01..549475bf02 100644 --- a/compiler/src/errors/compiler.rs +++ b/compiler/src/errors/compiler.rs @@ -1,4 +1,4 @@ -use crate::errors::{FunctionError, ImportError}; +use crate::errors::{FunctionError, ImportError, OutputBytesError, OutputsFileError}; use leo_ast::ParserError; use leo_inputs::InputParserError; @@ -25,6 +25,12 @@ pub enum CompilerError { #[error("`main` must be a function")] NoMainFunction, + #[error("{}", _0)] + OutputError(#[from] OutputsFileError), + + #[error("{}", _0)] + OutputStringError(#[from] OutputBytesError), + #[error("{}", _0)] ParserError(#[from] ParserError), @@ -36,6 +42,7 @@ impl CompilerError { pub fn set_path(&mut self, path: PathBuf) { match self { CompilerError::FunctionError(error) => error.set_path(path), + CompilerError::OutputStringError(error) => error.set_path(path), _ => {} } } diff --git a/compiler/src/errors/function.rs b/compiler/src/errors/function.rs index 60c694ace4..eb63787a73 100644 --- a/compiler/src/errors/function.rs +++ b/compiler/src/errors/function.rs @@ -5,6 +5,7 @@ use crate::errors::{ FieldError, GroupError, IntegerError, + OutputBytesError, StatementError, ValueError, }; @@ -35,6 +36,9 @@ pub enum FunctionError { #[error("{}", _0)] IntegerError(#[from] IntegerError), + #[error("{}", _0)] + OutputStringError(#[from] OutputBytesError), + #[error("{}", _0)] StatementError(#[from] StatementError), @@ -52,6 +56,7 @@ impl FunctionError { FunctionError::FieldError(error) => error.set_path(path), FunctionError::GroupError(error) => error.set_path(path), FunctionError::IntegerError(error) => error.set_path(path), + FunctionError::OutputStringError(error) => error.set_path(path), FunctionError::StatementError(error) => error.set_path(path), FunctionError::ValueError(error) => error.set_path(path), } @@ -78,4 +83,10 @@ impl FunctionError { Self::new_from_span(message, span) } + + pub fn input_not_found(expected: String, span: Span) -> Self { + let message = format!("main function input {} not found", expected); + + Self::new_from_span(message, span) + } } diff --git a/compiler/src/errors/mod.rs b/compiler/src/errors/mod.rs index 3599d55a2c..96ec87bdf4 100644 --- a/compiler/src/errors/mod.rs +++ b/compiler/src/errors/mod.rs @@ -13,6 +13,12 @@ pub use self::import::*; pub mod macro_; pub use self::macro_::*; +pub mod output_file; +pub use self::output_file::*; + +pub mod output_bytes; +pub use self::output_bytes::*; + pub mod statement; pub use self::statement::*; diff --git a/compiler/src/errors/output_bytes.rs b/compiler/src/errors/output_bytes.rs new file mode 100644 index 0000000000..0de3eb5117 --- /dev/null +++ b/compiler/src/errors/output_bytes.rs @@ -0,0 +1,33 @@ +use leo_types::{Error as FormattedError, Span}; + +use std::path::PathBuf; + +#[derive(Debug, Error)] +pub enum OutputBytesError { + #[error("{}", _0)] + Error(#[from] FormattedError), +} + +impl OutputBytesError { + pub fn set_path(&mut self, path: PathBuf) { + match self { + OutputBytesError::Error(error) => error.set_path(path), + } + } + + fn new_from_span(message: String, span: Span) -> Self { + OutputBytesError::Error(FormattedError::new_from_span(message, span)) + } + + pub fn illegal_return(value: String, span: Span) -> Self { + let message = format!("program return must be a return value, found `{}`", value); + + Self::new_from_span(message, span) + } + + pub fn not_enough_registers(span: Span) -> Self { + let message = format!("number of input registers must be greater than or equal to output registers"); + + Self::new_from_span(message, span) + } +} diff --git a/compiler/src/errors/output_file.rs b/compiler/src/errors/output_file.rs new file mode 100644 index 0000000000..29b8f84bba --- /dev/null +++ b/compiler/src/errors/output_file.rs @@ -0,0 +1,22 @@ +use std::{io, path::PathBuf}; + +#[derive(Debug, Error)] +pub enum OutputsFileError { + #[error("{}: {}", _0, _1)] + Crate(&'static str, String), + + #[error("creating: {}", _0)] + Creating(io::Error), + + #[error("Cannot read from the provided file path - {:?}", _0)] + FileReadError(PathBuf), + + #[error("writing: {}", _0)] + Writing(io::Error), +} + +impl From for OutputsFileError { + fn from(error: std::io::Error) -> Self { + OutputsFileError::Crate("std::io", format!("{}", error)) + } +} diff --git a/compiler/src/function/function.rs b/compiler/src/function/function.rs index 95876b0016..98c6743760 100644 --- a/compiler/src/function/function.rs +++ b/compiler/src/function/function.rs @@ -7,7 +7,7 @@ use crate::{ GroupType, }; -use leo_types::{Expression, Function, Span}; +use leo_types::{Expression, Function, Input, Span}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -39,23 +39,77 @@ impl> ConstrainedProgram { // Store input values as new variables in resolved program for (input_model, input_expression) in function.inputs.clone().iter().zip(inputs.into_iter()) { - // First evaluate input expression - let mut input_value = self.enforce_input( - cs, - scope.clone(), - caller_scope.clone(), - function_name.clone(), - vec![input_model._type.clone()], - input_expression, - )?; + let (name, value) = match input_model { + Input::FunctionInput(input_model) => { + // First evaluate input expression + let mut input_value = self.enforce_input( + cs, + scope.clone(), + caller_scope.clone(), + function_name.clone(), + vec![input_model.type_.clone()], + input_expression, + )?; - if input_model.mutable { - input_value = ConstrainedValue::Mutable(Box::new(input_value)) - } + if input_model.mutable { + input_value = ConstrainedValue::Mutable(Box::new(input_value)) + } + + (input_model.identifier.name.clone(), input_value) + } + Input::Registers(identifier) => { + let input_value = self.enforce_input( + cs, + scope.clone(), + caller_scope.clone(), + function_name.clone(), + vec![], + input_expression, + )?; + + (identifier.name.clone(), input_value) + } + Input::Record(identifier) => { + let input_value = self.enforce_input( + cs, + scope.clone(), + caller_scope.clone(), + function_name.clone(), + vec![], + input_expression, + )?; + + (identifier.name.clone(), input_value) + } + Input::State(identifier) => { + let input_value = self.enforce_input( + cs, + scope.clone(), + caller_scope.clone(), + function_name.clone(), + vec![], + input_expression, + )?; + + (identifier.name.clone(), input_value) + } + Input::StateLeaf(identifier) => { + let input_value = self.enforce_input( + cs, + scope.clone(), + caller_scope.clone(), + function_name.clone(), + vec![], + input_expression, + )?; + + (identifier.name.clone(), input_value) + } + }; // Store input as variable with {function_name}_{input_name} - let input_program_identifier = new_scope(function_name.clone(), input_model.identifier.name.clone()); - self.store(input_program_identifier, input_value); + let input_program_identifier = new_scope(function_name.clone(), name); + self.store(input_program_identifier, value); } // Evaluate every statement in the function and save all potential results diff --git a/compiler/src/function/input/array.rs b/compiler/src/function/input/array.rs index 8f2aa19e94..5614e5b900 100644 --- a/compiler/src/function/input/array.rs +++ b/compiler/src/function/input/array.rs @@ -2,7 +2,6 @@ use crate::{ errors::FunctionError, - function::check_arguments_length, program::{new_scope, ConstrainedProgram}, value::ConstrainedValue, GroupType, @@ -30,9 +29,6 @@ impl> ConstrainedProgram { match input_value { Some(InputValue::Array(arr)) => { - // Check the dimension of the array - check_arguments_length(expected_length, arr.len(), span.clone())?; - // Allocate each value in the current row for (i, value) in arr.into_iter().enumerate() { let value_name = new_scope(name.clone(), i.to_string()); diff --git a/compiler/src/function/input/main_input.rs b/compiler/src/function/input/main_input.rs index ab619dba96..1ffd0a4980 100644 --- a/compiler/src/function/input/main_input.rs +++ b/compiler/src/function/input/main_input.rs @@ -25,24 +25,24 @@ impl> ConstrainedProgram { pub fn allocate_main_function_input>( &mut self, cs: &mut CS, - _type: Type, + type_: Type, name: String, - input_value: Option, + input_option: Option, span: Span, ) -> Result, FunctionError> { - match _type { - Type::Address => Ok(Address::from_input(cs, name, input_value, span)?), - Type::Boolean => Ok(bool_from_input(cs, name, input_value, span)?), - Type::Field => Ok(field_from_input(cs, name, input_value, span)?), - Type::Group => Ok(group_from_input(cs, name, input_value, span)?), + match type_ { + Type::Address => Ok(Address::from_input(cs, name, input_option, span)?), + Type::Boolean => Ok(bool_from_input(cs, name, input_option, span)?), + Type::Field => Ok(field_from_input(cs, name, input_option, span)?), + Type::Group => Ok(group_from_input(cs, name, input_option, span)?), Type::IntegerType(integer_type) => Ok(ConstrainedValue::Integer(Integer::from_input( cs, integer_type, name, - input_value, + input_option, span, )?)), - Type::Array(_type, dimensions) => self.allocate_array(cs, name, *_type, dimensions, input_value, span), + Type::Array(_type, dimensions) => self.allocate_array(cs, name, *_type, dimensions, input_option, span), _ => unimplemented!("main function input not implemented for type"), } } diff --git a/compiler/src/function/input/mod.rs b/compiler/src/function/input/mod.rs index 27a55172fc..a00b16e4f7 100644 --- a/compiler/src/function/input/mod.rs +++ b/compiler/src/function/input/mod.rs @@ -8,3 +8,6 @@ pub use self::input::*; pub mod main_input; pub use self::main_input::*; + +pub mod section; +pub use self::section::*; diff --git a/compiler/src/function/input/section.rs b/compiler/src/function/input/section.rs new file mode 100644 index 0000000000..34a5824418 --- /dev/null +++ b/compiler/src/function/input/section.rs @@ -0,0 +1,37 @@ +use crate::{errors::FunctionError, ConstrainedCircuitMember, ConstrainedProgram, ConstrainedValue, GroupType}; + +use leo_types::{Identifier, InputValue, Parameter}; +use snarkos_models::{ + curves::{Field, PrimeField}, + gadgets::r1cs::ConstraintSystem, +}; +use std::collections::HashMap; + +impl> ConstrainedProgram { + pub fn allocate_input_section>( + &mut self, + cs: &mut CS, + identifier: Identifier, + section: HashMap>, + ) -> Result, FunctionError> { + let mut members = vec![]; + + // Store each section definition as a circuit member value + for (parameter, option) in section.into_iter() { + let member_name = parameter.variable.clone(); + let member_value = self.allocate_main_function_input( + cs, + parameter.type_, + parameter.variable.name, + option, + parameter.span, + )?; + let member = ConstrainedCircuitMember(member_name, member_value); + + members.push(member) + } + + // Return section as circuit expression + Ok(ConstrainedValue::CircuitExpression(identifier, members)) + } +} diff --git a/compiler/src/function/main_function.rs b/compiler/src/function/main_function.rs index cb044fc238..76bc30b74c 100644 --- a/compiler/src/function/main_function.rs +++ b/compiler/src/function/main_function.rs @@ -2,13 +2,12 @@ use crate::{ errors::FunctionError, - function::check_arguments_length, program::{new_scope, ConstrainedProgram}, - value::ConstrainedValue, GroupType, + OutputBytes, }; -use leo_types::{Expression, Function, InputValue}; +use leo_types::{Expression, Function, Input, Inputs}; use snarkos_models::{ curves::{Field, PrimeField}, @@ -21,31 +20,69 @@ impl> ConstrainedProgram { cs: &mut CS, scope: String, function: Function, - inputs: Vec>, - ) -> Result, FunctionError> { + inputs: Inputs, + ) -> Result { let function_name = new_scope(scope.clone(), function.get_name()); - - // Make sure we are given the correct number of inputs - check_arguments_length(function.inputs.len(), inputs.len(), function.span.clone())?; + let registers = inputs.get_registers(); // Iterate over main function inputs and allocate new passed-by variable values let mut input_variables = vec![]; - for (input_model, input_option) in function.inputs.clone().into_iter().zip(inputs.into_iter()) { - let input_value = self.allocate_main_function_input( - cs, - input_model._type, - input_model.identifier.name.clone(), - input_option, - function.span.clone(), - )?; + for input_model in function.inputs.clone().into_iter() { + let (identifier, value) = match input_model { + Input::FunctionInput(input_model) => { + let name = input_model.identifier.name.clone(); + let input_option = inputs + .get(&name) + .ok_or(FunctionError::input_not_found(name.clone(), function.span.clone()))?; + let input_value = self.allocate_main_function_input( + cs, + input_model.type_, + name.clone(), + input_option, + function.span.clone(), + )?; + + (input_model.identifier, input_value) + } + Input::Registers(identifier) => { + let section = inputs.get_registers().values(); + let value = self.allocate_input_section(cs, identifier.clone(), section)?; + + (identifier, value) + } + Input::Record(identifier) => { + let section = inputs.get_record().values(); + let value = self.allocate_input_section(cs, identifier.clone(), section)?; + + (identifier, value) + } + Input::State(identifier) => { + let section = inputs.get_state().values(); + let value = self.allocate_input_section(cs, identifier.clone(), section)?; + + (identifier, value) + } + Input::StateLeaf(identifier) => { + let section = inputs.get_state_leaf().values(); + let value = self.allocate_input_section(cs, identifier.clone(), section)?; + + (identifier, value) + } + }; + + // Store input as variable with {function_name}_{identifier_name} + let input_name = new_scope(function_name.clone(), identifier.name.clone()); // Store a new variable for every allocated main function input - let input_name = new_scope(function_name.clone(), input_model.identifier.name.clone()); - self.store(input_name.clone(), input_value); + self.store(input_name, value); - input_variables.push(Expression::Identifier(input_model.identifier)); + input_variables.push(Expression::Identifier(identifier)); } - self.enforce_function(cs, scope, function_name, function, input_variables) + let span = function.span.clone(); + let result_value = self.enforce_function(cs, scope, function_name, function, input_variables)?; + let output_bytes = OutputBytes::new_from_constrained_value(registers, result_value, span)?; + + Ok(output_bytes) } } diff --git a/compiler/src/lib.rs b/compiler/src/lib.rs index f163c5438a..1b0cd3a006 100644 --- a/compiler/src/lib.rs +++ b/compiler/src/lib.rs @@ -24,6 +24,9 @@ pub use self::import::*; pub mod macro_; pub use self::macro_::*; +pub mod output; +pub use self::output::*; + pub mod program; pub use self::program::*; diff --git a/compiler/src/output/mod.rs b/compiler/src/output/mod.rs new file mode 100644 index 0000000000..f112f0a02b --- /dev/null +++ b/compiler/src/output/mod.rs @@ -0,0 +1,5 @@ +pub mod output_file; +pub use self::output_file::*; + +pub mod output_bytes; +pub use self::output_bytes::*; diff --git a/compiler/src/output/output_bytes.rs b/compiler/src/output/output_bytes.rs new file mode 100644 index 0000000000..4c1e0595b1 --- /dev/null +++ b/compiler/src/output/output_bytes.rs @@ -0,0 +1,69 @@ +use crate::{errors::OutputBytesError, ConstrainedValue, GroupType}; +use leo_types::{Parameter, Registers, Span, REGISTERS_VARIABLE_NAME}; + +use snarkos_models::curves::{Field, PrimeField}; + +use serde::{Deserialize, Serialize}; + +/// Serialized program return output. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct OutputBytes(Vec); + +impl OutputBytes { + pub fn bytes(&self) -> &Vec { + &self.0 + } + + pub fn new_from_constrained_value>( + registers: &Registers, + value: ConstrainedValue, + span: Span, + ) -> Result { + let return_values = match value { + ConstrainedValue::Return(values) => values, + value => return Err(OutputBytesError::illegal_return(value.to_string(), span)), + }; + let register_hashmap = registers.values(); + + // Create vector of parameter values in alphabetical order + let mut register_values = register_hashmap + .into_iter() + .map(|register| register.0) + .collect::>(); + + register_values.sort_by(|a, b| a.variable.name.cmp(&b.variable.name)); + + // Return an error if we do not have enough return registers + if register_values.len() < return_values.len() { + return Err(OutputBytesError::not_enough_registers(span)); + } + + // Manually construct result string + let mut string = String::new(); + let header = format!("[{}]\n", REGISTERS_VARIABLE_NAME); + + string.push_str(&header); + + // format: "token_id: u64 = 1u64;" + for (parameter, value) in register_values.into_iter().zip(return_values.into_iter()) { + let name = parameter.variable.name; + let type_ = parameter.type_; + let value = value.to_string(); + + let format = format!("{}: {} = {};\n", name, type_, value,); + + string.push_str(&format); + } + + let mut bytes: Vec = vec![]; + bytes.extend_from_slice(string.as_bytes()); + + Ok(Self(bytes)) + } +} + +impl From> for OutputBytes { + fn from(bytes: Vec) -> Self { + Self(bytes) + } +} diff --git a/compiler/src/output/output_file.rs b/compiler/src/output/output_file.rs new file mode 100644 index 0000000000..63940eb826 --- /dev/null +++ b/compiler/src/output/output_file.rs @@ -0,0 +1,63 @@ +//! The `program.out` file. + +use crate::errors::OutputsFileError; + +use std::{ + fs::{self, File}, + io::Write, + path::PathBuf, +}; + +pub static OUTPUTS_DIRECTORY_NAME: &str = "outputs/"; +pub static OUTPUTS_FILE_EXTENSION: &str = ".out"; + +pub struct OutputsFile { + pub package_name: String, +} + +impl OutputsFile { + pub fn new(package_name: &str) -> Self { + Self { + package_name: package_name.to_string(), + } + } + + pub fn exists_at(&self, path: &PathBuf) -> bool { + let path = self.setup_file_path(path); + path.exists() + } + + /// Reads the outputs from the given file path if it exists. + pub fn read_from(&self, path: &PathBuf) -> Result { + let path = self.setup_file_path(path); + + let inputs = fs::read_to_string(&path).map_err(|_| OutputsFileError::FileReadError(path.clone()))?; + Ok(inputs) + } + + /// Writes output to a file. + pub fn write(&self, path: &PathBuf, bytes: &[u8]) -> Result<(), OutputsFileError> { + // create output file + let path = self.setup_file_path(path); + println!("setup {:?}", path); + let mut file = File::create(&path)?; + println!("created"); + log::info!("Writing to output registers..."); + + Ok(file.write_all(bytes)?) + } + + fn setup_file_path(&self, path: &PathBuf) -> PathBuf { + let mut path = path.to_owned(); + if path.is_dir() { + if !path.ends_with(OUTPUTS_DIRECTORY_NAME) { + path.push(PathBuf::from(OUTPUTS_DIRECTORY_NAME)); + } + path.push(PathBuf::from(format!( + "{}{}", + self.package_name, OUTPUTS_FILE_EXTENSION + ))); + } + path + } +} diff --git a/compiler/src/value/group/targets/edwards_bls12.rs b/compiler/src/value/group/targets/edwards_bls12.rs index a575c2a926..34a7ce94fb 100644 --- a/compiler/src/value/group/targets/edwards_bls12.rs +++ b/compiler/src/value/group/targets/edwards_bls12.rs @@ -303,8 +303,8 @@ impl CondSelectGadget for EdwardsGroupType { if let Boolean::Constant(cond) = *cond { if cond { Ok(first.clone()) } else { Ok(second.clone()) } } else { - let first_gadget = first.allocated(&mut cs)?; - let second_gadget = second.allocated(&mut cs)?; + let first_gadget = first.allocated(cs.ns(|| "first"))?; + let second_gadget = second.allocated(cs.ns(|| "second"))?; let result = EdwardsBlsGadget::conditionally_select(cs, cond, &first_gadget, &second_gadget)?; Ok(EdwardsGroupType::Allocated(result)) diff --git a/compiler/tests/address/equal.leo b/compiler/tests/address/equal.leo index 9c9ce2b308..704328e095 100644 --- a/compiler/tests/address/equal.leo +++ b/compiler/tests/address/equal.leo @@ -1,3 +1,3 @@ -function main(first: address, second: address) -> bool { - return first == second +function main(a: address, b: address, c: bool) { + assert_eq!(a == b, c); } \ No newline at end of file diff --git a/compiler/tests/address/mod.rs b/compiler/tests/address/mod.rs index 34b9a67e64..cf98e33020 100644 --- a/compiler/tests/address/mod.rs +++ b/compiler/tests/address/mod.rs @@ -1,38 +1,15 @@ -use crate::{ - boolean::{output_false, output_true}, - get_error, - get_output, - parse_program, - EdwardsConstrainedValue, - EdwardsTestCompiler, -}; -use leo_compiler::{Address, ConstrainedValue}; +use crate::{assert_satisfied, expect_compiler_error, generate_main_inputs, parse_program}; use leo_types::InputValue; -use snarkos_dpc::base_dpc::instantiated::Components; -use snarkos_objects::AccountAddress; -use std::str::FromStr; - static TEST_ADDRESS_1: &'static str = "aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8"; static TEST_ADDRESS_2: &'static str = "aleo18qgam03qe483tdrcc3fkqwpp38ehff4a2xma6lu7hams6lfpgcpq3dq05r"; -fn output_test_address(program: EdwardsTestCompiler, address: &str) { - let output = get_output(program); - - let address_1 = AccountAddress::::from_str(address).unwrap(); - - assert_eq!( - EdwardsConstrainedValue::Return(vec![ConstrainedValue::Address(Address(Some(address_1)))]).to_string(), - output.to_string() - ); -} - #[test] fn test_valid() { let bytes = include_bytes!("valid.leo"); let program = parse_program(bytes).unwrap(); - let _output = get_output(program); + assert_satisfied(program) } #[test] @@ -40,7 +17,7 @@ fn test_invalid() { let bytes = include_bytes!("invalid.leo"); let program = parse_program(bytes).unwrap(); - let _output = get_error(program); + let _output = expect_compiler_error(program); } #[test] @@ -48,7 +25,7 @@ fn test_implicit_valid() { let bytes = include_bytes!("implicit_valid.leo"); let program = parse_program(bytes).unwrap(); - let _output = get_output(program); + assert_satisfied(program); } #[test] @@ -56,7 +33,7 @@ fn test_implicit_invalid() { let bytes = include_bytes!("implicit_invalid.leo"); let program = parse_program(bytes).unwrap(); - let _output = get_error(program); + let _output = expect_compiler_error(program); } #[test] @@ -64,7 +41,7 @@ fn test_assert_eq_pass() { let bytes = include_bytes!("assert_eq_pass.leo"); let program = parse_program(bytes).unwrap(); - let _output = get_output(program); + assert_satisfied(program); } #[test] @@ -72,61 +49,59 @@ fn test_assert_eq_fail() { let bytes = include_bytes!("assert_eq_fail.leo"); let program = parse_program(bytes).unwrap(); - let _output = get_error(program); -} - -#[test] -fn test_input_pass() { - let bytes = include_bytes!("input.leo"); - let mut program = parse_program(bytes).unwrap(); - - program.set_inputs(vec![Some(InputValue::Address(TEST_ADDRESS_1.to_string()))]); - - let _output = get_output(program); -} - -#[test] -fn test_input_fail_bool() { - let bytes = include_bytes!("input.leo"); - let mut program = parse_program(bytes).unwrap(); - - program.set_inputs(vec![Some(InputValue::Boolean(true))]); - - let _err = get_error(program); + let _output = expect_compiler_error(program); } #[test] fn test_ternary() { let bytes = include_bytes!("ternary.leo"); - let mut program_1 = parse_program(bytes).unwrap(); - let mut program_2 = program_1.clone(); + let mut program = parse_program(bytes).unwrap(); - program_1.set_inputs(vec![Some(InputValue::Boolean(true))]); + let main_inputs = generate_main_inputs(vec![ + ("s", Some(InputValue::Boolean(true))), + ("c", Some(InputValue::Address(TEST_ADDRESS_1.to_string()))), + ]); - output_test_address(program_1, TEST_ADDRESS_1); + program.set_main_inputs(main_inputs); - program_2.set_inputs(vec![Some(InputValue::Boolean(false))]); + assert_satisfied(program); - output_test_address(program_2, TEST_ADDRESS_2); + let mut program = parse_program(bytes).unwrap(); + + let main_inputs = generate_main_inputs(vec![ + ("s", Some(InputValue::Boolean(false))), + ("c", Some(InputValue::Address(TEST_ADDRESS_2.to_string()))), + ]); + + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } #[test] fn test_equal() { let bytes = include_bytes!("equal.leo"); - let mut program_1 = parse_program(bytes).unwrap(); - let mut program_2 = program_1.clone(); + let mut program = parse_program(bytes).unwrap(); - program_1.set_inputs(vec![ - Some(InputValue::Address(TEST_ADDRESS_1.to_string())), - Some(InputValue::Address(TEST_ADDRESS_1.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Address(TEST_ADDRESS_1.to_string()))), + ("b", Some(InputValue::Address(TEST_ADDRESS_1.to_string()))), + ("c", Some(InputValue::Boolean(true))), ]); - output_true(program_1); + program.set_main_inputs(main_inputs); - program_2.set_inputs(vec![ - Some(InputValue::Address(TEST_ADDRESS_1.to_string())), - Some(InputValue::Address(TEST_ADDRESS_2.to_string())), + assert_satisfied(program); + + let mut program = parse_program(bytes).unwrap(); + + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Address(TEST_ADDRESS_1.to_string()))), + ("b", Some(InputValue::Address(TEST_ADDRESS_2.to_string()))), + ("c", Some(InputValue::Boolean(false))), ]); - output_false(program_2); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } diff --git a/compiler/tests/address/ternary.leo b/compiler/tests/address/ternary.leo index 05dcafa14e..9d6752791e 100644 --- a/compiler/tests/address/ternary.leo +++ b/compiler/tests/address/ternary.leo @@ -1,6 +1,8 @@ -function main(cond: bool) -> address { - let first = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8); - let second = address(aleo18qgam03qe483tdrcc3fkqwpp38ehff4a2xma6lu7hams6lfpgcpq3dq05r); +function main(s: bool, c: address) { + let a = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8); + let b = address(aleo18qgam03qe483tdrcc3fkqwpp38ehff4a2xma6lu7hams6lfpgcpq3dq05r); - return if cond ? first : second + let r = if s? a: b; + + assert_eq!(r, c); } \ No newline at end of file diff --git a/compiler/tests/array/initializer.leo b/compiler/tests/array/initializer.leo index d129bd704d..109c003fd3 100644 --- a/compiler/tests/array/initializer.leo +++ b/compiler/tests/array/initializer.leo @@ -1,3 +1,3 @@ -function main() -> u32[3] { - return [1u32; 3] +function main(a: u8[3]) { + assert_eq!(a, [1u8; 3]); } \ No newline at end of file diff --git a/compiler/tests/array/inline.leo b/compiler/tests/array/inline.leo index 3a77aa5546..649ec73262 100644 --- a/compiler/tests/array/inline.leo +++ b/compiler/tests/array/inline.leo @@ -1,3 +1,3 @@ -function main() -> u32[3] { - return [1u32, 1u32, 1u32] +function main(a: u8[3]) { + assert_eq!(a, [1u8, 1u8, 1u8]); } \ No newline at end of file diff --git a/compiler/tests/array/input.leo b/compiler/tests/array/input.leo deleted file mode 100644 index eade0fae25..0000000000 --- a/compiler/tests/array/input.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main(arr: u32[3]) -> u32[3] { - return arr -} \ No newline at end of file diff --git a/compiler/tests/array/inputs/inline_fail.leo b/compiler/tests/array/inputs/inline_fail.leo new file mode 100644 index 0000000000..ef826e9f0c --- /dev/null +++ b/compiler/tests/array/inputs/inline_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a = [1u8, bool]; +} \ No newline at end of file diff --git a/compiler/tests/array/inputs/registers_ones.in b/compiler/tests/array/inputs/registers_ones.in new file mode 100644 index 0000000000..47f8b756d1 --- /dev/null +++ b/compiler/tests/array/inputs/registers_ones.in @@ -0,0 +1,2 @@ +[registers] +r: u8[3] = [1u8, 1u8, 1u8]; diff --git a/compiler/tests/array/inputs/registers_zeros.in b/compiler/tests/array/inputs/registers_zeros.in new file mode 100644 index 0000000000..bda1f40229 --- /dev/null +++ b/compiler/tests/array/inputs/registers_zeros.in @@ -0,0 +1,2 @@ +[registers] +r: u8[3] = [0u8, 0u8, 0u8]; diff --git a/compiler/tests/array/inputs/six_zeros.in b/compiler/tests/array/inputs/six_zeros.in new file mode 100644 index 0000000000..f91102b28f --- /dev/null +++ b/compiler/tests/array/inputs/six_zeros.in @@ -0,0 +1,2 @@ +[main] +a: u8[3][2] = [[0; 3]; 2]; \ No newline at end of file diff --git a/compiler/tests/array/inputs/three_ones.in b/compiler/tests/array/inputs/three_ones.in new file mode 100644 index 0000000000..96bcc4ef51 --- /dev/null +++ b/compiler/tests/array/inputs/three_ones.in @@ -0,0 +1,2 @@ +[main] +a: u8[3] = [1u8, 1u8, 1u8]; \ No newline at end of file diff --git a/compiler/tests/array/mod.rs b/compiler/tests/array/mod.rs index 94886b1527..f6cde60ad9 100644 --- a/compiler/tests/array/mod.rs +++ b/compiler/tests/array/mod.rs @@ -1,133 +1,95 @@ use crate::{ - get_error, - get_output, - integers::fail_integer, + assert_satisfied, + expect_compiler_error, + get_outputs, parse_program, - EdwardsConstrainedValue, + parse_program_with_inputs, EdwardsTestCompiler, }; -use leo_compiler::{ - errors::{CompilerError, FunctionError}, - ConstrainedValue, - Integer, -}; -use leo_inputs::types::{IntegerType, U32Type}; -use leo_types::InputValue; -use snarkos_models::gadgets::utilities::uint::UInt32; +pub fn output_ones(program: EdwardsTestCompiler) { + let expected = include_bytes!("outputs_/registers_ones.out"); + let actual = get_outputs(program); -// [1, 1, 1] -fn output_ones(program: EdwardsTestCompiler) { - let output = get_output(program); - assert_eq!( - EdwardsConstrainedValue::Return(vec![ConstrainedValue::Array(vec![ - ConstrainedValue::Integer( - Integer::U32(UInt32::constant(1u32)) - ); - 3 - ])]) - .to_string(), - output.to_string() - ); + assert!(expected.eq(actual.bytes().as_slice())); } -// [[0, 0, 0], -// [0, 0, 0]] -fn output_multi(program: EdwardsTestCompiler) { - let output = get_output(program); - assert_eq!( - EdwardsConstrainedValue::Return(vec![ConstrainedValue::Array(vec![ - ConstrainedValue::Array( - vec![ConstrainedValue::Integer(Integer::U32(UInt32::constant(0u32))); 3] - ); - 2 - ])]) - .to_string(), - output.to_string() - ) +pub fn output_zeros(program: EdwardsTestCompiler) { + let expected = include_bytes!("outputs_/registers_zeros.out"); + let actual = get_outputs(program); + + assert!(expected.eq(actual.bytes().as_slice())); } -fn fail_array(program: EdwardsTestCompiler) { - match get_error(program) { - CompilerError::FunctionError(FunctionError::Error(_string)) => {} - error => panic!("Expected function error, found {}", error), - } -} +// Registers -pub(crate) fn input_value_u32_one() -> InputValue { - InputValue::Integer(IntegerType::U32Type(U32Type {}), 1.to_string()) +#[test] +fn test_registers() { + let program_bytes = include_bytes!("registers.leo"); + let ones_input_bytes = include_bytes!("inputs/registers_ones.in"); + let zeros_input_bytes = include_bytes!("inputs/registers_zeros.in"); + + // test ones input register => ones output register + let program = parse_program_with_inputs(program_bytes, ones_input_bytes).unwrap(); + + output_ones(program); + + // test zeros input register => zeros output register + let program = parse_program_with_inputs(program_bytes, zeros_input_bytes).unwrap(); + + output_zeros(program); } // Expressions #[test] fn test_inline() { - let bytes = include_bytes!("inline.leo"); - let program = parse_program(bytes).unwrap(); + let program_bytes = include_bytes!("inline.leo"); + let input_bytes = include_bytes!("inputs/three_ones.in"); + let program = parse_program_with_inputs(program_bytes, input_bytes).unwrap(); - output_ones(program); + assert_satisfied(program); +} + +#[test] +fn test_inline_fail() { + let program_bytes = include_bytes!("inline.leo"); + let program = parse_program(program_bytes).unwrap(); + + let _err = expect_compiler_error(program); } #[test] fn test_initializer() { - let bytes = include_bytes!("initializer.leo"); - let program = parse_program(bytes).unwrap(); + let program_bytes = include_bytes!("initializer.leo"); + let input_bytes = include_bytes!("inputs/three_ones.in"); + let program = parse_program_with_inputs(program_bytes, input_bytes).unwrap(); - output_ones(program); + assert_satisfied(program); } #[test] fn test_spread() { - let bytes = include_bytes!("spread.leo"); - let program = parse_program(bytes).unwrap(); + let program_bytes = include_bytes!("spread.leo"); + let input_bytes = include_bytes!("inputs/three_ones.in"); + let program = parse_program_with_inputs(program_bytes, input_bytes).unwrap(); - output_ones(program); + assert_satisfied(program); } #[test] fn test_slice() { - let bytes = include_bytes!("slice.leo"); - let program = parse_program(bytes).unwrap(); + let program_bytes = include_bytes!("slice.leo"); + let input_bytes = include_bytes!("inputs/three_ones.in"); + let program = parse_program_with_inputs(program_bytes, input_bytes).unwrap(); - output_ones(program); + assert_satisfied(program); } #[test] fn test_multi() { - let bytes = include_bytes!("multi.leo"); - let program = parse_program(bytes).unwrap(); + let program_bytes = include_bytes!("multi.leo"); + let program = parse_program(program_bytes).unwrap(); - output_multi(program); -} - -// Inputs - -#[test] -fn test_input_array() { - let bytes = include_bytes!("input.leo"); - let mut program = parse_program(bytes).unwrap(); - - program.set_inputs(vec![Some(InputValue::Array(vec![input_value_u32_one(); 3]))]); - - output_ones(program) -} - -#[test] -fn test_input_array_fail() { - let bytes = include_bytes!("input.leo"); - let mut program = parse_program(bytes).unwrap(); - - program.set_inputs(vec![Some(input_value_u32_one())]); - - fail_array(program); -} - -#[test] -fn test_input_field_none() { - let bytes = include_bytes!("input.leo"); - let mut program = parse_program(bytes).unwrap(); - - program.set_inputs(vec![None]); - - fail_integer(program) + assert_satisfied(program); } diff --git a/compiler/tests/array/multi.leo b/compiler/tests/array/multi.leo index baf94b2842..f5079b8615 100644 --- a/compiler/tests/array/multi.leo +++ b/compiler/tests/array/multi.leo @@ -1,8 +1,8 @@ // Multidimensional array syntax in leo -function main() -> u32[3][2] { - const m = [[0u32, 0u32, 0u32], [0u32, 0u32, 0u32]]; // inline +function main() { + const a = [[0u32, 0u32, 0u32], [0u32, 0u32, 0u32]]; // inline - const m: u32[3][2] = [[0; 3]; 2]; // initializer + const b: u32[3][2] = [[0; 3]; 2]; // initializer - return m + assert_eq!(a, b); } \ No newline at end of file diff --git a/compiler/tests/array/outputs_/registers_ones.out b/compiler/tests/array/outputs_/registers_ones.out new file mode 100644 index 0000000000..47f8b756d1 --- /dev/null +++ b/compiler/tests/array/outputs_/registers_ones.out @@ -0,0 +1,2 @@ +[registers] +r: u8[3] = [1u8, 1u8, 1u8]; diff --git a/compiler/tests/array/outputs_/registers_zeros.out b/compiler/tests/array/outputs_/registers_zeros.out new file mode 100644 index 0000000000..bda1f40229 --- /dev/null +++ b/compiler/tests/array/outputs_/registers_zeros.out @@ -0,0 +1,2 @@ +[registers] +r: u8[3] = [0u8, 0u8, 0u8]; diff --git a/compiler/tests/array/registers.leo b/compiler/tests/array/registers.leo new file mode 100644 index 0000000000..42d0fa4530 --- /dev/null +++ b/compiler/tests/array/registers.leo @@ -0,0 +1,3 @@ +function main(registers) -> u8[3] { + return registers.r +} \ No newline at end of file diff --git a/compiler/tests/array/slice.leo b/compiler/tests/array/slice.leo index 95390d0583..eeca972e26 100644 --- a/compiler/tests/array/slice.leo +++ b/compiler/tests/array/slice.leo @@ -1,6 +1,6 @@ // `{from}..{to}` copies the elements of one array into another exclusively -function main() -> u32[3] { - let a = [1u32; 4]; +function main(a: u8[3]) { + let b = [1u8; 4]; - return a[0..3] + assert_eq!(a, b[0..3]); } diff --git a/compiler/tests/array/spread.leo b/compiler/tests/array/spread.leo index 86d5612171..6a7922122f 100644 --- a/compiler/tests/array/spread.leo +++ b/compiler/tests/array/spread.leo @@ -1,6 +1,6 @@ // A spread operator `...` copies the elements of one array into another -function main() -> u32[3] { - let a = [1u32, 1u32]; +function main(a: u8[3]) { + let b = [1u8, 1u8]; - return [1u32, ...a] + assert_eq!(a, [1u8, ...b]); } \ No newline at end of file diff --git a/compiler/tests/boolean/all.leo b/compiler/tests/boolean/all.leo index f4329b77d5..fc3975013a 100644 --- a/compiler/tests/boolean/all.leo +++ b/compiler/tests/boolean/all.leo @@ -1,8 +1,8 @@ // !(true && (false || true)) -function main() -> bool { +function main() { const a = true; const b = false || a; const c = !(true && b); - return c + assert_eq!(c, false); } \ No newline at end of file diff --git a/compiler/tests/boolean/assert_eq_input.leo b/compiler/tests/boolean/assert_eq_input.leo new file mode 100644 index 0000000000..fc0c344500 --- /dev/null +++ b/compiler/tests/boolean/assert_eq_input.leo @@ -0,0 +1,3 @@ +function main(a: bool, b: bool) { + assert_eq!(a, b); +} \ No newline at end of file diff --git a/compiler/tests/boolean/false.leo b/compiler/tests/boolean/false.leo deleted file mode 100644 index 221958dbd9..0000000000 --- a/compiler/tests/boolean/false.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> bool { - return false -} \ No newline at end of file diff --git a/compiler/tests/boolean/false_and_false.leo b/compiler/tests/boolean/false_and_false.leo index 4814c7dbb6..8122a47cf0 100644 --- a/compiler/tests/boolean/false_and_false.leo +++ b/compiler/tests/boolean/false_and_false.leo @@ -1,3 +1,5 @@ -function main() -> bool { - return false && false +function main() { + let a = false && false; + + assert_eq!(a, false); } \ No newline at end of file diff --git a/compiler/tests/boolean/false_or_false.leo b/compiler/tests/boolean/false_or_false.leo index 5e98a6f8c9..939682f263 100644 --- a/compiler/tests/boolean/false_or_false.leo +++ b/compiler/tests/boolean/false_or_false.leo @@ -1,3 +1,5 @@ -function main() -> bool { - return false || false +function main() { + let a = false || false; + + assert_eq!(a, false); } \ No newline at end of file diff --git a/compiler/tests/boolean/input_bool.leo b/compiler/tests/boolean/input_bool.leo deleted file mode 100644 index c233ac7fad..0000000000 --- a/compiler/tests/boolean/input_bool.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main(b: bool) -> bool{ - return b -} \ No newline at end of file diff --git a/compiler/tests/boolean/inputs/registers_false.in b/compiler/tests/boolean/inputs/registers_false.in new file mode 100644 index 0000000000..f41110cca8 --- /dev/null +++ b/compiler/tests/boolean/inputs/registers_false.in @@ -0,0 +1,2 @@ +[registers] +r: bool = false; \ No newline at end of file diff --git a/compiler/tests/boolean/inputs/registers_true.in b/compiler/tests/boolean/inputs/registers_true.in new file mode 100644 index 0000000000..a51a0e2dc2 --- /dev/null +++ b/compiler/tests/boolean/inputs/registers_true.in @@ -0,0 +1,2 @@ +[registers] +r: bool = true; \ No newline at end of file diff --git a/compiler/tests/boolean/inputs/true_false.in b/compiler/tests/boolean/inputs/true_false.in new file mode 100644 index 0000000000..b786a3ab5f --- /dev/null +++ b/compiler/tests/boolean/inputs/true_false.in @@ -0,0 +1,3 @@ +[main] +a: bool = true; +b: bool = false; \ No newline at end of file diff --git a/compiler/tests/inputs/main.in b/compiler/tests/boolean/inputs/true_true.in similarity index 57% rename from compiler/tests/inputs/main.in rename to compiler/tests/boolean/inputs/true_true.in index b40103724a..2ce5aff495 100644 --- a/compiler/tests/inputs/main.in +++ b/compiler/tests/boolean/inputs/true_true.in @@ -1,2 +1,3 @@ [main] +a: bool = true; b: bool = true; \ No newline at end of file diff --git a/compiler/tests/boolean/mod.rs b/compiler/tests/boolean/mod.rs index fc849e6008..0eec88e967 100644 --- a/compiler/tests/boolean/mod.rs +++ b/compiler/tests/boolean/mod.rs @@ -1,37 +1,30 @@ -use crate::{get_error, get_output, parse_program, EdwardsConstrainedValue, EdwardsTestCompiler}; -use leo_compiler::{ - errors::{BooleanError, CompilerError, ExpressionError, FunctionError, StatementError}, - ConstrainedValue, +use crate::{ + assert_satisfied, + expect_compiler_error, + expect_synthesis_error, + get_outputs, + parse_program, + parse_program_with_inputs, + EdwardsTestCompiler, }; -use leo_types::InputValue; - -use snarkos_models::gadgets::utilities::boolean::Boolean; - -pub fn output_expected_boolean(program: EdwardsTestCompiler, boolean: bool) { - let output = get_output(program); - assert_eq!( - EdwardsConstrainedValue::Return(vec![ConstrainedValue::Boolean(Boolean::Constant(boolean))]).to_string(), - output.to_string() - ); -} +use leo_compiler::errors::{BooleanError, CompilerError, ExpressionError, FunctionError, StatementError}; pub fn output_true(program: EdwardsTestCompiler) { - output_expected_boolean(program, true) + let expected = include_bytes!("outputs_/registers_true.out"); + let actual = get_outputs(program); + + assert_eq!(expected, actual.bytes().as_slice()); } pub fn output_false(program: EdwardsTestCompiler) { - output_expected_boolean(program, false) -} + let expected = include_bytes!("outputs_/registers_false.out"); + let actual = get_outputs(program); -fn fail_boolean(program: EdwardsTestCompiler) { - match get_error(program) { - CompilerError::FunctionError(FunctionError::BooleanError(BooleanError::Error(_))) => {} - error => panic!("Expected boolean error, got {}", error), - } + assert_eq!(expected, actual.bytes().as_slice()); } fn fail_boolean_statement(program: EdwardsTestCompiler) { - match get_error(program) { + match expect_compiler_error(program) { CompilerError::FunctionError(FunctionError::StatementError(StatementError::ExpressionError( ExpressionError::BooleanError(BooleanError::Error(_)), ))) => {} @@ -40,41 +33,42 @@ fn fail_boolean_statement(program: EdwardsTestCompiler) { } #[test] -fn test_true() { - let bytes = include_bytes!("true.leo"); - let program = parse_program(bytes).unwrap(); +fn test_input_pass() { + let program_bytes = include_bytes!("assert_eq_input.leo"); + let input_bytes = include_bytes!("inputs/true_true.in"); + + let program = parse_program_with_inputs(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_input_fail() { + let program_bytes = include_bytes!("assert_eq_input.leo"); + let input_bytes = include_bytes!("inputs/true_false.in"); + + let program = parse_program_with_inputs(program_bytes, input_bytes).unwrap(); + + expect_synthesis_error(program); +} + +#[test] +fn test_registers() { + let program_bytes = include_bytes!("output_register.leo"); + let true_input_bytes = include_bytes!("inputs/registers_true.in"); + let false_input_bytes = include_bytes!("inputs/registers_false.in"); + + // test true input register => true output register + let program = parse_program_with_inputs(program_bytes, true_input_bytes).unwrap(); output_true(program); -} -#[test] -fn test_false() { - let bytes = include_bytes!("false.leo"); - let program = parse_program(bytes).unwrap(); + // test false input register => false output register + let program = parse_program_with_inputs(program_bytes, false_input_bytes).unwrap(); output_false(program); } -#[test] -fn test_input_bool_field() { - let bytes = include_bytes!("input_bool.leo"); - let mut program = parse_program(bytes).unwrap(); - - program.set_inputs(vec![Some(InputValue::Field("1field".to_string()))]); - - fail_boolean(program); -} - -#[test] -fn test_input_bool_none() { - let bytes = include_bytes!("input_bool.leo"); - let mut program = parse_program(bytes).unwrap(); - - program.set_inputs(vec![None]); - - fail_boolean(program); -} - // Boolean not ! #[test] @@ -82,7 +76,7 @@ fn test_not_true() { let bytes = include_bytes!("not_true.leo"); let program = parse_program(bytes).unwrap(); - output_false(program); + assert_satisfied(program); } #[test] @@ -90,7 +84,7 @@ fn test_not_false() { let bytes = include_bytes!("not_false.leo"); let program = parse_program(bytes).unwrap(); - output_true(program); + assert_satisfied(program); } #[test] @@ -98,7 +92,7 @@ fn test_not_u32() { let bytes = include_bytes!("not_u32.leo"); let program = parse_program(bytes).unwrap(); - fail_boolean_statement(program) + fail_boolean_statement(program); } // Boolean or || @@ -108,7 +102,7 @@ fn test_true_or_true() { let bytes = include_bytes!("true_or_true.leo"); let program = parse_program(bytes).unwrap(); - output_true(program); + assert_satisfied(program); } #[test] @@ -116,7 +110,7 @@ fn test_true_or_false() { let bytes = include_bytes!("true_or_false.leo"); let program = parse_program(bytes).unwrap(); - output_true(program); + assert_satisfied(program); } #[test] @@ -124,7 +118,7 @@ fn test_false_or_false() { let bytes = include_bytes!("false_or_false.leo"); let program = parse_program(bytes).unwrap(); - output_false(program); + assert_satisfied(program); } #[test] @@ -142,7 +136,7 @@ fn test_true_and_true() { let bytes = include_bytes!("true_and_true.leo"); let program = parse_program(bytes).unwrap(); - output_true(program); + assert_satisfied(program); } #[test] @@ -150,7 +144,7 @@ fn test_true_and_false() { let bytes = include_bytes!("true_and_false.leo"); let program = parse_program(bytes).unwrap(); - output_false(program); + assert_satisfied(program); } #[test] @@ -158,7 +152,7 @@ fn test_false_and_false() { let bytes = include_bytes!("false_and_false.leo"); let program = parse_program(bytes).unwrap(); - output_false(program); + assert_satisfied(program); } #[test] @@ -176,5 +170,5 @@ fn test_all() { let bytes = include_bytes!("all.leo"); let program = parse_program(bytes).unwrap(); - output_false(program); + assert_satisfied(program); } diff --git a/compiler/tests/boolean/not_false.leo b/compiler/tests/boolean/not_false.leo index 7a5a8f69a7..60b6e93c3c 100644 --- a/compiler/tests/boolean/not_false.leo +++ b/compiler/tests/boolean/not_false.leo @@ -1,3 +1,3 @@ -function main() -> bool { - return !false +function main() { + assert_eq!(!false, true); } \ No newline at end of file diff --git a/compiler/tests/boolean/not_true.leo b/compiler/tests/boolean/not_true.leo index 58d3799aed..e279de5b24 100644 --- a/compiler/tests/boolean/not_true.leo +++ b/compiler/tests/boolean/not_true.leo @@ -1,3 +1,3 @@ -function main() -> bool { - return !true +function main() { + assert_eq!(!true, false); } \ No newline at end of file diff --git a/compiler/tests/boolean/not_u32.leo b/compiler/tests/boolean/not_u32.leo index 04b52860ca..816642262b 100644 --- a/compiler/tests/boolean/not_u32.leo +++ b/compiler/tests/boolean/not_u32.leo @@ -1,3 +1,3 @@ function main() -> bool { - return !1u32 + assert_eq!(!1u32, 0u32); } \ No newline at end of file diff --git a/compiler/tests/boolean/output_register.leo b/compiler/tests/boolean/output_register.leo new file mode 100644 index 0000000000..ec46f3eb14 --- /dev/null +++ b/compiler/tests/boolean/output_register.leo @@ -0,0 +1,3 @@ +function main(registers) -> bool { + return registers.r +} \ No newline at end of file diff --git a/compiler/tests/boolean/outputs_/registers_false.out b/compiler/tests/boolean/outputs_/registers_false.out new file mode 100644 index 0000000000..8ddb2792bd --- /dev/null +++ b/compiler/tests/boolean/outputs_/registers_false.out @@ -0,0 +1,2 @@ +[registers] +r: bool = false; diff --git a/compiler/tests/boolean/outputs_/registers_true.out b/compiler/tests/boolean/outputs_/registers_true.out new file mode 100644 index 0000000000..ef0ca15b25 --- /dev/null +++ b/compiler/tests/boolean/outputs_/registers_true.out @@ -0,0 +1,2 @@ +[registers] +r: bool = true; diff --git a/compiler/tests/boolean/true.leo b/compiler/tests/boolean/true.leo deleted file mode 100644 index 837a259a92..0000000000 --- a/compiler/tests/boolean/true.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> bool { - return true -} \ No newline at end of file diff --git a/compiler/tests/boolean/true_and_false.leo b/compiler/tests/boolean/true_and_false.leo index 531abc407a..ee647a2e6a 100644 --- a/compiler/tests/boolean/true_and_false.leo +++ b/compiler/tests/boolean/true_and_false.leo @@ -1,3 +1,5 @@ -function main() -> bool { - return true && false +function main() { + let a = true && false; + + assert_eq!(a, false); } \ No newline at end of file diff --git a/compiler/tests/boolean/true_and_true.leo b/compiler/tests/boolean/true_and_true.leo index e030515842..db767f3c40 100644 --- a/compiler/tests/boolean/true_and_true.leo +++ b/compiler/tests/boolean/true_and_true.leo @@ -1,3 +1,5 @@ -function main() -> bool { - return true && true +function main() { + let a = true && true; + + assert_eq!(a, true); } \ No newline at end of file diff --git a/compiler/tests/boolean/true_and_u32.leo b/compiler/tests/boolean/true_and_u32.leo index d466f63a3e..e5b3a8c001 100644 --- a/compiler/tests/boolean/true_and_u32.leo +++ b/compiler/tests/boolean/true_and_u32.leo @@ -1,3 +1,3 @@ -function main() -> bool { - return true && 1u32 +function main() { + let a = true && 1u32; } \ No newline at end of file diff --git a/compiler/tests/boolean/true_or_false.leo b/compiler/tests/boolean/true_or_false.leo index cdb0ff3484..7499f9f183 100644 --- a/compiler/tests/boolean/true_or_false.leo +++ b/compiler/tests/boolean/true_or_false.leo @@ -1,3 +1,5 @@ -function main() -> bool { - return true || false +function main() { + let a = true || false; + + assert_eq!(a, true); } \ No newline at end of file diff --git a/compiler/tests/boolean/true_or_true.leo b/compiler/tests/boolean/true_or_true.leo index 0451e20b75..4452321e23 100644 --- a/compiler/tests/boolean/true_or_true.leo +++ b/compiler/tests/boolean/true_or_true.leo @@ -1,3 +1,5 @@ -function main() -> bool { - return true || true +function main() { + let a = true || true; + + assert_eq!(a, true); } \ No newline at end of file diff --git a/compiler/tests/boolean/true_or_u32.leo b/compiler/tests/boolean/true_or_u32.leo index bd12e19708..500b5f7bf4 100644 --- a/compiler/tests/boolean/true_or_u32.leo +++ b/compiler/tests/boolean/true_or_u32.leo @@ -1,3 +1,3 @@ -function main() -> bool { - return true || 1u32 +function main() { + let a = true || 1u32; } \ No newline at end of file diff --git a/compiler/tests/circuits/inline.leo b/compiler/tests/circuits/inline.leo index 0a9af217ff..8e214c729a 100644 --- a/compiler/tests/circuits/inline.leo +++ b/compiler/tests/circuits/inline.leo @@ -2,6 +2,6 @@ circuit Foo { x: u32 } -function main() -> Foo { - return Foo { x: 1u32 } +function main() { + let a = Foo { x: 1u32 }; } \ No newline at end of file diff --git a/compiler/tests/circuits/inline_fail.leo b/compiler/tests/circuits/inline_fail.leo index d5690cca95..52792a07e0 100644 --- a/compiler/tests/circuits/inline_fail.leo +++ b/compiler/tests/circuits/inline_fail.leo @@ -3,5 +3,5 @@ circuit Foo { } function main() { - let c = Foo { y: 0u32 }; + let a = Foo { y: 0u32 }; } \ No newline at end of file diff --git a/compiler/tests/circuits/inline_undefined.leo b/compiler/tests/circuits/inline_undefined.leo index 2167ed7160..af070e01e9 100644 --- a/compiler/tests/circuits/inline_undefined.leo +++ b/compiler/tests/circuits/inline_undefined.leo @@ -1,3 +1,3 @@ function main() { - let c = Foo { }; + let a = Foo { }; } \ No newline at end of file diff --git a/compiler/tests/circuits/member_field.leo b/compiler/tests/circuits/member_field.leo index 9cb2955ca3..60f0dea11c 100644 --- a/compiler/tests/circuits/member_field.leo +++ b/compiler/tests/circuits/member_field.leo @@ -2,8 +2,8 @@ circuit Foo { x: u32, } -function main() -> u32 { - let c = Foo { x: 1u32 }; +function main() { + let a = Foo { x: 1u32 }; - return c.x + assert_eq!(a.x, 1u32); } \ No newline at end of file diff --git a/compiler/tests/circuits/member_field_and_function.leo b/compiler/tests/circuits/member_field_and_function.leo index 207ae068e5..30988a2bba 100644 --- a/compiler/tests/circuits/member_field_and_function.leo +++ b/compiler/tests/circuits/member_field_and_function.leo @@ -2,11 +2,14 @@ circuit Foo { foo: u32, static function bar() -> u32 { - return 0 + return 1u32 } } -function main() -> u32 { - let f = Foo { foo: 1 }; - return f.foo + Foo::bar() +function main() { + let a = Foo { foo: 1 }; + + let b = a.foo + Foo::bar(); + + assert_eq!(b, 2u32); } diff --git a/compiler/tests/circuits/member_field_fail.leo b/compiler/tests/circuits/member_field_fail.leo index 643ac3dbff..5780704ea2 100644 --- a/compiler/tests/circuits/member_field_fail.leo +++ b/compiler/tests/circuits/member_field_fail.leo @@ -2,8 +2,8 @@ circuit Foo { x: u32 } -function main() -> u32 { - let c = Foo { x: 1u32 }; +function main() { + let a = Foo { x: 1u32 }; - return c.y + let err = a.y; } \ No newline at end of file diff --git a/compiler/tests/circuits/member_function.leo b/compiler/tests/circuits/member_function.leo index 4528b0e5e0..cd0a4956ed 100644 --- a/compiler/tests/circuits/member_function.leo +++ b/compiler/tests/circuits/member_function.leo @@ -4,7 +4,8 @@ circuit Foo { } } -function main() -> u32 { - let c = Foo { }; - return c.echo(1u32) +function main() { + let a = Foo { }; + + assert_eq!(a.echo(1u32), 1u32); } \ No newline at end of file diff --git a/compiler/tests/circuits/member_function_fail.leo b/compiler/tests/circuits/member_function_fail.leo index 7facc85cd5..224b79cbf4 100644 --- a/compiler/tests/circuits/member_function_fail.leo +++ b/compiler/tests/circuits/member_function_fail.leo @@ -4,7 +4,7 @@ circuit Foo { } } -function main() -> u32 { - let c = Foo { }; - return c.echoed(1u32) +function main() { + let a = Foo { }; + let err = a.echoed(1u32); } \ No newline at end of file diff --git a/compiler/tests/circuits/member_function_invalid.leo b/compiler/tests/circuits/member_function_invalid.leo index b882433dda..d0a7271a07 100644 --- a/compiler/tests/circuits/member_function_invalid.leo +++ b/compiler/tests/circuits/member_function_invalid.leo @@ -4,7 +4,7 @@ circuit Foo { } } -function main() -> u32 { - let c = Foo { }; - return c.echo(1u32) // echo is a static function and must be accessed using `::` +function main() { + let a = Foo { }; + let err = a.echo(1u32); // echo is a static function and must be accessed using `::` } \ No newline at end of file diff --git a/compiler/tests/circuits/member_function_nested.leo b/compiler/tests/circuits/member_function_nested.leo index d16b05a9b6..4531b20dca 100644 --- a/compiler/tests/circuits/member_function_nested.leo +++ b/compiler/tests/circuits/member_function_nested.leo @@ -10,8 +10,9 @@ circuit Foo { } } -function main() -> u32 { - let f = Foo { x: 1u32 }; +function main() { + let a = Foo { x: 1u32 }; + let b = a.call_add_x(1u32); - return f.call_add_x(1u32) + assert_eq!(b, 2u32); } diff --git a/compiler/tests/circuits/member_static_function.leo b/compiler/tests/circuits/member_static_function.leo index 34814d15bd..8d08229af9 100644 --- a/compiler/tests/circuits/member_static_function.leo +++ b/compiler/tests/circuits/member_static_function.leo @@ -4,6 +4,8 @@ circuit Foo { } } -function main() -> u32 { - return Foo::echo(1u32) +function main() { + let a = Foo::echo(1u32); + + assert_eq!(a, 1u32); } \ No newline at end of file diff --git a/compiler/tests/circuits/member_static_function_invalid.leo b/compiler/tests/circuits/member_static_function_invalid.leo index 54a1879d1a..b2782bfed4 100644 --- a/compiler/tests/circuits/member_static_function_invalid.leo +++ b/compiler/tests/circuits/member_static_function_invalid.leo @@ -4,6 +4,6 @@ circuit Foo { } } -function main() -> u32 { - return Foo::echo(1u32) // echo is a non-static function and must be accessed using `.` +function main() { + let err = Foo::echo(1u32); // echo is a non-static function and must be accessed using `.` } \ No newline at end of file diff --git a/compiler/tests/circuits/member_static_function_undefined.leo b/compiler/tests/circuits/member_static_function_undefined.leo index 8ded0d7619..e8e5cb20bc 100644 --- a/compiler/tests/circuits/member_static_function_undefined.leo +++ b/compiler/tests/circuits/member_static_function_undefined.leo @@ -4,6 +4,6 @@ circuit Foo { } } -function main() -> u32 { - return Foo::echoed(1u32) +function main() { + let err = Foo::echoed(1u32); } \ No newline at end of file diff --git a/compiler/tests/circuits/mod.rs b/compiler/tests/circuits/mod.rs index 46784d01e4..606e127ba6 100644 --- a/compiler/tests/circuits/mod.rs +++ b/compiler/tests/circuits/mod.rs @@ -1,55 +1,8 @@ -use crate::{ - get_error, - get_output, - integers::u32::{output_number, output_one}, - parse_program, - EdwardsConstrainedValue, - EdwardsTestCompiler, -}; -use leo_compiler::{ - errors::{CompilerError, ExpressionError, FunctionError, StatementError}, - ConstrainedCircuitMember, - ConstrainedValue, - Integer, -}; -use leo_types::{Expression, Function, Identifier, Span, Statement, Type}; - -use snarkos_models::gadgets::utilities::uint::UInt32; - -// Foo { x: 1u32 } -fn output_circuit(program: EdwardsTestCompiler) { - let output = get_output(program); - assert_eq!( - EdwardsConstrainedValue::Return(vec![ConstrainedValue::CircuitExpression( - Identifier { - name: "Foo".to_string(), - span: Span { - text: "".to_string(), - line: 0, - start: 0, - end: 0 - } - }, - vec![ConstrainedCircuitMember( - Identifier { - name: "x".to_string(), - span: Span { - text: "".to_string(), - line: 0, - start: 0, - end: 0 - } - }, - ConstrainedValue::Integer(Integer::U32(UInt32::constant(1u32))) - )] - )]) - .to_string(), - output.to_string() - ); -} +use crate::{assert_satisfied, expect_compiler_error, parse_program, EdwardsTestCompiler}; +use leo_compiler::errors::{CompilerError, ExpressionError, FunctionError, StatementError}; fn expect_fail(program: EdwardsTestCompiler) { - match get_error(program) { + match expect_compiler_error(program) { CompilerError::FunctionError(FunctionError::StatementError(StatementError::ExpressionError( ExpressionError::Error(_string), ))) => {} @@ -64,7 +17,7 @@ fn test_inline() { let bytes = include_bytes!("inline.leo"); let program = parse_program(bytes).unwrap(); - output_circuit(program); + assert_satisfied(program); } #[test] @@ -72,7 +25,7 @@ fn test_inline_fail() { let bytes = include_bytes!("inline_fail.leo"); let program = parse_program(bytes).unwrap(); - expect_fail(program) + expect_fail(program); } #[test] @@ -80,12 +33,7 @@ fn test_inline_undefined() { let bytes = include_bytes!("inline_undefined.leo"); let program = parse_program(bytes).unwrap(); - match get_error(program) { - CompilerError::FunctionError(FunctionError::StatementError(StatementError::ExpressionError( - ExpressionError::Error(_), - ))) => {} - error => panic!("Expected undefined circuit error, got {}", error), - } + expect_fail(program); } // Members @@ -95,7 +43,7 @@ fn test_member_field() { let bytes = include_bytes!("member_field.leo"); let program = parse_program(bytes).unwrap(); - output_one(program); + assert_satisfied(program); } #[test] @@ -111,7 +59,7 @@ fn test_member_field_and_function() { let bytes = include_bytes!("member_field_and_function.leo"); let program = parse_program(bytes).unwrap(); - output_one(program); + assert_satisfied(program); } #[test] @@ -119,7 +67,7 @@ fn test_member_function() { let bytes = include_bytes!("member_function.leo"); let program = parse_program(bytes).unwrap(); - output_one(program); + assert_satisfied(program); } #[test] @@ -143,7 +91,7 @@ fn test_member_function_nested() { let bytes = include_bytes!("member_function_nested.leo"); let program = parse_program(bytes).unwrap(); - output_number(program, 2u32); + assert_satisfied(program); } #[test] @@ -151,15 +99,7 @@ fn test_member_static_function() { let bytes = include_bytes!("member_static_function.leo"); let program = parse_program(bytes).unwrap(); - output_one(program); -} - -#[test] -fn test_member_static_function_undefined() { - let bytes = include_bytes!("member_static_function_undefined.leo"); - let program = parse_program(bytes).unwrap(); - - expect_fail(program) + assert_satisfied(program); } #[test] @@ -170,135 +110,45 @@ fn test_member_static_function_invalid() { expect_fail(program) } +#[test] +fn test_member_static_function_undefined() { + let bytes = include_bytes!("member_static_function_undefined.leo"); + let program = parse_program(bytes).unwrap(); + + expect_fail(program) +} + // Self #[test] -fn test_self_member() { +fn test_self_member_pass() { let bytes = include_bytes!("self_member.leo"); let program = parse_program(bytes).unwrap(); - output_one(program); + assert_satisfied(program); } #[test] -fn test_self_no_member_fail() { - let bytes = include_bytes!("self_no_member_fail.leo"); +fn test_self_member_invalid() { + let bytes = include_bytes!("self_member_invalid.leo"); let program = parse_program(bytes).unwrap(); - let _err = get_error(program); + let _err = expect_compiler_error(program); } #[test] -fn test_self_member_fail() { - let bytes = include_bytes!("self_member_fail.leo"); +fn test_self_member_undefined() { + let bytes = include_bytes!("self_member_undefined.leo"); let program = parse_program(bytes).unwrap(); - let _err = get_error(program); -} - -#[test] -fn test_self_circuit() { - let bytes = include_bytes!("self_circuit.leo"); - let program = parse_program(bytes).unwrap(); - - let output = get_output(program); - - // circuit Foo { - // static function new() -> Self { - // return Self { } - // } - // } - assert_eq!( - EdwardsConstrainedValue::Return(vec![ConstrainedValue::CircuitExpression( - Identifier { - name: "Foo".to_string(), - span: Span { - text: "".to_string(), - line: 0, - start: 0, - end: 0 - } - }, - vec![ConstrainedCircuitMember( - Identifier { - name: "new".to_string(), - span: Span { - text: "".to_string(), - line: 0, - start: 0, - end: 0 - } - }, - ConstrainedValue::Static(Box::new(ConstrainedValue::Function( - Some(Identifier { - name: "new".to_string(), - span: Span { - text: "".to_string(), - line: 0, - start: 0, - end: 0 - } - }), - Function { - function_name: Identifier { - name: "new".to_string(), - span: Span { - text: "".to_string(), - line: 0, - start: 0, - end: 0 - } - }, - inputs: vec![], - returns: vec![Type::SelfType], - statements: vec![Statement::Return( - vec![Expression::Circuit( - Identifier { - name: "Self".to_string(), - span: Span { - text: "".to_string(), - line: 0, - start: 0, - end: 0 - } - }, - vec![], - Span { - text: "".to_string(), - line: 0, - start: 0, - end: 0 - } - )], - Span { - text: "".to_string(), - line: 0, - start: 0, - end: 0 - } - )], - span: Span { - text: "".to_string(), - line: 0, - start: 0, - end: 0 - } - } - ))) - )] - )]) - .to_string(), - output.to_string() - ); + let _err = expect_compiler_error(program); } // All #[test] fn test_pedersen_mock() { - use crate::integers::u32::output_zero; - let bytes = include_bytes!("pedersen_mock.leo"); let program = parse_program(bytes).unwrap(); - output_zero(program); + assert_satisfied(program); } diff --git a/compiler/tests/circuits/pedersen_mock.leo b/compiler/tests/circuits/pedersen_mock.leo index f7928c94f0..a5ded96f60 100644 --- a/compiler/tests/circuits/pedersen_mock.leo +++ b/compiler/tests/circuits/pedersen_mock.leo @@ -16,9 +16,10 @@ circuit PedersenHash { } // The 'pedersen_hash' main function. -function main() -> u32 { +function main() { let parameters = [0u32; 512]; let pedersen = PedersenHash::new(parameters); let input: bool[512] = [true; 512]; - return pedersen.hash(input) + + assert_eq!(pedersen.hash(input), 0u32); } diff --git a/compiler/tests/circuits/self_circuit.leo b/compiler/tests/circuits/self_circuit.leo index 12713ed214..5a1d6c63be 100644 --- a/compiler/tests/circuits/self_circuit.leo +++ b/compiler/tests/circuits/self_circuit.leo @@ -4,6 +4,6 @@ circuit Foo { } } -function main() -> Foo { - return Foo::new() +function main() { + let a = Foo::new(); } \ No newline at end of file diff --git a/compiler/tests/circuits/self_member.leo b/compiler/tests/circuits/self_member.leo index 9e5701385e..d543267ce3 100644 --- a/compiler/tests/circuits/self_member.leo +++ b/compiler/tests/circuits/self_member.leo @@ -6,7 +6,9 @@ circuit Foo { } } -function main() -> u32 { - let foo = Foo { f: 1u32 }; - return foo.bar() +function main() { + let a = Foo { f: 1u32 }; + let b = a.bar(); + + assert_eq!(b, 1u32); } \ No newline at end of file diff --git a/compiler/tests/circuits/self_member_fail.leo b/compiler/tests/circuits/self_member_invalid.leo similarity index 84% rename from compiler/tests/circuits/self_member_fail.leo rename to compiler/tests/circuits/self_member_invalid.leo index 78f8811b5f..2e8b14f66c 100644 --- a/compiler/tests/circuits/self_member_fail.leo +++ b/compiler/tests/circuits/self_member_invalid.leo @@ -8,5 +8,5 @@ circuit Foo { function main() -> u32 { let foo = Foo { f: 1u32 }; - return foo.bar() + let err = foo.bar(); } \ No newline at end of file diff --git a/compiler/tests/circuits/self_no_member_fail.leo b/compiler/tests/circuits/self_member_undefined.leo similarity index 67% rename from compiler/tests/circuits/self_no_member_fail.leo rename to compiler/tests/circuits/self_member_undefined.leo index 6bafa9ae9d..471ffb973c 100644 --- a/compiler/tests/circuits/self_no_member_fail.leo +++ b/compiler/tests/circuits/self_member_undefined.leo @@ -4,7 +4,7 @@ circuit Foo { } } -function main() -> u32 { +function main() { let foo = Foo { }; - return foo.bar() + let err = foo.bar(); } \ No newline at end of file diff --git a/compiler/tests/compiler_outputs/empty.out b/compiler/tests/compiler_outputs/empty.out new file mode 100644 index 0000000000..3042270327 --- /dev/null +++ b/compiler/tests/compiler_outputs/empty.out @@ -0,0 +1 @@ +[registers] diff --git a/compiler/tests/field/add.leo b/compiler/tests/field/add.leo index 90a5d093b1..df9cdec45a 100644 --- a/compiler/tests/field/add.leo +++ b/compiler/tests/field/add.leo @@ -1,3 +1,3 @@ -function main(a: field, b: field) -> field { - return a + b +function main(a: field, b: field, c: field) { + assert_eq!(a + b, c); } \ No newline at end of file diff --git a/compiler/tests/field/div.leo b/compiler/tests/field/div.leo index f4b3378ebb..6bb4fd4bc5 100644 --- a/compiler/tests/field/div.leo +++ b/compiler/tests/field/div.leo @@ -1,3 +1,3 @@ -function main(a: field, b: field) -> field { - return a / b +function main(a: field, b: field, c: field) { + assert_eq!(a / b, c); } \ No newline at end of file diff --git a/compiler/tests/field/eq.leo b/compiler/tests/field/eq.leo index 0739f2baab..52699c0383 100644 --- a/compiler/tests/field/eq.leo +++ b/compiler/tests/field/eq.leo @@ -1,3 +1,3 @@ -function main(a: field, b: field) -> bool { - return a == b +function main(a: field, b: field, c: bool) { + assert_eq!(a == b, c); } \ No newline at end of file diff --git a/compiler/tests/field/input.leo b/compiler/tests/field/input.leo deleted file mode 100644 index 1b49fb06e3..0000000000 --- a/compiler/tests/field/input.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main(f: field) -> field{ - return f -} \ No newline at end of file diff --git a/compiler/tests/field/inputs/register_one.in b/compiler/tests/field/inputs/register_one.in new file mode 100644 index 0000000000..50ca7c02dd --- /dev/null +++ b/compiler/tests/field/inputs/register_one.in @@ -0,0 +1,2 @@ +[registers] +r: field = 1; \ No newline at end of file diff --git a/compiler/tests/field/inputs/register_zero.in b/compiler/tests/field/inputs/register_zero.in new file mode 100644 index 0000000000..15d3fe0c68 --- /dev/null +++ b/compiler/tests/field/inputs/register_zero.in @@ -0,0 +1,2 @@ +[registers] +r: field = 0; \ No newline at end of file diff --git a/compiler/tests/field/mod.rs b/compiler/tests/field/mod.rs index 456badc56b..f179ef5048 100644 --- a/compiler/tests/field/mod.rs +++ b/compiler/tests/field/mod.rs @@ -1,112 +1,26 @@ -use crate::{ - boolean::{output_expected_boolean, output_true}, - get_error, - get_output, - parse_program, - EdwardsConstrainedValue, - EdwardsTestCompiler, -}; -use leo_compiler::{ - errors::{CompilerError, FieldError, FunctionError}, - ConstrainedValue, - FieldType, -}; +use crate::{assert_satisfied, expect_synthesis_error, generate_main_inputs, parse_program}; use leo_types::InputValue; +use snarkos_curves::edwards_bls12::Fq; +use snarkos_utilities::bytes::ToBytes; + use num_bigint::BigUint; use rand::{Rng, SeedableRng}; use rand_xorshift::XorShiftRng; -use snarkos_curves::edwards_bls12::Fq; -use snarkos_gadgets::curves::edwards_bls12::FqGadget; -use snarkos_models::{ - curves::{One, PrimeField, Zero}, - gadgets::{ - curves::field::FieldGadget, - r1cs::{ConstraintSystem, TestConstraintSystem}, - }, -}; -use snarkos_utilities::{biginteger::BigInteger256, bytes::ToBytes}; -fn output_expected_constant(program: EdwardsTestCompiler, expected: Fq) { - let output = get_output(program); - assert_eq!( - EdwardsConstrainedValue::Return(vec![ConstrainedValue::Field(FieldType::Constant(expected))]).to_string(), - output.to_string() - ); -} +// Helper function to convert field element into decimal base 10 string +pub fn field_to_decimal_string(f: Fq) -> String { + // write field to buffer -fn output_expected_allocated(program: EdwardsTestCompiler, expected: FqGadget) { - let output = get_output(program); + let mut buf = Vec::new(); - match output { - EdwardsConstrainedValue::Return(vec) => match vec.as_slice() { - [ConstrainedValue::Field(FieldType::Allocated(fp_gadget))] => assert_eq!(*fp_gadget, expected as FqGadget), - _ => panic!("program output unknown return value"), - }, - _ => panic!("program output unknown return value"), - } -} + f.write(&mut buf).unwrap(); -fn output_zero(program: EdwardsTestCompiler) { - output_expected_constant(program, Fq::zero()) -} + // convert to big integer -fn output_one(program: EdwardsTestCompiler) { - output_expected_constant(program, Fq::one()) -} + let f_bigint = BigUint::from_bytes_le(&buf); -fn fail_field(program: EdwardsTestCompiler) { - match get_error(program) { - CompilerError::FunctionError(FunctionError::FieldError(FieldError::Error(_string))) => {} - error => panic!("Expected invalid field error, got {}", error), - } -} - -#[test] -fn test_zero() { - let bytes = include_bytes!("zero.leo"); - let program = parse_program(bytes).unwrap(); - - output_zero(program); -} - -#[test] -fn test_one() { - let bytes = include_bytes!("one.leo"); - let program = parse_program(bytes).unwrap(); - - output_one(program); -} - -#[test] -fn test_input_pass() { - let bytes = include_bytes!("input.leo"); - let mut program = parse_program(bytes).unwrap(); - - program.set_inputs(vec![Some(InputValue::Field("1".into()))]); - - let cs = TestConstraintSystem::::new(); - let expected = FqGadget::one(cs).unwrap(); - - output_expected_allocated(program, expected) -} - -#[test] -fn test_input_fail_bool() { - let bytes = include_bytes!("input.leo"); - let mut program = parse_program(bytes).unwrap(); - - program.set_inputs(vec![Some(InputValue::Boolean(true))]); - fail_field(program); -} - -#[test] -fn test_input_fail_none() { - let bytes = include_bytes!("input.leo"); - let mut program = parse_program(bytes).unwrap(); - - program.set_inputs(vec![None]); - fail_field(program); + f_bigint.to_str_radix(10) } #[test] @@ -116,32 +30,26 @@ fn test_add() { let mut rng = XorShiftRng::seed_from_u64(1231275789u64); for _ in 0..10 { - let r1: Fq = rng.gen(); - let r2: Fq = rng.gen(); + let a: Fq = rng.gen(); + let b: Fq = rng.gen(); + let c = a.add(&b); - let mut r1_buf = Vec::new(); - let mut r2_buf = Vec::new(); - - r1.write(&mut r1_buf).unwrap(); - r2.write(&mut r2_buf).unwrap(); - - let r1_bigint = BigUint::from_bytes_le(&r1_buf); - let r2_bigint = BigUint::from_bytes_le(&r2_buf); - - let sum = r1.add(&r2); - - let cs = TestConstraintSystem::::new(); - let sum_allocated = FqGadget::from(cs, &sum); + let a_string = field_to_decimal_string(a); + let b_string = field_to_decimal_string(b); + let c_string = field_to_decimal_string(c); let bytes = include_bytes!("add.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Field(r1_bigint.to_str_radix(10))), - Some(InputValue::Field(r2_bigint.to_str_radix(10))), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Field(a_string))), + ("b", Some(InputValue::Field(b_string))), + ("c", Some(InputValue::Field(c_string))), ]); - output_expected_allocated(program, sum_allocated); + program.set_main_inputs(main_inputs); + + assert_satisfied(program) } } @@ -152,68 +60,25 @@ fn test_sub() { let mut rng = XorShiftRng::seed_from_u64(1231275789u64); for _ in 0..10 { - let r1: Fq = rng.gen(); - let r2: Fq = rng.gen(); + let a: Fq = rng.gen(); + let b: Fq = rng.gen(); + let c = a.sub(&b); - let mut r1_buf = Vec::new(); - let mut r2_buf = Vec::new(); - - r1.write(&mut r1_buf).unwrap(); - r2.write(&mut r2_buf).unwrap(); - - let r1_bigint = BigUint::from_bytes_le(&r1_buf); - let r2_bigint = BigUint::from_bytes_le(&r2_buf); - - let difference = r1.sub(&r2); - - let cs = TestConstraintSystem::::new(); - let difference_allocated = FqGadget::from(cs, &difference); + let a_string = field_to_decimal_string(a); + let b_string = field_to_decimal_string(b); + let c_string = field_to_decimal_string(c); let bytes = include_bytes!("sub.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Field(r1_bigint.to_str_radix(10))), - Some(InputValue::Field(r2_bigint.to_str_radix(10))), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Field(a_string))), + ("b", Some(InputValue::Field(b_string))), + ("c", Some(InputValue::Field(c_string))), ]); + program.set_main_inputs(main_inputs); - output_expected_allocated(program, difference_allocated); - } -} - -#[test] -fn test_mul() { - use std::ops::Mul; - - let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - - for _ in 0..10 { - let r1: Fq = rng.gen(); - let r2: Fq = rng.gen(); - - let mut r1_buf = Vec::new(); - let mut r2_buf = Vec::new(); - - r1.write(&mut r1_buf).unwrap(); - r2.write(&mut r2_buf).unwrap(); - - let r1_bigint = BigUint::from_bytes_le(&r1_buf); - let r2_bigint = BigUint::from_bytes_le(&r2_buf); - - let product = r1.mul(&r2); - - let cs = TestConstraintSystem::::new(); - let product_allocated = FqGadget::from(cs, &product); - - let bytes = include_bytes!("mul.leo"); - let mut program = parse_program(bytes).unwrap(); - - program.set_inputs(vec![ - Some(InputValue::Field(r1_bigint.to_str_radix(10))), - Some(InputValue::Field(r2_bigint.to_str_radix(10))), - ]); - - output_expected_allocated(program, product_allocated); + assert_satisfied(program) } } @@ -224,32 +89,55 @@ fn test_div() { let mut rng = XorShiftRng::seed_from_u64(1231275789u64); for _ in 0..10 { - let r1: Fq = rng.gen(); - let r2: Fq = rng.gen(); + let a: Fq = rng.gen(); + let b: Fq = rng.gen(); + let c = a.div(&b); - let mut r1_buf = Vec::new(); - let mut r2_buf = Vec::new(); - - r1.write(&mut r1_buf).unwrap(); - r2.write(&mut r2_buf).unwrap(); - - let r1_bigint = BigUint::from_bytes_le(&r1_buf); - let r2_bigint = BigUint::from_bytes_le(&r2_buf); - - let quotient = r1.div(&r2); - - let cs = TestConstraintSystem::::new(); - let quotient_allocated = FqGadget::from(cs, "ient); + let a_string = field_to_decimal_string(a); + let b_string = field_to_decimal_string(b); + let c_string = field_to_decimal_string(c); let bytes = include_bytes!("div.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Field(r1_bigint.to_str_radix(10))), - Some(InputValue::Field(r2_bigint.to_str_radix(10))), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Field(a_string))), + ("b", Some(InputValue::Field(b_string))), + ("c", Some(InputValue::Field(c_string))), + ]); + program.set_main_inputs(main_inputs); + + assert_satisfied(program) + } +} + +#[test] +fn test_mul() { + use std::ops::Mul; + + let mut rng = XorShiftRng::seed_from_u64(1231275789u64); + + for _ in 0..10 { + let a: Fq = rng.gen(); + let b: Fq = rng.gen(); + let c = a.mul(&b); + + let a_string = field_to_decimal_string(a); + let b_string = field_to_decimal_string(b); + let c_string = field_to_decimal_string(c); + + let bytes = include_bytes!("mul.leo"); + let mut program = parse_program(bytes).unwrap(); + + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Field(a_string))), + ("b", Some(InputValue::Field(b_string))), + ("c", Some(InputValue::Field(c_string))), ]); - output_expected_allocated(program, quotient_allocated); + program.set_main_inputs(main_inputs); + + assert_satisfied(program) } } @@ -258,42 +146,42 @@ fn test_eq() { let mut rng = XorShiftRng::seed_from_u64(1231275789u64); for _ in 0..10 { - let r1: Fq = rng.gen(); - let r2: Fq = rng.gen(); + let a: Fq = rng.gen(); + let b: Fq = rng.gen(); - let mut r1_buf = Vec::new(); - let mut r2_buf = Vec::new(); - - r1.write(&mut r1_buf).unwrap(); - r2.write(&mut r2_buf).unwrap(); - - let r1_bigint = BigUint::from_bytes_le(&r1_buf); - let r2_bigint = BigUint::from_bytes_le(&r2_buf); + let a_string = field_to_decimal_string(a); + let b_string = field_to_decimal_string(b); // test equal let bytes = include_bytes!("eq.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Field(r1_bigint.to_str_radix(10))), - Some(InputValue::Field(r1_bigint.to_str_radix(10))), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Field(a_string.clone()))), + ("b", Some(InputValue::Field(a_string.clone()))), + ("c", Some(InputValue::Boolean(true))), ]); - output_true(program); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); // test not equal - let result = r1.eq(&r2); + let c = a.eq(&b); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Field(r1_bigint.to_str_radix(10))), - Some(InputValue::Field(r2_bigint.to_str_radix(10))), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Field(a_string))), + ("b", Some(InputValue::Field(b_string))), + ("c", Some(InputValue::Boolean(c))), ]); - output_expected_boolean(program, result) + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } @@ -302,20 +190,21 @@ fn test_assert_eq_pass() { let mut rng = XorShiftRng::seed_from_u64(1231275789u64); for _ in 0..10 { - let r1: Fq = rng.gen(); - let mut r1_buf = Vec::new(); - r1.write(&mut r1_buf).unwrap(); - let r1_bigint = BigUint::from_bytes_le(&r1_buf); + let a: Fq = rng.gen(); + + let a_string = field_to_decimal_string(a); let bytes = include_bytes!("assert_eq.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Field(r1_bigint.to_str_radix(10))), - Some(InputValue::Field(r1_bigint.to_str_radix(10))), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Field(a_string.clone()))), + ("b", Some(InputValue::Field(a_string))), ]); - let _ = get_output(program); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } @@ -324,68 +213,98 @@ fn test_assert_eq_fail() { let mut rng = XorShiftRng::seed_from_u64(1231275789u64); for _ in 0..10 { - let r1: Fq = rng.gen(); - let r2: Fq = rng.gen(); + let a: Fq = rng.gen(); + let b: Fq = rng.gen(); - let mut r1_buf = Vec::new(); - let mut r2_buf = Vec::new(); - r1.write(&mut r1_buf).unwrap(); - r2.write(&mut r2_buf).unwrap(); - let r1_bigint = BigUint::from_bytes_le(&r1_buf); - let r2_bigint = BigUint::from_bytes_le(&r2_buf); - - if r1 == r2 { + if a == b { continue; } + let a_string = field_to_decimal_string(a); + let b_string = field_to_decimal_string(b); + let bytes = include_bytes!("assert_eq.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Field(r1_bigint.to_str_radix(10))), - Some(InputValue::Field(r2_bigint.to_str_radix(10))), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Field(a_string))), + ("b", Some(InputValue::Field(b_string))), ]); - let mut cs = TestConstraintSystem::::new(); - let _ = program.compile_constraints(&mut cs).unwrap(); - assert!(!cs.is_satisfied()); + program.set_main_inputs(main_inputs); + + expect_synthesis_error(program); } } #[test] fn test_ternary() { - let r1: u64 = rand::random(); - let r2: u64 = rand::random(); + let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - let b1 = BigInteger256::from(r1); - let b2 = BigInteger256::from(r2); + let a: Fq = rng.gen(); + let b: Fq = rng.gen(); - let f1: Fq = Fq::from_repr(b1).unwrap(); - let f2: Fq = Fq::from_repr(b2).unwrap(); - - let mut cs = TestConstraintSystem::::new(); - let g1 = FqGadget::from(cs.ns(|| "g1"), &f1); - let g2 = FqGadget::from(cs.ns(|| "g2"), &f2); + let a_string = field_to_decimal_string(a); + let b_string = field_to_decimal_string(b); let bytes = include_bytes!("ternary.leo"); - let mut program_1 = parse_program(bytes).unwrap(); - let mut program_2 = program_1.clone(); + let mut program = parse_program(bytes).unwrap(); - // true -> field 1 - program_1.set_inputs(vec![ - Some(InputValue::Boolean(true)), - Some(InputValue::Field(r1.to_string())), - Some(InputValue::Field(r2.to_string())), + // true -> field a + let main_inputs = generate_main_inputs(vec![ + ("s", Some(InputValue::Boolean(true))), + ("a", Some(InputValue::Field(a_string.clone()))), + ("b", Some(InputValue::Field(b_string.clone()))), + ("c", Some(InputValue::Field(a_string.clone()))), ]); - output_expected_allocated(program_1, g1); + program.set_main_inputs(main_inputs); - // false -> field 2 - program_2.set_inputs(vec![ - Some(InputValue::Boolean(false)), - Some(InputValue::Field(r1.to_string())), - Some(InputValue::Field(r2.to_string())), + assert_satisfied(program); + + let mut program = parse_program(bytes).unwrap(); + + // false -> field b + let main_inputs = generate_main_inputs(vec![ + ("s", Some(InputValue::Boolean(false))), + ("a", Some(InputValue::Field(a_string))), + ("b", Some(InputValue::Field(b_string.clone()))), + ("c", Some(InputValue::Field(b_string))), ]); - output_expected_allocated(program_2, g2); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } + +// +// pub fn output_one(program: EdwardsTestCompiler) { +// let expected = include_bytes!("outputs_/register_one.out"); +// let actual = get_outputs(program); +// +// assert_eq!(expected, actual.bytes().as_slice()); +// } +// +// pub fn output_zero(program: EdwardsTestCompiler) { +// let expected = include_bytes!("outputs_/register_zero.out"); +// let actual = get_outputs(program); +// +// assert_eq!(expected, actual.bytes().as_slice()); +// } +// +// #[test] +// fn test_registers() { +// let program_bytes = include_bytes!("output_register.leo"); +// let one_input_bytes = include_bytes!("inputs/register_one.in"); +// let zero_input_bytes = include_bytes!("inputs/register_zero.in"); +// +// // test 1field input register => 1field output register +// let program = parse_program_with_inputs(program_bytes, one_input_bytes).unwrap(); +// +// output_one(program); +// +// // test 0field input register => 0field output register +// let program = parse_program_with_inputs(program_bytes, zero_input_bytes).unwrap(); +// +// output_zero(program); +// } diff --git a/compiler/tests/field/mul.leo b/compiler/tests/field/mul.leo index 5a383183e8..c96104aa23 100644 --- a/compiler/tests/field/mul.leo +++ b/compiler/tests/field/mul.leo @@ -1,3 +1,3 @@ -function main(a: field, b: field) -> field { - return a * b +function main(a: field, b: field, c: field) { + assert_eq!(a * b, c); } \ No newline at end of file diff --git a/compiler/tests/field/one.leo b/compiler/tests/field/one.leo deleted file mode 100644 index d97c60e14f..0000000000 --- a/compiler/tests/field/one.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> field { - return 1field -} \ No newline at end of file diff --git a/compiler/tests/field/output_register.leo b/compiler/tests/field/output_register.leo new file mode 100644 index 0000000000..258a6f2c74 --- /dev/null +++ b/compiler/tests/field/output_register.leo @@ -0,0 +1,3 @@ +function main(registers) -> field { + return registers.r +} \ No newline at end of file diff --git a/compiler/tests/field/outputs_/register_one.out b/compiler/tests/field/outputs_/register_one.out new file mode 100644 index 0000000000..16556c1c51 --- /dev/null +++ b/compiler/tests/field/outputs_/register_one.out @@ -0,0 +1,2 @@ +[registers] +r: field = 1; diff --git a/compiler/tests/field/outputs_/register_zero.out b/compiler/tests/field/outputs_/register_zero.out new file mode 100644 index 0000000000..2ba759ffc8 --- /dev/null +++ b/compiler/tests/field/outputs_/register_zero.out @@ -0,0 +1,2 @@ +[registers] +r: field = 0; diff --git a/compiler/tests/field/sub.leo b/compiler/tests/field/sub.leo index c304200040..2dbca87c07 100644 --- a/compiler/tests/field/sub.leo +++ b/compiler/tests/field/sub.leo @@ -1,3 +1,3 @@ -function main(a: field, b: field) -> field { - return a - b +function main(a: field, b: field, c: field) { + assert_eq!(a - b, c); } \ No newline at end of file diff --git a/compiler/tests/field/ternary.leo b/compiler/tests/field/ternary.leo index 108ec6cdb1..aeb196400e 100644 --- a/compiler/tests/field/ternary.leo +++ b/compiler/tests/field/ternary.leo @@ -1,3 +1,5 @@ -function main(b: bool, f1: field, f2: field) -> field { - return if b ? f1 : f2 +function main(s: bool, a: field, b: field, c: field) { + let r = if s ? a : b; + + assert_eq!(r, c); } \ No newline at end of file diff --git a/compiler/tests/field/zero.leo b/compiler/tests/field/zero.leo deleted file mode 100644 index 9a12e8aac0..0000000000 --- a/compiler/tests/field/zero.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> field { - return 0field -} \ No newline at end of file diff --git a/compiler/tests/function/inputs/registers.in b/compiler/tests/function/inputs/registers.in new file mode 100644 index 0000000000..306191c516 --- /dev/null +++ b/compiler/tests/function/inputs/registers.in @@ -0,0 +1,3 @@ +[registers] +a: bool = true; +b: bool = false; diff --git a/compiler/tests/function/iteration.leo b/compiler/tests/function/iteration.leo index 7a0229049f..931ce78180 100644 --- a/compiler/tests/function/iteration.leo +++ b/compiler/tests/function/iteration.leo @@ -2,12 +2,12 @@ function one() -> u32 { return 1u32 } -function main() -> u32 { +function main() { let mut a = 0u32; for i in 0..10 { a += one(); } - return a + assert_eq!(a, 10u32); } \ No newline at end of file diff --git a/compiler/tests/function/repeated_iteration.leo b/compiler/tests/function/iteration_repeated.leo similarity index 56% rename from compiler/tests/function/repeated_iteration.leo rename to compiler/tests/function/iteration_repeated.leo index 5db3b04df7..dcf357fe34 100644 --- a/compiler/tests/function/repeated_iteration.leo +++ b/compiler/tests/function/iteration_repeated.leo @@ -8,6 +8,8 @@ function iteration() -> u32 { return a } -function main() -> u32 { - return iteration() + iteration() +function main() { + let total = iteration() + iteration(); + + assert_eq!(total, 20); } \ No newline at end of file diff --git a/compiler/tests/function/mod.rs b/compiler/tests/function/mod.rs index 19e9a5c5d7..2c7c388140 100644 --- a/compiler/tests/function/mod.rs +++ b/compiler/tests/function/mod.rs @@ -1,39 +1,15 @@ use crate::{ - boolean::output_true, - get_error, - get_output, - integers::u32::{output_number, output_one}, + assert_satisfied, + expect_compiler_error, + get_outputs, parse_program, - EdwardsConstrainedValue, + parse_program_with_inputs, EdwardsTestCompiler, }; -use leo_compiler::{ - errors::{CompilerError, ExpressionError, FunctionError, StatementError}, - ConstrainedValue, -}; +use leo_compiler::errors::{CompilerError, ExpressionError, FunctionError, StatementError}; -use snarkos_models::gadgets::utilities::boolean::Boolean; - -pub(crate) fn output_empty(program: EdwardsTestCompiler) { - let output = get_output(program); - assert_eq!(EdwardsConstrainedValue::Return(vec![]).to_string(), output.to_string()); -} - -// (true, false) -pub(crate) fn output_multiple(program: EdwardsTestCompiler) { - let output = get_output(program); - assert_eq!( - EdwardsConstrainedValue::Return(vec![ - ConstrainedValue::Boolean(Boolean::Constant(true)), - ConstrainedValue::Boolean(Boolean::Constant(false)) - ]) - .to_string(), - output.to_string() - ) -} - -fn fail_undefined_identifier(program: EdwardsTestCompiler) { - match get_error(program) { +fn expect_undefined_identifier(program: EdwardsTestCompiler) { + match expect_compiler_error(program) { CompilerError::FunctionError(FunctionError::StatementError(StatementError::ExpressionError( ExpressionError::Error(_), ))) => {} @@ -41,14 +17,59 @@ fn fail_undefined_identifier(program: EdwardsTestCompiler) { } } -// Inline function call - #[test] fn test_empty() { let bytes = include_bytes!("empty.leo"); let program = parse_program(bytes).unwrap(); - output_empty(program); + assert_satisfied(program); +} + +#[test] +fn test_iteration() { + let bytes = include_bytes!("iteration.leo"); + let program = parse_program(bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_iteration_repeated() { + let bytes = include_bytes!("iteration_repeated.leo"); + let program = parse_program(bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_multiple_returns() { + let bytes = include_bytes!("multiple.leo"); + let program = parse_program(bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_multiple_returns_main() { + let program_bytes = include_bytes!("multiple_main.leo"); + let inputs_bytes = include_bytes!("inputs/registers.in"); + + let program = parse_program_with_inputs(program_bytes, inputs_bytes).unwrap(); + + let expected_bytes = include_bytes!("outputs_/registers.out"); + let expected = std::str::from_utf8(expected_bytes).unwrap(); + let actual_bytes = get_outputs(program); + let actual = std::str::from_utf8(actual_bytes.bytes().as_slice()).unwrap(); + + assert_eq!(expected, actual); +} + +#[test] +fn test_repeated_function_call() { + let bytes = include_bytes!("repeated.leo"); + let program = parse_program(bytes).unwrap(); + + assert_satisfied(program); } #[test] @@ -56,25 +77,15 @@ fn test_return() { let bytes = include_bytes!("return.leo"); let program = parse_program(bytes).unwrap(); - output_one(program); + assert_satisfied(program); } #[test] -fn test_undefined() { - let bytes = include_bytes!("undefined.leo"); - let program = parse_program(bytes).unwrap(); - - fail_undefined_identifier(program); -} - -// Function scope - -#[test] -fn test_global_scope_fail() { +fn test_scope_fail() { let bytes = include_bytes!("scope_fail.leo"); let program = parse_program(bytes).unwrap(); - match get_error(program) { + match expect_compiler_error(program) { CompilerError::FunctionError(FunctionError::StatementError(StatementError::ExpressionError( ExpressionError::FunctionError(value), ))) => match *value { @@ -85,53 +96,18 @@ fn test_global_scope_fail() { } } +#[test] +fn test_undefined() { + let bytes = include_bytes!("undefined.leo"); + let program = parse_program(bytes).unwrap(); + + expect_undefined_identifier(program); +} + #[test] fn test_value_unchanged() { let bytes = include_bytes!("value_unchanged.leo"); let program = parse_program(bytes).unwrap(); - output_one(program); -} - -// Multiple returns - -#[test] -fn test_multiple_returns() { - let bytes = include_bytes!("multiple.leo"); - let program = parse_program(bytes).unwrap(); - - output_multiple(program); -} - -#[test] -fn test_multiple_returns_main() { - let bytes = include_bytes!("multiple_main.leo"); - let program = parse_program(bytes).unwrap(); - - output_multiple(program); -} - -// Repeated calls - -#[test] -fn test_repeated_function_call() { - let bytes = include_bytes!("repeated.leo"); - let program = parse_program(bytes).unwrap(); - - output_true(program); -} -#[test] -fn test_iteration() { - let bytes = include_bytes!("iteration.leo"); - let program = parse_program(bytes).unwrap(); - - output_number(program, 10); -} - -#[test] -fn test_repeated_iteration() { - let bytes = include_bytes!("repeated_iteration.leo"); - let program = parse_program(bytes).unwrap(); - - output_number(program, 20u32); + assert_satisfied(program); } diff --git a/compiler/tests/function/multiple.leo b/compiler/tests/function/multiple.leo index 88baba4a3b..0603745623 100644 --- a/compiler/tests/function/multiple.leo +++ b/compiler/tests/function/multiple.leo @@ -2,7 +2,9 @@ function tuple() -> (bool, bool) { return (true, false) } -function main() -> (bool, bool) { +function main() { let (a, b) = tuple(); - return (a, b) + + assert_eq!(a, true); + assert_eq!(b, false); } \ No newline at end of file diff --git a/compiler/tests/function/multiple_main.leo b/compiler/tests/function/multiple_main.leo index c1e5d41276..aad2dd26fc 100644 --- a/compiler/tests/function/multiple_main.leo +++ b/compiler/tests/function/multiple_main.leo @@ -1,3 +1,3 @@ -function main() -> (bool, bool) { - return (true, false) +function main(registers) -> (bool, bool) { + return (registers.a, registers.b) } \ No newline at end of file diff --git a/compiler/tests/function/outputs_/registers.out b/compiler/tests/function/outputs_/registers.out new file mode 100644 index 0000000000..306191c516 --- /dev/null +++ b/compiler/tests/function/outputs_/registers.out @@ -0,0 +1,3 @@ +[registers] +a: bool = true; +b: bool = false; diff --git a/compiler/tests/function/repeated.leo b/compiler/tests/function/repeated.leo index 238f6b1931..c8b987ff00 100644 --- a/compiler/tests/function/repeated.leo +++ b/compiler/tests/function/repeated.leo @@ -2,6 +2,8 @@ function one() -> bool { return true } -function main() -> bool { - return one() && one() +function main() { + let a = one() && one(); + + assert_eq!(a, true); } \ No newline at end of file diff --git a/compiler/tests/function/return.leo b/compiler/tests/function/return.leo index a2ccc954c6..58fbd6ac95 100644 --- a/compiler/tests/function/return.leo +++ b/compiler/tests/function/return.leo @@ -2,6 +2,6 @@ function one() -> u32 { return 1u32 } -function main() -> u32 { - return one() +function main() { + assert_eq!(one(), 1u32); } \ No newline at end of file diff --git a/compiler/tests/function/scope_fail.leo b/compiler/tests/function/scope_fail.leo index 32777e9ebf..ac6bfcad37 100644 --- a/compiler/tests/function/scope_fail.leo +++ b/compiler/tests/function/scope_fail.leo @@ -2,7 +2,7 @@ function foo() -> field { return myGlobal } -function main() -> field { +function main() { const myGlobal = 42field; - return foo() + let err = foo(); } \ No newline at end of file diff --git a/compiler/tests/function/value_unchanged.leo b/compiler/tests/function/value_unchanged.leo index 46bcd78f1b..56e912a188 100644 --- a/compiler/tests/function/value_unchanged.leo +++ b/compiler/tests/function/value_unchanged.leo @@ -11,9 +11,9 @@ function bad_mutate(mut x: u32) { x = 0; // <- does not change `a` } -function main() -> u32 { +function main() { let a = 1u32; bad_mutate(a); - return a // <- returns 1 + assert_eq!(a, 1u32); // <- value `a` is still `1u32` } \ No newline at end of file diff --git a/compiler/tests/group/add.leo b/compiler/tests/group/add.leo index fe3839ba47..2b8713ac94 100644 --- a/compiler/tests/group/add.leo +++ b/compiler/tests/group/add.leo @@ -1,6 +1,3 @@ -function main() -> group { - const point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - const point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group; - - return point_1 + point_2 +function main(a: group, b: group, c: group) { + assert_eq!(a + b, c); } \ No newline at end of file diff --git a/compiler/tests/group/assert_eq.leo b/compiler/tests/group/assert_eq.leo new file mode 100644 index 0000000000..0d67b938c7 --- /dev/null +++ b/compiler/tests/group/assert_eq.leo @@ -0,0 +1,3 @@ +function main(a: group, b: group) { + assert_eq!(a, b); +} \ No newline at end of file diff --git a/compiler/tests/group/assert_eq_false.leo b/compiler/tests/group/assert_eq_false.leo deleted file mode 100644 index 63d8d428d2..0000000000 --- a/compiler/tests/group/assert_eq_false.leo +++ /dev/null @@ -1,6 +0,0 @@ -function main() { - const point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - const point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group; - - assert_eq!(point_1, point_2); -} \ No newline at end of file diff --git a/compiler/tests/group/assert_eq_true.leo b/compiler/tests/group/assert_eq_true.leo deleted file mode 100644 index 91b1e560cd..0000000000 --- a/compiler/tests/group/assert_eq_true.leo +++ /dev/null @@ -1,6 +0,0 @@ -function main() { - const point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - const point_2 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - - assert_eq!(point_1, point_2); -} \ No newline at end of file diff --git a/compiler/tests/group/eq.leo b/compiler/tests/group/eq.leo new file mode 100644 index 0000000000..07feb0b8be --- /dev/null +++ b/compiler/tests/group/eq.leo @@ -0,0 +1,3 @@ +function main(a: group, b: group, c: bool) { + assert_eq!(a == b, c); +} \ No newline at end of file diff --git a/compiler/tests/group/eq_false.leo b/compiler/tests/group/eq_false.leo deleted file mode 100644 index 8aea82b204..0000000000 --- a/compiler/tests/group/eq_false.leo +++ /dev/null @@ -1,6 +0,0 @@ -function main() -> bool { - const point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - const point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group; - - return point_1 == point_2 -} \ No newline at end of file diff --git a/compiler/tests/group/eq_true.leo b/compiler/tests/group/eq_true.leo deleted file mode 100644 index 7759c33fd5..0000000000 --- a/compiler/tests/group/eq_true.leo +++ /dev/null @@ -1,6 +0,0 @@ -function main() -> bool { - const point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - const point_2 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - - return point_1 == point_2 -} \ No newline at end of file diff --git a/compiler/tests/group/input.leo b/compiler/tests/group/input.leo index f19fb29b23..0d67b938c7 100644 --- a/compiler/tests/group/input.leo +++ b/compiler/tests/group/input.leo @@ -1,3 +1,3 @@ -function main(g: group) -> group { - return g +function main(a: group, b: group) { + assert_eq!(a, b); } \ No newline at end of file diff --git a/compiler/tests/group/inputs/one_one.in b/compiler/tests/group/inputs/one_one.in new file mode 100644 index 0000000000..27d529509f --- /dev/null +++ b/compiler/tests/group/inputs/one_one.in @@ -0,0 +1,3 @@ +[main] +a: group = 1; +b: group = 1; diff --git a/compiler/tests/group/inputs/one_zero.in b/compiler/tests/group/inputs/one_zero.in new file mode 100644 index 0000000000..98bcfb999d --- /dev/null +++ b/compiler/tests/group/inputs/one_zero.in @@ -0,0 +1,3 @@ +[main] +a: group = 1; +b: group = 0; diff --git a/compiler/tests/group/mod.rs b/compiler/tests/group/mod.rs index ea056fed13..3cb72f46ed 100644 --- a/compiler/tests/group/mod.rs +++ b/compiler/tests/group/mod.rs @@ -1,57 +1,23 @@ use crate::{ - boolean::{output_false, output_true}, - fail_enforce, - get_output, + assert_satisfied, + expect_synthesis_error, + field::field_to_decimal_string, + generate_main_inputs, parse_program, - EdwardsConstrainedValue, - EdwardsTestCompiler, + parse_program_with_inputs, }; -use leo_compiler::{group::targets::edwards_bls12::EdwardsGroupType, ConstrainedValue}; use leo_types::InputValue; -use snarkos_curves::edwards_bls12::{EdwardsAffine, EdwardsParameters, Fq}; -use snarkos_gadgets::curves::edwards_bls12::EdwardsBlsGadget; -use snarkos_models::{ - curves::{TEModelParameters, Zero}, - gadgets::{r1cs::TestConstraintSystem, utilities::alloc::AllocGadget}, -}; -use std::str::FromStr; +use snarkos_curves::edwards_bls12::EdwardsAffine; -const TEST_POINT_1: &str = "(7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)"; -const TEST_POINT_2: &str = "(1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)"; +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; -fn output_expected_constant(program: EdwardsTestCompiler, expected: EdwardsAffine) { - let output = get_output(program); - assert_eq!( - EdwardsConstrainedValue::Return(vec![ConstrainedValue::Group(EdwardsGroupType::Constant(expected))]) - .to_string(), - output.to_string() - ) -} +pub fn group_to_decimal_string(g: EdwardsAffine) -> String { + let x = field_to_decimal_string(g.x); + let y = field_to_decimal_string(g.y); -fn output_expected_allocated(program: EdwardsTestCompiler, expected: EdwardsBlsGadget) { - let output = get_output(program); - - match output { - EdwardsConstrainedValue::Return(vec) => match vec.as_slice() { - [ConstrainedValue::Group(EdwardsGroupType::Allocated(gadget))] => { - assert_eq!(*gadget, expected as EdwardsBlsGadget) - } - _ => panic!("program output unknown return value"), - }, - _ => panic!("program output unknown return value"), - } -} - -fn output_zero(program: EdwardsTestCompiler) { - output_expected_constant(program, EdwardsAffine::zero()) -} - -fn output_one(program: EdwardsTestCompiler) { - let (x, y) = EdwardsParameters::AFFINE_GENERATOR_COEFFS; - let one = EdwardsAffine::new(x, y); - - output_expected_constant(program, one) + format!("({}, {})", x, y) } #[test] @@ -59,7 +25,7 @@ fn test_zero() { let bytes = include_bytes!("zero.leo"); let program = parse_program(bytes).unwrap(); - output_zero(program); + assert_satisfied(program); } #[test] @@ -67,116 +33,222 @@ fn test_one() { let bytes = include_bytes!("one.leo"); let program = parse_program(bytes).unwrap(); - output_one(program) + assert_satisfied(program) } #[test] fn test_point() { - let point = EdwardsAffine::from_str(TEST_POINT_1).unwrap(); let bytes = include_bytes!("point.leo"); let program = parse_program(bytes).unwrap(); - output_expected_constant(program, point); + assert_satisfied(program); } #[test] -fn test_input() { - let bytes = include_bytes!("input.leo"); - let mut program = parse_program(bytes).unwrap(); +fn test_inputs() { + let program_bytes = include_bytes!("input.leo"); + let input_bytes_pass = include_bytes!("inputs/one_one.in"); + let input_bytes_fail = include_bytes!("inputs/one_zero.in"); - program.set_inputs(vec![Some(InputValue::Group(TEST_POINT_1.into()))]); + let program = parse_program_with_inputs(program_bytes, input_bytes_pass).unwrap(); - let mut cs = TestConstraintSystem::::new(); - let constant_point = EdwardsAffine::from_str(TEST_POINT_1).unwrap(); - let allocated_point = - >::alloc(&mut cs, || Ok(constant_point)).unwrap(); + assert_satisfied(program); - output_expected_allocated(program, allocated_point); + let program = parse_program_with_inputs(program_bytes, input_bytes_fail).unwrap(); + + expect_synthesis_error(program); } #[test] fn test_add() { use std::ops::Add; - let point_1 = EdwardsAffine::from_str(TEST_POINT_1).unwrap(); - let point_2 = EdwardsAffine::from_str(TEST_POINT_2).unwrap(); + let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - let sum = point_1.add(&point_2); + for _ in 0..10 { + let a: EdwardsAffine = rng.gen(); + let b: EdwardsAffine = rng.gen(); + let c = a.add(&b); - let bytes = include_bytes!("add.leo"); - let program = parse_program(bytes).unwrap(); + let a_string = group_to_decimal_string(a); + let b_string = group_to_decimal_string(b); + let c_string = group_to_decimal_string(c); - output_expected_constant(program, sum); + let bytes = include_bytes!("add.leo"); + let mut program = parse_program(bytes).unwrap(); + + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Group(a_string))), + ("b", Some(InputValue::Group(b_string))), + ("c", Some(InputValue::Group(c_string))), + ]); + program.set_main_inputs(main_inputs); + + assert_satisfied(program) + } } #[test] fn test_sub() { use std::ops::Sub; - let point_1 = EdwardsAffine::from_str(TEST_POINT_1).unwrap(); - let point_2 = EdwardsAffine::from_str(TEST_POINT_2).unwrap(); + let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - let sum = point_1.sub(&point_2); + for _ in 0..10 { + let a: EdwardsAffine = rng.gen(); + let b: EdwardsAffine = rng.gen(); + let c = a.sub(&b); - let bytes = include_bytes!("sub.leo"); - let program = parse_program(bytes).unwrap(); + let a_string = group_to_decimal_string(a); + let b_string = group_to_decimal_string(b); + let c_string = group_to_decimal_string(c); - output_expected_constant(program, sum); -} + let bytes = include_bytes!("sub.leo"); + let mut program = parse_program(bytes).unwrap(); -#[test] -fn test_eq_true() { - let bytes = include_bytes!("eq_true.leo"); - let program = parse_program(bytes).unwrap(); + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Group(a_string))), + ("b", Some(InputValue::Group(b_string))), + ("c", Some(InputValue::Group(c_string))), + ]); + program.set_main_inputs(main_inputs); - output_true(program) -} - -#[test] -fn test_eq_false() { - let bytes = include_bytes!("eq_false.leo"); - let program = parse_program(bytes).unwrap(); - - output_false(program) + assert_satisfied(program) + } } #[test] fn test_assert_eq_pass() { - let bytes = include_bytes!("assert_eq_true.leo"); - let program = parse_program(bytes).unwrap(); - let _res = get_output(program); + let mut rng = XorShiftRng::seed_from_u64(1231275789u64); + + for _ in 0..10 { + let a: EdwardsAffine = rng.gen(); + + let a_string = group_to_decimal_string(a); + + let bytes = include_bytes!("assert_eq.leo"); + let mut program = parse_program(bytes).unwrap(); + + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Group(a_string.clone()))), + ("b", Some(InputValue::Group(a_string))), + ]); + + program.set_main_inputs(main_inputs); + + assert_satisfied(program); + } } #[test] fn test_assert_eq_fail() { - let bytes = include_bytes!("assert_eq_false.leo"); - let program = parse_program(bytes).unwrap(); + let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - fail_enforce(program); + for _ in 0..10 { + let a: EdwardsAffine = rng.gen(); + let b: EdwardsAffine = rng.gen(); + + if a == b { + continue; + } + + let a_string = group_to_decimal_string(a); + let b_string = group_to_decimal_string(b); + + let bytes = include_bytes!("assert_eq.leo"); + let mut program = parse_program(bytes).unwrap(); + + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Group(a_string))), + ("b", Some(InputValue::Group(b_string))), + ]); + + program.set_main_inputs(main_inputs); + + expect_synthesis_error(program); + } +} + +#[test] +fn test_eq() { + let mut rng = XorShiftRng::seed_from_u64(1231275789u64); + + for _ in 0..10 { + let a: EdwardsAffine = rng.gen(); + let b: EdwardsAffine = rng.gen(); + + let a_string = group_to_decimal_string(a); + let b_string = group_to_decimal_string(b); + + // test equal + + let bytes = include_bytes!("eq.leo"); + let mut program = parse_program(bytes).unwrap(); + + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Group(a_string.clone()))), + ("b", Some(InputValue::Group(a_string.clone()))), + ("c", Some(InputValue::Boolean(true))), + ]); + + program.set_main_inputs(main_inputs); + + assert_satisfied(program); + + // test not equal + + let c = a.eq(&b); + + let mut program = parse_program(bytes).unwrap(); + + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Group(a_string))), + ("b", Some(InputValue::Group(b_string))), + ("c", Some(InputValue::Boolean(c))), + ]); + + program.set_main_inputs(main_inputs); + + assert_satisfied(program); + } } #[test] fn test_ternary() { + let mut rng = XorShiftRng::seed_from_u64(1231275789u64); + + let a: EdwardsAffine = rng.gen(); + let b: EdwardsAffine = rng.gen(); + + let a_string = group_to_decimal_string(a); + let b_string = group_to_decimal_string(b); + let bytes = include_bytes!("ternary.leo"); - let mut program_1 = parse_program(bytes).unwrap(); + let mut program = parse_program(bytes).unwrap(); - let mut program_2 = program_1.clone(); + // true -> field a + let main_inputs = generate_main_inputs(vec![ + ("s", Some(InputValue::Boolean(true))), + ("a", Some(InputValue::Group(a_string.clone()))), + ("b", Some(InputValue::Group(b_string.clone()))), + ("c", Some(InputValue::Group(a_string.clone()))), + ]); - // true -> point_1 - program_1.set_inputs(vec![Some(InputValue::Boolean(true))]); + program.set_main_inputs(main_inputs); - let mut cs = TestConstraintSystem::::new(); - let point_1 = EdwardsAffine::from_str(TEST_POINT_1).unwrap(); - let expected_point_1 = - >::alloc(&mut cs, || Ok(point_1)).unwrap(); - output_expected_allocated(program_1, expected_point_1); + assert_satisfied(program); - // false -> point_2 - program_2.set_inputs(vec![Some(InputValue::Boolean(false))]); + let mut program = parse_program(bytes).unwrap(); - let mut cs = TestConstraintSystem::::new(); - let point_2 = EdwardsAffine::from_str(TEST_POINT_2).unwrap(); - let expected_point_2 = - >::alloc(&mut cs, || Ok(point_2)).unwrap(); - output_expected_allocated(program_2, expected_point_2); + // false -> field b + let main_inputs = generate_main_inputs(vec![ + ("s", Some(InputValue::Boolean(false))), + ("a", Some(InputValue::Group(a_string))), + ("b", Some(InputValue::Group(b_string.clone()))), + ("c", Some(InputValue::Group(b_string))), + ]); + + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } diff --git a/compiler/tests/group/one.leo b/compiler/tests/group/one.leo index 1dc4eac9e4..78188d4893 100644 --- a/compiler/tests/group/one.leo +++ b/compiler/tests/group/one.leo @@ -1,3 +1,3 @@ -function main() -> group { - return 1group +function main() { + let a = 1group; } \ No newline at end of file diff --git a/compiler/tests/group/point.leo b/compiler/tests/group/point.leo index 43dd2173cc..5e68415a0d 100644 --- a/compiler/tests/group/point.leo +++ b/compiler/tests/group/point.leo @@ -1,5 +1,3 @@ -function main() -> group { +function main() { const point = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - - return point } \ No newline at end of file diff --git a/compiler/tests/group/sub.leo b/compiler/tests/group/sub.leo index adf9a4542b..982a0ed1f0 100644 --- a/compiler/tests/group/sub.leo +++ b/compiler/tests/group/sub.leo @@ -1,6 +1,3 @@ -function main() -> group { - const point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - const point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group; - - return point_1 - point_2 +function main(a: group, b: group, c: group) { + assert_eq!(a - b, c); } \ No newline at end of file diff --git a/compiler/tests/group/ternary.leo b/compiler/tests/group/ternary.leo index 094cede5b2..fc2dd439c1 100644 --- a/compiler/tests/group/ternary.leo +++ b/compiler/tests/group/ternary.leo @@ -1,6 +1,5 @@ -function main (b: bool) -> group { - const point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; - const point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group; +function main(s: bool, a: group, b: group, c: group) { + let r = if s ? a : b; - return if b ? point_1 : point_2 + assert_eq!(r, c); } \ No newline at end of file diff --git a/compiler/tests/group/zero.leo b/compiler/tests/group/zero.leo index 298cf5fe2e..199a8498a7 100644 --- a/compiler/tests/group/zero.leo +++ b/compiler/tests/group/zero.leo @@ -1,3 +1,3 @@ -function main() -> group { - return 0group +function main() { + let a = 0group; } \ No newline at end of file diff --git a/compiler/tests/import/alias.leo b/compiler/tests/import/alias.leo index 9236d8f01f..576e5d5acb 100644 --- a/compiler/tests/import/alias.leo +++ b/compiler/tests/import/alias.leo @@ -1,5 +1,5 @@ import test_import.foo as bar; -function main() -> u32 { - return bar() +function main() { + assert_eq!(bar(), 1u32); } \ No newline at end of file diff --git a/compiler/tests/import/basic.leo b/compiler/tests/import/basic.leo index 4aa4fa050e..ace5c1624f 100644 --- a/compiler/tests/import/basic.leo +++ b/compiler/tests/import/basic.leo @@ -1,5 +1,5 @@ import test_import.foo; -function main() -> u32 { - return foo() +function main() { + assert_eq!(foo(), 1u32); } \ No newline at end of file diff --git a/compiler/tests/import/many_import.leo b/compiler/tests/import/many_import.leo index 8fad0137a9..1cbbea72e4 100644 --- a/compiler/tests/import/many_import.leo +++ b/compiler/tests/import/many_import.leo @@ -11,7 +11,7 @@ import bar.( // imports directory import import car.Car; // imports directory import -function main() -> u32 { +function main() { const point = Point { x: 1u32, y: 1u32 }; const foo = foo(); @@ -21,5 +21,5 @@ function main() -> u32 { const car = Car { c: 1u32 }; - return car.c + assert_eq!(car.c, 1u32); } \ No newline at end of file diff --git a/compiler/tests/import/many_import_star.leo b/compiler/tests/import/many_import_star.leo index 1099efd166..90c6d7aad0 100644 --- a/compiler/tests/import/many_import_star.leo +++ b/compiler/tests/import/many_import_star.leo @@ -5,7 +5,7 @@ import bar.baz.*; // imports directory import import bar.bat.bat.*; // imports directory import import car.*; // imports directory import -function main() -> u32 { +function main() { const point = Point { x: 1u32, y: 1u32 }; const foo = foo(); @@ -15,5 +15,5 @@ function main() -> u32 { const car = Car { c: 1u32 }; - return car.c + assert_eq!(car.c, 1u32); } \ No newline at end of file diff --git a/compiler/tests/import/mod.rs b/compiler/tests/import/mod.rs index 4f00d4259c..d3c1cd3c5d 100644 --- a/compiler/tests/import/mod.rs +++ b/compiler/tests/import/mod.rs @@ -1,4 +1,4 @@ -use crate::{integers::u32::output_one, parse_program}; +use crate::{assert_satisfied, parse_program}; use std::env::{current_dir, set_current_dir}; @@ -21,7 +21,7 @@ fn test_basic() { let bytes = include_bytes!("basic.leo"); let program = parse_program(bytes).unwrap(); - output_one(program); + assert_satisfied(program); } #[test] @@ -32,7 +32,7 @@ fn test_multiple() { let bytes = include_bytes!("multiple.leo"); let program = parse_program(bytes).unwrap(); - output_one(program); + assert_satisfied(program); } #[test] @@ -43,7 +43,7 @@ fn test_star() { let bytes = include_bytes!("star.leo"); let program = parse_program(bytes).unwrap(); - output_one(program); + assert_satisfied(program); } #[test] @@ -63,7 +63,7 @@ fn test_alias() { let bytes = include_bytes!("alias.leo"); let program = parse_program(bytes).unwrap(); - output_one(program); + assert_satisfied(program); } // more complex tests @@ -75,7 +75,7 @@ fn test_many_import() { let bytes = include_bytes!("many_import.leo"); let program = parse_program(bytes).unwrap(); - output_one(program); + assert_satisfied(program); } #[test] @@ -86,5 +86,5 @@ fn test_many_import_star() { let bytes = include_bytes!("many_import_star.leo"); let program = parse_program(bytes).unwrap(); - output_one(program); + assert_satisfied(program); } diff --git a/compiler/tests/import/multiple.leo b/compiler/tests/import/multiple.leo index 38b2c2e301..0be311af36 100644 --- a/compiler/tests/import/multiple.leo +++ b/compiler/tests/import/multiple.leo @@ -3,7 +3,8 @@ import test_import.( foo ); -function main() -> u32 { - let p = Point { x: 1u32, y: 0u32 }; - return p.x +function main() { + let a = Point { x: 1u32, y: 0u32 }; + + assert_eq!(a.x, 1u32); } \ No newline at end of file diff --git a/compiler/tests/import/star.leo b/compiler/tests/import/star.leo index ccc876600c..4f347d6f93 100644 --- a/compiler/tests/import/star.leo +++ b/compiler/tests/import/star.leo @@ -1,6 +1,7 @@ import test_import.*; -function main() -> u32 { - let p = Point { x: 1u32, y: 0u32 }; - return foo() +function main() { + let a = Point { x: 1u32, y: 0u32 }; + + assert_eq!(foo(), 1u32); } \ No newline at end of file diff --git a/compiler/tests/input_files/mod.rs b/compiler/tests/input_files/mod.rs new file mode 100644 index 0000000000..a420a7e6e2 --- /dev/null +++ b/compiler/tests/input_files/mod.rs @@ -0,0 +1,3 @@ +mod program_inputs; +mod program_inputs_and_state; +mod state; diff --git a/compiler/tests/input_files/program_inputs/inputs/main.in b/compiler/tests/input_files/program_inputs/inputs/main.in new file mode 100644 index 0000000000..16ba5231af --- /dev/null +++ b/compiler/tests/input_files/program_inputs/inputs/main.in @@ -0,0 +1,2 @@ +[main] +a: bool = true; \ No newline at end of file diff --git a/compiler/tests/inputs/main_fail_name.in b/compiler/tests/input_files/program_inputs/inputs/main_fail_name.in similarity index 100% rename from compiler/tests/inputs/main_fail_name.in rename to compiler/tests/input_files/program_inputs/inputs/main_fail_name.in diff --git a/compiler/tests/input_files/program_inputs/inputs/main_fail_type.in b/compiler/tests/input_files/program_inputs/inputs/main_fail_type.in new file mode 100644 index 0000000000..a5cf30c8cc --- /dev/null +++ b/compiler/tests/input_files/program_inputs/inputs/main_fail_type.in @@ -0,0 +1,2 @@ +[main] +a: u8 = 1; \ No newline at end of file diff --git a/compiler/tests/input_files/program_inputs/inputs/main_multiple.in b/compiler/tests/input_files/program_inputs/inputs/main_multiple.in new file mode 100644 index 0000000000..546c971bf8 --- /dev/null +++ b/compiler/tests/input_files/program_inputs/inputs/main_multiple.in @@ -0,0 +1,3 @@ +[main] +a: bool = true; +b: bool = false; diff --git a/compiler/tests/input_files/program_inputs/main.leo b/compiler/tests/input_files/program_inputs/main.leo new file mode 100644 index 0000000000..8a8ab02f28 --- /dev/null +++ b/compiler/tests/input_files/program_inputs/main.leo @@ -0,0 +1,3 @@ +function main(a: bool) { + assert_eq!(a, true); +} \ No newline at end of file diff --git a/compiler/tests/input_files/program_inputs/main_multiple.leo b/compiler/tests/input_files/program_inputs/main_multiple.leo new file mode 100644 index 0000000000..49ad704a2f --- /dev/null +++ b/compiler/tests/input_files/program_inputs/main_multiple.leo @@ -0,0 +1,4 @@ +function main(a: bool, b: bool) { + assert_eq!(a, true); + assert_eq!(b, false); +} \ No newline at end of file diff --git a/compiler/tests/input_files/program_inputs/mod.rs b/compiler/tests/input_files/program_inputs/mod.rs new file mode 100644 index 0000000000..8ecec380c3 --- /dev/null +++ b/compiler/tests/input_files/program_inputs/mod.rs @@ -0,0 +1,49 @@ +use crate::{assert_satisfied, expect_compiler_error, parse_program_with_inputs, EdwardsTestCompiler}; +use leo_compiler::errors::CompilerError; + +fn expect_fail(program: EdwardsTestCompiler) { + match expect_compiler_error(program) { + CompilerError::FunctionError(_) => {} + err => panic!("expected input parser error, got {:?}", err), + } +} + +#[test] +fn test_inputs_pass() { + let program_bytes = include_bytes!("main.leo"); + let input_bytes = include_bytes!("inputs/main.in"); + + let program = parse_program_with_inputs(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_inputs_fail_name() { + let program_bytes = include_bytes!("main.leo"); + let input_bytes = include_bytes!("inputs/main_fail_name.in"); + + let program = parse_program_with_inputs(program_bytes, input_bytes).unwrap(); + + expect_fail(program); +} + +#[test] +fn test_inputs_fail_type() { + let program_bytes = include_bytes!("main.leo"); + let input_bytes = include_bytes!("inputs/main_fail_type.in"); + + let program = parse_program_with_inputs(program_bytes, input_bytes).unwrap(); + + expect_fail(program); +} + +#[test] +fn test_inputs_multiple() { + let program_bytes = include_bytes!("main_multiple.leo"); + let input_bytes = include_bytes!("inputs/main_multiple.in"); + + let program = parse_program_with_inputs(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} diff --git a/compiler/tests/input_files/program_inputs_and_state/access.leo b/compiler/tests/input_files/program_inputs_and_state/access.leo new file mode 100644 index 0000000000..0d924e357e --- /dev/null +++ b/compiler/tests/input_files/program_inputs_and_state/access.leo @@ -0,0 +1,17 @@ +function main( + registers, + state, + record, + state_leaf, + data: u8[32] +) { + assert_eq!(registers.value_balance, 0u64); + + assert_eq!(state.leaf_index, 0u32); + + assert_eq!(record.value, 5u64); + + assert_eq!(state_leaf.network_id, 0u8); + + assert_eq!(data, [0u8; 32]); +} \ No newline at end of file diff --git a/compiler/tests/input_files/program_inputs_and_state/inputs/basic.in b/compiler/tests/input_files/program_inputs_and_state/inputs/basic.in new file mode 100644 index 0000000000..b62eee0443 --- /dev/null +++ b/compiler/tests/input_files/program_inputs_and_state/inputs/basic.in @@ -0,0 +1,5 @@ +[main] +a: bool = true; + +[registers] +b: bool = true; \ No newline at end of file diff --git a/compiler/tests/input_files/program_inputs_and_state/inputs/basic.state b/compiler/tests/input_files/program_inputs_and_state/inputs/basic.state new file mode 100644 index 0000000000..78706190fe --- /dev/null +++ b/compiler/tests/input_files/program_inputs_and_state/inputs/basic.state @@ -0,0 +1,12 @@ +[[public]] + +[state] +a: bool = true; + +[[private]] + +[record] +a: bool = true; + +[state_leaf] +a: bool = true; \ No newline at end of file diff --git a/compiler/tests/input_files/program_inputs_and_state/inputs/token_withdraw.in b/compiler/tests/input_files/program_inputs_and_state/inputs/token_withdraw.in new file mode 100644 index 0000000000..5e570eef23 --- /dev/null +++ b/compiler/tests/input_files/program_inputs_and_state/inputs/token_withdraw.in @@ -0,0 +1,6 @@ +[main] +data: u8[32] = [0u8; 32]; + +[registers] +token_id: u8[32] = [0u8; 32]; +value_balance: u64 = 0; \ No newline at end of file diff --git a/compiler/tests/input_files/program_inputs_and_state/inputs/token_withdraw.state b/compiler/tests/input_files/program_inputs_and_state/inputs/token_withdraw.state new file mode 100644 index 0000000000..9d35cf30aa --- /dev/null +++ b/compiler/tests/input_files/program_inputs_and_state/inputs/token_withdraw.state @@ -0,0 +1,24 @@ +[[public]] + +[state] +leaf_index: u32 = 0; +root: u8[32] = [0u8; 32]; + +[[private]] + +[record] +serial_number: u8[32] = [0u8; 32]; +commitment: u8[32] = [0u8; 32]; +owner: address = aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8; +value: u64 = 5; +payload: u8[32] = [0u8; 32]; +birth_program_id: u8[32] = [0u8; 32]; +death_program_id: u8[32] = [0u8; 32]; +serial_number_nonce: u8[32] = [0u8; 32]; +commitment_randomness: u8[32] = [0u8; 32]; + +[state_leaf] +path: u8[32][2] = [ [0u8; 32], [0u8; 32] ]; +memo: u8[32] = [0u8; 32]; +network_id: u8 = 0; +leaf_randomness: u8[32] = [0u8; 32]; \ No newline at end of file diff --git a/compiler/tests/input_files/program_inputs_and_state/mod.rs b/compiler/tests/input_files/program_inputs_and_state/mod.rs new file mode 100644 index 0000000000..9cfa29f248 --- /dev/null +++ b/compiler/tests/input_files/program_inputs_and_state/mod.rs @@ -0,0 +1,28 @@ +use crate::{assert_satisfied, parse_inputs_and_state, parse_program_with_inputs_and_state}; + +#[test] +fn test_basic() { + let inputs_bytes = include_bytes!("inputs/basic.in"); + let state_bytes = include_bytes!("inputs/basic.state"); + + parse_inputs_and_state(inputs_bytes, state_bytes).unwrap(); +} + +#[test] +fn test_full() { + let inputs_bytes = include_bytes!("inputs/token_withdraw.in"); + let state_bytes = include_bytes!("inputs/token_withdraw.state"); + + parse_inputs_and_state(inputs_bytes, state_bytes).unwrap(); +} + +#[test] +fn test_access() { + let program_bytes = include_bytes!("access.leo"); + let inputs_bytes = include_bytes!("inputs/token_withdraw.in"); + let state_bytes = include_bytes!("inputs/token_withdraw.state"); + + let program = parse_program_with_inputs_and_state(program_bytes, inputs_bytes, state_bytes).unwrap(); + + assert_satisfied(program); +} diff --git a/compiler/tests/input_files/state/access_all.leo b/compiler/tests/input_files/state/access_all.leo new file mode 100644 index 0000000000..0d9ab2e64c --- /dev/null +++ b/compiler/tests/input_files/state/access_all.leo @@ -0,0 +1,8 @@ +function main(state, record, state_leaf) { + assert_eq!(state.root, [0u8; 32]); + + let expected: address = aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8; + assert_eq!(record.owner, expected); + + assert_eq!(state_leaf.network_id, 0u8); +} \ No newline at end of file diff --git a/compiler/tests/input_files/state/access_state.leo b/compiler/tests/input_files/state/access_state.leo new file mode 100644 index 0000000000..096cd2be83 --- /dev/null +++ b/compiler/tests/input_files/state/access_state.leo @@ -0,0 +1,3 @@ +function main(state) { + assert_eq!(state.root, [0u8; 32]); +} \ No newline at end of file diff --git a/compiler/tests/input_files/state/inputs/basic.state b/compiler/tests/input_files/state/inputs/basic.state new file mode 100644 index 0000000000..2f40f7f1c4 --- /dev/null +++ b/compiler/tests/input_files/state/inputs/basic.state @@ -0,0 +1,10 @@ +[[public]] +[state] +root: bool = true; + +[[private]] +[record] +id: bool = false; + +[state_leaf] +leaf: bool = true; \ No newline at end of file diff --git a/compiler/tests/input_files/state/inputs/section_invalid.state b/compiler/tests/input_files/state/inputs/section_invalid.state new file mode 100644 index 0000000000..955b881192 --- /dev/null +++ b/compiler/tests/input_files/state/inputs/section_invalid.state @@ -0,0 +1,4 @@ +[[public]] + +[record] +a: bool = true; \ No newline at end of file diff --git a/compiler/tests/input_files/state/inputs/section_undefined.state b/compiler/tests/input_files/state/inputs/section_undefined.state new file mode 100644 index 0000000000..5f881cbb29 --- /dev/null +++ b/compiler/tests/input_files/state/inputs/section_undefined.state @@ -0,0 +1,4 @@ +[[public]] + +[invalid] +a: bool = true; \ No newline at end of file diff --git a/compiler/tests/input_files/state/inputs/token_withdraw.state b/compiler/tests/input_files/state/inputs/token_withdraw.state new file mode 100644 index 0000000000..9d35cf30aa --- /dev/null +++ b/compiler/tests/input_files/state/inputs/token_withdraw.state @@ -0,0 +1,24 @@ +[[public]] + +[state] +leaf_index: u32 = 0; +root: u8[32] = [0u8; 32]; + +[[private]] + +[record] +serial_number: u8[32] = [0u8; 32]; +commitment: u8[32] = [0u8; 32]; +owner: address = aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8; +value: u64 = 5; +payload: u8[32] = [0u8; 32]; +birth_program_id: u8[32] = [0u8; 32]; +death_program_id: u8[32] = [0u8; 32]; +serial_number_nonce: u8[32] = [0u8; 32]; +commitment_randomness: u8[32] = [0u8; 32]; + +[state_leaf] +path: u8[32][2] = [ [0u8; 32], [0u8; 32] ]; +memo: u8[32] = [0u8; 32]; +network_id: u8 = 0; +leaf_randomness: u8[32] = [0u8; 32]; \ No newline at end of file diff --git a/compiler/tests/input_files/state/inputs/visibility_fail.state b/compiler/tests/input_files/state/inputs/visibility_fail.state new file mode 100644 index 0000000000..c5928ddcbd --- /dev/null +++ b/compiler/tests/input_files/state/inputs/visibility_fail.state @@ -0,0 +1 @@ +[[pure]] \ No newline at end of file diff --git a/compiler/tests/input_files/state/mod.rs b/compiler/tests/input_files/state/mod.rs new file mode 100644 index 0000000000..e7736d1284 --- /dev/null +++ b/compiler/tests/input_files/state/mod.rs @@ -0,0 +1,62 @@ +use crate::{assert_satisfied, parse_program_with_state, parse_state}; + +#[test] +fn test_basic() { + let bytes = include_bytes!("inputs/basic.state"); + + parse_state(bytes).unwrap(); +} + +#[test] +fn test_token_withdraw() { + let bytes = include_bytes!("inputs/token_withdraw.state"); + + parse_state(bytes).unwrap(); +} + +#[test] +fn test_access_state() { + let program_bytes = include_bytes!("access_state.leo"); + let state_bytes = include_bytes!("inputs/token_withdraw.state"); + + let program = parse_program_with_state(program_bytes, state_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_access_all() { + let program_bytes = include_bytes!("access_all.leo"); + let state_bytes = include_bytes!("inputs/token_withdraw.state"); + + let program = parse_program_with_state(program_bytes, state_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_visibility_fail() { + let state_bytes = include_bytes!("inputs/visibility_fail.state"); + + let is_err = parse_state(state_bytes).is_err(); + + assert!(is_err); +} + +#[test] +fn test_section_undefined() { + let state_bytes = include_bytes!("inputs/section_undefined.state"); + + let is_err = parse_state(state_bytes).is_err(); + + assert!(is_err); +} + +#[test] +fn test_section_invalid() { + let state_bytes = include_bytes!("inputs/section_invalid.state"); + + let is_err = parse_state(state_bytes).is_err(); + + assert!(is_err); +} diff --git a/compiler/tests/inputs/main.leo b/compiler/tests/inputs/main.leo deleted file mode 100644 index 7e2a1c7e0c..0000000000 --- a/compiler/tests/inputs/main.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main(b: bool) -> bool { - return b -} \ No newline at end of file diff --git a/compiler/tests/inputs/main_fail_type.in b/compiler/tests/inputs/main_fail_type.in deleted file mode 100644 index 04cd884d05..0000000000 --- a/compiler/tests/inputs/main_fail_type.in +++ /dev/null @@ -1,2 +0,0 @@ -[main] -b: u8 = 1; \ No newline at end of file diff --git a/compiler/tests/inputs/main_multiple.in b/compiler/tests/inputs/main_multiple.in deleted file mode 100644 index 85ee0349ec..0000000000 --- a/compiler/tests/inputs/main_multiple.in +++ /dev/null @@ -1,3 +0,0 @@ -[main] -b: bool = true; -a: bool = false; \ No newline at end of file diff --git a/compiler/tests/inputs/main_multiple.leo b/compiler/tests/inputs/main_multiple.leo deleted file mode 100644 index e2231f14bc..0000000000 --- a/compiler/tests/inputs/main_multiple.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main(a: bool, b: bool) -> bool { - return a || b -} \ No newline at end of file diff --git a/compiler/tests/inputs/mod.rs b/compiler/tests/inputs/mod.rs deleted file mode 100644 index da5bf9836d..0000000000 --- a/compiler/tests/inputs/mod.rs +++ /dev/null @@ -1,58 +0,0 @@ -use crate::{boolean::output_true, parse_program}; -use leo_compiler::errors::CompilerError; -use leo_inputs::InputParserError; - -fn fail_input_parser(error: CompilerError) { - match error { - CompilerError::InputParserError(InputParserError::InputNotFound(_)) => {} - err => panic!("expected input parser error, got {}", err), - } -} - -#[test] -fn test_inputs_pass() { - let program_bytes = include_bytes!("main.leo"); - let input_bytes = include_bytes!("main.in"); - let input_string = String::from_utf8_lossy(input_bytes); - - let mut program = parse_program(program_bytes).unwrap(); - program.parse_inputs(&input_string).unwrap(); - - output_true(program); -} - -#[test] -fn test_inputs_fail_name() { - let program_bytes = include_bytes!("main.leo"); - let input_bytes = include_bytes!("main_fail_name.in"); - let input_string = String::from_utf8_lossy(input_bytes); - - let mut program = parse_program(program_bytes).unwrap(); - let error = program.parse_inputs(&input_string).unwrap_err(); - - fail_input_parser(error); -} - -#[test] -fn test_inputs_fail_type() { - let program_bytes = include_bytes!("main.leo"); - let input_bytes = include_bytes!("main_fail_type.in"); - let input_string = String::from_utf8_lossy(input_bytes); - - let mut program = parse_program(program_bytes).unwrap(); - let error = program.parse_inputs(&input_string).unwrap_err(); - - fail_input_parser(error); -} - -#[test] -fn test_inputs_multiple() { - let program_bytes = include_bytes!("main_multiple.leo"); - let input_bytes = include_bytes!("main_multiple.in"); - let input_string = String::from_utf8_lossy(input_bytes); - - let mut program = parse_program(program_bytes).unwrap(); - program.parse_inputs(&input_string).unwrap(); - - output_true(program); -} diff --git a/compiler/tests/integers/i128/add.leo b/compiler/tests/integers/i128/add.leo index 1a90ea377d..868354c66a 100644 --- a/compiler/tests/integers/i128/add.leo +++ b/compiler/tests/integers/i128/add.leo @@ -1,3 +1,3 @@ -function main(a: i128, b: i128) -> i128 { - return a + b +function main(a: i128, b: i128, c: i128) { + assert_eq!(a + b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i128/div.leo b/compiler/tests/integers/i128/div.leo index e2f9f2853e..3674db9571 100644 --- a/compiler/tests/integers/i128/div.leo +++ b/compiler/tests/integers/i128/div.leo @@ -1,3 +1,3 @@ -function main(a: i128, b: i128) -> i128 { - return a / b +function main(a: i128, b: i128, c: i128) { + assert_eq!(a / b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i128/eq.leo b/compiler/tests/integers/i128/eq.leo index 5681aa7263..c1662f7ef9 100644 --- a/compiler/tests/integers/i128/eq.leo +++ b/compiler/tests/integers/i128/eq.leo @@ -1,3 +1,3 @@ -function main(a: i128, b: i128) -> bool { - return a == b +function main(a: i128, b: i128, c: bool) { + assert_eq!(a == b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i128/ge.leo b/compiler/tests/integers/i128/ge.leo index 05949082f4..f9b17623a9 100644 --- a/compiler/tests/integers/i128/ge.leo +++ b/compiler/tests/integers/i128/ge.leo @@ -1,3 +1,3 @@ -function main(a: i128, b: i128) -> bool { - return a >= b +function main(a: i128, b: i128, c: bool) { + assert_eq!(a >= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i128/gt.leo b/compiler/tests/integers/i128/gt.leo index 5eedfa3ec0..4c45bf6605 100644 --- a/compiler/tests/integers/i128/gt.leo +++ b/compiler/tests/integers/i128/gt.leo @@ -1,3 +1,3 @@ -function main(a: i128, b: i128) -> bool { - return a > b +function main(a: i128, b: i128, c: bool) { + assert_eq!(a > b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i128/input.leo b/compiler/tests/integers/i128/input.leo index aa49ca84f8..a6dc495a84 100644 --- a/compiler/tests/integers/i128/input.leo +++ b/compiler/tests/integers/i128/input.leo @@ -1,3 +1,3 @@ -function main(x: i128) -> i128 { - return x +function main(a: i128, b: i128) { + assert_eq!(a, b); } \ No newline at end of file diff --git a/compiler/tests/integers/i128/le.leo b/compiler/tests/integers/i128/le.leo index 472e1f53ce..2f9d100793 100644 --- a/compiler/tests/integers/i128/le.leo +++ b/compiler/tests/integers/i128/le.leo @@ -1,3 +1,3 @@ -function main(a: i128, b: i128) -> bool { - return a <= b +function main(a: i128, b: i128, c: bool) { + assert_eq!(a <= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i128/lt.leo b/compiler/tests/integers/i128/lt.leo index 610a51e55f..766024aaac 100644 --- a/compiler/tests/integers/i128/lt.leo +++ b/compiler/tests/integers/i128/lt.leo @@ -1,3 +1,3 @@ -function main(a: i128, b: i128) -> bool { - return a < b +function main(a: i128, b: i128, c: bool) { + assert_eq!(a < b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i128/max.leo b/compiler/tests/integers/i128/max.leo index 06bf685187..46c0a32599 100644 --- a/compiler/tests/integers/i128/max.leo +++ b/compiler/tests/integers/i128/max.leo @@ -1,3 +1,3 @@ -function main() -> i128 { - return 170141183460469231731687303715884105727 +function main() { + let a: i128 = 170141183460469231731687303715884105727; } \ No newline at end of file diff --git a/compiler/tests/integers/i128/max_fail.leo b/compiler/tests/integers/i128/max_fail.leo new file mode 100644 index 0000000000..820eda8759 --- /dev/null +++ b/compiler/tests/integers/i128/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i128 = 170141183460469231731687303715884105728; +} \ No newline at end of file diff --git a/compiler/tests/integers/i128/min.leo b/compiler/tests/integers/i128/min.leo index 1f90232344..5f32e5add5 100644 --- a/compiler/tests/integers/i128/min.leo +++ b/compiler/tests/integers/i128/min.leo @@ -1,3 +1,3 @@ -function main() -> i128 { - return -170141183460469231731687303715884105728 +function main() { + let a: i128 = -170141183460469231731687303715884105728; } \ No newline at end of file diff --git a/compiler/tests/integers/i128/min_fail.leo b/compiler/tests/integers/i128/min_fail.leo new file mode 100644 index 0000000000..9035444fa9 --- /dev/null +++ b/compiler/tests/integers/i128/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i128 = -170141183460469231731687303715884105729; +} \ No newline at end of file diff --git a/compiler/tests/integers/i128/mod.rs b/compiler/tests/integers/i128/mod.rs index 6b9f332e3e..75522b510c 100644 --- a/compiler/tests/integers/i128/mod.rs +++ b/compiler/tests/integers/i128/mod.rs @@ -1,105 +1,92 @@ use crate::{ - boolean::{output_expected_boolean, output_false, output_true}, - get_error, - get_output, - integers::{fail_integer, IntegerTester}, + assert_satisfied, + expect_synthesis_error, + generate_main_inputs, + integers::{expect_computation_error, expect_parsing_error, IntegerTester}, parse_program, - EdwardsConstrainedValue, - EdwardsTestCompiler, }; -use leo_compiler::{ConstrainedValue, Integer}; -use leo_gadgets::*; use leo_inputs::types::{I128Type, IntegerType}; use leo_types::InputValue; -use snarkos_curves::edwards_bls12::Fq; -use snarkos_models::gadgets::{r1cs::TestConstraintSystem, utilities::alloc::AllocGadget}; - -fn output_expected_allocated(program: EdwardsTestCompiler, expected: Int128) { - let output = get_output(program); - - match output { - EdwardsConstrainedValue::Return(vec) => match vec.as_slice() { - [ConstrainedValue::Integer(Integer::I128(actual))] => assert_eq!(*actual, expected), - _ => panic!("program output unknown return value"), - }, - _ => panic!("program output unknown return value"), - } -} - -test_int!(TestI128, i128, IntegerType::I128Type(I128Type {}), Int128); +test_int!(Testi128, i128, IntegerType::I128Type(I128Type {}), Int128); #[test] fn test_i128_min() { - TestI128::test_min(std::i128::MIN); + Testi128::test_min(); +} + +#[test] +fn test_i128_min_fail() { + Testi128::test_min_fail(); } #[test] fn test_i128_max() { - TestI128::test_max(std::i128::MAX); + Testi128::test_max(); } #[test] -fn test_i128_input() { - TestI128::test_input(); +fn test_i128_max_fail() { + Testi128::test_max_fail(); } #[test] fn test_i128_add() { - TestI128::test_add(); + Testi128::test_add(); } #[test] fn test_i128_sub() { - TestI128::test_sub(); + Testi128::test_sub(); } #[test] fn test_i128_mul() { - TestI128::test_mul(); + Testi128::test_mul(); } #[test] +#[ignore] // takes several minutes fn test_i128_div() { - TestI128::test_div(); + Testi128::test_div(); } #[test] fn test_i128_pow() { - TestI128::test_pow(); + Testi128::test_pow(); } #[test] fn test_i128_eq() { - TestI128::test_eq(); + Testi128::test_eq(); } #[test] fn test_i128_ge() { - TestI128::test_ge(); + Testi128::test_ge(); } #[test] fn test_i128_gt() { - TestI128::test_gt(); + Testi128::test_gt(); } #[test] fn test_i128_le() { - TestI128::test_le(); + Testi128::test_le(); } #[test] fn test_i128_lt() { - TestI128::test_lt(); + Testi128::test_lt(); } #[test] fn test_i128_assert_eq() { - TestI128::test_assert_eq(); + Testi128::test_assert_eq(); } #[test] fn test_i128_ternary() { - TestI128::test_ternary(); + Testi128::test_ternary(); } diff --git a/compiler/tests/integers/i128/mul.leo b/compiler/tests/integers/i128/mul.leo index 1d2595ca16..f03ca57dd1 100644 --- a/compiler/tests/integers/i128/mul.leo +++ b/compiler/tests/integers/i128/mul.leo @@ -1,3 +1,3 @@ -function main(a: i128, b: i128) -> i128 { - return a * b +function main(a: i128, b: i128, c: i128) { + assert_eq!(a * b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i128/one.leo b/compiler/tests/integers/i128/one.leo deleted file mode 100644 index 94313ac666..0000000000 --- a/compiler/tests/integers/i128/one.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> i128 { - return 1 -} diff --git a/compiler/tests/integers/i128/pow.leo b/compiler/tests/integers/i128/pow.leo index c98bdcfe0d..dde3d48fe7 100644 --- a/compiler/tests/integers/i128/pow.leo +++ b/compiler/tests/integers/i128/pow.leo @@ -1,3 +1,3 @@ -function main(a: i128, b: i128) -> i128 { - return a ** b +function main(a: i128, b: i128, c: i128) { + assert_eq!(a ** b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i128/sub.leo b/compiler/tests/integers/i128/sub.leo index 87e617798f..bb473336c7 100644 --- a/compiler/tests/integers/i128/sub.leo +++ b/compiler/tests/integers/i128/sub.leo @@ -1,3 +1,3 @@ -function main(a: i128, b: i128) -> i128 { - return a - b +function main(a: i128, b: i128, c: i128) { + assert_eq!(a - b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i128/ternary.leo b/compiler/tests/integers/i128/ternary.leo index cb1ff53c68..a0e207d69b 100644 --- a/compiler/tests/integers/i128/ternary.leo +++ b/compiler/tests/integers/i128/ternary.leo @@ -1,3 +1,5 @@ -function main(b: bool, x: i128, y: i128) -> i128 { - return if b ? x : y +function main(s: bool, a: i128, b: i128, c: i128) { + let r = if s ? a : b; + + assert_eq!(r, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i128/zero.leo b/compiler/tests/integers/i128/zero.leo deleted file mode 100644 index e58cdfd4ff..0000000000 --- a/compiler/tests/integers/i128/zero.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> i128 { - return 0 -} diff --git a/compiler/tests/integers/i16/add.leo b/compiler/tests/integers/i16/add.leo index 44486b97ee..ac0bfd8127 100644 --- a/compiler/tests/integers/i16/add.leo +++ b/compiler/tests/integers/i16/add.leo @@ -1,3 +1,3 @@ -function main(a: i16, b: i16) -> i16 { - return a + b +function main(a: i16, b: i16, c: i16) { + assert_eq!(a + b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i16/div.leo b/compiler/tests/integers/i16/div.leo index ea4d4ecded..7facede4fb 100644 --- a/compiler/tests/integers/i16/div.leo +++ b/compiler/tests/integers/i16/div.leo @@ -1,3 +1,3 @@ -function main(a: i16, b: i16) -> i16 { - return a / b +function main(a: i16, b: i16, c: i16) { + assert_eq!(a / b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i16/eq.leo b/compiler/tests/integers/i16/eq.leo index 1ea29bd65e..7cdea269f3 100644 --- a/compiler/tests/integers/i16/eq.leo +++ b/compiler/tests/integers/i16/eq.leo @@ -1,3 +1,3 @@ -function main(a: i16, b: i16) -> bool { - return a == b +function main(a: i16, b: i16, c: bool) { + assert_eq!(a == b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i16/ge.leo b/compiler/tests/integers/i16/ge.leo index 51bb45b725..b4e27b787b 100644 --- a/compiler/tests/integers/i16/ge.leo +++ b/compiler/tests/integers/i16/ge.leo @@ -1,3 +1,3 @@ -function main(a: i16, b: i16) -> bool { - return a >= b +function main(a: i16, b: i16, c: bool) { + assert_eq!(a >= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i16/gt.leo b/compiler/tests/integers/i16/gt.leo index 2a6eeac47a..2132a8aa6b 100644 --- a/compiler/tests/integers/i16/gt.leo +++ b/compiler/tests/integers/i16/gt.leo @@ -1,3 +1,3 @@ -function main(a: i16, b: i16) -> bool { - return a > b +function main(a: i16, b: i16, c: bool) { + assert_eq!(a > b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i16/input.leo b/compiler/tests/integers/i16/input.leo index c4cb048ff6..4bc5fffcad 100644 --- a/compiler/tests/integers/i16/input.leo +++ b/compiler/tests/integers/i16/input.leo @@ -1,3 +1,3 @@ -function main(x: i16) -> i16 { - return x +function main(a: i16, b: i16) { + assert_eq!(a, b); } \ No newline at end of file diff --git a/compiler/tests/integers/i16/le.leo b/compiler/tests/integers/i16/le.leo index cd6d0eb87b..e33b3212f1 100644 --- a/compiler/tests/integers/i16/le.leo +++ b/compiler/tests/integers/i16/le.leo @@ -1,3 +1,3 @@ -function main(a: i16, b: i16) -> bool { - return a <= b +function main(a: i16, b: i16, c: bool) { + assert_eq!(a <= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i16/lt.leo b/compiler/tests/integers/i16/lt.leo index cfdfd24bcb..2a93c04ae3 100644 --- a/compiler/tests/integers/i16/lt.leo +++ b/compiler/tests/integers/i16/lt.leo @@ -1,3 +1,3 @@ -function main(a: i16, b: i16) -> bool { - return a < b +function main(a: i16, b: i16, c: bool) { + assert_eq!(a < b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i16/max.leo b/compiler/tests/integers/i16/max.leo index df19a40dd2..084fe4969a 100644 --- a/compiler/tests/integers/i16/max.leo +++ b/compiler/tests/integers/i16/max.leo @@ -1,3 +1,3 @@ -function main() -> i16 { - return 32767 +function main() { + let a: i16 = 32767; } \ No newline at end of file diff --git a/compiler/tests/integers/i16/max_fail.leo b/compiler/tests/integers/i16/max_fail.leo new file mode 100644 index 0000000000..8dd2b7f50a --- /dev/null +++ b/compiler/tests/integers/i16/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i16 = 32768; +} \ No newline at end of file diff --git a/compiler/tests/integers/i16/min.leo b/compiler/tests/integers/i16/min.leo index 3d5949f073..3331281fcf 100644 --- a/compiler/tests/integers/i16/min.leo +++ b/compiler/tests/integers/i16/min.leo @@ -1,3 +1,3 @@ -function main() -> i16 { - return -32768 +function main() { + let a: i16 = -32768; } \ No newline at end of file diff --git a/compiler/tests/integers/i16/min_fail.leo b/compiler/tests/integers/i16/min_fail.leo new file mode 100644 index 0000000000..380848381a --- /dev/null +++ b/compiler/tests/integers/i16/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i16 = -32769; +} \ No newline at end of file diff --git a/compiler/tests/integers/i16/mod.rs b/compiler/tests/integers/i16/mod.rs index bddaeb84be..adaa1f22f7 100644 --- a/compiler/tests/integers/i16/mod.rs +++ b/compiler/tests/integers/i16/mod.rs @@ -1,105 +1,91 @@ use crate::{ - boolean::{output_expected_boolean, output_false, output_true}, - get_error, - get_output, - integers::{fail_integer, IntegerTester}, + assert_satisfied, + expect_synthesis_error, + generate_main_inputs, + integers::{expect_computation_error, expect_parsing_error, IntegerTester}, parse_program, - EdwardsConstrainedValue, - EdwardsTestCompiler, }; -use leo_compiler::{ConstrainedValue, Integer}; -use leo_gadgets::*; use leo_inputs::types::{I16Type, IntegerType}; use leo_types::InputValue; -use snarkos_curves::edwards_bls12::Fq; -use snarkos_models::gadgets::{r1cs::TestConstraintSystem, utilities::alloc::AllocGadget}; - -fn output_expected_allocated(program: EdwardsTestCompiler, expected: Int16) { - let output = get_output(program); - - match output { - EdwardsConstrainedValue::Return(vec) => match vec.as_slice() { - [ConstrainedValue::Integer(Integer::I16(actual))] => assert_eq!(*actual, expected), - _ => panic!("program output unknown return value"), - }, - _ => panic!("program output unknown return value"), - } -} - -test_int!(TestI16, i16, IntegerType::I16Type(I16Type {}), Int16); +test_int!(Testi16, i16, IntegerType::I16Type(I16Type {}), Int16); #[test] fn test_i16_min() { - TestI16::test_min(std::i16::MIN); + Testi16::test_min(); +} + +#[test] +fn test_i16_min_fail() { + Testi16::test_min_fail(); } #[test] fn test_i16_max() { - TestI16::test_max(std::i16::MAX); + Testi16::test_max(); } #[test] -fn test_i16_input() { - TestI16::test_input(); +fn test_i16_max_fail() { + Testi16::test_max_fail(); } #[test] fn test_i16_add() { - TestI16::test_add(); + Testi16::test_add(); } #[test] fn test_i16_sub() { - TestI16::test_sub(); + Testi16::test_sub(); } #[test] fn test_i16_mul() { - TestI16::test_mul(); + Testi16::test_mul(); } #[test] fn test_i16_div() { - TestI16::test_div(); + Testi16::test_div(); } #[test] fn test_i16_pow() { - TestI16::test_pow(); + Testi16::test_pow(); } #[test] fn test_i16_eq() { - TestI16::test_eq(); + Testi16::test_eq(); } #[test] fn test_i16_ge() { - TestI16::test_ge(); + Testi16::test_ge(); } #[test] fn test_i16_gt() { - TestI16::test_gt(); + Testi16::test_gt(); } #[test] fn test_i16_le() { - TestI16::test_le(); + Testi16::test_le(); } #[test] fn test_i16_lt() { - TestI16::test_lt(); + Testi16::test_lt(); } #[test] fn test_i16_assert_eq() { - TestI16::test_assert_eq(); + Testi16::test_assert_eq(); } #[test] fn test_i16_ternary() { - TestI16::test_ternary(); + Testi16::test_ternary(); } diff --git a/compiler/tests/integers/i16/mul.leo b/compiler/tests/integers/i16/mul.leo index ce0eb504fc..314381d199 100644 --- a/compiler/tests/integers/i16/mul.leo +++ b/compiler/tests/integers/i16/mul.leo @@ -1,3 +1,3 @@ -function main(a: i16, b: i16) -> i16 { - return a * b +function main(a: i16, b: i16, c: i16) { + assert_eq!(a * b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i16/one.leo b/compiler/tests/integers/i16/one.leo deleted file mode 100644 index 40af477ea3..0000000000 --- a/compiler/tests/integers/i16/one.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> i16 { - return 1 -} diff --git a/compiler/tests/integers/i16/pow.leo b/compiler/tests/integers/i16/pow.leo index ca18827873..22bd4baa5d 100644 --- a/compiler/tests/integers/i16/pow.leo +++ b/compiler/tests/integers/i16/pow.leo @@ -1,3 +1,3 @@ -function main(a: i16, b: i16) -> i16 { - return a ** b +function main(a: i16, b: i16, c: i16) { + assert_eq!(a ** b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i16/sub.leo b/compiler/tests/integers/i16/sub.leo index 608aac1793..ef1143d3f5 100644 --- a/compiler/tests/integers/i16/sub.leo +++ b/compiler/tests/integers/i16/sub.leo @@ -1,3 +1,3 @@ -function main(a: i16, b: i16) -> i16 { - return a - b +function main(a: i16, b: i16, c: i16) { + assert_eq!(a - b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i16/ternary.leo b/compiler/tests/integers/i16/ternary.leo index 21d92e0818..0ef5670781 100644 --- a/compiler/tests/integers/i16/ternary.leo +++ b/compiler/tests/integers/i16/ternary.leo @@ -1,3 +1,5 @@ -function main(b: bool, x: i16, y: i16) -> i16 { - return if b ? x : y +function main(s: bool, a: i16, b: i16, c: i16) { + let r = if s ? a : b; + + assert_eq!(r, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i16/zero.leo b/compiler/tests/integers/i16/zero.leo deleted file mode 100644 index 781030f10a..0000000000 --- a/compiler/tests/integers/i16/zero.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> i16 { - return 0 -} diff --git a/compiler/tests/integers/i32/add.leo b/compiler/tests/integers/i32/add.leo index 9c7e8f6433..d670593866 100644 --- a/compiler/tests/integers/i32/add.leo +++ b/compiler/tests/integers/i32/add.leo @@ -1,3 +1,3 @@ -function main(a: i32, b: i32) -> i32 { - return a + b +function main(a: i32, b: i32, c: i32) { + assert_eq!(a + b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i32/div.leo b/compiler/tests/integers/i32/div.leo index 3b1392a921..c183f43ea0 100644 --- a/compiler/tests/integers/i32/div.leo +++ b/compiler/tests/integers/i32/div.leo @@ -1,3 +1,3 @@ -function main(a: i32, b: i32) -> i32 { - return a / b +function main(a: i32, b: i32, c: i32) { + assert_eq!(a / b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i32/eq.leo b/compiler/tests/integers/i32/eq.leo index b3284a07d0..09a3c69f73 100644 --- a/compiler/tests/integers/i32/eq.leo +++ b/compiler/tests/integers/i32/eq.leo @@ -1,3 +1,3 @@ -function main(a: i32, b: i32) -> bool { - return a == b +function main(a: i32, b: i32, c: bool) { + assert_eq!(a == b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i32/ge.leo b/compiler/tests/integers/i32/ge.leo index 073955b53f..99ca610acd 100644 --- a/compiler/tests/integers/i32/ge.leo +++ b/compiler/tests/integers/i32/ge.leo @@ -1,3 +1,3 @@ -function main(a: i32, b: i32) -> bool { - return a >= b +function main(a: i32, b: i32, c: bool) { + assert_eq!(a >= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i32/gt.leo b/compiler/tests/integers/i32/gt.leo index acf027eade..be6645354d 100644 --- a/compiler/tests/integers/i32/gt.leo +++ b/compiler/tests/integers/i32/gt.leo @@ -1,3 +1,3 @@ -function main(a: i32, b: i32) -> bool { - return a > b +function main(a: i32, b: i32, c: bool) { + assert_eq!(a > b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i32/input.leo b/compiler/tests/integers/i32/input.leo index ea6d7f9d30..326cca12b6 100644 --- a/compiler/tests/integers/i32/input.leo +++ b/compiler/tests/integers/i32/input.leo @@ -1,3 +1,3 @@ -function main(x: i32) -> i32 { - return x +function main(a: i32, b: i32) { + assert_eq!(a, b); } \ No newline at end of file diff --git a/compiler/tests/integers/i32/le.leo b/compiler/tests/integers/i32/le.leo index 5f2615cd0a..37682aeda2 100644 --- a/compiler/tests/integers/i32/le.leo +++ b/compiler/tests/integers/i32/le.leo @@ -1,3 +1,3 @@ -function main(a: i32, b: i32) -> bool { - return a <= b +function main(a: i32, b: i32, c: bool) { + assert_eq!(a <= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i32/lt.leo b/compiler/tests/integers/i32/lt.leo index aea55410fa..90965ae47a 100644 --- a/compiler/tests/integers/i32/lt.leo +++ b/compiler/tests/integers/i32/lt.leo @@ -1,3 +1,3 @@ -function main(a: i32, b: i32) -> bool { - return a < b +function main(a: i32, b: i32, c: bool) { + assert_eq!(a < b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i32/max.leo b/compiler/tests/integers/i32/max.leo index d5e3a94dd4..a9c707eb7f 100644 --- a/compiler/tests/integers/i32/max.leo +++ b/compiler/tests/integers/i32/max.leo @@ -1,3 +1,3 @@ -function main() -> i32 { - return 2147483647 +function main() { + let a: i32 = 2147483647; } \ No newline at end of file diff --git a/compiler/tests/integers/i32/max_fail.leo b/compiler/tests/integers/i32/max_fail.leo new file mode 100644 index 0000000000..f3fd81815f --- /dev/null +++ b/compiler/tests/integers/i32/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i32 = 2147483648; +} \ No newline at end of file diff --git a/compiler/tests/integers/i32/min.leo b/compiler/tests/integers/i32/min.leo index 1625435322..a29d591029 100644 --- a/compiler/tests/integers/i32/min.leo +++ b/compiler/tests/integers/i32/min.leo @@ -1,3 +1,3 @@ -function main() -> i32 { - return -2147483648 +function main() { + let a: i32 = -2147483648; } \ No newline at end of file diff --git a/compiler/tests/integers/i32/min_fail.leo b/compiler/tests/integers/i32/min_fail.leo new file mode 100644 index 0000000000..1462d207e9 --- /dev/null +++ b/compiler/tests/integers/i32/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i32 = -2147483649; +} \ No newline at end of file diff --git a/compiler/tests/integers/i32/mod.rs b/compiler/tests/integers/i32/mod.rs index 940379ad8d..e03721dd31 100644 --- a/compiler/tests/integers/i32/mod.rs +++ b/compiler/tests/integers/i32/mod.rs @@ -1,105 +1,91 @@ use crate::{ - boolean::{output_expected_boolean, output_false, output_true}, - get_error, - get_output, - integers::{fail_integer, IntegerTester}, + assert_satisfied, + expect_synthesis_error, + generate_main_inputs, + integers::{expect_computation_error, expect_parsing_error, IntegerTester}, parse_program, - EdwardsConstrainedValue, - EdwardsTestCompiler, }; -use leo_compiler::{ConstrainedValue, Integer}; -use leo_gadgets::*; use leo_inputs::types::{I32Type, IntegerType}; use leo_types::InputValue; -use snarkos_curves::edwards_bls12::Fq; -use snarkos_models::gadgets::{r1cs::TestConstraintSystem, utilities::alloc::AllocGadget}; - -fn output_expected_allocated(program: EdwardsTestCompiler, expected: Int32) { - let output = get_output(program); - - match output { - EdwardsConstrainedValue::Return(vec) => match vec.as_slice() { - [ConstrainedValue::Integer(Integer::I32(actual))] => assert_eq!(*actual, expected), - _ => panic!("program output unknown return value"), - }, - _ => panic!("program output unknown return value"), - } -} - -test_int!(TestI32, i32, IntegerType::I32Type(I32Type {}), Int32); +test_int!(Testi32, i32, IntegerType::I32Type(I32Type {}), Int32); #[test] fn test_i32_min() { - TestI32::test_min(std::i32::MIN); + Testi32::test_min(); +} + +#[test] +fn test_i32_min_fail() { + Testi32::test_min_fail(); } #[test] fn test_i32_max() { - TestI32::test_max(std::i32::MAX); + Testi32::test_max(); } #[test] -fn test_i32_input() { - TestI32::test_input(); +fn test_i32_max_fail() { + Testi32::test_max_fail(); } #[test] fn test_i32_add() { - TestI32::test_add(); + Testi32::test_add(); } #[test] fn test_i32_sub() { - TestI32::test_sub(); + Testi32::test_sub(); } #[test] fn test_i32_mul() { - TestI32::test_mul(); + Testi32::test_mul(); } #[test] fn test_i32_div() { - TestI32::test_div(); + Testi32::test_div(); } #[test] fn test_i32_pow() { - TestI32::test_pow(); + Testi32::test_pow(); } #[test] fn test_i32_eq() { - TestI32::test_eq(); + Testi32::test_eq(); } #[test] fn test_i32_ge() { - TestI32::test_ge(); + Testi32::test_ge(); } #[test] fn test_i32_gt() { - TestI32::test_gt(); + Testi32::test_gt(); } #[test] fn test_i32_le() { - TestI32::test_le(); + Testi32::test_le(); } #[test] fn test_i32_lt() { - TestI32::test_lt(); + Testi32::test_lt(); } #[test] fn test_i32_assert_eq() { - TestI32::test_assert_eq(); + Testi32::test_assert_eq(); } #[test] fn test_i32_ternary() { - TestI32::test_ternary(); + Testi32::test_ternary(); } diff --git a/compiler/tests/integers/i32/mul.leo b/compiler/tests/integers/i32/mul.leo index 8ab0c36205..029aa60758 100644 --- a/compiler/tests/integers/i32/mul.leo +++ b/compiler/tests/integers/i32/mul.leo @@ -1,3 +1,3 @@ -function main(a: i32, b: i32) -> i32 { - return a * b +function main(a: i32, b: i32, c: i32) { + assert_eq!(a * b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i32/one.leo b/compiler/tests/integers/i32/one.leo deleted file mode 100644 index 5ef3894d5e..0000000000 --- a/compiler/tests/integers/i32/one.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> i32 { - return 1 -} diff --git a/compiler/tests/integers/i32/pow.leo b/compiler/tests/integers/i32/pow.leo index 790da91ead..65a840cf26 100644 --- a/compiler/tests/integers/i32/pow.leo +++ b/compiler/tests/integers/i32/pow.leo @@ -1,3 +1,3 @@ -function main(a: i32, b: i32) -> i32 { - return a ** b +function main(a: i32, b: i32, c: i32) { + assert_eq!(a ** b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i32/sub.leo b/compiler/tests/integers/i32/sub.leo index c446484173..03179a547d 100644 --- a/compiler/tests/integers/i32/sub.leo +++ b/compiler/tests/integers/i32/sub.leo @@ -1,3 +1,3 @@ -function main(a: i32, b: i32) -> i32 { - return a - b +function main(a: i32, b: i32, c: i32) { + assert_eq!(a - b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i32/ternary.leo b/compiler/tests/integers/i32/ternary.leo index fbff679a00..211065cea2 100644 --- a/compiler/tests/integers/i32/ternary.leo +++ b/compiler/tests/integers/i32/ternary.leo @@ -1,3 +1,5 @@ -function main(b: bool, x: i32, y: i32) -> i32 { - return if b ? x : y +function main(s: bool, a: i32, b: i32, c: i32) { + let r = if s ? a : b; + + assert_eq!(r, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i32/zero.leo b/compiler/tests/integers/i32/zero.leo deleted file mode 100644 index 53922fcf02..0000000000 --- a/compiler/tests/integers/i32/zero.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> i32 { - return 0 -} diff --git a/compiler/tests/integers/i64/add.leo b/compiler/tests/integers/i64/add.leo index 67d83b4193..edd5137eae 100644 --- a/compiler/tests/integers/i64/add.leo +++ b/compiler/tests/integers/i64/add.leo @@ -1,3 +1,3 @@ -function main(a: i64, b: i64) -> i64 { - return a + b +function main(a: i64, b: i64, c: i64) { + assert_eq!(a + b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i64/div.leo b/compiler/tests/integers/i64/div.leo index e61e6f0850..5fd9b5929e 100644 --- a/compiler/tests/integers/i64/div.leo +++ b/compiler/tests/integers/i64/div.leo @@ -1,3 +1,3 @@ -function main(a: i64, b: i64) -> i64 { - return a / b +function main(a: i64, b: i64, c: i64) { + assert_eq!(a / b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i64/eq.leo b/compiler/tests/integers/i64/eq.leo index af2017d361..736b94efd2 100644 --- a/compiler/tests/integers/i64/eq.leo +++ b/compiler/tests/integers/i64/eq.leo @@ -1,3 +1,3 @@ -function main(a: i64, b: i64) -> bool { - return a == b +function main(a: i64, b: i64, c: bool) { + assert_eq!(a == b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i64/ge.leo b/compiler/tests/integers/i64/ge.leo index cbe7fe0635..00ea4e716b 100644 --- a/compiler/tests/integers/i64/ge.leo +++ b/compiler/tests/integers/i64/ge.leo @@ -1,3 +1,3 @@ -function main(a: i64, b: i64) -> bool { - return a >= b +function main(a: i64, b: i64, c: bool) { + assert_eq!(a >= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i64/gt.leo b/compiler/tests/integers/i64/gt.leo index 77286d5c82..c39799fb2c 100644 --- a/compiler/tests/integers/i64/gt.leo +++ b/compiler/tests/integers/i64/gt.leo @@ -1,3 +1,3 @@ -function main(a: i64, b: i64) -> bool { - return a > b +function main(a: i64, b: i64, c: bool) { + assert_eq!(a > b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i64/input.leo b/compiler/tests/integers/i64/input.leo index b9e90054a6..a9e7b44750 100644 --- a/compiler/tests/integers/i64/input.leo +++ b/compiler/tests/integers/i64/input.leo @@ -1,3 +1,3 @@ -function main(x: i64) -> i64 { - return x +function main(a: i64, b: i64) { + assert_eq!(a, b); } \ No newline at end of file diff --git a/compiler/tests/integers/i64/le.leo b/compiler/tests/integers/i64/le.leo index e2d31dcac5..e8b1f47478 100644 --- a/compiler/tests/integers/i64/le.leo +++ b/compiler/tests/integers/i64/le.leo @@ -1,3 +1,3 @@ -function main(a: i64, b: i64) -> bool { - return a <= b +function main(a: i64, b: i64, c: bool) { + assert_eq!(a <= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i64/lt.leo b/compiler/tests/integers/i64/lt.leo index c46123fc42..a908b8b0f7 100644 --- a/compiler/tests/integers/i64/lt.leo +++ b/compiler/tests/integers/i64/lt.leo @@ -1,3 +1,3 @@ -function main(a: i64, b: i64) -> bool { - return a < b +function main(a: i64, b: i64, c: bool) { + assert_eq!(a < b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i64/max.leo b/compiler/tests/integers/i64/max.leo index 0173b80e94..e0d19881e6 100644 --- a/compiler/tests/integers/i64/max.leo +++ b/compiler/tests/integers/i64/max.leo @@ -1,3 +1,3 @@ -function main() -> i64 { - return 9223372036854775807 +function main() { + let a: i64 = 9223372036854775807; } \ No newline at end of file diff --git a/compiler/tests/integers/i64/max_fail.leo b/compiler/tests/integers/i64/max_fail.leo new file mode 100644 index 0000000000..3e6603e4be --- /dev/null +++ b/compiler/tests/integers/i64/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i64 = 9223372036854775808; +} \ No newline at end of file diff --git a/compiler/tests/integers/i64/min.leo b/compiler/tests/integers/i64/min.leo index 3a1817a736..d7e99a87f8 100644 --- a/compiler/tests/integers/i64/min.leo +++ b/compiler/tests/integers/i64/min.leo @@ -1,3 +1,3 @@ -function main() -> i64 { - return -9223372036854775808 +function main() { + let a: i64 = -9223372036854775808; } \ No newline at end of file diff --git a/compiler/tests/integers/i64/min_fail.leo b/compiler/tests/integers/i64/min_fail.leo new file mode 100644 index 0000000000..11e43646b0 --- /dev/null +++ b/compiler/tests/integers/i64/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i64 = -9223372036854775809; +} \ No newline at end of file diff --git a/compiler/tests/integers/i64/mod.rs b/compiler/tests/integers/i64/mod.rs index e0774f4a85..28dc2b1ae3 100644 --- a/compiler/tests/integers/i64/mod.rs +++ b/compiler/tests/integers/i64/mod.rs @@ -1,105 +1,92 @@ use crate::{ - boolean::{output_expected_boolean, output_false, output_true}, - get_error, - get_output, - integers::{fail_integer, IntegerTester}, + assert_satisfied, + expect_synthesis_error, + generate_main_inputs, + integers::{expect_computation_error, expect_parsing_error, IntegerTester}, parse_program, - EdwardsConstrainedValue, - EdwardsTestCompiler, }; -use leo_compiler::{ConstrainedValue, Integer}; -use leo_gadgets::*; use leo_inputs::types::{I64Type, IntegerType}; use leo_types::InputValue; -use snarkos_curves::edwards_bls12::Fq; -use snarkos_models::gadgets::{r1cs::TestConstraintSystem, utilities::alloc::AllocGadget}; - -fn output_expected_allocated(program: EdwardsTestCompiler, expected: Int64) { - let output = get_output(program); - - match output { - EdwardsConstrainedValue::Return(vec) => match vec.as_slice() { - [ConstrainedValue::Integer(Integer::I64(actual))] => assert_eq!(*actual, expected), - _ => panic!("program output unknown return value"), - }, - _ => panic!("program output unknown return value"), - } -} - -test_int!(TestI64, i64, IntegerType::I64Type(I64Type {}), Int64); +test_int!(Testi64, i64, IntegerType::I64Type(I64Type {}), Int64); #[test] fn test_i64_min() { - TestI64::test_min(std::i64::MIN); + Testi64::test_min(); +} + +#[test] +fn test_i64_min_fail() { + Testi64::test_min_fail(); } #[test] fn test_i64_max() { - TestI64::test_max(std::i64::MAX); + Testi64::test_max(); } #[test] -fn test_i64_input() { - TestI64::test_input(); +fn test_i64_max_fail() { + Testi64::test_max_fail(); } #[test] fn test_i64_add() { - TestI64::test_add(); + Testi64::test_add(); } #[test] fn test_i64_sub() { - TestI64::test_sub(); + Testi64::test_sub(); } #[test] fn test_i64_mul() { - TestI64::test_mul(); + Testi64::test_mul(); } #[test] +#[ignore] // takes 2 minutes fn test_i64_div() { - TestI64::test_div(); + Testi64::test_div(); } #[test] fn test_i64_pow() { - TestI64::test_pow(); + Testi64::test_pow(); } #[test] fn test_i64_eq() { - TestI64::test_eq(); + Testi64::test_eq(); } #[test] fn test_i64_ge() { - TestI64::test_ge(); + Testi64::test_ge(); } #[test] fn test_i64_gt() { - TestI64::test_gt(); + Testi64::test_gt(); } #[test] fn test_i64_le() { - TestI64::test_le(); + Testi64::test_le(); } #[test] fn test_i64_lt() { - TestI64::test_lt(); + Testi64::test_lt(); } #[test] fn test_i64_assert_eq() { - TestI64::test_assert_eq(); + Testi64::test_assert_eq(); } #[test] fn test_i64_ternary() { - TestI64::test_ternary(); + Testi64::test_ternary(); } diff --git a/compiler/tests/integers/i64/mul.leo b/compiler/tests/integers/i64/mul.leo index f9d415009b..cbff5a9cc8 100644 --- a/compiler/tests/integers/i64/mul.leo +++ b/compiler/tests/integers/i64/mul.leo @@ -1,3 +1,3 @@ -function main(a: i64, b: i64) -> i64 { - return a * b +function main(a: i64, b: i64, c: i64) { + assert_eq!(a * b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i64/one.leo b/compiler/tests/integers/i64/one.leo deleted file mode 100644 index c3fd8abc72..0000000000 --- a/compiler/tests/integers/i64/one.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> i64 { - return 1 -} diff --git a/compiler/tests/integers/i64/pow.leo b/compiler/tests/integers/i64/pow.leo index efad660c04..99e71b1968 100644 --- a/compiler/tests/integers/i64/pow.leo +++ b/compiler/tests/integers/i64/pow.leo @@ -1,3 +1,3 @@ -function main(a: i64, b: i64) -> i64 { - return a ** b +function main(a: i64, b: i64, c: i64) { + assert_eq!(a ** b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i64/sub.leo b/compiler/tests/integers/i64/sub.leo index bc5be06b7a..98af2e973a 100644 --- a/compiler/tests/integers/i64/sub.leo +++ b/compiler/tests/integers/i64/sub.leo @@ -1,3 +1,3 @@ -function main(a: i64, b: i64) -> i64 { - return a - b +function main(a: i64, b: i64, c: i64) { + assert_eq!(a - b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i64/ternary.leo b/compiler/tests/integers/i64/ternary.leo index dc7bf1f81e..049e1d8d4e 100644 --- a/compiler/tests/integers/i64/ternary.leo +++ b/compiler/tests/integers/i64/ternary.leo @@ -1,3 +1,5 @@ -function main(b: bool, x: i64, y: i64) -> i64 { - return if b ? x : y +function main(s: bool, a: i64, b: i64, c: i64) { + let r = if s ? a : b; + + assert_eq!(r, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i64/zero.leo b/compiler/tests/integers/i64/zero.leo deleted file mode 100644 index ce0a3bd9c2..0000000000 --- a/compiler/tests/integers/i64/zero.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> i64 { - return 0 -} diff --git a/compiler/tests/integers/i8/add.leo b/compiler/tests/integers/i8/add.leo index 47cd676483..054c46374a 100644 --- a/compiler/tests/integers/i8/add.leo +++ b/compiler/tests/integers/i8/add.leo @@ -1,3 +1,3 @@ -function main(a: i8, b: i8) -> i8 { - return a + b +function main(a: i8, b: i8, c: i8) { + assert_eq!(a + b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i8/div.leo b/compiler/tests/integers/i8/div.leo index 7382b985e9..02cbcb6ee8 100644 --- a/compiler/tests/integers/i8/div.leo +++ b/compiler/tests/integers/i8/div.leo @@ -1,3 +1,3 @@ -function main(a: i8, b: i8) -> i8 { - return a / b +function main(a: i8, b: i8, c: i8) { + assert_eq!(a / b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i8/eq.leo b/compiler/tests/integers/i8/eq.leo index 2b8c3c11bd..6dee94580b 100644 --- a/compiler/tests/integers/i8/eq.leo +++ b/compiler/tests/integers/i8/eq.leo @@ -1,3 +1,3 @@ -function main(a: i8, b: i8) -> bool { - return a == b +function main(a: i8, b: i8, c: bool) { + assert_eq!(a == b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i8/ge.leo b/compiler/tests/integers/i8/ge.leo index 69d9808a09..df95a325bd 100644 --- a/compiler/tests/integers/i8/ge.leo +++ b/compiler/tests/integers/i8/ge.leo @@ -1,3 +1,3 @@ -function main(a: i8, b: i8) -> bool { - return a >= b +function main(a: i8, b: i8, c: bool) { + assert_eq!(a >= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i8/gt.leo b/compiler/tests/integers/i8/gt.leo index 6346b285cd..70c59e398c 100644 --- a/compiler/tests/integers/i8/gt.leo +++ b/compiler/tests/integers/i8/gt.leo @@ -1,3 +1,3 @@ -function main(a: i8, b: i8) -> bool { - return a > b +function main(a: i8, b: i8, c: bool) { + assert_eq!(a > b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i8/input.leo b/compiler/tests/integers/i8/input.leo index ae50705338..c397ca8c07 100644 --- a/compiler/tests/integers/i8/input.leo +++ b/compiler/tests/integers/i8/input.leo @@ -1,3 +1,3 @@ -function main(x: i8) -> i8 { - return x +function main(a: i8, b: i8) { + assert_eq!(a, b); } \ No newline at end of file diff --git a/compiler/tests/integers/i8/le.leo b/compiler/tests/integers/i8/le.leo index 791e64d793..dba7694960 100644 --- a/compiler/tests/integers/i8/le.leo +++ b/compiler/tests/integers/i8/le.leo @@ -1,3 +1,3 @@ -function main(a: i8, b: i8) -> bool { - return a <= b +function main(a: i8, b: i8, c: bool) { + assert_eq!(a <= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i8/lt.leo b/compiler/tests/integers/i8/lt.leo index 00c6e61324..0385ce1c49 100644 --- a/compiler/tests/integers/i8/lt.leo +++ b/compiler/tests/integers/i8/lt.leo @@ -1,3 +1,3 @@ -function main(a: i8, b: i8) -> bool { - return a < b +function main(a: i8, b: i8, c: bool) { + assert_eq!(a < b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i8/max.leo b/compiler/tests/integers/i8/max.leo index ed57f26a33..b51126da59 100644 --- a/compiler/tests/integers/i8/max.leo +++ b/compiler/tests/integers/i8/max.leo @@ -1,3 +1,3 @@ -function main() -> i8 { - return 127 +function main() { + let a: i8 = 127; } \ No newline at end of file diff --git a/compiler/tests/integers/i8/max_fail.leo b/compiler/tests/integers/i8/max_fail.leo new file mode 100644 index 0000000000..4892505915 --- /dev/null +++ b/compiler/tests/integers/i8/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i8 = 128; +} \ No newline at end of file diff --git a/compiler/tests/integers/i8/min.leo b/compiler/tests/integers/i8/min.leo index d334e0ad4c..d3c1bff5e4 100644 --- a/compiler/tests/integers/i8/min.leo +++ b/compiler/tests/integers/i8/min.leo @@ -1,3 +1,3 @@ -function main() -> i8 { - return -128 +function main() { + let a: i8 = -128; } \ No newline at end of file diff --git a/compiler/tests/integers/i8/min_fail.leo b/compiler/tests/integers/i8/min_fail.leo new file mode 100644 index 0000000000..051468ea70 --- /dev/null +++ b/compiler/tests/integers/i8/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i8 = -129; +} \ No newline at end of file diff --git a/compiler/tests/integers/i8/mod.rs b/compiler/tests/integers/i8/mod.rs index 94c1dde76a..3eea9853c1 100644 --- a/compiler/tests/integers/i8/mod.rs +++ b/compiler/tests/integers/i8/mod.rs @@ -1,105 +1,91 @@ use crate::{ - boolean::{output_expected_boolean, output_false, output_true}, - get_error, - get_output, - integers::{fail_integer, IntegerTester}, + assert_satisfied, + expect_synthesis_error, + generate_main_inputs, + integers::{expect_computation_error, expect_parsing_error, IntegerTester}, parse_program, - EdwardsConstrainedValue, - EdwardsTestCompiler, }; -use leo_compiler::{ConstrainedValue, Integer}; -use leo_gadgets::*; use leo_inputs::types::{I8Type, IntegerType}; use leo_types::InputValue; -use snarkos_curves::edwards_bls12::Fq; -use snarkos_models::gadgets::{r1cs::TestConstraintSystem, utilities::alloc::AllocGadget}; - -fn output_expected_allocated(program: EdwardsTestCompiler, expected: Int8) { - let output = get_output(program); - - match output { - EdwardsConstrainedValue::Return(vec) => match vec.as_slice() { - [ConstrainedValue::Integer(Integer::I8(actual))] => assert_eq!(*actual, expected), - _ => panic!("program output unknown return value"), - }, - _ => panic!("program output unknown return value"), - } -} - -test_int!(TestI8, i8, IntegerType::I8Type(I8Type {}), Int8); +test_int!(Testi8, i8, IntegerType::I8Type(I8Type {}), Int8); #[test] fn test_i8_min() { - TestI8::test_min(std::i8::MIN); + Testi8::test_min(); +} + +#[test] +fn test_i8_min_fail() { + Testi8::test_min_fail(); } #[test] fn test_i8_max() { - TestI8::test_max(std::i8::MAX); + Testi8::test_max(); } #[test] -fn test_i8_input() { - TestI8::test_input(); +fn test_i8_max_fail() { + Testi8::test_max_fail(); } #[test] fn test_i8_add() { - TestI8::test_add(); + Testi8::test_add(); } #[test] fn test_i8_sub() { - TestI8::test_sub(); + Testi8::test_sub(); } #[test] fn test_i8_mul() { - TestI8::test_mul(); + Testi8::test_mul(); } #[test] fn test_i8_div() { - TestI8::test_div(); + Testi8::test_div(); } #[test] fn test_i8_pow() { - TestI8::test_pow(); + Testi8::test_pow(); } #[test] fn test_i8_eq() { - TestI8::test_eq(); + Testi8::test_eq(); } #[test] fn test_i8_ge() { - TestI8::test_ge(); + Testi8::test_ge(); } #[test] fn test_i8_gt() { - TestI8::test_gt(); + Testi8::test_gt(); } #[test] fn test_i8_le() { - TestI8::test_le(); + Testi8::test_le(); } #[test] fn test_i8_lt() { - TestI8::test_lt(); + Testi8::test_lt(); } #[test] fn test_i8_assert_eq() { - TestI8::test_assert_eq(); + Testi8::test_assert_eq(); } #[test] fn test_i8_ternary() { - TestI8::test_ternary(); + Testi8::test_ternary(); } diff --git a/compiler/tests/integers/i8/mul.leo b/compiler/tests/integers/i8/mul.leo index 88c4fa5b5d..3542bc092c 100644 --- a/compiler/tests/integers/i8/mul.leo +++ b/compiler/tests/integers/i8/mul.leo @@ -1,3 +1,3 @@ -function main(a: i8, b: i8) -> i8 { - return a * b +function main(a: i8, b: i8, c: i8) { + assert_eq!(a * b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i8/one.leo b/compiler/tests/integers/i8/one.leo deleted file mode 100644 index 2e0ffefa27..0000000000 --- a/compiler/tests/integers/i8/one.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> i8 { - return 1 -} diff --git a/compiler/tests/integers/i8/pow.leo b/compiler/tests/integers/i8/pow.leo index 68837dda70..c66bb67b7a 100644 --- a/compiler/tests/integers/i8/pow.leo +++ b/compiler/tests/integers/i8/pow.leo @@ -1,3 +1,3 @@ -function main(a: i8, b: i8) -> i8 { - return a ** b +function main(a: i8, b: i8, c: i8) { + assert_eq!(a ** b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i8/sub.leo b/compiler/tests/integers/i8/sub.leo index 234a4f4fee..b4a4ad01d9 100644 --- a/compiler/tests/integers/i8/sub.leo +++ b/compiler/tests/integers/i8/sub.leo @@ -1,3 +1,3 @@ -function main(a: i8, b: i8) -> i8 { - return a - b +function main(a: i8, b: i8, c: i8) { + assert_eq!(a - b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i8/ternary.leo b/compiler/tests/integers/i8/ternary.leo index 68bcbd1a03..1de75a7b99 100644 --- a/compiler/tests/integers/i8/ternary.leo +++ b/compiler/tests/integers/i8/ternary.leo @@ -1,3 +1,5 @@ -function main(b: bool, x: i8, y: i8) -> i8 { - return if b ? x : y +function main(s: bool, a: i8, b: i8, c: i8) { + let r = if s ? a : b; + + assert_eq!(r, c); } \ No newline at end of file diff --git a/compiler/tests/integers/i8/zero.leo b/compiler/tests/integers/i8/zero.leo deleted file mode 100644 index d58befa8b9..0000000000 --- a/compiler/tests/integers/i8/zero.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> i8 { - return 0 -} diff --git a/compiler/tests/integers/int_macro.rs b/compiler/tests/integers/int_macro.rs index 0c40e783ee..a5db68321f 100644 --- a/compiler/tests/integers/int_macro.rs +++ b/compiler/tests/integers/int_macro.rs @@ -2,405 +2,437 @@ macro_rules! test_int { ($name: ident, $type_: ty, $integer_type: expr, $gadget: ty) => { pub struct $name {} - impl $name { - fn test_min(min: $type_) { - let min_allocated = <$gadget>::constant(min); - + impl IntegerTester for $name { + fn test_min() { let bytes = include_bytes!("min.leo"); let program = parse_program(bytes).unwrap(); - output_expected_allocated(program, min_allocated); + assert_satisfied(program); } - fn test_max(max: $type_) { - let max_allocated = <$gadget>::constant(max); + fn test_min_fail() { + let bytes = include_bytes!("min_fail.leo"); + let program = parse_program(bytes).unwrap(); + expect_parsing_error(program); + } + + fn test_max() { let bytes = include_bytes!("max.leo"); let program = parse_program(bytes).unwrap(); - output_expected_allocated(program, max_allocated); + assert_satisfied(program); } - } - impl IntegerTester for $name { - fn test_input() { - // valid input - let num: $type_ = rand::random(); - let expected = <$gadget>::constant(num); + fn test_max_fail() { + let bytes = include_bytes!("max_fail.leo"); + let program = parse_program(bytes).unwrap(); - let bytes = include_bytes!("input.leo"); - let mut program = parse_program(bytes).unwrap(); - - program.set_inputs(vec![Some(InputValue::Integer($integer_type, num.to_string()))]); - - output_expected_allocated(program, expected); - - // invalid input - let mut program = parse_program(bytes).unwrap(); - - program.set_inputs(vec![Some(InputValue::Boolean(true))]); - fail_integer(program); - - // None input - let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![None]); - fail_integer(program); + expect_parsing_error(program); } fn test_add() { for _ in 0..10 { - let r1: $type_ = rand::random(); - let r2: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); - let sum = match r1.checked_add(r2) { + let c = match a.checked_add(b) { Some(valid) => valid, None => continue, }; - let cs = TestConstraintSystem::::new(); - let sum_allocated = <$gadget>::alloc(cs, || Ok(sum)).unwrap(); - let bytes = include_bytes!("add.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Integer($integer_type, c.to_string()))), ]); - output_expected_allocated(program, sum_allocated); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_sub() { for _ in 0..10 { - let r1: $type_ = rand::random(); - let r2: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); - if r2.checked_neg().is_none() { + if b.checked_neg().is_none() { continue; } - let difference = match r1.checked_sub(r2) { + let c = match a.checked_sub(b) { Some(valid) => valid, None => continue, }; - let cs = TestConstraintSystem::::new(); - let difference_allocated = <$gadget>::alloc(cs, || Ok(difference)).unwrap(); - let bytes = include_bytes!("sub.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Integer($integer_type, c.to_string()))), ]); - output_expected_allocated(program, difference_allocated); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_mul() { for _ in 0..10 { - let r1: $type_ = rand::random(); - let r2: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); - let product = match r1.checked_mul(r2) { + let c = match a.checked_mul(b) { Some(valid) => valid, None => continue, }; - let cs = TestConstraintSystem::::new(); - let product_allocated = <$gadget>::alloc(cs, || Ok(product)).unwrap(); - let bytes = include_bytes!("mul.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Integer($integer_type, c.to_string()))), ]); - output_expected_allocated(program, product_allocated); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_div() { - // for _ in 0..10 {// these loops take an excessive amount of time - let r1: $type_ = rand::random(); - let r2: $type_ = rand::random(); + for _ in 0..10 { + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); - let bytes = include_bytes!("div.leo"); - let mut program = parse_program(bytes).unwrap(); + let bytes = include_bytes!("div.leo"); + let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), - ]); + // expect an error when dividing by zero + if b == 0 { + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Integer($integer_type, b.to_string()))), + ]); - // expect an error when dividing by zero - if r2 == 0 { - let _err = get_error(program); - } else { - let cs = TestConstraintSystem::::new(); + program.set_main_inputs(main_inputs); - let quotient = match r1.checked_div(r2) { - Some(valid) => valid, - None => return, - }; - let quotient_allocated = <$gadget>::alloc(cs, || Ok(quotient)).unwrap(); + expect_computation_error(program); + } else { + let c = match a.checked_div(b) { + Some(valid) => valid, + None => continue, + }; - output_expected_allocated(program, quotient_allocated); + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Integer($integer_type, c.to_string()))), + ]); + + program.set_main_inputs(main_inputs); + + assert_satisfied(program); + } } - // } } fn test_pow() { - // for _ in 0..10 {// these loops take an excessive amount of time - let r1: $type_ = rand::random(); - let r2: $type_ = rand::random(); - let r2 = r2 as u32; // we cast to u32 here because of rust pow() requirements + for _ in 0..10 { + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); - let result = match r1.checked_pow(r2) { - Some(valid) => valid, - None => return, - }; + // rust specific conversion see https://doc.rust-lang.org/std/primitive.u8.html#method.checked_pow + let c = match a.checked_pow(b as u32) { + Some(valid) => valid, + None => continue, + }; - let cs = TestConstraintSystem::::new(); - let result_allocated = <$gadget>::alloc(cs, || Ok(result)).unwrap(); + let bytes = include_bytes!("pow.leo"); + let mut program = parse_program(bytes).unwrap(); - let bytes = include_bytes!("pow.leo"); - let mut program = parse_program(bytes).unwrap(); + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Integer($integer_type, c.to_string()))), + ]); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), - ]); + program.set_main_inputs(main_inputs); - output_expected_allocated(program, result_allocated); - // } + assert_satisfied(program); + } } fn test_eq() { for _ in 0..10 { - let r1: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); // test equal + let bytes = include_bytes!("eq.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r1.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, a.to_string()))), + ("c", Some(InputValue::Boolean(true))), ]); - output_true(program); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); // test not equal - let r2: $type_ = rand::random(); - let result = r1.eq(&r2); + let c = a.eq(&b); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Boolean(c))), ]); - output_expected_boolean(program, result); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_ge() { for _ in 0..10 { - let r1: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); // test equal + let bytes = include_bytes!("ge.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r1.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, a.to_string()))), + ("c", Some(InputValue::Boolean(true))), ]); - output_true(program); + program.set_main_inputs(main_inputs); - // test not equal - let r2: $type_ = rand::random(); + assert_satisfied(program); - let result = r1.ge(&r2); + // test greater or equal + + let c = a.ge(&b); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Boolean(c))), ]); - output_expected_boolean(program, result); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_gt() { for _ in 0..10 { - let r1: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); // test equal + let bytes = include_bytes!("gt.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r1.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, a.to_string()))), + ("c", Some(InputValue::Boolean(false))), ]); - output_false(program); + program.set_main_inputs(main_inputs); - // test not equal - let r2: $type_ = rand::random(); + assert_satisfied(program); - let result = r1.gt(&r2); + // test greater than + + let c = a.gt(&b); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Boolean(c))), ]); - output_expected_boolean(program, result); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_le() { for _ in 0..10 { - let r1: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); // test equal + let bytes = include_bytes!("le.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r1.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, a.to_string()))), + ("c", Some(InputValue::Boolean(true))), ]); - output_true(program); + program.set_main_inputs(main_inputs); - // test not equal - let r2: $type_ = rand::random(); + assert_satisfied(program); - let result = r1.le(&r2); + // test less or equal + + let c = a.le(&b); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Boolean(c))), ]); - output_expected_boolean(program, result); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_lt() { for _ in 0..10 { - let r1: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); // test equal + let bytes = include_bytes!("lt.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r1.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, a.to_string()))), + ("c", Some(InputValue::Boolean(false))), ]); - output_false(program); + program.set_main_inputs(main_inputs); - // test not equal - let r2: $type_ = rand::random(); + assert_satisfied(program); - let result = r1.lt(&r2); + // test less or equal + + let c = a.lt(&b); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Boolean(c))), ]); - output_expected_boolean(program, result); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_assert_eq() { for _ in 0..10 { - let r1: $type_ = rand::random(); + let a: $type_ = rand::random(); // test equal let bytes = include_bytes!("assert_eq.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r1.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, a.to_string()))), ]); - let _ = get_output(program); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); // test not equal - let r2: $type_ = rand::random(); + let b: $type_ = rand::random(); - if r1 == r2 { + if a == b { continue; } let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), ]); - let mut cs = TestConstraintSystem::::new(); - let _ = program.compile_constraints(&mut cs).unwrap(); - assert!(!cs.is_satisfied()); + program.set_main_inputs(main_inputs); + + expect_synthesis_error(program); } } fn test_ternary() { - let r1: $type_ = rand::random(); - let r2: $type_ = rand::random(); - - let g1 = <$gadget>::constant(r1); - let g2 = <$gadget>::constant(r2); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); let bytes = include_bytes!("ternary.leo"); - let mut program_1 = parse_program(bytes).unwrap(); - - let mut program_2 = program_1.clone(); + let mut program = parse_program(bytes).unwrap(); // true -> field 1 - program_1.set_inputs(vec![ - Some(InputValue::Boolean(true)), - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("s", Some(InputValue::Boolean(true))), + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Integer($integer_type, a.to_string()))), ]); - output_expected_allocated(program_1, g1); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); // false -> field 2 - program_2.set_inputs(vec![ - Some(InputValue::Boolean(false)), - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let mut program = parse_program(bytes).unwrap(); + + let main_inputs = generate_main_inputs(vec![ + ("s", Some(InputValue::Boolean(false))), + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Integer($integer_type, b.to_string()))), ]); - output_expected_allocated(program_2, g2); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } }; diff --git a/compiler/tests/integers/integer_tester.rs b/compiler/tests/integers/integer_tester.rs index 700edb0bbc..713bfc34e0 100644 --- a/compiler/tests/integers/integer_tester.rs +++ b/compiler/tests/integers/integer_tester.rs @@ -1,23 +1,32 @@ -use crate::{get_error, EdwardsTestCompiler}; -use leo_compiler::errors::{CompilerError, FunctionError, IntegerError}; +use crate::{expect_compiler_error, EdwardsTestCompiler}; +use leo_compiler::errors::{CompilerError, ExpressionError, FunctionError, IntegerError, StatementError, ValueError}; pub trait IntegerTester { - /// Tests use of the integer in a function input - fn test_input(); + /// Tests defining the smalled value that can be represented by the integer type + fn test_min(); - /// Tests a wrapping addition + /// Tests defining the smallest value - 1 + fn test_min_fail(); + + /// Tests defining the largest value that can be represented by the integer type + fn test_max(); + + /// Tests defining the largest value + 1 + fn test_max_fail(); + + /// Tests a non-wrapping addition fn test_add(); - /// Tests a wrapping subtraction + /// Tests a non-wrapping subtraction fn test_sub(); - /// Tests a wrapping multiplication + /// Tests a non-wrapping multiplication fn test_mul(); /// Tests a non-wrapping division fn test_div(); - /// Tests a wrapping exponentiation + /// Tests a non-wrapping exponentiation fn test_pow(); /// Tests == evaluation @@ -42,9 +51,23 @@ pub trait IntegerTester { fn test_ternary(); } -pub(crate) fn fail_integer(program: EdwardsTestCompiler) { - match get_error(program) { - CompilerError::FunctionError(FunctionError::IntegerError(IntegerError::Error(_string))) => {} - error => panic!("Expected invalid boolean error, got {}", error), +pub(crate) fn expect_parsing_error(program: EdwardsTestCompiler) { + match expect_compiler_error(program) { + CompilerError::FunctionError(FunctionError::StatementError(StatementError::ExpressionError( + ExpressionError::ValueError(ValueError::IntegerError(IntegerError::Error(_))), + ))) => {} + error => panic!("Expected integer parsing error, found {:?}", error), + } +} + +pub(crate) fn expect_computation_error(program: EdwardsTestCompiler) { + match expect_compiler_error(program) { + CompilerError::FunctionError(FunctionError::StatementError(StatementError::ExpressionError( + ExpressionError::IntegerError(IntegerError::Error(_)), + ))) => {} + error => panic!( + "Expected integer computation error such as `DivisionByZero`, found {:?}", + error + ), } } diff --git a/compiler/tests/integers/u128/add.leo b/compiler/tests/integers/u128/add.leo index 7f35c07751..d03c236d3e 100644 --- a/compiler/tests/integers/u128/add.leo +++ b/compiler/tests/integers/u128/add.leo @@ -1,3 +1,3 @@ -function main(a: u128, b: u128) -> u128 { - return a + b +function main(a: u128, b: u128, c: u128) { + assert_eq!(a + b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u128/div.leo b/compiler/tests/integers/u128/div.leo index a9c65e885c..04e75f6cff 100644 --- a/compiler/tests/integers/u128/div.leo +++ b/compiler/tests/integers/u128/div.leo @@ -1,3 +1,3 @@ -function main(a: u128, b: u128) -> u128 { - return a / b +function main(a: u128, b: u128, c: u128) { + assert_eq!(a / b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u128/eq.leo b/compiler/tests/integers/u128/eq.leo index c1fd10e66b..52821882d0 100644 --- a/compiler/tests/integers/u128/eq.leo +++ b/compiler/tests/integers/u128/eq.leo @@ -1,3 +1,3 @@ -function main(a: u128, b: u128) -> bool { - return a == b +function main(a: u128, b: u128, c: bool) { + assert_eq!(a == b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u128/ge.leo b/compiler/tests/integers/u128/ge.leo index 8488e49b55..8e18e647a8 100644 --- a/compiler/tests/integers/u128/ge.leo +++ b/compiler/tests/integers/u128/ge.leo @@ -1,3 +1,3 @@ -function main(a: u128, b: u128) -> bool { - return a >= b +function main(a: u128, b: u128, c: bool) { + assert_eq!(a >= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u128/gt.leo b/compiler/tests/integers/u128/gt.leo index d67b008595..6c2208917c 100644 --- a/compiler/tests/integers/u128/gt.leo +++ b/compiler/tests/integers/u128/gt.leo @@ -1,3 +1,3 @@ -function main(a: u128, b: u128) -> bool { - return a > b +function main(a: u128, b: u128, c: bool) { + assert_eq!(a > b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u128/input.leo b/compiler/tests/integers/u128/input.leo index 4424cccda9..9ee2ff0f12 100644 --- a/compiler/tests/integers/u128/input.leo +++ b/compiler/tests/integers/u128/input.leo @@ -1,3 +1,3 @@ -function main(x: u128) -> u128 { - return x +function main(a: u128, b: u128) { + assert_eq!(a, b); } \ No newline at end of file diff --git a/compiler/tests/integers/u128/le.leo b/compiler/tests/integers/u128/le.leo index cfc4fb9d7c..c2cd03db53 100644 --- a/compiler/tests/integers/u128/le.leo +++ b/compiler/tests/integers/u128/le.leo @@ -1,3 +1,3 @@ -function main(a: u128, b: u128) -> bool { - return a <= b +function main(a: u128, b: u128, c: bool) { + assert_eq!(a <= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u128/lt.leo b/compiler/tests/integers/u128/lt.leo index 35fdd5dd6b..af80c96c34 100644 --- a/compiler/tests/integers/u128/lt.leo +++ b/compiler/tests/integers/u128/lt.leo @@ -1,3 +1,3 @@ -function main(a: u128, b: u128) -> bool { - return a < b +function main(a: u128, b: u128, c: bool) { + assert_eq!(a < b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u128/max.leo b/compiler/tests/integers/u128/max.leo index 91965c2bc4..6da59dd058 100644 --- a/compiler/tests/integers/u128/max.leo +++ b/compiler/tests/integers/u128/max.leo @@ -1,3 +1,3 @@ -function main() -> u128 { - return 340282366920938463463374607431768211455 +function main() { + let a: u128 = 340282366920938463463374607431768211455; } \ No newline at end of file diff --git a/compiler/tests/integers/u128/max_fail.leo b/compiler/tests/integers/u128/max_fail.leo new file mode 100644 index 0000000000..40cdf7d2bb --- /dev/null +++ b/compiler/tests/integers/u128/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u128 = 340282366920938463463374607431768211456; +} \ No newline at end of file diff --git a/compiler/tests/integers/u128/min.leo b/compiler/tests/integers/u128/min.leo index cd626f2125..044bda9e1c 100644 --- a/compiler/tests/integers/u128/min.leo +++ b/compiler/tests/integers/u128/min.leo @@ -1,3 +1,3 @@ -function main() -> u128 { - return 0 +function main() { + let a: u128 = 0; } \ No newline at end of file diff --git a/compiler/tests/integers/u128/min_fail.leo b/compiler/tests/integers/u128/min_fail.leo new file mode 100644 index 0000000000..df2390c576 --- /dev/null +++ b/compiler/tests/integers/u128/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u128 = -1; +} \ No newline at end of file diff --git a/compiler/tests/integers/u128/mod.rs b/compiler/tests/integers/u128/mod.rs index e1a8470c60..fa0b42ffca 100644 --- a/compiler/tests/integers/u128/mod.rs +++ b/compiler/tests/integers/u128/mod.rs @@ -1,48 +1,33 @@ use crate::{ - boolean::{output_expected_boolean, output_false, output_true}, - get_error, - get_output, - integers::{fail_integer, IntegerTester}, + assert_satisfied, + expect_synthesis_error, + generate_main_inputs, + integers::{expect_parsing_error, IntegerTester}, parse_program, - EdwardsConstrainedValue, - EdwardsTestCompiler, }; -use leo_compiler::{ConstrainedValue, Integer}; use leo_inputs::types::{IntegerType, U128Type}; use leo_types::InputValue; -use snarkos_curves::edwards_bls12::Fq; -use snarkos_models::gadgets::{ - r1cs::TestConstraintSystem, - utilities::{alloc::AllocGadget, uint::UInt128}, -}; - -fn output_expected_allocated(program: EdwardsTestCompiler, expected: UInt128) { - let output = get_output(program); - - match output { - EdwardsConstrainedValue::Return(vec) => match vec.as_slice() { - [ConstrainedValue::Integer(Integer::U128(actual))] => assert_eq!(*actual, expected), - _ => panic!("program output unknown return value"), - }, - _ => panic!("program output unknown return value"), - } -} test_uint!(TestU128, u128, IntegerType::U128Type(U128Type {}), UInt128); #[test] fn test_u128_min() { - TestU128::test_min(std::u128::MIN); + TestU128::test_min(); +} + +#[test] +fn test_u128_min_fail() { + TestU128::test_min_fail(); } #[test] fn test_u128_max() { - TestU128::test_max(std::u128::MAX); + TestU128::test_max(); } #[test] -fn test_u128_input() { - TestU128::test_input(); +fn test_u128_max_fail() { + TestU128::test_max_fail(); } #[test] @@ -55,18 +40,17 @@ fn test_u128_sub() { TestU128::test_sub(); } -#[test] // this test take ~1 min +#[test] fn test_u128_mul() { TestU128::test_mul(); } -#[test] // this test takes ~30 sec +#[test] fn test_u128_div() { TestU128::test_div(); } #[test] -#[ignore] // this test takes ~10 mins fn test_u128_pow() { TestU128::test_pow(); } diff --git a/compiler/tests/integers/u128/mul.leo b/compiler/tests/integers/u128/mul.leo index 69f5787c02..eb22c254e3 100644 --- a/compiler/tests/integers/u128/mul.leo +++ b/compiler/tests/integers/u128/mul.leo @@ -1,3 +1,3 @@ -function main(a: u128, b: u128) -> u128 { - return a * b +function main(a: u128, b: u128, c: u128) { + assert_eq!(a * b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u128/one.leo b/compiler/tests/integers/u128/one.leo deleted file mode 100644 index 68a6eaf479..0000000000 --- a/compiler/tests/integers/u128/one.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> u128 { - return 1 -} diff --git a/compiler/tests/integers/u128/pow.leo b/compiler/tests/integers/u128/pow.leo index b18fad1df3..4d63290922 100644 --- a/compiler/tests/integers/u128/pow.leo +++ b/compiler/tests/integers/u128/pow.leo @@ -1,3 +1,3 @@ -function main(a: u128, b: u128) -> u128 { - return a ** b +function main(a: u128, b: u128, c: u128) { + assert_eq!(a ** b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u128/sub.leo b/compiler/tests/integers/u128/sub.leo index 408ff755ff..14b9925cbe 100644 --- a/compiler/tests/integers/u128/sub.leo +++ b/compiler/tests/integers/u128/sub.leo @@ -1,3 +1,3 @@ -function main(a: u128, b: u128) -> u128 { - return a - b +function main(a: u128, b: u128, c: u128) { + assert_eq!(a - b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u128/ternary.leo b/compiler/tests/integers/u128/ternary.leo index 2ebc800648..f604e6dcf6 100644 --- a/compiler/tests/integers/u128/ternary.leo +++ b/compiler/tests/integers/u128/ternary.leo @@ -1,3 +1,5 @@ -function main(b: bool, x: u128, y: u128) -> u128 { - return if b ? x : y +function main(s: bool, a: u128, b: u128, c: u128) { + let r = if s ? a : b; + + assert_eq!(r, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u128/zero.leo b/compiler/tests/integers/u128/zero.leo deleted file mode 100644 index e18253a062..0000000000 --- a/compiler/tests/integers/u128/zero.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> u128 { - return 0 -} diff --git a/compiler/tests/integers/u16/add.leo b/compiler/tests/integers/u16/add.leo index 93b807afda..e693fb7075 100644 --- a/compiler/tests/integers/u16/add.leo +++ b/compiler/tests/integers/u16/add.leo @@ -1,3 +1,3 @@ -function main(a: u16, b: u16) -> u16 { - return a + b +function main(a: u16, b: u16, c: u16) { + assert_eq!(a + b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u16/div.leo b/compiler/tests/integers/u16/div.leo index 1290856935..a136fd238e 100644 --- a/compiler/tests/integers/u16/div.leo +++ b/compiler/tests/integers/u16/div.leo @@ -1,3 +1,3 @@ -function main(a: u16, b: u16) -> u16 { - return a / b +function main(a: u16, b: u16, c: u16) { + assert_eq!(a / b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u16/eq.leo b/compiler/tests/integers/u16/eq.leo index bb643aca0b..d194b3a60c 100644 --- a/compiler/tests/integers/u16/eq.leo +++ b/compiler/tests/integers/u16/eq.leo @@ -1,3 +1,3 @@ -function main(a: u16, b: u16) -> bool { - return a == b +function main(a: u16, b: u16, c: bool) { + assert_eq!(a == b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u16/ge.leo b/compiler/tests/integers/u16/ge.leo index 4f4d2b8a79..91e03c4303 100644 --- a/compiler/tests/integers/u16/ge.leo +++ b/compiler/tests/integers/u16/ge.leo @@ -1,3 +1,3 @@ -function main(a: u16, b: u16) -> bool { - return a >= b +function main(a: u16, b: u16, c: bool) { + assert_eq!(a >= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u16/gt.leo b/compiler/tests/integers/u16/gt.leo index 4c234b4c9a..499d0296c3 100644 --- a/compiler/tests/integers/u16/gt.leo +++ b/compiler/tests/integers/u16/gt.leo @@ -1,3 +1,3 @@ -function main(a: u16, b: u16) -> bool { - return a > b +function main(a: u16, b: u16, c: bool) { + assert_eq!(a > b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u16/input.leo b/compiler/tests/integers/u16/input.leo index 2a4801074f..38f850139c 100644 --- a/compiler/tests/integers/u16/input.leo +++ b/compiler/tests/integers/u16/input.leo @@ -1,3 +1,3 @@ -function main(x: u16) -> u16 { - return x +function main(a: u16, b: u16) { + assert_eq!(a, b); } \ No newline at end of file diff --git a/compiler/tests/integers/u16/le.leo b/compiler/tests/integers/u16/le.leo index b463e929a4..bcee775d58 100644 --- a/compiler/tests/integers/u16/le.leo +++ b/compiler/tests/integers/u16/le.leo @@ -1,3 +1,3 @@ -function main(a: u16, b: u16) -> bool { - return a <= b +function main(a: u16, b: u16, c: bool) { + assert_eq!(a <= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u16/lt.leo b/compiler/tests/integers/u16/lt.leo index 05cb9b54b5..2fe4a8a37a 100644 --- a/compiler/tests/integers/u16/lt.leo +++ b/compiler/tests/integers/u16/lt.leo @@ -1,3 +1,3 @@ -function main(a: u16, b: u16) -> bool { - return a < b +function main(a: u16, b: u16, c: bool) { + assert_eq!(a < b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u16/max.leo b/compiler/tests/integers/u16/max.leo index 2e87cbac0e..a707df9af8 100644 --- a/compiler/tests/integers/u16/max.leo +++ b/compiler/tests/integers/u16/max.leo @@ -1,3 +1,3 @@ -function main() -> u16 { - return 65535 +function main() { + let a: u16 = 65535; } \ No newline at end of file diff --git a/compiler/tests/integers/u16/max_fail.leo b/compiler/tests/integers/u16/max_fail.leo new file mode 100644 index 0000000000..68ff0481e0 --- /dev/null +++ b/compiler/tests/integers/u16/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u16 = 65536; +} \ No newline at end of file diff --git a/compiler/tests/integers/u16/min.leo b/compiler/tests/integers/u16/min.leo index d3f9ed6824..ab1bd7db48 100644 --- a/compiler/tests/integers/u16/min.leo +++ b/compiler/tests/integers/u16/min.leo @@ -1,3 +1,3 @@ -function main() -> u16 { - return 0 +function main() { + let a: u16 = 0; } \ No newline at end of file diff --git a/compiler/tests/integers/u16/min_fail.leo b/compiler/tests/integers/u16/min_fail.leo new file mode 100644 index 0000000000..99b7310362 --- /dev/null +++ b/compiler/tests/integers/u16/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u16 = -1; +} \ No newline at end of file diff --git a/compiler/tests/integers/u16/mod.rs b/compiler/tests/integers/u16/mod.rs index 15534974e3..dd50f0788a 100644 --- a/compiler/tests/integers/u16/mod.rs +++ b/compiler/tests/integers/u16/mod.rs @@ -1,49 +1,33 @@ use crate::{ - boolean::{output_expected_boolean, output_false, output_true}, - get_error, - get_output, - integers::{fail_integer, IntegerTester}, + assert_satisfied, + expect_synthesis_error, + generate_main_inputs, + integers::{expect_parsing_error, IntegerTester}, parse_program, - EdwardsConstrainedValue, - EdwardsTestCompiler, }; -use leo_compiler::{ConstrainedValue, Integer}; use leo_inputs::types::{IntegerType, U16Type}; use leo_types::InputValue; -use snarkos_curves::edwards_bls12::Fq; -use snarkos_models::gadgets::{ - r1cs::TestConstraintSystem, - utilities::{alloc::AllocGadget, uint::UInt16}, -}; - -fn output_expected_allocated(program: EdwardsTestCompiler, expected: UInt16) { - let output = get_output(program); - - match output { - EdwardsConstrainedValue::Return(vec) => match vec.as_slice() { - [ConstrainedValue::Integer(Integer::U16(actual))] => assert_eq!(*actual, expected), - _ => panic!("program output unknown return value"), - }, - _ => panic!("program output unknown return value"), - } -} - test_uint!(TestU16, u16, IntegerType::U16Type(U16Type {}), UInt16); #[test] fn test_u16_min() { - TestU16::test_min(std::u16::MIN); + TestU16::test_min(); +} + +#[test] +fn test_u16_min_fail() { + TestU16::test_min_fail(); } #[test] fn test_u16_max() { - TestU16::test_max(std::u16::MAX); + TestU16::test_max(); } #[test] -fn test_u16_input() { - TestU16::test_input(); +fn test_u16_max_fail() { + TestU16::test_max_fail(); } #[test] diff --git a/compiler/tests/integers/u16/mul.leo b/compiler/tests/integers/u16/mul.leo index 4eba72e95e..87fa28c5d2 100644 --- a/compiler/tests/integers/u16/mul.leo +++ b/compiler/tests/integers/u16/mul.leo @@ -1,3 +1,3 @@ -function main(a: u16, b: u16) -> u16 { - return a * b +function main(a: u16, b: u16, c: u16) { + assert_eq!(a * b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u16/one.leo b/compiler/tests/integers/u16/one.leo deleted file mode 100644 index e3622e2b64..0000000000 --- a/compiler/tests/integers/u16/one.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> u16 { - return 1 -} diff --git a/compiler/tests/integers/u16/pow.leo b/compiler/tests/integers/u16/pow.leo index d772278ddc..2fe42e8822 100644 --- a/compiler/tests/integers/u16/pow.leo +++ b/compiler/tests/integers/u16/pow.leo @@ -1,3 +1,3 @@ -function main(a: u16, b: u16) -> u16 { - return a ** b +function main(a: u16, b: u16, c: u16) { + assert_eq!(a ** b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u16/sub.leo b/compiler/tests/integers/u16/sub.leo index 6c3f358a67..5f60b58a52 100644 --- a/compiler/tests/integers/u16/sub.leo +++ b/compiler/tests/integers/u16/sub.leo @@ -1,3 +1,3 @@ -function main(a: u16, b: u16) -> u16 { - return a - b +function main(a: u16, b: u16, c: u16) { + assert_eq!(a - b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u16/ternary.leo b/compiler/tests/integers/u16/ternary.leo index 2c45a21b4f..22f9f76e38 100644 --- a/compiler/tests/integers/u16/ternary.leo +++ b/compiler/tests/integers/u16/ternary.leo @@ -1,3 +1,5 @@ -function main(b: bool, x: u16, y: u16) -> u16 { - return if b ? x : y +function main(s: bool, a: u16, b: u16, c: u16) { + let r = if s ? a : b; + + assert_eq!(r, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u16/zero.leo b/compiler/tests/integers/u16/zero.leo deleted file mode 100644 index 1d838bb416..0000000000 --- a/compiler/tests/integers/u16/zero.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> u16 { - return 0 -} diff --git a/compiler/tests/integers/u32/add.leo b/compiler/tests/integers/u32/add.leo index 63b288881e..6b1a19fb4e 100644 --- a/compiler/tests/integers/u32/add.leo +++ b/compiler/tests/integers/u32/add.leo @@ -1,3 +1,3 @@ -function main(a: u32, b: u32) -> u32 { - return a + b +function main(a: u32, b: u32, c: u32) { + assert_eq!(a + b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u32/div.leo b/compiler/tests/integers/u32/div.leo index fe9f4b4c30..b9e9acea9d 100644 --- a/compiler/tests/integers/u32/div.leo +++ b/compiler/tests/integers/u32/div.leo @@ -1,3 +1,3 @@ -function main(a: u32, b: u32) -> u32 { - return a / b +function main(a: u32, b: u32, c: u32) { + assert_eq!(a / b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u32/eq.leo b/compiler/tests/integers/u32/eq.leo index 5a4810ded2..68f873f6e9 100644 --- a/compiler/tests/integers/u32/eq.leo +++ b/compiler/tests/integers/u32/eq.leo @@ -1,3 +1,3 @@ -function main(a: u32, b: u32) -> bool { - return a == b +function main(a: u32, b: u32, c: bool) { + assert_eq!(a == b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u32/ge.leo b/compiler/tests/integers/u32/ge.leo index d0fdfe346d..99ba75da83 100644 --- a/compiler/tests/integers/u32/ge.leo +++ b/compiler/tests/integers/u32/ge.leo @@ -1,3 +1,3 @@ -function main(a: u32, b: u32) -> bool { - return a >= b +function main(a: u32, b: u32, c: bool) { + assert_eq!(a >= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u32/gt.leo b/compiler/tests/integers/u32/gt.leo index 87aef82e4a..aa5f66bf2c 100644 --- a/compiler/tests/integers/u32/gt.leo +++ b/compiler/tests/integers/u32/gt.leo @@ -1,3 +1,3 @@ -function main(a: u32, b: u32) -> bool { - return a > b +function main(a: u32, b: u32, c: bool) { + assert_eq!(a > b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u32/input.leo b/compiler/tests/integers/u32/input.leo index 1d6d071c2c..b95ae3bef0 100644 --- a/compiler/tests/integers/u32/input.leo +++ b/compiler/tests/integers/u32/input.leo @@ -1,3 +1,3 @@ -function main(x: u32) -> u32 { - return x +function main(a: u32, b: u32) { + assert_eq!(a, b); } \ No newline at end of file diff --git a/compiler/tests/integers/u32/le.leo b/compiler/tests/integers/u32/le.leo index 229ecdf340..8d82db212d 100644 --- a/compiler/tests/integers/u32/le.leo +++ b/compiler/tests/integers/u32/le.leo @@ -1,3 +1,3 @@ -function main(a: u32, b: u32) -> bool { - return a <= b +function main(a: u32, b: u32, c: bool) { + assert_eq!(a <= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u32/lt.leo b/compiler/tests/integers/u32/lt.leo index 31093aaa28..6cd57df2c9 100644 --- a/compiler/tests/integers/u32/lt.leo +++ b/compiler/tests/integers/u32/lt.leo @@ -1,3 +1,3 @@ -function main(a: u32, b: u32) -> bool { - return a < b +function main(a: u32, b: u32, c: bool) { + assert_eq!(a < b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u32/max.leo b/compiler/tests/integers/u32/max.leo index b08a1b5ef7..2950164a08 100644 --- a/compiler/tests/integers/u32/max.leo +++ b/compiler/tests/integers/u32/max.leo @@ -1,3 +1,3 @@ -function main() -> u32 { - return 4294967295 +function main() { + let a: u32 = 4294967295; } \ No newline at end of file diff --git a/compiler/tests/integers/u32/max_fail.leo b/compiler/tests/integers/u32/max_fail.leo new file mode 100644 index 0000000000..96c7e01657 --- /dev/null +++ b/compiler/tests/integers/u32/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u32 = 4294967296; +} \ No newline at end of file diff --git a/compiler/tests/integers/u32/min.leo b/compiler/tests/integers/u32/min.leo index 2bda23cdc5..0f1c080938 100644 --- a/compiler/tests/integers/u32/min.leo +++ b/compiler/tests/integers/u32/min.leo @@ -1,3 +1,3 @@ -function main() -> u32 { - return 0 +function main() { + let a: u32 = 0; } \ No newline at end of file diff --git a/compiler/tests/integers/u32/min_fail.leo b/compiler/tests/integers/u32/min_fail.leo new file mode 100644 index 0000000000..a8d41c475a --- /dev/null +++ b/compiler/tests/integers/u32/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u32 = -1; +} \ No newline at end of file diff --git a/compiler/tests/integers/u32/mod.rs b/compiler/tests/integers/u32/mod.rs index ce5cf6f951..1f21ec70e5 100644 --- a/compiler/tests/integers/u32/mod.rs +++ b/compiler/tests/integers/u32/mod.rs @@ -1,66 +1,33 @@ use crate::{ - boolean::{output_expected_boolean, output_false, output_true}, - get_error, - get_output, - integers::{fail_integer, IntegerTester}, + assert_satisfied, + expect_synthesis_error, + generate_main_inputs, + integers::{expect_parsing_error, IntegerTester}, parse_program, - EdwardsConstrainedValue, - EdwardsTestCompiler, }; -use leo_compiler::{ConstrainedValue, Integer}; use leo_inputs::types::{IntegerType, U32Type}; use leo_types::InputValue; -use snarkos_curves::edwards_bls12::Fq; -use snarkos_models::gadgets::{ - r1cs::TestConstraintSystem, - utilities::{alloc::AllocGadget, uint::UInt32}, -}; - -fn output_expected_allocated(program: EdwardsTestCompiler, expected: UInt32) { - let output = get_output(program); - - match output { - EdwardsConstrainedValue::Return(vec) => match vec.as_slice() { - [ConstrainedValue::Integer(Integer::U32(actual))] => assert_eq!(*actual, expected), - _ => panic!("program output unknown return value"), - }, - _ => panic!("program output unknown return value"), - } -} - -pub(crate) fn output_number(program: EdwardsTestCompiler, number: u32) { - let output = get_output(program); - assert_eq!( - EdwardsConstrainedValue::Return(vec![ConstrainedValue::Integer(Integer::U32(UInt32::constant(number)))]) - .to_string(), - output.to_string() - ) -} - -pub(crate) fn output_zero(program: EdwardsTestCompiler) { - output_number(program, 0u32); -} - -pub(crate) fn output_one(program: EdwardsTestCompiler) { - output_number(program, 1u32); -} - test_uint!(TestU32, u32, IntegerType::U32Type(U32Type {}), UInt32); #[test] fn test_u32_min() { - TestU32::test_min(std::u32::MIN); + TestU32::test_min(); +} + +#[test] +fn test_u32_min_fail() { + TestU32::test_min_fail(); } #[test] fn test_u32_max() { - TestU32::test_max(std::u32::MAX); + TestU32::test_max(); } #[test] -fn test_u32_input() { - TestU32::test_input(); +fn test_u32_max_fail() { + TestU32::test_max_fail(); } #[test] diff --git a/compiler/tests/integers/u32/mul.leo b/compiler/tests/integers/u32/mul.leo index c549375c63..e2120276e7 100644 --- a/compiler/tests/integers/u32/mul.leo +++ b/compiler/tests/integers/u32/mul.leo @@ -1,3 +1,3 @@ -function main(a: u32, b: u32) -> u32 { - return a * b +function main(a: u32, b: u32, c: u32) { + assert_eq!(a * b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u32/one.leo b/compiler/tests/integers/u32/one.leo deleted file mode 100644 index 5ab8717e9e..0000000000 --- a/compiler/tests/integers/u32/one.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> u32 { - return 1 -} diff --git a/compiler/tests/integers/u32/pow.leo b/compiler/tests/integers/u32/pow.leo index 6a9b24e424..dc598a4d0d 100644 --- a/compiler/tests/integers/u32/pow.leo +++ b/compiler/tests/integers/u32/pow.leo @@ -1,3 +1,3 @@ -function main(a: u32, b: u32) -> u32 { - return a ** b +function main(a: u32, b: u32, c: u32) { + assert_eq!(a ** b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u32/sub.leo b/compiler/tests/integers/u32/sub.leo index aa430d5b46..38e12009a3 100644 --- a/compiler/tests/integers/u32/sub.leo +++ b/compiler/tests/integers/u32/sub.leo @@ -1,3 +1,3 @@ -function main(a: u32, b: u32) -> u32 { - return a - b +function main(a: u32, b: u32, c: u32) { + assert_eq!(a - b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u32/ternary.leo b/compiler/tests/integers/u32/ternary.leo index cd957c2a38..72370f1367 100644 --- a/compiler/tests/integers/u32/ternary.leo +++ b/compiler/tests/integers/u32/ternary.leo @@ -1,3 +1,5 @@ -function main(b: bool, x: u32, y: u32) -> u32 { - return if b ? x : y +function main(s: bool, a: u32, b: u32, c: u32) { + let r = if s ? a : b; + + assert_eq!(r, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u32/zero.leo b/compiler/tests/integers/u32/zero.leo deleted file mode 100644 index 8462178e2d..0000000000 --- a/compiler/tests/integers/u32/zero.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> u32 { - return 0 -} diff --git a/compiler/tests/integers/u64/add.leo b/compiler/tests/integers/u64/add.leo index d7850737fe..eab76baebd 100644 --- a/compiler/tests/integers/u64/add.leo +++ b/compiler/tests/integers/u64/add.leo @@ -1,3 +1,3 @@ -function main(a: u64, b: u64) -> u64 { - return a + b +function main(a: u64, b: u64, c: u64) { + assert_eq!(a + b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u64/div.leo b/compiler/tests/integers/u64/div.leo index 3ee457c9f6..4502cc7273 100644 --- a/compiler/tests/integers/u64/div.leo +++ b/compiler/tests/integers/u64/div.leo @@ -1,3 +1,3 @@ -function main(a: u64, b: u64) -> u64 { - return a / b +function main(a: u64, b: u64, c: u64) { + assert_eq!(a / b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u64/eq.leo b/compiler/tests/integers/u64/eq.leo index 658fc442fa..afccdf875e 100644 --- a/compiler/tests/integers/u64/eq.leo +++ b/compiler/tests/integers/u64/eq.leo @@ -1,3 +1,3 @@ -function main(a: u64, b: u64) -> bool { - return a == b +function main(a: u64, b: u64, c: bool) { + assert_eq!(a == b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u64/ge.leo b/compiler/tests/integers/u64/ge.leo index 696501c52f..000a59deca 100644 --- a/compiler/tests/integers/u64/ge.leo +++ b/compiler/tests/integers/u64/ge.leo @@ -1,3 +1,3 @@ -function main(a: u64, b: u64) -> bool { - return a >= b +function main(a: u64, b: u64, c: bool) { + assert_eq!(a >= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u64/gt.leo b/compiler/tests/integers/u64/gt.leo index 5aa797aba6..37629b508e 100644 --- a/compiler/tests/integers/u64/gt.leo +++ b/compiler/tests/integers/u64/gt.leo @@ -1,3 +1,3 @@ -function main(a: u64, b: u64) -> bool { - return a > b +function main(a: u64, b: u64, c: bool) { + assert_eq!(a > b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u64/input.leo b/compiler/tests/integers/u64/input.leo index b12c15e14f..5ea21a4097 100644 --- a/compiler/tests/integers/u64/input.leo +++ b/compiler/tests/integers/u64/input.leo @@ -1,3 +1,3 @@ -function main(x: u64) -> u64 { - return x +function main(a: u64, b: u64) { + assert_eq!(a, b); } \ No newline at end of file diff --git a/compiler/tests/integers/u64/le.leo b/compiler/tests/integers/u64/le.leo index a9dfdf1ed1..b27259d4ee 100644 --- a/compiler/tests/integers/u64/le.leo +++ b/compiler/tests/integers/u64/le.leo @@ -1,3 +1,3 @@ -function main(a: u64, b: u64) -> bool { - return a <= b +function main(a: u64, b: u64, c: bool) { + assert_eq!(a <= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u64/lt.leo b/compiler/tests/integers/u64/lt.leo index a50a8f8ee3..3e95f330eb 100644 --- a/compiler/tests/integers/u64/lt.leo +++ b/compiler/tests/integers/u64/lt.leo @@ -1,3 +1,3 @@ -function main(a: u64, b: u64) -> bool { - return a < b +function main(a: u64, b: u64, c: bool) { + assert_eq!(a < b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u64/max.leo b/compiler/tests/integers/u64/max.leo index 004816a9ce..985897c006 100644 --- a/compiler/tests/integers/u64/max.leo +++ b/compiler/tests/integers/u64/max.leo @@ -1,3 +1,3 @@ -function main() -> u64 { - return 18446744073709551615 +function main() { + let a: u64 = 18446744073709551615; } \ No newline at end of file diff --git a/compiler/tests/integers/u64/max_fail.leo b/compiler/tests/integers/u64/max_fail.leo new file mode 100644 index 0000000000..0ca3f13895 --- /dev/null +++ b/compiler/tests/integers/u64/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u64 = 18446744073709551616; +} \ No newline at end of file diff --git a/compiler/tests/integers/u64/min.leo b/compiler/tests/integers/u64/min.leo index 20e2cf3518..aa9b72fc8a 100644 --- a/compiler/tests/integers/u64/min.leo +++ b/compiler/tests/integers/u64/min.leo @@ -1,3 +1,3 @@ -function main() -> u64 { - return 0 +function main() { + let a: u64 = 0; } \ No newline at end of file diff --git a/compiler/tests/integers/u64/min_fail.leo b/compiler/tests/integers/u64/min_fail.leo new file mode 100644 index 0000000000..81b90cc74a --- /dev/null +++ b/compiler/tests/integers/u64/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u64 = -1; +} \ No newline at end of file diff --git a/compiler/tests/integers/u64/mod.rs b/compiler/tests/integers/u64/mod.rs index 924079e1c5..a97745f301 100644 --- a/compiler/tests/integers/u64/mod.rs +++ b/compiler/tests/integers/u64/mod.rs @@ -1,49 +1,33 @@ use crate::{ - boolean::{output_expected_boolean, output_false, output_true}, - get_error, - get_output, - integers::{fail_integer, IntegerTester}, + assert_satisfied, + expect_synthesis_error, + generate_main_inputs, + integers::{expect_parsing_error, IntegerTester}, parse_program, - EdwardsConstrainedValue, - EdwardsTestCompiler, }; -use leo_compiler::{ConstrainedValue, Integer}; use leo_inputs::types::{IntegerType, U64Type}; use leo_types::InputValue; -use snarkos_curves::edwards_bls12::Fq; -use snarkos_models::gadgets::{ - r1cs::TestConstraintSystem, - utilities::{alloc::AllocGadget, uint::UInt64}, -}; - -fn output_expected_allocated(program: EdwardsTestCompiler, expected: UInt64) { - let output = get_output(program); - - match output { - EdwardsConstrainedValue::Return(vec) => match vec.as_slice() { - [ConstrainedValue::Integer(Integer::U64(actual))] => assert_eq!(*actual, expected), - _ => panic!("program output unknown return value"), - }, - _ => panic!("program output unknown return value"), - } -} - test_uint!(TestU64, u64, IntegerType::U64Type(U64Type {}), UInt64); #[test] fn test_u64_min() { - TestU64::test_min(std::u64::MIN); + TestU64::test_min(); +} + +#[test] +fn test_u64_min_fail() { + TestU64::test_min_fail(); } #[test] fn test_u64_max() { - TestU64::test_max(std::u64::MAX); + TestU64::test_max(); } #[test] -fn test_u64_input() { - TestU64::test_input(); +fn test_u64_max_fail() { + TestU64::test_max_fail(); } #[test] @@ -67,7 +51,6 @@ fn test_u64_div() { } #[test] -#[ignore] // this test takes ~7 mins fn test_u64_pow() { TestU64::test_pow(); } diff --git a/compiler/tests/integers/u64/mul.leo b/compiler/tests/integers/u64/mul.leo index fb64709694..832142ffbf 100644 --- a/compiler/tests/integers/u64/mul.leo +++ b/compiler/tests/integers/u64/mul.leo @@ -1,3 +1,3 @@ -function main(a: u64, b: u64) -> u64 { - return a * b +function main(a: u64, b: u64, c: u64) { + assert_eq!(a * b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u64/one.leo b/compiler/tests/integers/u64/one.leo deleted file mode 100644 index 4459d84384..0000000000 --- a/compiler/tests/integers/u64/one.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> u64 { - return 1 -} diff --git a/compiler/tests/integers/u64/pow.leo b/compiler/tests/integers/u64/pow.leo index a2267f64e1..3fd7074871 100644 --- a/compiler/tests/integers/u64/pow.leo +++ b/compiler/tests/integers/u64/pow.leo @@ -1,3 +1,3 @@ -function main(a: u64, b: u64) -> u64 { - return a ** b +function main(a: u64, b: u64, c: u64) { + assert_eq!(a ** b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u64/sub.leo b/compiler/tests/integers/u64/sub.leo index 55479de911..820c264745 100644 --- a/compiler/tests/integers/u64/sub.leo +++ b/compiler/tests/integers/u64/sub.leo @@ -1,3 +1,3 @@ -function main(a: u64, b: u64) -> u64 { - return a - b +function main(a: u64, b: u64, c: u64) { + assert_eq!(a - b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u64/ternary.leo b/compiler/tests/integers/u64/ternary.leo index befa05ef7a..8d8e9bb312 100644 --- a/compiler/tests/integers/u64/ternary.leo +++ b/compiler/tests/integers/u64/ternary.leo @@ -1,3 +1,5 @@ -function main(b: bool, x: u64, y: u64) -> u64 { - return if b ? x : y +function main(s: bool, a: u64, b: u64, c: u64) { + let r = if s ? a : b; + + assert_eq!(r, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u64/zero.leo b/compiler/tests/integers/u64/zero.leo deleted file mode 100644 index 69df40b378..0000000000 --- a/compiler/tests/integers/u64/zero.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> u64 { - return 0 -} diff --git a/compiler/tests/integers/u8/add.leo b/compiler/tests/integers/u8/add.leo index 297820fb7e..df22ad8c05 100644 --- a/compiler/tests/integers/u8/add.leo +++ b/compiler/tests/integers/u8/add.leo @@ -1,3 +1,3 @@ -function main(a: u8, b: u8) -> u8 { - return a + b +function main(a: u8, b: u8, c: u8) { + assert_eq!(a + b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u8/div.leo b/compiler/tests/integers/u8/div.leo index 97a6546b8f..e8b85479b1 100644 --- a/compiler/tests/integers/u8/div.leo +++ b/compiler/tests/integers/u8/div.leo @@ -1,3 +1,3 @@ -function main(a: u8, b: u8) -> u8 { - return a / b +function main(a: u8, b: u8, c: u8) { + assert_eq!(a / b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u8/eq.leo b/compiler/tests/integers/u8/eq.leo index 0a8bd1fd8d..4421872b20 100644 --- a/compiler/tests/integers/u8/eq.leo +++ b/compiler/tests/integers/u8/eq.leo @@ -1,3 +1,3 @@ -function main(a: u8, b: u8) -> bool { - return a == b +function main(a: u8, b: u8, c: bool) { + assert_eq!(a == b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u8/ge.leo b/compiler/tests/integers/u8/ge.leo index 8e00f7575a..db539a77d3 100644 --- a/compiler/tests/integers/u8/ge.leo +++ b/compiler/tests/integers/u8/ge.leo @@ -1,3 +1,3 @@ -function main(a: u8, b: u8) -> bool { - return a >= b +function main(a: u8, b: u8, c: bool) { + assert_eq!(a >= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u8/gt.leo b/compiler/tests/integers/u8/gt.leo index 5af71ef04d..f26697c3ce 100644 --- a/compiler/tests/integers/u8/gt.leo +++ b/compiler/tests/integers/u8/gt.leo @@ -1,3 +1,3 @@ -function main(a: u8, b: u8) -> bool { - return a > b +function main(a: u8, b: u8, c: bool) { + assert_eq!(a > b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u8/input.leo b/compiler/tests/integers/u8/input.leo index 28d6f3e80e..c4ffe7b4a0 100644 --- a/compiler/tests/integers/u8/input.leo +++ b/compiler/tests/integers/u8/input.leo @@ -1,3 +1,3 @@ -function main(x: u8) -> u8 { - return x +function main(a: u8, b: u8) { + assert_eq!(a, b); } \ No newline at end of file diff --git a/compiler/tests/integers/u8/le.leo b/compiler/tests/integers/u8/le.leo index bfe459dcd1..09876d4175 100644 --- a/compiler/tests/integers/u8/le.leo +++ b/compiler/tests/integers/u8/le.leo @@ -1,3 +1,3 @@ -function main(a: u8, b: u8) -> bool { - return a <= b +function main(a: u8, b: u8, c: bool) { + assert_eq!(a <= b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u8/lt.leo b/compiler/tests/integers/u8/lt.leo index 1434643dde..8cea3ccab8 100644 --- a/compiler/tests/integers/u8/lt.leo +++ b/compiler/tests/integers/u8/lt.leo @@ -1,3 +1,3 @@ -function main(a: u8, b: u8) -> bool { - return a < b +function main(a: u8, b: u8, c: bool) { + assert_eq!(a < b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u8/max.leo b/compiler/tests/integers/u8/max.leo index 06aebc3936..684bdfba10 100644 --- a/compiler/tests/integers/u8/max.leo +++ b/compiler/tests/integers/u8/max.leo @@ -1,3 +1,3 @@ -function main() -> u8 { - return 255 +function main() { + let a: u8 = 255; } \ No newline at end of file diff --git a/compiler/tests/integers/u8/max_fail.leo b/compiler/tests/integers/u8/max_fail.leo new file mode 100644 index 0000000000..f2b870096d --- /dev/null +++ b/compiler/tests/integers/u8/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u8 = 256; +} \ No newline at end of file diff --git a/compiler/tests/integers/u8/min.leo b/compiler/tests/integers/u8/min.leo index fe2a219c54..a88e33c5a6 100644 --- a/compiler/tests/integers/u8/min.leo +++ b/compiler/tests/integers/u8/min.leo @@ -1,3 +1,3 @@ -function main() -> u8 { - return 0 +function main() { + let a: u8 = 0; } \ No newline at end of file diff --git a/compiler/tests/integers/u8/min_fail.leo b/compiler/tests/integers/u8/min_fail.leo new file mode 100644 index 0000000000..7b91dc6e1a --- /dev/null +++ b/compiler/tests/integers/u8/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u8 = -1; +} \ No newline at end of file diff --git a/compiler/tests/integers/u8/mod.rs b/compiler/tests/integers/u8/mod.rs index f872a6c3b9..81fc118148 100644 --- a/compiler/tests/integers/u8/mod.rs +++ b/compiler/tests/integers/u8/mod.rs @@ -1,49 +1,33 @@ use crate::{ - boolean::{output_expected_boolean, output_false, output_true}, - get_error, - get_output, - integers::{fail_integer, IntegerTester}, + assert_satisfied, + expect_synthesis_error, + generate_main_inputs, + integers::{expect_parsing_error, IntegerTester}, parse_program, - EdwardsConstrainedValue, - EdwardsTestCompiler, }; -use leo_compiler::{ConstrainedValue, Integer}; use leo_inputs::types::{IntegerType, U8Type}; use leo_types::InputValue; -use snarkos_curves::edwards_bls12::Fq; -use snarkos_models::gadgets::{ - r1cs::TestConstraintSystem, - utilities::{alloc::AllocGadget, uint::UInt8}, -}; - -fn output_expected_allocated(program: EdwardsTestCompiler, expected: UInt8) { - let output = get_output(program); - - match output { - EdwardsConstrainedValue::Return(vec) => match vec.as_slice() { - [ConstrainedValue::Integer(Integer::U8(actual))] => assert_eq!(*actual, expected), - _ => panic!("program output unknown return value"), - }, - _ => panic!("program output unknown return value"), - } -} - test_uint!(TestU8, u8, IntegerType::U8Type(U8Type {}), UInt8); #[test] fn test_u8_min() { - TestU8::test_min(std::u8::MIN); + TestU8::test_min(); +} + +#[test] +fn test_u8_min_fail() { + TestU8::test_min_fail(); } #[test] fn test_u8_max() { - TestU8::test_max(std::u8::MAX); + TestU8::test_max(); } #[test] -fn test_u8_input() { - TestU8::test_input(); +fn test_u8_max_fail() { + TestU8::test_max_fail(); } #[test] diff --git a/compiler/tests/integers/u8/mul.leo b/compiler/tests/integers/u8/mul.leo index 51d11c8b58..a5d6e7664c 100644 --- a/compiler/tests/integers/u8/mul.leo +++ b/compiler/tests/integers/u8/mul.leo @@ -1,3 +1,3 @@ -function main(a: u8, b: u8) -> u8 { - return a * b +function main(a: u8, b: u8, c: u8) { + assert_eq!(a * b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u8/one.leo b/compiler/tests/integers/u8/one.leo deleted file mode 100644 index 82ea60773a..0000000000 --- a/compiler/tests/integers/u8/one.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> u8 { - return 1 -} diff --git a/compiler/tests/integers/u8/pow.leo b/compiler/tests/integers/u8/pow.leo index 2e4c4fef95..143106b1b4 100644 --- a/compiler/tests/integers/u8/pow.leo +++ b/compiler/tests/integers/u8/pow.leo @@ -1,3 +1,3 @@ -function main(a: u8, b: u8) -> u8 { - return a ** b +function main(a: u8, b: u8, c: u8) { + assert_eq!(a ** b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u8/sub.leo b/compiler/tests/integers/u8/sub.leo index e1420f05bb..dedd23d2f7 100644 --- a/compiler/tests/integers/u8/sub.leo +++ b/compiler/tests/integers/u8/sub.leo @@ -1,3 +1,3 @@ -function main(a: u8, b: u8) -> u8 { - return a - b +function main(a: u8, b: u8, c: u8) { + assert_eq!(a - b, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u8/ternary.leo b/compiler/tests/integers/u8/ternary.leo index 1a4ca0ba5f..7ae0af35c1 100644 --- a/compiler/tests/integers/u8/ternary.leo +++ b/compiler/tests/integers/u8/ternary.leo @@ -1,3 +1,5 @@ -function main(b: bool, x: u8, y: u8) -> u8 { - return if b ? x : y +function main(s: bool, a: u8, b: u8, c: u8) { + let r = if s ? a : b; + + assert_eq!(r, c); } \ No newline at end of file diff --git a/compiler/tests/integers/u8/zero.leo b/compiler/tests/integers/u8/zero.leo deleted file mode 100644 index fa60d675c4..0000000000 --- a/compiler/tests/integers/u8/zero.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() -> u8 { - return 0 -} diff --git a/compiler/tests/integers/uint_macro.rs b/compiler/tests/integers/uint_macro.rs index 60def3c225..26a7aa2f36 100644 --- a/compiler/tests/integers/uint_macro.rs +++ b/compiler/tests/integers/uint_macro.rs @@ -2,387 +2,420 @@ macro_rules! test_uint { ($name: ident, $type_: ty, $integer_type: expr, $gadget: ty) => { pub struct $name {} - impl $name { - fn test_min(min: $type_) { - let min_allocated = <$gadget>::constant(min); - + impl IntegerTester for $name { + fn test_min() { let bytes = include_bytes!("min.leo"); let program = parse_program(bytes).unwrap(); - output_expected_allocated(program, min_allocated); + assert_satisfied(program); } - fn test_max(max: $type_) { - let max_allocated = <$gadget>::constant(max); + fn test_min_fail() { + let bytes = include_bytes!("min_fail.leo"); + let program = parse_program(bytes).unwrap(); + expect_parsing_error(program); + } + + fn test_max() { let bytes = include_bytes!("max.leo"); let program = parse_program(bytes).unwrap(); - output_expected_allocated(program, max_allocated); + assert_satisfied(program); } - } - impl IntegerTester for $name { - fn test_input() { - // valid input - let num: $type_ = rand::random(); - let expected = <$gadget>::constant(num); + fn test_max_fail() { + let bytes = include_bytes!("max_fail.leo"); + let program = parse_program(bytes).unwrap(); - let bytes = include_bytes!("input.leo"); - let mut program = parse_program(bytes).unwrap(); - - program.set_inputs(vec![Some(InputValue::Integer($integer_type, num.to_string()))]); - - output_expected_allocated(program, expected); - - // invalid input - let mut program = parse_program(bytes).unwrap(); - - program.set_inputs(vec![Some(InputValue::Boolean(true))]); - fail_integer(program); - - // None input - let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![None]); - fail_integer(program); + expect_parsing_error(program); } fn test_add() { for _ in 0..10 { - let r1: $type_ = rand::random(); - let r2: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); - let sum = r1.wrapping_add(r2); - - let cs = TestConstraintSystem::::new(); - let sum_allocated = <$gadget>::alloc(cs, || Ok(sum)).unwrap(); + let c = match a.checked_add(b) { + Some(valid) => valid, + None => continue, + }; let bytes = include_bytes!("add.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Integer($integer_type, c.to_string()))), ]); - output_expected_allocated(program, sum_allocated); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_sub() { for _ in 0..10 { - let r1: $type_ = rand::random(); - let r2: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); - let difference = match r1.checked_sub(r2) { + let c = match a.checked_sub(b) { Some(valid) => valid, None => continue, }; - let cs = TestConstraintSystem::::new(); - let difference_allocated = <$gadget>::alloc(cs, || Ok(difference)).unwrap(); - let bytes = include_bytes!("sub.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Integer($integer_type, c.to_string()))), ]); - output_expected_allocated(program, difference_allocated); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_mul() { for _ in 0..10 { - let r1: $type_ = rand::random(); - let r2: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); - let product = r1.wrapping_mul(r2); - - let cs = TestConstraintSystem::::new(); - let product_allocated = <$gadget>::alloc(cs, || Ok(product)).unwrap(); + let c = match a.checked_mul(b) { + Some(valid) => valid, + None => continue, + }; let bytes = include_bytes!("mul.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Integer($integer_type, c.to_string()))), ]); - output_expected_allocated(program, product_allocated); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_div() { - // for _ in 0..10 {// these loops take an excessive amount of time - let r1: $type_ = rand::random(); - let r2: $type_ = rand::random(); + for _ in 0..10 { + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); - let bytes = include_bytes!("div.leo"); - let mut program = parse_program(bytes).unwrap(); + let c = match a.checked_div(b) { + Some(valid) => valid, + None => continue, + }; - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), - ]); + let bytes = include_bytes!("div.leo"); + let mut program = parse_program(bytes).unwrap(); - // expect an error when dividing by zero - if r2 == 0 { - let _err = get_error(program); - } else { - let cs = TestConstraintSystem::::new(); - let quotient = r1.wrapping_div(r2); - let quotient_allocated = <$gadget>::alloc(cs, || Ok(quotient)).unwrap(); + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Integer($integer_type, c.to_string()))), + ]); - output_expected_allocated(program, quotient_allocated); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } - // } } fn test_pow() { - // for _ in 0..10 {// these loops take an excessive amount of time - let r1: $type_ = rand::random(); - let r2: $type_ = rand::random(); - let r2 = r2 as u32; // we cast to u32 here because of rust pow() requirements + for _ in 0..10 { + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); - let result = r1.wrapping_pow(r2); + // rust specific conversion see https://doc.rust-lang.org/std/primitive.u8.html#method.checked_pow + let c = match a.checked_pow(b as u32) { + Some(valid) => valid, + None => continue, + }; - let cs = TestConstraintSystem::::new(); - let result_allocated = <$gadget>::alloc(cs, || Ok(result)).unwrap(); + let bytes = include_bytes!("pow.leo"); + let mut program = parse_program(bytes).unwrap(); - let bytes = include_bytes!("pow.leo"); - let mut program = parse_program(bytes).unwrap(); + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Integer($integer_type, c.to_string()))), + ]); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), - ]); + program.set_main_inputs(main_inputs); - output_expected_allocated(program, result_allocated); - // } + assert_satisfied(program); + } } fn test_eq() { for _ in 0..10 { - let r1: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); // test equal + let bytes = include_bytes!("eq.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r1.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, a.to_string()))), + ("c", Some(InputValue::Boolean(true))), ]); - output_true(program); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); // test not equal - let r2: $type_ = rand::random(); - let result = r1.eq(&r2); + let c = a.eq(&b); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Boolean(c))), ]); - output_expected_boolean(program, result); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_ge() { for _ in 0..10 { - let r1: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); // test equal + let bytes = include_bytes!("ge.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r1.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, a.to_string()))), + ("c", Some(InputValue::Boolean(true))), ]); - output_true(program); + program.set_main_inputs(main_inputs); - // test not equal - let r2: $type_ = rand::random(); + assert_satisfied(program); - let result = r1.ge(&r2); + // test greater or equal + + let c = a.ge(&b); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Boolean(c))), ]); - output_expected_boolean(program, result); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_gt() { for _ in 0..10 { - let r1: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); // test equal + let bytes = include_bytes!("gt.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r1.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, a.to_string()))), + ("c", Some(InputValue::Boolean(false))), ]); - output_false(program); + program.set_main_inputs(main_inputs); - // test not equal - let r2: $type_ = rand::random(); + assert_satisfied(program); - let result = r1.gt(&r2); + // test greater than + + let c = a.gt(&b); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Boolean(c))), ]); - output_expected_boolean(program, result); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_le() { for _ in 0..10 { - let r1: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); // test equal + let bytes = include_bytes!("le.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r1.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, a.to_string()))), + ("c", Some(InputValue::Boolean(true))), ]); - output_true(program); + program.set_main_inputs(main_inputs); - // test not equal - let r2: $type_ = rand::random(); + assert_satisfied(program); - let result = r1.le(&r2); + // test less or equal + + let c = a.le(&b); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Boolean(c))), ]); - output_expected_boolean(program, result); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_lt() { for _ in 0..10 { - let r1: $type_ = rand::random(); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); // test equal + let bytes = include_bytes!("lt.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r1.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, a.to_string()))), + ("c", Some(InputValue::Boolean(false))), ]); - output_false(program); - // test not equal - let r2: $type_ = rand::random(); + program.set_main_inputs(main_inputs); - let result = r1.lt(&r2); + assert_satisfied(program); + + // test less or equal + + let c = a.lt(&b); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Boolean(c))), ]); - output_expected_boolean(program, result); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } fn test_assert_eq() { for _ in 0..10 { - let r1: $type_ = rand::random(); + let a: $type_ = rand::random(); // test equal let bytes = include_bytes!("assert_eq.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r1.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, a.to_string()))), ]); - let _ = get_output(program); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); // test not equal - let r2: $type_ = rand::random(); + let b: $type_ = rand::random(); - if r1 == r2 { + if a == b { continue; } let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![ - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), ]); - let mut cs = TestConstraintSystem::::new(); - let _ = program.compile_constraints(&mut cs).unwrap(); - assert!(!cs.is_satisfied()); + program.set_main_inputs(main_inputs); + + expect_synthesis_error(program); } } fn test_ternary() { - let r1: $type_ = rand::random(); - let r2: $type_ = rand::random(); - - let g1 = <$gadget>::constant(r1); - let g2 = <$gadget>::constant(r2); + let a: $type_ = rand::random(); + let b: $type_ = rand::random(); let bytes = include_bytes!("ternary.leo"); - let mut program_1 = parse_program(bytes).unwrap(); - - let mut program_2 = program_1.clone(); + let mut program = parse_program(bytes).unwrap(); // true -> field 1 - program_1.set_inputs(vec![ - Some(InputValue::Boolean(true)), - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let main_inputs = generate_main_inputs(vec![ + ("s", Some(InputValue::Boolean(true))), + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Integer($integer_type, a.to_string()))), ]); - output_expected_allocated(program_1, g1); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); // false -> field 2 - program_2.set_inputs(vec![ - Some(InputValue::Boolean(false)), - Some(InputValue::Integer($integer_type, r1.to_string())), - Some(InputValue::Integer($integer_type, r2.to_string())), + let mut program = parse_program(bytes).unwrap(); + + let main_inputs = generate_main_inputs(vec![ + ("s", Some(InputValue::Boolean(false))), + ("a", Some(InputValue::Integer($integer_type, a.to_string()))), + ("b", Some(InputValue::Integer($integer_type, b.to_string()))), + ("c", Some(InputValue::Integer($integer_type, b.to_string()))), ]); - output_expected_allocated(program_2, g2); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } } }; diff --git a/compiler/tests/macros/mod.rs b/compiler/tests/macros/mod.rs index 7d14bfebdf..9a4c1698d7 100644 --- a/compiler/tests/macros/mod.rs +++ b/compiler/tests/macros/mod.rs @@ -1,4 +1,4 @@ -use crate::{get_error, get_output, parse_program}; +use crate::{assert_satisfied, expect_compiler_error, generate_main_inputs, parse_program}; use leo_types::InputValue; #[test] @@ -6,7 +6,7 @@ fn test_print() { let bytes = include_bytes!("print.leo"); let program = parse_program(bytes).unwrap(); - let _output = get_output(program); + assert_satisfied(program); } #[test] @@ -21,7 +21,7 @@ fn test_print_parameter() { let bytes = include_bytes!("print_parameter.leo"); let program = parse_program(bytes).unwrap(); - let _output = get_output(program); + assert_satisfied(program); } #[test] @@ -29,7 +29,7 @@ fn test_print_parameter_many() { let bytes = include_bytes!("print_parameter_many.leo"); let program = parse_program(bytes).unwrap(); - let _output = get_output(program); + assert_satisfied(program); } #[test] @@ -37,7 +37,7 @@ fn test_print_parameter_fail_unknown() { let bytes = include_bytes!("print_parameter_fail_unknown.leo"); let program = parse_program(bytes).unwrap(); - let _err = get_error(program); + expect_compiler_error(program); } #[test] @@ -45,7 +45,7 @@ fn test_print_parameter_fail_empty() { let bytes = include_bytes!("print_parameter_fail_empty.leo"); let program = parse_program(bytes).unwrap(); - let _err = get_error(program); + expect_compiler_error(program); } #[test] @@ -53,7 +53,7 @@ fn test_print_parameter_fail_none() { let bytes = include_bytes!("print_parameter_fail_empty.leo"); let program = parse_program(bytes).unwrap(); - let _err = get_error(program); + expect_compiler_error(program); } #[test] @@ -61,9 +61,11 @@ fn test_print_input() { let bytes = include_bytes!("print_input.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![Some(InputValue::Boolean(true))]); + let main_inputs = generate_main_inputs(vec![("a", Some(InputValue::Boolean(true)))]); - let _output = get_output(program); + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } #[test] @@ -71,12 +73,13 @@ fn test_debug() { let bytes = include_bytes!("debug.leo"); let program = parse_program(bytes).unwrap(); - let _output = get_output(program); + assert_satisfied(program); } + #[test] fn test_error() { let bytes = include_bytes!("error.leo"); let program = parse_program(bytes).unwrap(); - let _output = get_output(program); + assert_satisfied(program); } diff --git a/compiler/tests/macros/print_input.leo b/compiler/tests/macros/print_input.leo index 8190a6621f..fa307720ab 100644 --- a/compiler/tests/macros/print_input.leo +++ b/compiler/tests/macros/print_input.leo @@ -1,3 +1,3 @@ -function main(b: bool) { - print!("b = {}", b); +function main(a: bool) { + print!("a = {}", a); } \ No newline at end of file diff --git a/compiler/tests/mod.rs b/compiler/tests/mod.rs index ee1770e40c..1837615b3a 100644 --- a/compiler/tests/mod.rs +++ b/compiler/tests/mod.rs @@ -6,7 +6,7 @@ pub mod field; pub mod function; pub mod group; pub mod import; -pub mod inputs; +pub mod input_files; pub mod integers; pub mod macros; pub mod mutability; @@ -15,44 +15,31 @@ pub mod syntax; use leo_compiler::{ compiler::Compiler, - errors::{CompilerError, FunctionError, StatementError}, + errors::CompilerError, group::targets::edwards_bls12::EdwardsGroupType, ConstrainedValue, + OutputBytes, }; +use leo_types::{InputValue, MainInputs}; use snarkos_curves::edwards_bls12::Fq; use snarkos_models::gadgets::r1cs::TestConstraintSystem; + use std::path::PathBuf; +pub const TEST_OUTPUTS_DIRECTORY: &str = "/outputs/"; +pub const TEST_OUTPUTS_FILE_NAME: &str = "/outputs/test.out"; +const EMPTY_FILE: &str = ""; + pub type EdwardsTestCompiler = Compiler; pub type EdwardsConstrainedValue = ConstrainedValue; -pub(crate) fn get_output(program: EdwardsTestCompiler) -> EdwardsConstrainedValue { - let mut cs = TestConstraintSystem::::new(); - let output = program.compile_constraints(&mut cs).unwrap(); - assert!(cs.is_satisfied()); - output -} - -pub(crate) fn get_error(program: EdwardsTestCompiler) -> CompilerError { - let mut cs = TestConstraintSystem::::new(); - program.compile_constraints(&mut cs).unwrap_err() -} - -pub(crate) fn fail_enforce(program: EdwardsTestCompiler) { - match get_error(program) { - CompilerError::FunctionError(FunctionError::StatementError(StatementError::Error(_))) => {} - error => panic!("Expected evaluate error, got {}", error), - } -} - fn new_compiler() -> EdwardsTestCompiler { let program_name = "test".to_string(); let path = PathBuf::from("/test/src/main.leo"); - let mut compiler = EdwardsTestCompiler::new(program_name); - compiler.set_path(path); + let outputs_dir = PathBuf::from(TEST_OUTPUTS_DIRECTORY); - compiler + EdwardsTestCompiler::new(program_name, path, outputs_dir) } pub(crate) fn parse_program(bytes: &[u8]) -> Result { @@ -68,7 +55,117 @@ pub(crate) fn parse_inputs(bytes: &[u8]) -> Result Result { + let mut compiler = new_compiler(); + let state_string = String::from_utf8_lossy(bytes); + + compiler.parse_inputs(EMPTY_FILE, &state_string)?; + + Ok(compiler) +} + +pub(crate) fn parse_inputs_and_state( + inputs_bytes: &[u8], + state_bytes: &[u8], +) -> Result { + let mut compiler = new_compiler(); + let inputs_string = String::from_utf8_lossy(inputs_bytes); + let state_string = String::from_utf8_lossy(state_bytes); + + compiler.parse_inputs(&inputs_string, &state_string)?; + + Ok(compiler) +} + +pub fn parse_program_with_inputs( + program_bytes: &[u8], + input_bytes: &[u8], +) -> Result { + let mut compiler = new_compiler(); + + let program_string = String::from_utf8_lossy(program_bytes); + let inputs_string = String::from_utf8_lossy(input_bytes); + + compiler.parse_inputs(&inputs_string, EMPTY_FILE)?; + compiler.parse_program(&program_string)?; + + Ok(compiler) +} + +pub fn parse_program_with_state( + program_bytes: &[u8], + state_bytes: &[u8], +) -> Result { + let mut compiler = new_compiler(); + + let program_string = String::from_utf8_lossy(program_bytes); + let state_string = String::from_utf8_lossy(state_bytes); + + compiler.parse_inputs(EMPTY_FILE, &state_string)?; + compiler.parse_program(&program_string)?; + + Ok(compiler) +} + +pub fn parse_program_with_inputs_and_state( + program_bytes: &[u8], + inputs_bytes: &[u8], + state_bytes: &[u8], +) -> Result { + let mut compiler = new_compiler(); + + let program_string = String::from_utf8_lossy(program_bytes); + let inputs_string = String::from_utf8_lossy(inputs_bytes); + let state_string = String::from_utf8_lossy(state_bytes); + + compiler.parse_inputs(&inputs_string, &state_string)?; + compiler.parse_program(&program_string)?; + + Ok(compiler) +} + +pub(crate) fn get_outputs(program: EdwardsTestCompiler) -> OutputBytes { + // synthesize the circuit on the test constraint system + let mut cs = TestConstraintSystem::::new(); + let output = program.generate_constraints_helper(&mut cs).unwrap(); + + // assert the constraint system is satisfied + assert!(cs.is_satisfied()); + + output +} + +pub(crate) fn assert_satisfied(program: EdwardsTestCompiler) { + let empty_output_bytes = include_bytes!("compiler_outputs/empty.out"); + let res = get_outputs(program); + + // assert that the output is empty + assert_eq!(empty_output_bytes, res.bytes().as_slice()); +} + +pub(crate) fn expect_compiler_error(program: EdwardsTestCompiler) -> CompilerError { + let mut cs = TestConstraintSystem::::new(); + program.generate_constraints_helper(&mut cs).unwrap_err() +} + +pub(crate) fn expect_synthesis_error(program: EdwardsTestCompiler) { + let mut cs = TestConstraintSystem::::new(); + let _output = program.generate_constraints_helper(&mut cs).unwrap(); + + assert!(!cs.is_satisfied()); +} + +pub(crate) fn generate_main_inputs(inputs: Vec<(&str, Option)>) -> MainInputs { + let mut main_inputs = MainInputs::new(); + + for (name, value) in inputs { + main_inputs.insert(name.to_string(), value); + } + + main_inputs +} diff --git a/compiler/tests/mutability/array_mut.leo b/compiler/tests/mutability/array_mut.leo index 768f8fb092..9df3503777 100644 --- a/compiler/tests/mutability/array_mut.leo +++ b/compiler/tests/mutability/array_mut.leo @@ -1,7 +1,7 @@ // Adding the `mut` keyword makes an array variable mutable. -function main() -> u32 { +function main() { let mut a = [1u32]; a[0] = 0; - return a[0] + assert_eq!(a[0], 0u32); } \ No newline at end of file diff --git a/compiler/tests/mutability/circuit_mut.leo b/compiler/tests/mutability/circuit_mut.leo index 5d4ba9f14f..cc3fbb2f9b 100644 --- a/compiler/tests/mutability/circuit_mut.leo +++ b/compiler/tests/mutability/circuit_mut.leo @@ -3,9 +3,9 @@ circuit Foo { x: u32 } -function main() -> u32 { +function main() { let mut a = Foo { x: 1 }; a.x = 0; - return a.x + assert_eq!(a.x, 0u32); } \ No newline at end of file diff --git a/compiler/tests/mutability/function_input.leo b/compiler/tests/mutability/function_input.leo index c3cef38959..2a379d5e83 100644 --- a/compiler/tests/mutability/function_input.leo +++ b/compiler/tests/mutability/function_input.leo @@ -1,4 +1,4 @@ // Function inputs are immutable by default. -function main(a: u32) { - a = 0; +function main(a: bool) { + a = false; } \ No newline at end of file diff --git a/compiler/tests/mutability/function_input_mut.leo b/compiler/tests/mutability/function_input_mut.leo index accd891cfd..631e2ff57e 100644 --- a/compiler/tests/mutability/function_input_mut.leo +++ b/compiler/tests/mutability/function_input_mut.leo @@ -1,6 +1,6 @@ // Adding the `mut` keyword makes a function variable mutable. -function main(mut a: u32) -> u32 { - a = 0; +function main(mut a: bool) { + a = true; - return a + assert_eq!(a, true); } \ No newline at end of file diff --git a/compiler/tests/mutability/let_mut.leo b/compiler/tests/mutability/let_mut.leo index 59af4c461a..756729cad5 100644 --- a/compiler/tests/mutability/let_mut.leo +++ b/compiler/tests/mutability/let_mut.leo @@ -1,7 +1,7 @@ // Adding the `mut` keyword makes a variable mutable. -function main() -> u32 { +function main() { let mut a = 1u32; a = 0; - return a + assert_eq!(a, 0u32); } \ No newline at end of file diff --git a/compiler/tests/mutability/mod.rs b/compiler/tests/mutability/mod.rs index cc8dcdb2dd..de98c42121 100644 --- a/compiler/tests/mutability/mod.rs +++ b/compiler/tests/mutability/mod.rs @@ -1,42 +1,12 @@ -use crate::{array::input_value_u32_one, parse_program, EdwardsConstrainedValue, EdwardsTestCompiler}; -use leo_compiler::{ - errors::{CompilerError, FunctionError, StatementError}, - ConstrainedValue, - Integer, -}; - -use snarkos_curves::edwards_bls12::Fq; -use snarkos_models::gadgets::{r1cs::TestConstraintSystem, utilities::uint::UInt32}; - -fn mut_success(program: EdwardsTestCompiler) { - let mut cs = TestConstraintSystem::::new(); - let output = program.compile_constraints(&mut cs).unwrap(); - - assert!(cs.is_satisfied()); - assert_eq!( - EdwardsConstrainedValue::Return(vec![ConstrainedValue::Integer(Integer::U32(UInt32::constant(0)))]).to_string(), - output.to_string() - ); -} - -fn mut_fail(program: EdwardsTestCompiler) { - let mut cs = TestConstraintSystem::::new(); - let err = program.compile_constraints(&mut cs).unwrap_err(); - - // It would be ideal if assert_eq!(Error1, Error2) were possible but unfortunately it is not due to - // https://github.com/rust-lang/rust/issues/34158#issuecomment-224910299 - match err { - CompilerError::FunctionError(FunctionError::StatementError(StatementError::Error(_string))) => {} - err => panic!("Expected immutable assign error, got {}", err), - } -} +use crate::{assert_satisfied, expect_compiler_error, generate_main_inputs, parse_program}; +use leo_types::InputValue; #[test] fn test_let() { let bytes = include_bytes!("let.leo"); let program = parse_program(bytes).unwrap(); - mut_fail(program); + expect_compiler_error(program); } #[test] @@ -44,7 +14,7 @@ fn test_let_mut() { let bytes = include_bytes!("let_mut.leo"); let program = parse_program(bytes).unwrap(); - mut_success(program); + assert_satisfied(program); } #[test] @@ -52,7 +22,7 @@ fn test_const_fail() { let bytes = include_bytes!("const.leo"); let program = parse_program(bytes).unwrap(); - mut_fail(program); + expect_compiler_error(program); } #[test] @@ -60,7 +30,7 @@ fn test_const_mut_fail() { let bytes = include_bytes!("const_mut.leo"); let program = parse_program(bytes).unwrap(); - mut_fail(program); + expect_compiler_error(program); } #[test] @@ -68,7 +38,7 @@ fn test_array() { let bytes = include_bytes!("array.leo"); let program = parse_program(bytes).unwrap(); - mut_fail(program); + expect_compiler_error(program); } #[test] @@ -76,7 +46,7 @@ fn test_array_mut() { let bytes = include_bytes!("array_mut.leo"); let program = parse_program(bytes).unwrap(); - mut_success(program); + assert_satisfied(program); } #[test] @@ -84,7 +54,7 @@ fn test_circuit() { let bytes = include_bytes!("circuit.leo"); let program = parse_program(bytes).unwrap(); - mut_fail(program); + expect_compiler_error(program); } #[test] @@ -92,7 +62,7 @@ fn test_circuit_mut() { let bytes = include_bytes!("circuit_mut.leo"); let program = parse_program(bytes).unwrap(); - mut_success(program); + assert_satisfied(program); } #[test] @@ -100,8 +70,11 @@ fn test_function_input() { let bytes = include_bytes!("function_input.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![Some(input_value_u32_one())]); - mut_fail(program); + let main_inputs = generate_main_inputs(vec![("a", Some(InputValue::Boolean(true)))]); + + program.set_main_inputs(main_inputs); + + expect_compiler_error(program); } #[test] @@ -109,6 +82,9 @@ fn test_function_input_mut() { let bytes = include_bytes!("function_input_mut.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![Some(input_value_u32_one())]); - mut_success(program); + let main_inputs = generate_main_inputs(vec![("a", Some(InputValue::Boolean(true)))]); + + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } diff --git a/compiler/tests/statements/assertion_basic.leo b/compiler/tests/statements/assertion_basic.leo index 6c1fe116d0..8a8ab02f28 100644 --- a/compiler/tests/statements/assertion_basic.leo +++ b/compiler/tests/statements/assertion_basic.leo @@ -1,3 +1,3 @@ -function main(b: bool) { - assert_eq!(b, true); +function main(a: bool) { + assert_eq!(a, true); } \ No newline at end of file diff --git a/compiler/tests/statements/conditional/assert.leo b/compiler/tests/statements/conditional/assert.leo index c0c24db693..c6025b26de 100644 --- a/compiler/tests/statements/conditional/assert.leo +++ b/compiler/tests/statements/conditional/assert.leo @@ -1,7 +1,7 @@ -function main(bit: u32) { - if bit == 1 { - assert_eq!(bit, 1); +function main(a: u32) { + if a == 1 { + assert_eq!(a, 1); } else { - assert_eq!(bit, 0); + assert_eq!(a, 0); } } diff --git a/compiler/tests/statements/conditional/chain.leo b/compiler/tests/statements/conditional/chain.leo index 65b391c1e8..6b789fb1c1 100644 --- a/compiler/tests/statements/conditional/chain.leo +++ b/compiler/tests/statements/conditional/chain.leo @@ -1,13 +1,13 @@ -function main(bit: u32) -> u32 { - let mut result = 0u32; +function main(a: u32, b: u32) { + let mut c = 0u32; - if bit == 1 { - result = 1; - } else if bit == 2 { - result = 2; + if a == 1 { + c = 1; + } else if a == 2 { + c = 2; } else { - result = 3; + c = 3; } - return result + assert_eq!(c, b); } \ No newline at end of file diff --git a/compiler/tests/statements/conditional/for_loop.leo b/compiler/tests/statements/conditional/for_loop.leo index b8228333a2..3c123e6fe4 100644 --- a/compiler/tests/statements/conditional/for_loop.leo +++ b/compiler/tests/statements/conditional/for_loop.leo @@ -1,11 +1,13 @@ -function main(cond: bool) -> u32 { - let mut a = 0u32; +function main(a: bool) { + let mut b = 0u32; - if cond { + if a { for i in 0..4 { - a += i; + b += i; } } - return a + let r: u32 = if a ? 6 : 0; + + assert_eq!(r, b); } diff --git a/compiler/tests/statements/conditional/inputs/registers_one.in b/compiler/tests/statements/conditional/inputs/registers_one.in new file mode 100644 index 0000000000..be39f343fa --- /dev/null +++ b/compiler/tests/statements/conditional/inputs/registers_one.in @@ -0,0 +1,2 @@ +[registers] +a: u32 = 1; diff --git a/compiler/tests/statements/conditional/inputs/registers_zero.in b/compiler/tests/statements/conditional/inputs/registers_zero.in new file mode 100644 index 0000000000..ae20e35199 --- /dev/null +++ b/compiler/tests/statements/conditional/inputs/registers_zero.in @@ -0,0 +1,2 @@ +[registers] +a: u32 = 0; diff --git a/compiler/tests/statements/conditional/mod.rs b/compiler/tests/statements/conditional/mod.rs index b9e8f959ae..d1907445b4 100644 --- a/compiler/tests/statements/conditional/mod.rs +++ b/compiler/tests/statements/conditional/mod.rs @@ -1,31 +1,15 @@ use crate::{ - get_output, - integers::u32::{output_number, output_one, output_zero}, + assert_satisfied, + expect_synthesis_error, + generate_main_inputs, + get_outputs, parse_program, - EdwardsConstrainedValue, + parse_program_with_inputs, EdwardsTestCompiler, }; use leo_inputs::types::{IntegerType, U32Type}; use leo_types::InputValue; -use snarkos_curves::edwards_bls12::Fq; -use snarkos_models::gadgets::r1cs::TestConstraintSystem; - -fn empty_output_satisfied(program: EdwardsTestCompiler) { - let output = get_output(program); - - assert_eq!(EdwardsConstrainedValue::Return(vec![]).to_string(), output.to_string()); -} - -// Tests a statements.conditional enforceBit() program -// -// function main(bit: u8) { -// if bit == 1u8 { -// assert_eq!(bit, 1u8); -// } else { -// assert_eq!(bit, 0u8); -// } -// } #[test] fn test_assert() { let bytes = include_bytes!("assert.leo"); @@ -35,52 +19,65 @@ fn test_assert() { // Check that an input value of 1 satisfies the constraint system - program_1_pass.set_inputs(vec![Some(InputValue::Integer( - IntegerType::U32Type(U32Type {}), - 1.to_string(), - ))]); - empty_output_satisfied(program_1_pass); + let main_inputs = generate_main_inputs(vec![( + "a", + Some(InputValue::Integer(IntegerType::U32Type(U32Type {}), 1.to_string())), + )]); + + program_1_pass.set_main_inputs(main_inputs); + + assert_satisfied(program_1_pass); // Check that an input value of 0 satisfies the constraint system - program_0_pass.set_inputs(vec![Some(InputValue::Integer( - IntegerType::U32Type(U32Type {}), - 0.to_string(), - ))]); - empty_output_satisfied(program_0_pass); + let main_inputs = generate_main_inputs(vec![( + "a", + Some(InputValue::Integer(IntegerType::U32Type(U32Type {}), 0.to_string())), + )]); + + program_0_pass.set_main_inputs(main_inputs); + + assert_satisfied(program_0_pass); // Check that an input value of 2 does not satisfy the constraint system - program_2_fail.set_inputs(vec![Some(InputValue::Integer( - IntegerType::U32Type(U32Type {}), - 2.to_string(), - ))]); - let mut cs = TestConstraintSystem::::new(); - let _output = program_2_fail.compile_constraints(&mut cs).unwrap(); - assert!(!cs.is_satisfied()); + let main_inputs = generate_main_inputs(vec![( + "a", + Some(InputValue::Integer(IntegerType::U32Type(U32Type {}), 2.to_string())), + )]); + + program_2_fail.set_main_inputs(main_inputs); + + expect_synthesis_error(program_2_fail); } #[test] fn test_mutate() { let bytes = include_bytes!("mutate.leo"); - let mut program_1_true = parse_program(bytes).unwrap(); - let mut program_0_pass = program_1_true.clone(); + let mut program_1_pass = parse_program(bytes).unwrap(); + let mut program_0_pass = program_1_pass.clone(); // Check that an input value of 1 satisfies the constraint system - program_1_true.set_inputs(vec![Some(InputValue::Integer( - IntegerType::U32Type(U32Type {}), - 1.to_string(), - ))]); - output_one(program_1_true); + let main_inputs = generate_main_inputs(vec![( + "a", + Some(InputValue::Integer(IntegerType::U32Type(U32Type {}), 1.to_string())), + )]); + + program_1_pass.set_main_inputs(main_inputs); + + assert_satisfied(program_1_pass); // Check that an input value of 0 satisfies the constraint system - program_0_pass.set_inputs(vec![Some(InputValue::Integer( - IntegerType::U32Type(U32Type {}), - 0.to_string(), - ))]); - output_zero(program_0_pass); + let main_inputs = generate_main_inputs(vec![( + "a", + Some(InputValue::Integer(IntegerType::U32Type(U32Type {}), 0.to_string())), + )]); + + program_0_pass.set_main_inputs(main_inputs); + + assert_satisfied(program_0_pass); } #[test] @@ -91,13 +88,19 @@ fn test_for_loop() { // Check that an input value of true satisfies the constraint system - program_true_6.set_inputs(vec![Some(InputValue::Boolean(true))]); - output_number(program_true_6, 6u32); + let main_inputs = generate_main_inputs(vec![("a", Some(InputValue::Boolean(true)))]); + + program_true_6.set_main_inputs(main_inputs); + + assert_satisfied(program_true_6); // Check that an input value of false satisfies the constraint system - program_false_0.set_inputs(vec![Some(InputValue::Boolean(false))]); - output_zero(program_false_0); + let main_inputs = generate_main_inputs(vec![("a", Some(InputValue::Boolean(false)))]); + + program_false_0.set_main_inputs(main_inputs); + + assert_satisfied(program_false_0); } #[test] @@ -105,28 +108,58 @@ fn test_chain() { let bytes = include_bytes!("chain.leo"); let mut program_1_1 = parse_program(bytes).unwrap(); let mut program_2_2 = program_1_1.clone(); - let mut program_2_3 = program_1_1.clone(); + let mut program_4_3 = program_1_1.clone(); - // Check that an input of 1 outputs true - program_1_1.set_inputs(vec![Some(InputValue::Integer( - IntegerType::U32Type(U32Type {}), - 1.to_string(), - ))]); - output_number(program_1_1, 1u32); + // Check that an input of 1 outputs 1 - // Check that an input of 0 outputs true - program_2_2.set_inputs(vec![Some(InputValue::Integer( - IntegerType::U32Type(U32Type {}), - 2.to_string(), - ))]); - output_number(program_2_2, 2u32); + let main_inputs = generate_main_inputs(vec![ + ( + "a", + Some(InputValue::Integer(IntegerType::U32Type(U32Type {}), 1.to_string())), + ), + ( + "b", + Some(InputValue::Integer(IntegerType::U32Type(U32Type {}), 1.to_string())), + ), + ]); - // Check that an input of 0 outputs true - program_2_3.set_inputs(vec![Some(InputValue::Integer( - IntegerType::U32Type(U32Type {}), - 5.to_string(), - ))]); - output_number(program_2_3, 3u32); + program_1_1.set_main_inputs(main_inputs); + + assert_satisfied(program_1_1); + + // Check that an input of 2 outputs 2 + + let main_inputs = generate_main_inputs(vec![ + ( + "a", + Some(InputValue::Integer(IntegerType::U32Type(U32Type {}), 2.to_string())), + ), + ( + "b", + Some(InputValue::Integer(IntegerType::U32Type(U32Type {}), 2.to_string())), + ), + ]); + + program_2_2.set_main_inputs(main_inputs); + + assert_satisfied(program_2_2); + + // Check that an input of 4 outputs 3 + + let main_inputs = generate_main_inputs(vec![ + ( + "a", + Some(InputValue::Integer(IntegerType::U32Type(U32Type {}), 4.to_string())), + ), + ( + "b", + Some(InputValue::Integer(IntegerType::U32Type(U32Type {}), 3.to_string())), + ), + ]); + + program_4_3.set_main_inputs(main_inputs); + + assert_satisfied(program_4_3); } #[test] @@ -136,35 +169,81 @@ fn test_nested() { let mut program_true_false_1 = program_true_true_3.clone(); let mut program_false_false_0 = program_true_true_3.clone(); - // Check that an input value of true true satisfies the constraint system + // Check that an input value of true true outputs 3 - program_true_true_3.set_inputs(vec![Some(InputValue::Boolean(true)); 2]); - output_number(program_true_true_3, 3u32); + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Boolean(true))), + ("b", Some(InputValue::Boolean(true))), + ( + "c", + Some(InputValue::Integer(IntegerType::U32Type(U32Type {}), 3.to_string())), + ), + ]); - // Check that an input value of true false satisfies the constraint system + program_true_true_3.set_main_inputs(main_inputs); - program_true_false_1.set_inputs(vec![Some(InputValue::Boolean(true)), Some(InputValue::Boolean(false))]); - output_number(program_true_false_1, 1u32); + assert_satisfied(program_true_true_3); - // Check that an input value of false false satisfies the constraint system + // Check that an input value of true false outputs 1 - program_false_false_0.set_inputs(vec![Some(InputValue::Boolean(false)), Some(InputValue::Boolean(false))]); - output_number(program_false_false_0, 0u32); + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Boolean(true))), + ("b", Some(InputValue::Boolean(false))), + ( + "c", + Some(InputValue::Integer(IntegerType::U32Type(U32Type {}), 1.to_string())), + ), + ]); + + program_true_false_1.set_main_inputs(main_inputs); + + assert_satisfied(program_true_false_1); + + // Check that an input value of false false outputs 0 + + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Boolean(false))), + ("b", Some(InputValue::Boolean(false))), + ( + "c", + Some(InputValue::Integer(IntegerType::U32Type(U32Type {}), 0.to_string())), + ), + ]); + + program_false_false_0.set_main_inputs(main_inputs); + + assert_satisfied(program_false_false_0); +} + +fn output_one(program: EdwardsTestCompiler) { + let expected = include_bytes!("outputs_/registers_one.out"); + let actual = get_outputs(program); + + assert_eq!(expected, actual.bytes().as_slice()); +} + +fn output_zero(program: EdwardsTestCompiler) { + let expected = include_bytes!("outputs_/registers_zero.out"); + let actual = get_outputs(program); + + assert_eq!(expected, actual.bytes().as_slice()); } #[test] fn test_multiple_returns() { - let bytes = include_bytes!("multiple_returns.leo"); - let mut program_true_1 = parse_program(bytes).unwrap(); - let mut program_false_0 = program_true_1.clone(); + let program_bytes = include_bytes!("multiple_returns.leo"); - // Check that an input value of true returns 1 and satisfies the constraint system + // Check that an input value of 1 writes 1 to the output registers - program_true_1.set_inputs(vec![Some(InputValue::Boolean(true))]); - output_number(program_true_1, 1u32); + let registers_one_bytes = include_bytes!("inputs/registers_one.in"); + let program = parse_program_with_inputs(program_bytes, registers_one_bytes).unwrap(); - // Check that an input value of false returns 0 and satisfies the constraint system + output_one(program); - program_false_0.set_inputs(vec![Some(InputValue::Boolean(false))]); - output_number(program_false_0, 0u32); + // Check that an input value of 0 writes 0 to the output registers + + let registers_zero_bytes = include_bytes!("inputs/registers_zero.in"); + let program = parse_program_with_inputs(program_bytes, registers_zero_bytes).unwrap(); + + output_zero(program); } diff --git a/compiler/tests/statements/conditional/multiple_returns.leo b/compiler/tests/statements/conditional/multiple_returns.leo index 434bd8e458..3eda7d7063 100644 --- a/compiler/tests/statements/conditional/multiple_returns.leo +++ b/compiler/tests/statements/conditional/multiple_returns.leo @@ -1,7 +1,7 @@ -function main(cond: bool) -> u32 { - if cond { - return 1u32 - } else { +function main(registers) -> u32 { + if registers.a == 0 { return 0u32 + } else { + return 1u32 } } \ No newline at end of file diff --git a/compiler/tests/statements/conditional/mutate.leo b/compiler/tests/statements/conditional/mutate.leo index 67ec956874..3bb7cb1839 100644 --- a/compiler/tests/statements/conditional/mutate.leo +++ b/compiler/tests/statements/conditional/mutate.leo @@ -1,11 +1,15 @@ -function main(bit: u32) -> u32 { - let mut a = 5u32; +function main(a: u32) { + let mut b = 5u32; - if bit == 1 { - a = 1; + if a == 1 { + b = 1; } else { - a = 0; + b = 0; } - return a + if a == 1 { + assert_eq!(b, 1); + } else { + assert_eq!(b, 0); + } } diff --git a/compiler/tests/statements/conditional/nested.leo b/compiler/tests/statements/conditional/nested.leo index b4570077fc..b903aad345 100644 --- a/compiler/tests/statements/conditional/nested.leo +++ b/compiler/tests/statements/conditional/nested.leo @@ -1,12 +1,12 @@ -function main(a: bool, b: bool) -> u32 { - let mut result = 0u32; +function main(a: bool, b: bool, c: u32) { + let mut d = 0u32; if a { - result += 1; + d += 1; if b { - result += 2; + d += 2; } } - return result + assert_eq!(d, c); } \ No newline at end of file diff --git a/compiler/tests/statements/conditional/outputs_/registers_one.out b/compiler/tests/statements/conditional/outputs_/registers_one.out new file mode 100644 index 0000000000..663014ef39 --- /dev/null +++ b/compiler/tests/statements/conditional/outputs_/registers_one.out @@ -0,0 +1,2 @@ +[registers] +a: u32 = 1u32; diff --git a/compiler/tests/statements/conditional/outputs_/registers_zero.out b/compiler/tests/statements/conditional/outputs_/registers_zero.out new file mode 100644 index 0000000000..fb12d4d334 --- /dev/null +++ b/compiler/tests/statements/conditional/outputs_/registers_zero.out @@ -0,0 +1,2 @@ +[registers] +a: u32 = 0u32; diff --git a/compiler/tests/statements/iteration_basic.leo b/compiler/tests/statements/iteration_basic.leo index 19460cc543..3dae3d3761 100644 --- a/compiler/tests/statements/iteration_basic.leo +++ b/compiler/tests/statements/iteration_basic.leo @@ -1,8 +1,8 @@ -function main() -> u32 { +function main() { let mut x = 4u32; for i in 0..3 { x -= 1; } - return x + assert_eq!(x, 1u32); } \ No newline at end of file diff --git a/compiler/tests/statements/mod.rs b/compiler/tests/statements/mod.rs index 2d59beaa39..c178b501d9 100644 --- a/compiler/tests/statements/mod.rs +++ b/compiler/tests/statements/mod.rs @@ -1,13 +1,6 @@ -use crate::{ - get_error, - integers::u32::{output_one, output_zero}, - parse_program, -}; +use crate::{assert_satisfied, expect_compiler_error, expect_synthesis_error, generate_main_inputs, parse_program}; use leo_types::InputValue; -use snarkos_curves::edwards_bls12::Fq; -use snarkos_models::gadgets::r1cs::TestConstraintSystem; - pub mod conditional; // Ternary if {bool}? {expression} : {expression}; @@ -15,15 +8,27 @@ pub mod conditional; #[test] fn test_ternary_basic() { let bytes = include_bytes!("ternary_basic.leo"); - let mut program_input_true = parse_program(bytes).unwrap(); + let mut program = parse_program(bytes).unwrap(); - let mut program_input_false = program_input_true.clone(); + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Boolean(true))), + ("b", Some(InputValue::Boolean(true))), + ]); - program_input_true.set_inputs(vec![Some(InputValue::Boolean(true))]); - output_one(program_input_true); + program.set_main_inputs(main_inputs); - program_input_false.set_inputs(vec![Some(InputValue::Boolean(false))]); - output_zero(program_input_false); + assert_satisfied(program); + + let mut program = parse_program(bytes).unwrap(); + + let main_inputs = generate_main_inputs(vec![ + ("a", Some(InputValue::Boolean(false))), + ("b", Some(InputValue::Boolean(false))), + ]); + + program.set_main_inputs(main_inputs); + + assert_satisfied(program); } // Iteration for i {start}..{stop} { statements } @@ -33,7 +38,7 @@ fn test_iteration_basic() { let bytes = include_bytes!("iteration_basic.leo"); let program = parse_program(bytes).unwrap(); - output_one(program); + assert_satisfied(program); } // Assertion @@ -41,23 +46,21 @@ fn test_iteration_basic() { #[test] fn test_assertion_basic() { let bytes = include_bytes!("assertion_basic.leo"); - let program = parse_program(bytes).unwrap(); + let mut program = parse_program(bytes).unwrap(); - let mut program_input_true = program.clone(); - let mut cs_satisfied = TestConstraintSystem::::new(); + let main_inputs = generate_main_inputs(vec![("a", Some(InputValue::Boolean(true)))]); - program_input_true.set_inputs(vec![Some(InputValue::Boolean(true))]); - let _output = program_input_true.compile_constraints(&mut cs_satisfied).unwrap(); + program.set_main_inputs(main_inputs); - assert!(cs_satisfied.is_satisfied()); + assert_satisfied(program); - let mut program_input_false = program.clone(); - let mut cs_unsatisfied = TestConstraintSystem::::new(); + let mut program = parse_program(bytes).unwrap(); - program_input_false.set_inputs(vec![Some(InputValue::Boolean(false))]); - let _output = program_input_false.compile_constraints(&mut cs_unsatisfied).unwrap(); + let main_inputs = generate_main_inputs(vec![("a", Some(InputValue::Boolean(false)))]); - assert!(!cs_unsatisfied.is_satisfied()); + program.set_main_inputs(main_inputs); + + expect_synthesis_error(program); } #[test] @@ -65,5 +68,5 @@ fn test_num_returns_fail() { let bytes = include_bytes!("num_returns_fail.leo"); let program = parse_program(bytes).unwrap(); - let _ = get_error(program); + expect_compiler_error(program); } diff --git a/compiler/tests/statements/ternary_basic.leo b/compiler/tests/statements/ternary_basic.leo index 26909325e0..8ba6a71283 100644 --- a/compiler/tests/statements/ternary_basic.leo +++ b/compiler/tests/statements/ternary_basic.leo @@ -1,3 +1,5 @@ -function main(b: bool) -> u32 { - return if b ? 1 : 0 +function main(a: bool, b: bool) { + let c = if a ? true : false; + + assert_eq!(c, b); } \ No newline at end of file diff --git a/compiler/tests/syntax/mod.rs b/compiler/tests/syntax/mod.rs index b851bfafb1..9a13b69616 100644 --- a/compiler/tests/syntax/mod.rs +++ b/compiler/tests/syntax/mod.rs @@ -1,4 +1,4 @@ -use crate::{get_error, parse_inputs, parse_program}; +use crate::{expect_compiler_error, parse_inputs, parse_program}; use leo_ast::ParserError; use leo_compiler::errors::{CompilerError, ExpressionError, FunctionError, StatementError}; use leo_inputs::InputParserError; @@ -19,7 +19,7 @@ fn test_undefined() { let bytes = include_bytes!("undefined.leo"); let program = parse_program(bytes).unwrap(); - let error = get_error(program); + let error = expect_compiler_error(program); match error { CompilerError::FunctionError(FunctionError::StatementError(StatementError::ExpressionError( diff --git a/leo-inputs/src/assignments/mod.rs b/leo-inputs/src/assignments/mod.rs deleted file mode 100644 index e02881fe86..0000000000 --- a/leo-inputs/src/assignments/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod assignment; -pub use assignment::*; diff --git a/leo-inputs/src/assignments/assignment.rs b/leo-inputs/src/definitions/definition.rs similarity index 83% rename from leo-inputs/src/assignments/assignment.rs rename to leo-inputs/src/definitions/definition.rs index 0945a146a1..7f33591ba9 100644 --- a/leo-inputs/src/assignments/assignment.rs +++ b/leo-inputs/src/definitions/definition.rs @@ -4,8 +4,8 @@ use pest::Span; use pest_ast::FromPest; #[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::assignment))] -pub struct Assignment<'ast> { +#[pest_ast(rule(Rule::definition))] +pub struct Definition<'ast> { pub parameter: Parameter<'ast>, pub expression: Expression<'ast>, pub line_end: LineEnd, diff --git a/leo-inputs/src/definitions/mod.rs b/leo-inputs/src/definitions/mod.rs new file mode 100644 index 0000000000..c4cce58786 --- /dev/null +++ b/leo-inputs/src/definitions/mod.rs @@ -0,0 +1,2 @@ +pub mod definition; +pub use definition::*; diff --git a/leo-inputs/src/errors/parser.rs b/leo-inputs/src/errors/parser.rs index 5753af6bbd..0b9c81cb4d 100644 --- a/leo-inputs/src/errors/parser.rs +++ b/leo-inputs/src/errors/parser.rs @@ -2,6 +2,8 @@ use crate::{ ast::Rule, errors::SyntaxError as InputSyntaxError, expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression}, + sections::Header, + tables::Table, types::{DataType, Type}, values::{NumberImplicitValue, NumberValue, Value}, }; @@ -81,6 +83,46 @@ impl InputParserError { Self::new_from_span(message, span) } + + pub fn input_section_header(header: Header) -> Self { + let message = format!("the section header `{}` is not valid in an input `.in` file", header); + let span = header.span(); + + Self::new_from_span(message, span) + } + + pub fn public_section(header: Header) -> Self { + let message = format!("the section header `{}` is not a public section", header); + let span = header.span(); + + Self::new_from_span(message, span) + } + + pub fn private_section(header: Header) -> Self { + let message = format!("the section header `{}` is not a private section", header); + let span = header.span(); + + Self::new_from_span(message, span) + } + + pub fn table(table: Table) -> Self { + let message = format!( + "the double bracket section `{}` is not valid in an input `.in` file", + table + ); + + Self::new_from_span(message, table.span) + } + + pub fn section(header: Header) -> Self { + let message = format!( + "the section header `{}` must have a double bracket visibility in a state `.state` file", + header + ); + let span = header.span(); + + Self::new_from_span(message, span) + } } impl From> for InputParserError { diff --git a/leo-inputs/src/errors/syntax.rs b/leo-inputs/src/errors/syntax.rs index a436ec15b1..4bca70f5f6 100644 --- a/leo-inputs/src/errors/syntax.rs +++ b/leo-inputs/src/errors/syntax.rs @@ -15,9 +15,10 @@ impl From> for SyntaxError { Rule::type_integer => "`u32`".to_owned(), Rule::type_field => "`field`".to_owned(), Rule::type_group => "`group`".to_owned(), - Rule::file => "an import, circuit, or function".to_owned(), + Rule::file => "a table or section".to_owned(), Rule::identifier => "a variable name".to_owned(), Rule::type_ => "a type".to_owned(), + Rule::header => "[[public]] or [[private]]".to_owned(), rule => format!("{:?}", rule), }); diff --git a/leo-inputs/src/files/file.rs b/leo-inputs/src/files/file.rs index 1c6a1ddeb9..8d2fdfa3bc 100644 --- a/leo-inputs/src/files/file.rs +++ b/leo-inputs/src/files/file.rs @@ -1,4 +1,4 @@ -use crate::{ast::Rule, common::EOI, sections::Section}; +use crate::{ast::Rule, common::EOI, files::TableOrSection}; use pest::Span; use pest_ast::FromPest; @@ -6,7 +6,7 @@ use pest_ast::FromPest; #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::file))] pub struct File<'ast> { - pub sections: Vec>, + pub entries: Vec>, pub eoi: EOI, #[pest_ast(outer())] pub span: Span<'ast>, diff --git a/leo-inputs/src/files/mod.rs b/leo-inputs/src/files/mod.rs index de03a628a4..1638d8b176 100644 --- a/leo-inputs/src/files/mod.rs +++ b/leo-inputs/src/files/mod.rs @@ -1,2 +1,5 @@ pub mod file; pub use file::*; + +pub mod table_or_section; +pub use table_or_section::*; diff --git a/leo-inputs/src/files/table_or_section.rs b/leo-inputs/src/files/table_or_section.rs new file mode 100644 index 0000000000..071fa3e790 --- /dev/null +++ b/leo-inputs/src/files/table_or_section.rs @@ -0,0 +1,10 @@ +use crate::{ast::Rule, sections::Section, tables::Table}; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::table_or_section))] +pub enum TableOrSection<'ast> { + Section(Section<'ast>), + Table(Table<'ast>), +} diff --git a/leo-inputs/src/leo-inputs.pest b/leo-inputs/src/leo-inputs.pest index 601e0693ec..986548f78f 100644 --- a/leo-inputs/src/leo-inputs.pest +++ b/leo-inputs/src/leo-inputs.pest @@ -14,8 +14,15 @@ protected_name = { | "import" | "in" | "let" + | main | "mut" + | private + | public + | record + | registers | "return" + | state + | state_leaf | "static" | "test" | "true" @@ -23,8 +30,6 @@ protected_name = { // Declared in common/line_end.rs LINE_END = { ";" ~ NEWLINE* } - - /// Types // Declared in types/type_.rs @@ -71,7 +76,7 @@ type_boolean = { "bool" } type_address = { "address" } // Declared in types/data_type.rs -type_data = { type_field | type_group | type_boolean | type_integer } +type_data = { type_field | type_group | type_boolean | type_address | type_integer } // Declared in types/array_type.rs type_array = { type_data ~ ("[" ~ value_number ~ "]")+ } @@ -138,15 +143,44 @@ parameter = { identifier ~ ":" ~ type_ } /// Section // Declared in sections/section.rs -section = { header ~ NEWLINE+ ~ (assignment ~ NEWLINE*)* } +section = { "[" ~ header ~ "]" ~ NEWLINE+ ~ (definition ~ NEWLINE*)* } + +// Declared in sections/main_.rs +main = { "main" } + +// Declared in sections/record.rs +record = { "record" } + +// Declared in sections/registers.rs +registers = { "registers" } + +// Declared in sections/state.rs +state = { "state" } + +// Declared in sections/state_leaf.rs +state_leaf = { "state_leaf" } // Declared in sections/header.rs -header = { "[" ~ identifier ~ "]" } +header = { main | record | registers | state_leaf | state | identifier } -/// Assignments +/// Definitions -// Declared in assignment/assignment.rs -assignment = { parameter ~ "=" ~ NEWLINE* ~ expression ~ LINE_END } +// Declared in definition/definition.rs +definition = { parameter ~ "=" ~ NEWLINE* ~ expression ~ LINE_END } + +/// Table + +// Declared in tables/public.rs +public = { "public" } + +// Declared in tables/private.rs +private = { "private" } + +// Declared in tables/visibility.rs +visibility = { public | private } + +// Declared in sections/table.rs +table = {"[[" ~ visibility ~ "]]" ~ NEWLINE+ ~ section*} /// Utilities @@ -155,5 +189,8 @@ WHITESPACE = _{ " " | "\t" ~ (NEWLINE)* } /// Files +// Declared in files/table_or_section.rs +table_or_section = { table | section } + // Declared in files/file.rs -file = { SOI ~ NEWLINE* ~ section* ~ NEWLINE* ~ EOI } +file = { SOI ~ NEWLINE* ~ table_or_section* ~ NEWLINE* ~ EOI } diff --git a/leo-inputs/src/lib.rs b/leo-inputs/src/lib.rs index 80ae76ed80..6c25dba251 100644 --- a/leo-inputs/src/lib.rs +++ b/leo-inputs/src/lib.rs @@ -6,13 +6,14 @@ extern crate thiserror; pub mod errors; pub use errors::*; -pub mod assignments; mod ast; pub mod common; +pub mod definitions; pub mod expressions; pub mod files; pub mod parameters; pub mod sections; +pub mod tables; pub mod types; pub mod values; @@ -29,7 +30,7 @@ impl LeoInputsParser { /// Parses the input file and constructs a syntax tree. pub fn parse_file(input_file: &str) -> Result { - // Parse the file using leo.pest + // Parse the file using leo-inputs.pest let mut file = ast::parse(input_file)?; // Build the abstract syntax tree diff --git a/leo-inputs/src/sections/header.rs b/leo-inputs/src/sections/header.rs index 5ecb08eb14..d5aa339251 100644 --- a/leo-inputs/src/sections/header.rs +++ b/leo-inputs/src/sections/header.rs @@ -1,12 +1,46 @@ -use crate::{ast::Rule, common::Identifier}; +use crate::{ + ast::Rule, + common::Identifier, + sections::{Main, Record, Registers, State, StateLeaf}, +}; use pest::Span; use pest_ast::FromPest; +use std::fmt; #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::header))] -pub struct Header<'ast> { - pub name: Identifier<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, +pub enum Header<'ast> { + Main(Main<'ast>), + Record(Record<'ast>), + Registers(Registers<'ast>), + State(State<'ast>), + StateLeaf(StateLeaf<'ast>), + Identifier(Identifier<'ast>), +} + +impl<'ast> Header<'ast> { + pub fn span(self) -> Span<'ast> { + match self { + Header::Main(main) => main.span, + Header::Record(record) => record.span, + Header::Registers(registers) => registers.span, + Header::State(state) => state.span, + Header::StateLeaf(state_leaf) => state_leaf.span, + Header::Identifier(identifier) => identifier.span, + } + } +} + +impl<'ast> fmt::Display for Header<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Header::Main(_main) => write!(f, "main"), + Header::Record(_record) => write!(f, "record"), + Header::Registers(_registers) => write!(f, "registers"), + Header::State(_state) => write!(f, "state"), + Header::StateLeaf(_state_leaf) => write!(f, "state_leaf"), + Header::Identifier(identifier) => write!(f, "{}", identifier.value), + } + } } diff --git a/leo-inputs/src/sections/main_.rs b/leo-inputs/src/sections/main_.rs new file mode 100644 index 0000000000..9f52418153 --- /dev/null +++ b/leo-inputs/src/sections/main_.rs @@ -0,0 +1,11 @@ +use crate::ast::Rule; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::main))] +pub struct Main<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/sections/mod.rs b/leo-inputs/src/sections/mod.rs index ad84b1fade..8fd04e6ba3 100644 --- a/leo-inputs/src/sections/mod.rs +++ b/leo-inputs/src/sections/mod.rs @@ -1,5 +1,20 @@ pub mod header; pub use header::*; +pub mod main_; +pub use main_::*; + +pub mod record; +pub use record::*; + +pub mod registers; +pub use registers::*; + +pub mod state; +pub use state::*; + +pub mod state_leaf; +pub use state_leaf::*; + pub mod section; pub use section::*; diff --git a/leo-inputs/src/sections/record.rs b/leo-inputs/src/sections/record.rs new file mode 100644 index 0000000000..2f67290130 --- /dev/null +++ b/leo-inputs/src/sections/record.rs @@ -0,0 +1,11 @@ +use crate::ast::Rule; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::record))] +pub struct Record<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/sections/registers.rs b/leo-inputs/src/sections/registers.rs new file mode 100644 index 0000000000..8e11fde122 --- /dev/null +++ b/leo-inputs/src/sections/registers.rs @@ -0,0 +1,11 @@ +use crate::ast::Rule; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::registers))] +pub struct Registers<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/sections/section.rs b/leo-inputs/src/sections/section.rs index 02186b2c61..0e43dd9778 100644 --- a/leo-inputs/src/sections/section.rs +++ b/leo-inputs/src/sections/section.rs @@ -1,4 +1,4 @@ -use crate::{assignments::Assignment, ast::Rule, sections::Header}; +use crate::{ast::Rule, definitions::Definition, sections::Header}; use pest::Span; use pest_ast::FromPest; @@ -7,7 +7,7 @@ use pest_ast::FromPest; #[pest_ast(rule(Rule::section))] pub struct Section<'ast> { pub header: Header<'ast>, - pub assignments: Vec>, + pub definitions: Vec>, #[pest_ast(outer())] pub span: Span<'ast>, } diff --git a/leo-inputs/src/sections/state.rs b/leo-inputs/src/sections/state.rs new file mode 100644 index 0000000000..8063e4f8a9 --- /dev/null +++ b/leo-inputs/src/sections/state.rs @@ -0,0 +1,11 @@ +use crate::ast::Rule; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::state))] +pub struct State<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/sections/state_leaf.rs b/leo-inputs/src/sections/state_leaf.rs new file mode 100644 index 0000000000..932203f24c --- /dev/null +++ b/leo-inputs/src/sections/state_leaf.rs @@ -0,0 +1,11 @@ +use crate::ast::Rule; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::state_leaf))] +pub struct StateLeaf<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/tables/mod.rs b/leo-inputs/src/tables/mod.rs new file mode 100644 index 0000000000..089015621f --- /dev/null +++ b/leo-inputs/src/tables/mod.rs @@ -0,0 +1,11 @@ +pub mod private; +pub use private::*; + +pub mod public; +pub use public::*; + +pub mod table; +pub use table::*; + +pub mod visibility; +pub use visibility::*; diff --git a/leo-inputs/src/tables/private.rs b/leo-inputs/src/tables/private.rs new file mode 100644 index 0000000000..1c1c86d44b --- /dev/null +++ b/leo-inputs/src/tables/private.rs @@ -0,0 +1,18 @@ +use crate::ast::Rule; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::private))] +pub struct Private<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for Private<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.span.as_str().to_string()) + } +} diff --git a/leo-inputs/src/tables/public.rs b/leo-inputs/src/tables/public.rs new file mode 100644 index 0000000000..a16e567914 --- /dev/null +++ b/leo-inputs/src/tables/public.rs @@ -0,0 +1,18 @@ +use crate::ast::Rule; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::public))] +pub struct Public<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for Public<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.span.as_str().to_string()) + } +} diff --git a/leo-inputs/src/tables/table.rs b/leo-inputs/src/tables/table.rs new file mode 100644 index 0000000000..e115c237ea --- /dev/null +++ b/leo-inputs/src/tables/table.rs @@ -0,0 +1,20 @@ +use crate::{ast::Rule, sections::Section, tables::Visibility}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::table))] +pub struct Table<'ast> { + pub visibility: Visibility<'ast>, + pub sections: Vec>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for Table<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "[[{}]]", self.visibility) + } +} diff --git a/leo-inputs/src/tables/visibility.rs b/leo-inputs/src/tables/visibility.rs new file mode 100644 index 0000000000..af2c93e2e4 --- /dev/null +++ b/leo-inputs/src/tables/visibility.rs @@ -0,0 +1,23 @@ +use crate::{ + ast::Rule, + tables::{Private, Public}, +}; + +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::visibility))] +pub enum Visibility<'ast> { + Private(Private<'ast>), + Public(Public<'ast>), +} + +impl<'ast> fmt::Display for Visibility<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Visibility::Private(private) => write!(f, "{}", private), + Visibility::Public(public) => write!(f, "{}", public), + } + } +} diff --git a/leo/commands/build.rs b/leo/commands/build.rs index a3086931c3..52aa4b864b 100644 --- a/leo/commands/build.rs +++ b/leo/commands/build.rs @@ -1,9 +1,9 @@ use crate::{ cli::*, cli_types::*, - directories::{source::SOURCE_DIRECTORY_NAME, OutputsDirectory}, + directories::{source::SOURCE_DIRECTORY_NAME, OutputsDirectory, OUTPUTS_DIRECTORY_NAME}, errors::CLIError, - files::{ChecksumFile, LibFile, MainFile, Manifest, LIB_FILE_NAME, MAIN_FILE_NAME}, + files::{ChecksumFile, InputsFile, LibFile, MainFile, Manifest, StateFile, LIB_FILE_NAME, MAIN_FILE_NAME}, }; use leo_compiler::{compiler::Compiler, group::targets::edwards_bls12::EdwardsGroupType}; @@ -47,6 +47,10 @@ impl CLI for BuildCommand { package_path.pop(); } + // Construct the path to the outputs directory + let mut outputs_directory = package_path.clone(); + outputs_directory.push(OUTPUTS_DIRECTORY_NAME); + // Compile the package starting with the lib.leo file if LibFile::exists_at(&package_path) { // Construct the path to the library file in the source directory @@ -55,8 +59,11 @@ impl CLI for BuildCommand { lib_file_path.push(LIB_FILE_NAME); // Compile the library file but do not output - let _program = - Compiler::::new_from_path(package_name.clone(), lib_file_path.clone())?; + let _program = Compiler::::parse_program_without_inputs( + package_name.clone(), + lib_file_path.clone(), + outputs_directory.clone(), + )?; log::info!("Compiled library file {:?}", lib_file_path); }; @@ -71,9 +78,20 @@ impl CLI for BuildCommand { main_file_path.push(SOURCE_DIRECTORY_NAME); main_file_path.push(MAIN_FILE_NAME); + // Load the inputs file at `package_name.in` + let inputs_string = InputsFile::new(&package_name).read_from(&path)?; + + // Load the state file at `package_name.in` + let state_string = StateFile::new(&package_name).read_from(&path)?; + // Load the program at `main_file_path` - let program = - Compiler::::new_from_path(package_name.clone(), main_file_path.clone())?; + let program = Compiler::::parse_program_with_inputs( + package_name.clone(), + main_file_path.clone(), + outputs_directory, + &inputs_string, + &state_string, + )?; // Compute the current program checksum let program_checksum = program.checksum()?; diff --git a/leo/commands/prove.rs b/leo/commands/prove.rs index fa1a584ba1..01319da4d3 100644 --- a/leo/commands/prove.rs +++ b/leo/commands/prove.rs @@ -3,7 +3,7 @@ use crate::{ cli_types::*, commands::SetupCommand, errors::CLIError, - files::{InputsFile, Manifest, ProofFile}, + files::{Manifest, ProofFile}, }; use snarkos_algorithms::snark::groth16::{Groth16, PreparedVerifyingKey, Proof}; @@ -35,7 +35,7 @@ impl CLI for ProveCommand { #[cfg_attr(tarpaulin, skip)] fn output(options: Self::Options) -> Result { - let (mut program, parameters, prepared_verifying_key) = SetupCommand::output(options)?; + let (program, parameters, prepared_verifying_key) = SetupCommand::output(options)?; // Get the package name let path = current_dir()?; @@ -43,10 +43,6 @@ impl CLI for ProveCommand { log::info!("Proving..."); - // Fetch program inputs here - let inputs_string = InputsFile::new(&package_name).read_from(&path)?; - program.parse_inputs(&inputs_string)?; - // Start the timer let start = Instant::now(); diff --git a/leo/commands/test.rs b/leo/commands/test.rs index f23b9df6c7..c9d5370b58 100644 --- a/leo/commands/test.rs +++ b/leo/commands/test.rs @@ -1,9 +1,9 @@ use crate::{ cli::*, cli_types::*, - directories::source::SOURCE_DIRECTORY_NAME, + directories::{outputs::OUTPUTS_DIRECTORY_NAME, source::SOURCE_DIRECTORY_NAME}, errors::{CLIError, TestError}, - files::{MainFile, Manifest, MAIN_FILE_NAME}, + files::{InputsFile, MainFile, Manifest, StateFile, MAIN_FILE_NAME}, }; use leo_compiler::{compiler::Compiler, group::targets::edwards_bls12::EdwardsGroupType}; @@ -56,8 +56,24 @@ impl CLI for TestCommand { main_file_path.push(SOURCE_DIRECTORY_NAME); main_file_path.push(MAIN_FILE_NAME); + // Construct the path to the outputs directory; + let mut outputs_directory = package_path.clone(); + outputs_directory.push(OUTPUTS_DIRECTORY_NAME); + + // Load the inputs file at `package_name` + let inputs_string = InputsFile::new(&package_name).read_from(&path)?; + + // Load the state file at `package_name.in` + let state_string = StateFile::new(&package_name).read_from(&path)?; + // Compute the current program checksum - let program = Compiler::::new_from_path(package_name.clone(), main_file_path.clone())?; + let program = Compiler::::parse_program_with_inputs( + package_name.clone(), + main_file_path.clone(), + outputs_directory, + &inputs_string, + &state_string, + )?; // Generate the program on the constraint system and verify correctness { diff --git a/leo/errors/cli.rs b/leo/errors/cli.rs index a4fcb3c17b..abc51430ff 100644 --- a/leo/errors/cli.rs +++ b/leo/errors/cli.rs @@ -56,6 +56,9 @@ pub enum CLIError { #[error("{}", _0)] SourceDirectoryError(SourceDirectoryError), + #[error("{}", _0)] + StateFileError(StateFileError), + #[error("{}", _0)] TestError(TestError), @@ -175,6 +178,13 @@ impl From for CLIError { } } +impl From for CLIError { + fn from(error: StateFileError) -> Self { + log::error!("{}\n", error); + CLIError::StateFileError(error) + } +} + impl From for CLIError { fn from(error: TestError) -> Self { log::error!("{}\n", error); diff --git a/leo/errors/files/mod.rs b/leo/errors/files/mod.rs index 97bcc19e30..22638df0eb 100644 --- a/leo/errors/files/mod.rs +++ b/leo/errors/files/mod.rs @@ -25,5 +25,8 @@ pub use self::proof::*; pub mod proving_key; pub use self::proving_key::*; +pub mod state; +pub use self::state::*; + pub mod verification_key; pub use self::verification_key::*; diff --git a/leo/errors/files/state.rs b/leo/errors/files/state.rs new file mode 100644 index 0000000000..a0cd41d28a --- /dev/null +++ b/leo/errors/files/state.rs @@ -0,0 +1,22 @@ +use std::{io, path::PathBuf}; + +#[derive(Debug, Error)] +pub enum StateFileError { + #[error("{}: {}", _0, _1)] + Crate(&'static str, String), + + #[error("creating: {}", _0)] + Creating(io::Error), + + #[error("Cannot read from the provided file path - {:?}", _0)] + FileReadError(PathBuf), + + #[error("writing: {}", _0)] + Writing(io::Error), +} + +impl From for StateFileError { + fn from(error: std::io::Error) -> Self { + StateFileError::Crate("std::io", format!("{}", error)) + } +} diff --git a/leo/files/inputs.rs b/leo/files/inputs.rs index 10bb9a185e..538f9adc13 100644 --- a/leo/files/inputs.rs +++ b/leo/files/inputs.rs @@ -1,4 +1,4 @@ -//! The `inputs.leo` file. +//! The `program.in` file. use crate::{directories::inputs::INPUTS_DIRECTORY_NAME, errors::InputsFileError}; @@ -28,7 +28,7 @@ impl InputsFile { path.exists() } - /// Reads the proof from the given file path if it exists. + /// Reads the inputs from the given file path if it exists. pub fn read_from(&self, path: &PathBuf) -> Result { let path = self.setup_file_path(path); diff --git a/leo/files/mod.rs b/leo/files/mod.rs index 0e4f02c8dc..8c273c1146 100644 --- a/leo/files/mod.rs +++ b/leo/files/mod.rs @@ -25,5 +25,8 @@ pub use self::proof::*; pub mod proving_key; pub use self::proving_key::*; +pub mod state; +pub use self::state::*; + pub mod verification_key; pub use self::verification_key::*; diff --git a/leo/files/state.rs b/leo/files/state.rs new file mode 100644 index 0000000000..0dfab788dc --- /dev/null +++ b/leo/files/state.rs @@ -0,0 +1,89 @@ +//! The `program.state` file. + +use crate::{directories::inputs::INPUTS_DIRECTORY_NAME, errors::StateFileError}; + +use serde::Deserialize; +use std::{ + fs::{self, File}, + io::Write, + path::PathBuf, +}; + +pub static STATE_FILE_EXTENSION: &str = ".state"; + +#[derive(Deserialize)] +pub struct StateFile { + pub package_name: String, +} + +impl StateFile { + pub fn new(package_name: &str) -> Self { + Self { + package_name: package_name.to_string(), + } + } + + pub fn exists_at(&self, path: &PathBuf) -> bool { + let path = self.setup_file_path(path); + path.exists() + } + + /// Reads the state inputs from the given file path if it exists. + pub fn read_from(&self, path: &PathBuf) -> Result { + let path = self.setup_file_path(path); + + let inputs = fs::read_to_string(&path).map_err(|_| StateFileError::FileReadError(path.clone()))?; + Ok(inputs) + } + + /// Writes the standard input format to a file. + pub fn write_to(self, path: &PathBuf) -> Result<(), StateFileError> { + let path = self.setup_file_path(path); + + let mut file = File::create(&path)?; + Ok(file.write_all(self.template().as_bytes())?) + } + + fn template(&self) -> String { + format!( + r#"// The program state for {}/src/main.leo +[[public]] + +[state] +leaf_index: u32 = 0; +root: u8[32] = [0u8; 32]; + +[[private]] + +[record] +serial_number: u8[32] = [0u8; 32]; +commitment: u8[32] = [0u8; 32]; +owner: address = aleo1...; +value: u64 = 5; +payload: u8[32] = [0u8; 32]; // TBD +birth_program_id: u8[32] = [0u8; 32]; +death_program_id: u8[32] = [0u8; 32]; +serial_number_nonce: u8[32] = [0u8; 32]; +commitment_randomness: u8[32] = [0u8; 32]; + +[state_leaf] +path: u8[32][2] = [ [0u8; 32], [0u8; 32] ]; +memo: u8[32] = [0u8; 32]; +network_id: u8 = 0; +leaf_randomness: u8[32] = [0u8; 32]; +"#, + self.package_name + ) + } + + fn setup_file_path(&self, path: &PathBuf) -> PathBuf { + let mut path = path.to_owned(); + if path.is_dir() { + if !path.ends_with(INPUTS_DIRECTORY_NAME) { + path.push(PathBuf::from(INPUTS_DIRECTORY_NAME)); + } + path.push(PathBuf::from(format!("{}{}", self.package_name, STATE_FILE_EXTENSION))); + } + path + } +} diff --git a/types/src/common/identifier.rs b/types/src/common/identifier.rs index cd152b5ccd..799596fca6 100644 --- a/types/src/common/identifier.rs +++ b/types/src/common/identifier.rs @@ -1,5 +1,6 @@ use crate::Span; use leo_ast::common::Identifier as AstIdentifier; +use leo_inputs::common::Identifier as InputsAstIdentifier; use serde::{Deserialize, Serialize}; use std::fmt; @@ -26,6 +27,15 @@ impl<'ast> From> for Identifier { } } +impl<'ast> From> for Identifier { + fn from(identifier: InputsAstIdentifier<'ast>) -> Self { + Self { + name: identifier.value, + span: Span::from(identifier.span), + } + } +} + impl fmt::Display for Identifier { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.name) diff --git a/types/src/expression.rs b/types/src/expression.rs index e0ef19abcc..dcfd5b34df 100644 --- a/types/src/expression.rs +++ b/types/src/expression.rs @@ -17,6 +17,7 @@ use leo_ast::{ }; use leo_ast::values::AddressValue; +use leo_inputs::values::NumberValue; use serde::{Deserialize, Serialize}; use std::fmt; @@ -103,7 +104,7 @@ impl Expression { } impl<'ast> Expression { - pub(crate) fn get_count(count: Value<'ast>) -> usize { + pub(crate) fn get_count_from_value(count: Value<'ast>) -> usize { match count { Value::Integer(integer) => integer .number @@ -114,6 +115,10 @@ impl<'ast> Expression { size => unimplemented!("Array size should be an integer {}", size), } } + + pub(crate) fn get_count_from_number(number: NumberValue<'ast>) -> usize { + number.value.parse::().expect("Unable to read array size") + } } impl<'ast> fmt::Display for Expression { @@ -398,7 +403,7 @@ impl<'ast> From> for Expression { impl<'ast> From> for Expression { fn from(array: ArrayInitializerExpression<'ast>) -> Self { - let count = Expression::get_count(array.count); + let count = Expression::get_count_from_value(array.count); let expression = Box::new(SpreadOrExpression::from(*array.expression)); Expression::Array(vec![expression; count], Span::from(array.span)) diff --git a/types/src/functions/function.rs b/types/src/functions/function.rs index 8808234d61..2bc6e7cc50 100644 --- a/types/src/functions/function.rs +++ b/types/src/functions/function.rs @@ -1,4 +1,4 @@ -use crate::{FunctionInput, Identifier, Span, Statement, Type}; +use crate::{Identifier, Input, Span, Statement, Type}; use leo_ast::functions::Function as AstFunction; use serde::{Deserialize, Serialize}; @@ -7,7 +7,7 @@ use std::fmt; #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Function { pub function_name: Identifier, - pub inputs: Vec, + pub inputs: Vec, pub returns: Vec, pub statements: Vec, pub span: Span, @@ -19,7 +19,7 @@ impl<'ast> From> for Function { let parameters = function_definition .parameters .into_iter() - .map(|parameter| FunctionInput::from(parameter)) + .map(|parameter| Input::from(parameter)) .collect(); let returns = function_definition .returns diff --git a/types/src/functions/function_input.rs b/types/src/functions/inputs/function_input.rs similarity index 91% rename from types/src/functions/function_input.rs rename to types/src/functions/inputs/function_input.rs index 98c88071dc..e2f49cad21 100644 --- a/types/src/functions/function_input.rs +++ b/types/src/functions/inputs/function_input.rs @@ -8,7 +8,7 @@ use std::fmt; pub struct FunctionInput { pub identifier: Identifier, pub mutable: bool, - pub _type: Type, + pub type_: Type, pub span: Span, } @@ -17,7 +17,7 @@ impl<'ast> From> for FunctionInput { FunctionInput { identifier: Identifier::from(parameter.identifier), mutable: parameter.mutable.is_some(), - _type: Type::from(parameter._type), + type_: Type::from(parameter._type), span: Span::from(parameter.span), } } @@ -30,7 +30,7 @@ impl FunctionInput { write!(f, "mut ")?; } write!(f, "{}: ", self.identifier)?; - write!(f, "{}", self._type) + write!(f, "{}", self.type_) } } diff --git a/types/src/functions/inputs/input.rs b/types/src/functions/inputs/input.rs new file mode 100644 index 0000000000..6168515e5c --- /dev/null +++ b/types/src/functions/inputs/input.rs @@ -0,0 +1,83 @@ +use crate::{FunctionInput, Identifier, Span}; +use leo_ast::functions::inputs::Input as AstInput; + +use serde::{Deserialize, Serialize}; +use std::fmt; + +pub const RECORD_VARIABLE_NAME: &str = "record"; +pub const REGISTERS_VARIABLE_NAME: &str = "registers"; +pub const STATE_VARIABLE_NAME: &str = "state"; +pub const STATE_LEAF_VARIABLE_NAME: &str = "state_leaf"; + +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum Input { + FunctionInput(FunctionInput), + Record(Identifier), + Registers(Identifier), + State(Identifier), + StateLeaf(Identifier), +} + +impl<'ast> From> for Input { + fn from(input: AstInput<'ast>) -> Self { + match input { + AstInput::FunctionInput(function_input) => Input::FunctionInput(FunctionInput::from(function_input)), + AstInput::Record(record) => { + let id = Identifier { + name: RECORD_VARIABLE_NAME.to_string(), + span: Span::from(record.span), + }; + + Input::Record(id) + } + AstInput::Registers(registers) => { + let id = Identifier { + name: REGISTERS_VARIABLE_NAME.to_string(), + span: Span::from(registers.span), + }; + + Input::Registers(id) + } + AstInput::State(state) => { + let id = Identifier { + name: STATE_VARIABLE_NAME.to_string(), + span: Span::from(state.span), + }; + + Input::State(id) + } + AstInput::StateLeaf(state_leaf) => { + let id = Identifier { + name: STATE_LEAF_VARIABLE_NAME.to_string(), + span: Span::from(state_leaf.span), + }; + + Input::StateLeaf(id) + } + } + } +} + +impl Input { + fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Input::FunctionInput(function_input) => write!(f, "{}", function_input), + Input::Record(id) => write!(f, "{}", id), + Input::Registers(id) => write!(f, "{}", id), + Input::State(id) => write!(f, "{}", id), + Input::StateLeaf(id) => write!(f, "{}", id), + } + } +} + +impl fmt::Display for Input { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } +} + +impl fmt::Debug for Input { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } +} diff --git a/types/src/functions/inputs/mod.rs b/types/src/functions/inputs/mod.rs new file mode 100644 index 0000000000..a545b7282e --- /dev/null +++ b/types/src/functions/inputs/mod.rs @@ -0,0 +1,5 @@ +pub mod function_input; +pub use function_input::*; + +pub mod input; +pub use input::*; diff --git a/types/src/functions/mod.rs b/types/src/functions/mod.rs index fadb2897b1..7ae6a0a9fe 100644 --- a/types/src/functions/mod.rs +++ b/types/src/functions/mod.rs @@ -1,8 +1,8 @@ pub mod function; pub use function::*; -pub mod function_input; -pub use function_input::*; +pub mod inputs; +pub use inputs::*; pub mod test_function; pub use test_function::*; diff --git a/types/src/inputs/inputs.rs b/types/src/inputs/inputs.rs index d1a17d2aca..0515792d14 100644 --- a/types/src/inputs/inputs.rs +++ b/types/src/inputs/inputs.rs @@ -1,57 +1,92 @@ -use crate::{FunctionInput, InputValue}; -use leo_inputs::{files::File, InputParserError}; +use crate::{InputValue, MainInputs, ProgramInputs, ProgramState, Record, Registers, State, StateLeaf}; +use leo_inputs::{ + files::{File, TableOrSection}, + InputParserError, +}; -static MAIN_INPUT_FILE_HEADER: &'static str = "main"; - -#[derive(Clone)] +#[derive(Clone, PartialEq, Eq)] pub struct Inputs { - program_inputs: Vec>, + inputs: ProgramInputs, + state: ProgramState, } impl Inputs { pub fn new() -> Self { - Self { program_inputs: vec![] } + Self { + inputs: ProgramInputs::new(), + state: ProgramState::new(), + } } - pub fn get_inputs(&self) -> Vec> { - self.program_inputs.clone() + /// Returns an empty version of this struct with `None` values. + /// Called during constraint synthesis to provide private inputs. + pub fn empty(&self) -> Self { + let inputs = self.inputs.empty(); + let state = self.state.empty(); + + Self { inputs, state } } - pub fn set_inputs(&mut self, inputs: Vec>) { - self.program_inputs = inputs; + /// Returns the number of input variables to pass into the `main` program function + pub fn len(&self) -> usize { + self.inputs.len() + self.state.len() } - pub fn set_inputs_size(&mut self, size: usize) { - self.program_inputs = vec![None; size]; + /// Manually set the input variables to the `main` program function + pub fn set_main_inputs(&mut self, inputs: MainInputs) { + self.inputs.main = inputs; } - pub fn from_inputs_file(file: File, expected_inputs: Vec) -> Result { - let mut program_inputs = vec![]; + /// Parse all inputs included in a file and store them in `self`. + pub fn parse_inputs(&mut self, file: File) -> Result<(), InputParserError> { + for entry in file.entries.into_iter() { + match entry { + TableOrSection::Section(section) => { + self.inputs.parse(section)?; + } + TableOrSection::Table(table) => return Err(InputParserError::table(table)), + } + } - for section in file.sections.into_iter() { - if section.header.name.value.eq(MAIN_INPUT_FILE_HEADER) { - for input in &expected_inputs { - // find input with matching name - let matched_input = section.assignments.clone().into_iter().find(|assignment| { - // name match - assignment.parameter.variable.value.eq(&input.identifier.name) - // type match - && assignment.parameter.type_.to_string().eq(&input._type.to_string()) - }); + Ok(()) + } - match matched_input { - Some(assignment) => { - let value = InputValue::from_expression(assignment.parameter.type_, assignment.expression)?; - - // push value to vector - program_inputs.push(Some(value)); - } - None => return Err(InputParserError::InputNotFound(input.to_string())), - } + /// Parse all inputs included in a file and store them in `self`. + pub fn parse_state(&mut self, file: File) -> Result<(), InputParserError> { + for entry in file.entries.into_iter() { + match entry { + TableOrSection::Section(section) => return Err(InputParserError::section(section.header)), + TableOrSection::Table(table) => { + self.state.parse(table)?; } } } - Ok(Self { program_inputs }) + Ok(()) + } + + /// Returns the main function input value with the given `name` + pub fn get(&self, name: &String) -> Option> { + self.inputs.get(name) + } + + /// Returns the runtime register input values + pub fn get_registers(&self) -> &Registers { + self.inputs.get_registers() + } + + /// Returns the runtime record input values + pub fn get_record(&self) -> &Record { + self.state.get_record() + } + + /// Returns the runtime state input values + pub fn get_state(&self) -> &State { + self.state.get_state() + } + + /// Returns the runtime state leaf input values + pub fn get_state_leaf(&self) -> &StateLeaf { + self.state.get_state_leaf() } } diff --git a/types/src/inputs/macros.rs b/types/src/inputs/macros.rs new file mode 100644 index 0000000000..eda9be1049 --- /dev/null +++ b/types/src/inputs/macros.rs @@ -0,0 +1,59 @@ +#[macro_export] +macro_rules! input_section_impl { + ($($name: ident), *) => ($( + + /// An input section declared in an input file with `[$name]` + #[derive(Clone, PartialEq, Eq)] + pub struct $name { + is_present: bool, + values: HashMap>, + } + + impl $name { + pub fn new() -> Self { + Self { + is_present: false, + values: HashMap::new(), + } + } + + /// Returns an empty version of this struct with `None` values. + /// Called during constraint synthesis to provide private inputs. + pub fn empty(&self) -> Self { + let is_present = self.is_present; + let mut values = self.values.clone(); + + values.iter_mut().for_each(|(_parameter, value)| { + *value = None; + }); + + Self { is_present, values } + } + + /// Returns `true` if the main function contains the `$name` variable. + pub fn is_present(&self) -> bool { + self.is_present + } + + /// Parses register input definitions and stores them in `self`. + /// This function is called if the main function input contains the `$name` variable. + pub fn parse(&mut self, definitions: Vec) -> Result<(), InputParserError> { + self.is_present = true; + + for definition in definitions { + let value = InputValue::from_expression(definition.parameter.type_.clone(), definition.expression)?; + let parameter = Parameter::from(definition.parameter); + + self.values.insert(parameter, Some(value)); + } + + Ok(()) + } + + /// Returns this section's hashmap of values + pub fn values(&self) -> HashMap> { + self.values.clone() + } + } + )*) +} diff --git a/types/src/inputs/mod.rs b/types/src/inputs/mod.rs index 5f93ed25d3..79244864c6 100644 --- a/types/src/inputs/mod.rs +++ b/types/src/inputs/mod.rs @@ -1,5 +1,18 @@ +#[macro_use] +pub mod macros; +pub use macros::*; + pub mod inputs; pub use inputs::*; pub mod input_value; pub use input_value::*; + +pub mod parameters; +pub use parameters::*; + +pub mod program_inputs; +pub use program_inputs::*; + +pub mod program_state; +pub use program_state::*; diff --git a/types/src/inputs/parameters/mod.rs b/types/src/inputs/parameters/mod.rs new file mode 100644 index 0000000000..cf55dbc6dd --- /dev/null +++ b/types/src/inputs/parameters/mod.rs @@ -0,0 +1,2 @@ +pub mod parameter; +pub use parameter::*; diff --git a/types/src/inputs/parameters/parameter.rs b/types/src/inputs/parameters/parameter.rs new file mode 100644 index 0000000000..f5ad9880fa --- /dev/null +++ b/types/src/inputs/parameters/parameter.rs @@ -0,0 +1,19 @@ +use crate::{Identifier, Span, Type}; +use leo_inputs::parameters::Parameter as AstParameter; + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct Parameter { + pub variable: Identifier, + pub type_: Type, + pub span: Span, +} + +impl<'ast> From> for Parameter { + fn from(parameter: AstParameter<'ast>) -> Self { + Self { + variable: Identifier::from(parameter.variable), + type_: Type::from(parameter.type_), + span: Span::from(parameter.span), + } + } +} diff --git a/types/src/inputs/program_inputs/main_inputs.rs b/types/src/inputs/program_inputs/main_inputs.rs new file mode 100644 index 0000000000..e74cbd9f72 --- /dev/null +++ b/types/src/inputs/program_inputs/main_inputs.rs @@ -0,0 +1,51 @@ +use crate::InputValue; +use leo_inputs::{definitions::Definition, InputParserError}; +use std::collections::HashMap; + +#[derive(Clone, PartialEq, Eq)] +pub struct MainInputs { + inputs: HashMap>, +} + +impl MainInputs { + pub fn new() -> Self { + Self { inputs: HashMap::new() } + } + + /// Returns an empty version of this struct with `None` values. + /// Called during constraint synthesis to provide private inputs. + pub fn empty(&self) -> Self { + let mut inputs = self.inputs.clone(); + + inputs.iter_mut().for_each(|(_name, value)| { + *value = None; + }); + + Self { inputs } + } + + pub fn len(&self) -> usize { + self.inputs.len() + } + + pub fn insert(&mut self, key: String, value: Option) { + self.inputs.insert(key, value); + } + + /// Parses main input definitions and stores them in `self`. + pub fn parse(&mut self, definitions: Vec) -> Result<(), InputParserError> { + for definition in definitions { + let name = definition.parameter.variable.value; + let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?; + + self.insert(name, Some(value)); + } + + Ok(()) + } + + /// Returns an `Option` of the main function input at `name` + pub fn get(&self, name: &String) -> Option> { + self.inputs.get(name).map(|input| input.clone()) + } +} diff --git a/types/src/inputs/program_inputs/mod.rs b/types/src/inputs/program_inputs/mod.rs new file mode 100644 index 0000000000..d929c034aa --- /dev/null +++ b/types/src/inputs/program_inputs/mod.rs @@ -0,0 +1,8 @@ +pub mod main_inputs; +pub use main_inputs::*; + +pub mod program_inputs; +pub use program_inputs::*; + +pub mod registers; +pub use registers::*; diff --git a/types/src/inputs/program_inputs/program_inputs.rs b/types/src/inputs/program_inputs/program_inputs.rs new file mode 100644 index 0000000000..2ffb0d304d --- /dev/null +++ b/types/src/inputs/program_inputs/program_inputs.rs @@ -0,0 +1,62 @@ +use crate::{InputValue, MainInputs, Registers}; +use leo_inputs::{ + sections::{Header, Section}, + InputParserError, +}; + +#[derive(Clone, PartialEq, Eq)] +pub struct ProgramInputs { + pub main: MainInputs, + registers: Registers, +} + +impl ProgramInputs { + pub fn new() -> Self { + Self { + main: MainInputs::new(), + registers: Registers::new(), + } + } + + /// Returns an empty version of this struct with `None` values. + /// Called during constraint synthesis to provide private inputs. + pub fn empty(&self) -> Self { + let main = self.main.empty(); + let registers = self.registers.empty(); + + Self { main, registers } + } + + pub fn len(&self) -> usize { + let mut len = 0; + + // add main inputs + len += self.main.len(); + + // add registers + if self.registers.is_present() { + len += 1; + } + + len + } + + /// Parse all inputs included in a file and store them in `self`. + pub fn parse(&mut self, section: Section) -> Result<(), InputParserError> { + match section.header { + Header::Main(_main) => self.main.parse(section.definitions), + Header::Registers(_registers) => self.registers.parse(section.definitions), + header => Err(InputParserError::input_section_header(header)), + } + } + + /// Returns the main function input value with the given `name` + pub fn get(&self, name: &String) -> Option> { + self.main.get(name) + } + + /// Returns the runtime register input values + pub fn get_registers(&self) -> &Registers { + &self.registers + } +} diff --git a/types/src/inputs/program_inputs/registers.rs b/types/src/inputs/program_inputs/registers.rs new file mode 100644 index 0000000000..32e1d1b328 --- /dev/null +++ b/types/src/inputs/program_inputs/registers.rs @@ -0,0 +1,6 @@ +use crate::{InputValue, Parameter}; +use leo_inputs::{definitions::Definition, InputParserError}; + +use std::collections::HashMap; + +input_section_impl!(Registers); diff --git a/types/src/inputs/program_state/mod.rs b/types/src/inputs/program_state/mod.rs new file mode 100644 index 0000000000..cb46f6ba9c --- /dev/null +++ b/types/src/inputs/program_state/mod.rs @@ -0,0 +1,8 @@ +pub mod private_state; +pub use private_state::*; + +pub mod program_state; +pub use program_state::*; + +pub mod public_state; +pub use public_state::*; diff --git a/types/src/inputs/program_state/private_state/mod.rs b/types/src/inputs/program_state/private_state/mod.rs new file mode 100644 index 0000000000..2dafb8f530 --- /dev/null +++ b/types/src/inputs/program_state/private_state/mod.rs @@ -0,0 +1,8 @@ +pub mod private_state; +pub use private_state::*; + +pub mod record; +pub use record::*; + +pub mod state_leaf; +pub use state_leaf::*; diff --git a/types/src/inputs/program_state/private_state/private_state.rs b/types/src/inputs/program_state/private_state/private_state.rs new file mode 100644 index 0000000000..7fe6d85fb4 --- /dev/null +++ b/types/src/inputs/program_state/private_state/private_state.rs @@ -0,0 +1,68 @@ +use crate::{Record, StateLeaf}; +use leo_inputs::{ + sections::{Header, Section}, + InputParserError, +}; + +#[derive(Clone, PartialEq, Eq)] +pub struct PrivateState { + record: Record, + state_leaf: StateLeaf, +} + +impl PrivateState { + pub fn new() -> Self { + Self { + record: Record::new(), + state_leaf: StateLeaf::new(), + } + } + + /// Returns an empty version of this struct with `None` values. + /// Called during constraint synthesis to provide private inputs. + pub fn empty(&self) -> Self { + let record = self.record.empty(); + let state_leaf = self.state_leaf.empty(); + + Self { record, state_leaf } + } + + pub fn len(&self) -> usize { + let mut len = 0; + + // add record variable + if self.record.is_present() { + len += 1; + } + + // add state_leaf variable + if self.state_leaf.is_present() { + len += 1; + } + + len + } + + /// Parse all inputs included in a file and store them in `self`. + pub fn parse(&mut self, sections: Vec
) -> Result<(), InputParserError> { + for section in sections { + match section.header { + Header::Record(_state) => self.record.parse(section.definitions)?, + Header::StateLeaf(_state_leaf) => self.state_leaf.parse(section.definitions)?, + header => return Err(InputParserError::private_section(header)), + } + } + + Ok(()) + } + + /// Returns the runtime record input values + pub fn get_record(&self) -> &Record { + &self.record + } + + /// Returns the runtime state leaf input values + pub fn get_state_leaf(&self) -> &StateLeaf { + &self.state_leaf + } +} diff --git a/types/src/inputs/program_state/private_state/record.rs b/types/src/inputs/program_state/private_state/record.rs new file mode 100644 index 0000000000..fa08deca91 --- /dev/null +++ b/types/src/inputs/program_state/private_state/record.rs @@ -0,0 +1,6 @@ +use crate::{InputValue, Parameter}; +use leo_inputs::{definitions::Definition, InputParserError}; + +use std::collections::HashMap; + +input_section_impl!(Record); diff --git a/types/src/inputs/program_state/private_state/state_leaf.rs b/types/src/inputs/program_state/private_state/state_leaf.rs new file mode 100644 index 0000000000..fa79aa6d68 --- /dev/null +++ b/types/src/inputs/program_state/private_state/state_leaf.rs @@ -0,0 +1,6 @@ +use crate::{InputValue, Parameter}; +use leo_inputs::{definitions::Definition, InputParserError}; + +use std::collections::HashMap; + +input_section_impl!(StateLeaf); diff --git a/types/src/inputs/program_state/program_state.rs b/types/src/inputs/program_state/program_state.rs new file mode 100644 index 0000000000..5e6f7cb036 --- /dev/null +++ b/types/src/inputs/program_state/program_state.rs @@ -0,0 +1,56 @@ +use crate::{PrivateState, PublicState, Record, State, StateLeaf}; +use leo_inputs::{ + tables::{Table, Visibility}, + InputParserError, +}; + +#[derive(Clone, PartialEq, Eq)] +pub struct ProgramState { + public: PublicState, + private: PrivateState, +} + +impl ProgramState { + pub fn new() -> Self { + Self { + public: PublicState::new(), + private: PrivateState::new(), + } + } + + /// Returns an empty version of this struct with `None` values. + /// Called during constraint synthesis to provide private inputs. + pub fn empty(&self) -> Self { + let public = self.public.empty(); + let private = self.private.empty(); + + Self { public, private } + } + + pub fn len(&self) -> usize { + self.public.len() + self.private.len() + } + + /// Parse all inputs included in a file and store them in `self`. + pub fn parse(&mut self, table: Table) -> Result<(), InputParserError> { + match table.visibility { + Visibility::Private(_private) => self.private.parse(table.sections), + Visibility::Public(_public) => self.public.parse(table.sections), + } + } + + /// Returns the runtime record input values + pub fn get_record(&self) -> &Record { + self.private.get_record() + } + + /// Returns the runtime state input values + pub fn get_state(&self) -> &State { + self.public.get_state() + } + + /// Returns the runtime state leaf input values + pub fn get_state_leaf(&self) -> &StateLeaf { + self.private.get_state_leaf() + } +} diff --git a/types/src/inputs/program_state/public_state/mod.rs b/types/src/inputs/program_state/public_state/mod.rs new file mode 100644 index 0000000000..227bc30313 --- /dev/null +++ b/types/src/inputs/program_state/public_state/mod.rs @@ -0,0 +1,5 @@ +pub mod public_state; +pub use public_state::*; + +pub mod state; +pub use state::*; diff --git a/types/src/inputs/program_state/public_state/public_state.rs b/types/src/inputs/program_state/public_state/public_state.rs new file mode 100644 index 0000000000..0cfb98e926 --- /dev/null +++ b/types/src/inputs/program_state/public_state/public_state.rs @@ -0,0 +1,45 @@ +use crate::State; +use leo_inputs::{ + sections::{Header, Section}, + InputParserError, +}; + +#[derive(Clone, PartialEq, Eq)] +pub struct PublicState { + state: State, +} + +impl PublicState { + pub fn new() -> Self { + Self { state: State::new() } + } + + /// Returns an empty version of this struct with `None` values. + /// Called during constraint synthesis to provide private inputs. + pub fn empty(&self) -> Self { + let state = self.state.empty(); + + Self { state } + } + + pub fn len(&self) -> usize { + if self.state.is_present() { 1usize } else { 0usize } + } + + /// Parse all inputs included in a file and store them in `self`. + pub fn parse(&mut self, sections: Vec
) -> Result<(), InputParserError> { + for section in sections { + match section.header { + Header::State(_state) => self.state.parse(section.definitions)?, + header => return Err(InputParserError::public_section(header)), + } + } + + Ok(()) + } + + /// Returns the runtime state input values + pub fn get_state(&self) -> &State { + &self.state + } +} diff --git a/types/src/inputs/program_state/public_state/state.rs b/types/src/inputs/program_state/public_state/state.rs new file mode 100644 index 0000000000..eb5d40c21d --- /dev/null +++ b/types/src/inputs/program_state/public_state/state.rs @@ -0,0 +1,6 @@ +use crate::{InputValue, Parameter}; +use leo_inputs::{definitions::Definition, InputParserError}; + +use std::collections::HashMap; + +input_section_impl!(State); diff --git a/types/src/program.rs b/types/src/program.rs index 931766122d..3f58ac0443 100644 --- a/types/src/program.rs +++ b/types/src/program.rs @@ -1,7 +1,7 @@ //! A typed Leo program consists of import, circuit, and function definitions. //! Each defined type consists of typed statements and expressions. -use crate::{Circuit, Function, FunctionInput, Identifier, Import, TestFunction}; +use crate::{Circuit, Function, Identifier, Import, Input, TestFunction}; use leo_ast::files::File; use serde::{Deserialize, Serialize}; @@ -11,13 +11,15 @@ use std::collections::HashMap; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Program { pub name: String, - pub expected_inputs: Vec, + pub expected_inputs: Vec, pub imports: Vec, pub circuits: HashMap, pub functions: HashMap, pub tests: HashMap, } +const MAIN_FUNCTION_NAME: &str = "main"; + impl<'ast> Program { //! Logic to convert from an abstract syntax tree (ast) representation to a Leo program. pub fn from(file: File<'ast>, name: String) -> Self { @@ -38,7 +40,7 @@ impl<'ast> Program { }); file.functions.into_iter().for_each(|function_def| { let function = Function::from(function_def); - if function.function_name.name.eq("main") { + if function.function_name.name.eq(MAIN_FUNCTION_NAME) { expected_inputs = function.inputs.clone(); } functions.insert(function.function_name.clone(), function); diff --git a/types/src/types/integer_type.rs b/types/src/types/integer_type.rs index 01736f4647..65aed392e5 100644 --- a/types/src/types/integer_type.rs +++ b/types/src/types/integer_type.rs @@ -1,10 +1,11 @@ use leo_ast::types::IntegerType as AstIntegerType; +use leo_inputs::types::IntegerType as InputsAstIntegerType; use serde::{Deserialize, Serialize}; use std::fmt; /// Explicit integer type -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum IntegerType { U8, U16, @@ -37,6 +38,24 @@ impl From for IntegerType { } } +impl From for IntegerType { + fn from(integer_type: InputsAstIntegerType) -> Self { + match integer_type { + InputsAstIntegerType::U8Type(_type) => IntegerType::U8, + InputsAstIntegerType::U16Type(_type) => IntegerType::U16, + InputsAstIntegerType::U32Type(_type) => IntegerType::U32, + InputsAstIntegerType::U64Type(_type) => IntegerType::U64, + InputsAstIntegerType::U128Type(_type) => IntegerType::U128, + + InputsAstIntegerType::I8Type(_type) => IntegerType::I8, + InputsAstIntegerType::I16Type(_type) => IntegerType::I16, + InputsAstIntegerType::I32Type(_type) => IntegerType::I32, + InputsAstIntegerType::I64Type(_type) => IntegerType::I64, + InputsAstIntegerType::I128Type(_type) => IntegerType::I128, + } + } +} + impl fmt::Display for IntegerType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { diff --git a/types/src/types/type_.rs b/types/src/types/type_.rs index 8c4711a4b3..7bd1680057 100644 --- a/types/src/types/type_.rs +++ b/types/src/types/type_.rs @@ -1,11 +1,12 @@ use crate::{Expression, Identifier, IntegerType}; use leo_ast::types::{ArrayType, CircuitType, DataType, Type as AstType}; +use leo_inputs::types::{ArrayType as InputsArrayType, DataType as InputsDataType, Type as InputsAstType}; use serde::{Deserialize, Serialize}; use std::fmt; /// Explicit type used for defining a variable or expression type -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Type { // Data types Address, @@ -50,13 +51,13 @@ impl From for Type { } } -impl<'ast> From> for Type { - fn from(array_type: ArrayType<'ast>) -> Self { +impl<'ast> From> for Type { + fn from(array_type: InputsArrayType<'ast>) -> Self { let element_type = Box::new(Type::from(array_type._type)); let dimensions = array_type .dimensions .into_iter() - .map(|row| Expression::get_count(row)) + .map(|row| Expression::get_count_from_number(row)) .collect(); Type::Array(element_type, dimensions) @@ -70,16 +71,52 @@ impl<'ast> From> for Type { } impl<'ast> From> for Type { - fn from(_type: AstType<'ast>) -> Self { - match _type { - AstType::Basic(_type) => Type::from(_type), - AstType::Array(_type) => Type::from(_type), - AstType::Circuit(_type) => Type::from(_type), + fn from(type_: AstType<'ast>) -> Self { + match type_ { + AstType::Basic(type_) => Type::from(type_), + AstType::Array(type_) => Type::from(type_), + AstType::Circuit(type_) => Type::from(type_), AstType::SelfType(_type) => Type::SelfType, } } } +/// inputs pest ast -> Explicit Type + +impl From for Type { + fn from(data_type: InputsDataType) -> Self { + match data_type { + InputsDataType::Address(_type) => Type::Address, + InputsDataType::Boolean(_type) => Type::Boolean, + InputsDataType::Field(_type) => Type::Field, + InputsDataType::Group(_type) => Type::Group, + InputsDataType::Integer(type_) => Type::IntegerType(IntegerType::from(type_)), + } + } +} + +impl<'ast> From> for Type { + fn from(array_type: ArrayType<'ast>) -> Self { + let element_type = Box::new(Type::from(array_type._type)); + let dimensions = array_type + .dimensions + .into_iter() + .map(|row| Expression::get_count_from_value(row)) + .collect(); + + Type::Array(element_type, dimensions) + } +} + +impl<'ast> From> for Type { + fn from(type_: InputsAstType<'ast>) -> Self { + match type_ { + InputsAstType::Basic(type_) => Type::from(type_), + InputsAstType::Array(type_) => Type::from(type_), + } + } +} + impl Type { pub fn outer_dimension(&self, dimensions: &Vec) -> Self { let type_ = self.clone();