From 67b8a48fcfbadf4d2c10d2bc1976d5a50d7abad0 Mon Sep 17 00:00:00 2001 From: collin Date: Wed, 10 Jun 2020 16:14:55 -0700 Subject: [PATCH] public input booleans and integers --- .gitignore | 1 + compiler/src/compiler.rs | 15 +++++--- compiler/tests/array/mod.rs | 9 ++++- compiler/tests/boolean/mod.rs | 3 +- compiler/tests/mutability/mod.rs | 5 ++- leo-inputs/src/types/integer_type.rs | 12 +++--- leo/commands/prove.rs | 12 +++--- leo/commands/run.rs | 9 +++-- tmp/inputs/inputs.leo | 2 +- tmp/src/main.leo | 4 +- types/src/inputs/input_fields.rs | 34 +++++++++++++++++ types/src/inputs/input_value.rs | 36 ++++++++++++------ types/src/inputs/inputs.rs | 56 +++++++++++++++++++--------- types/src/inputs/mod.rs | 3 ++ types/src/integer.rs | 2 +- 15 files changed, 142 insertions(+), 61 deletions(-) create mode 100644 types/src/inputs/input_fields.rs diff --git a/.gitignore b/.gitignore index e995008d72..a2f8c9699b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /target +/tmp/ **.idea/ outputs/ *.DS_Store diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index 1be9a384b9..55da44d852 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -16,6 +16,7 @@ use snarkos_models::{ }; use sha2::{Digest, Sha256}; +use snarkos_models::curves::PairingEngine; use std::{fs, marker::PhantomData, path::PathBuf}; #[derive(Clone)] @@ -58,7 +59,11 @@ impl> Compiler { } pub fn set_inputs(&mut self, program_inputs: Vec>) { - self.program_inputs.set_private_inputs(program_inputs); + self.program_inputs.set_inputs(program_inputs); + } + + pub fn get_public_inputs(&self) -> Result, CompilerError> { + Ok(self.program_inputs.get_public_inputs::()?) } pub fn checksum(&self) -> Result { @@ -78,7 +83,7 @@ impl> Compiler { self, cs: &mut CS, ) -> Result, CompilerError> { - generate_constraints(cs, self.program, self.program_inputs.get_private_inputs()) + generate_constraints(cs, self.program, self.program_inputs.get_inputs()) } pub fn compile_test_constraints(self, cs: &mut TestConstraintSystem) -> Result<(), CompilerError> { @@ -99,7 +104,7 @@ impl> Compiler { let package_name = self.package_name.clone(); self.program = Program::from(syntax_tree, package_name); - self.program_inputs.set_private_inputs_size(self.program.num_parameters); + self.program_inputs.set_inputs_size(self.program.num_parameters); log::debug!("Program parsing complete\n{:#?}", self.program); @@ -116,7 +121,6 @@ impl> Compiler { // println!("{:?}", syntax_tree); // Check number of private parameters here - self.program_inputs = Inputs::from_inputs_file(syntax_tree)?; Ok(()) @@ -125,8 +129,7 @@ impl> Compiler { impl> ConstraintSynthesizer for Compiler { fn generate_constraints>(self, cs: &mut CS) -> Result<(), SynthesisError> { - let _result = - generate_constraints::<_, G, _>(cs, self.program, self.program_inputs.get_private_inputs()).unwrap(); + let _result = generate_constraints::<_, G, _>(cs, self.program, self.program_inputs.get_inputs()).unwrap(); // Write results to file or something diff --git a/compiler/tests/array/mod.rs b/compiler/tests/array/mod.rs index f38d620719..2df023642b 100644 --- a/compiler/tests/array/mod.rs +++ b/compiler/tests/array/mod.rs @@ -5,6 +5,7 @@ use leo_compiler::{ }; use leo_types::{InputValue, Integer, IntegerError}; +use leo_inputs::types::{IntegerType, U32Type}; use snarkos_models::gadgets::utilities::uint::UInt32; // [1, 1, 1] @@ -52,6 +53,10 @@ fn fail_synthesis(program: EdwardsTestCompiler) { } } +pub(crate) fn input_value_u32_one() -> InputValue { + InputValue::Integer(IntegerType::U32Type(U32Type {}), 1) +} + // Expressions #[test] @@ -101,7 +106,7 @@ 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![InputValue::Integer(1u128); 3]))]); + program.set_inputs(vec![Some(InputValue::Array(vec![input_value_u32_one(); 3]))]); output_ones(program) } @@ -111,7 +116,7 @@ fn test_input_array_fail() { let bytes = include_bytes!("input.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![Some(InputValue::Integer(1u128))]); + program.set_inputs(vec![Some(input_value_u32_one())]); fail_array(program); } diff --git a/compiler/tests/boolean/mod.rs b/compiler/tests/boolean/mod.rs index 5ad4313719..dd4065da9c 100644 --- a/compiler/tests/boolean/mod.rs +++ b/compiler/tests/boolean/mod.rs @@ -5,6 +5,7 @@ use leo_compiler::{ }; use leo_types::InputValue; +use crate::array::input_value_u32_one; use snarkos_models::gadgets::utilities::boolean::Boolean; pub fn output_expected_boolean(program: EdwardsTestCompiler, boolean: bool) { @@ -76,7 +77,7 @@ 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::Integer(1u128))]); + program.set_inputs(vec![Some(input_value_u32_one())]); fail_boolean(program); } diff --git a/compiler/tests/mutability/mod.rs b/compiler/tests/mutability/mod.rs index 5a6defbfd8..e5daaefa63 100644 --- a/compiler/tests/mutability/mod.rs +++ b/compiler/tests/mutability/mod.rs @@ -5,6 +5,7 @@ use leo_compiler::{ }; use leo_types::{InputValue, Integer}; +use crate::array::input_value_u32_one; use snarkos_curves::edwards_bls12::Fq; use snarkos_models::gadgets::{r1cs::TestConstraintSystem, utilities::uint::UInt32}; @@ -84,7 +85,7 @@ fn test_function_input() { let bytes = include_bytes!("function_input.leo"); let mut program = parse_program(bytes).unwrap(); - program.set_inputs(vec![Some(InputValue::Integer(1))]); + program.set_inputs(vec![Some(input_value_u32_one())]); mut_fail(program); } @@ -93,6 +94,6 @@ 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(InputValue::Integer(1))]); + program.set_inputs(vec![Some(input_value_u32_one())]); mut_success(program); } diff --git a/leo-inputs/src/types/integer_type.rs b/leo-inputs/src/types/integer_type.rs index 6d74555f09..504a1c3706 100644 --- a/leo-inputs/src/types/integer_type.rs +++ b/leo-inputs/src/types/integer_type.rs @@ -2,7 +2,7 @@ use crate::ast::Rule; use pest_ast::FromPest; -#[derive(Clone, Debug, FromPest, PartialEq)] +#[derive(Clone, Debug, FromPest, PartialEq, Eq)] #[pest_ast(rule(Rule::type_integer))] pub enum IntegerType { U8Type(U8Type), @@ -12,22 +12,22 @@ pub enum IntegerType { U128Type(U128Type), } -#[derive(Clone, Debug, FromPest, PartialEq)] +#[derive(Clone, Debug, FromPest, PartialEq, Eq)] #[pest_ast(rule(Rule::type_u8))] pub struct U8Type {} -#[derive(Clone, Debug, FromPest, PartialEq)] +#[derive(Clone, Debug, FromPest, PartialEq, Eq)] #[pest_ast(rule(Rule::type_u16))] pub struct U16Type {} -#[derive(Clone, Debug, FromPest, PartialEq)] +#[derive(Clone, Debug, FromPest, PartialEq, Eq)] #[pest_ast(rule(Rule::type_u32))] pub struct U32Type {} -#[derive(Clone, Debug, FromPest, PartialEq)] +#[derive(Clone, Debug, FromPest, PartialEq, Eq)] #[pest_ast(rule(Rule::type_u64))] pub struct U64Type {} -#[derive(Clone, Debug, FromPest, PartialEq)] +#[derive(Clone, Debug, FromPest, PartialEq, Eq)] #[pest_ast(rule(Rule::type_u128))] pub struct U128Type {} diff --git a/leo/commands/prove.rs b/leo/commands/prove.rs index 5c8243b8a1..dc9740b0b5 100644 --- a/leo/commands/prove.rs +++ b/leo/commands/prove.rs @@ -10,7 +10,9 @@ use snarkos_algorithms::snark::{create_random_proof, Proof}; use snarkos_curves::bls12_377::Bls12_377; use clap::ArgMatches; +use leo_compiler::{compiler::Compiler, edwards_bls12::EdwardsGroupType}; use rand::thread_rng; +use snarkos_curves::edwards_bls12::Fq; use std::{convert::TryFrom, env::current_dir, time::Instant}; #[derive(Debug)] @@ -18,7 +20,7 @@ pub struct ProveCommand; impl CLI for ProveCommand { type Options = (); - type Output = Proof; + type Output = (Compiler, Proof); const ABOUT: AboutType = "Run the program and produce a proof"; const ARGUMENTS: &'static [ArgumentType] = &[]; @@ -42,16 +44,12 @@ impl CLI for ProveCommand { // Fetch private inputs here program.parse_inputs(&path)?; - // let _res = LeoInputsParser::get_private(&path).unwrap(); - // let inputs_path = path.clone().push("/inputs") - // LeoInputsParser::load_file() - // program.set_inputs(); // Start the timer let start = Instant::now(); let rng = &mut thread_rng(); - let program_proof = create_random_proof(program, ¶meters, rng).unwrap(); + let program_proof = create_random_proof(program.clone(), ¶meters, rng).unwrap(); log::info!("Prover completed in {:?} milliseconds", start.elapsed().as_millis()); @@ -62,6 +60,6 @@ impl CLI for ProveCommand { log::info!("Completed program proving"); - Ok(program_proof) + Ok((program, program_proof)) } } diff --git a/leo/commands/run.rs b/leo/commands/run.rs index 522cfcea95..20f4dd290c 100644 --- a/leo/commands/run.rs +++ b/leo/commands/run.rs @@ -6,6 +6,7 @@ use crate::{ }; use snarkos_algorithms::snark::verify_proof; +use snarkos_curves::bls12_377::Bls12_377; use clap::ArgMatches; use std::time::{Duration, Instant}; @@ -32,16 +33,16 @@ impl CLI for RunCommand { #[cfg_attr(tarpaulin, skip)] fn output(options: Self::Options) -> Result<(), CLIError> { let (_program, _parameters, prepared_verifying_key) = SetupCommand::output(options)?; - let proof = ProveCommand::output(options)?; + let (program, proof) = ProveCommand::output(options)?; let mut verifying = Duration::new(0, 0); - // fetch public inputs here - // let _inputs: Vec<_> = [1u32; 1].to_vec(); + // fetch public inputs + let inputs: Vec<_> = program.get_public_inputs::().unwrap(); let start = Instant::now(); - let is_success = verify_proof(&prepared_verifying_key, &proof, &[]).unwrap(); + let is_success = verify_proof(&prepared_verifying_key, &proof, &inputs).unwrap(); verifying += start.elapsed(); diff --git a/tmp/inputs/inputs.leo b/tmp/inputs/inputs.leo index 9e8858bdde..d822cd1b41 100644 --- a/tmp/inputs/inputs.leo +++ b/tmp/inputs/inputs.leo @@ -1,2 +1,2 @@ [main] -a: private bool[2] = [true; 2]; \ No newline at end of file +a: public u128 = 120; \ No newline at end of file diff --git a/tmp/src/main.leo b/tmp/src/main.leo index 60ac840043..13ed40de78 100644 --- a/tmp/src/main.leo +++ b/tmp/src/main.leo @@ -1,4 +1,4 @@ // The 'tmp' main function. -function main(a: bool[2]) -> bool { - return a[0] +function main(a: public u128) -> u128 { + return a } diff --git a/types/src/inputs/input_fields.rs b/types/src/inputs/input_fields.rs new file mode 100644 index 0000000000..fecb030498 --- /dev/null +++ b/types/src/inputs/input_fields.rs @@ -0,0 +1,34 @@ +use leo_inputs::{types::IntegerType, InputParserError}; +use snarkos_models::curves::{Field, PairingEngine}; + +pub struct InputFields(pub Vec); + +impl InputFields { + pub(crate) fn from_boolean(boolean: &bool) -> Self { + if *boolean { + Self(vec![E::Fr::one()]) + } else { + Self(vec![E::Fr::zero()]) + } + } + + pub(crate) fn from_integer(type_: &IntegerType, integer: &u128) -> Result { + let bits: usize = match type_ { + IntegerType::U8Type(_) => 8, + IntegerType::U16Type(_) => 16, + IntegerType::U32Type(_) => 32, + IntegerType::U64Type(_) => 64, + IntegerType::U128Type(_) => 128, + }; + let mut fields = vec![]; + + for i in 0..bits { + let boolean = (integer.to_le() >> i) & 1 == 1; + let mut boolean_fields = InputFields::::from_boolean(&boolean); + + fields.append(&mut boolean_fields.0); + } + + Ok(Self(fields)) + } +} diff --git a/types/src/inputs/input_value.rs b/types/src/inputs/input_value.rs index f3cb251a39..6403f8b2f3 100644 --- a/types/src/inputs/input_value.rs +++ b/types/src/inputs/input_value.rs @@ -1,14 +1,16 @@ +use crate::InputFields; use leo_inputs::{ errors::InputParserError, expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression}, - types::{ArrayType, DataType, Type}, + types::{ArrayType, DataType, IntegerType, Type}, values::{BooleanValue, FieldValue, GroupValue, NumberImplicitValue, NumberValue, Value}, }; +use snarkos_models::curves::PairingEngine; use std::fmt; #[derive(Clone, PartialEq, Eq)] pub enum InputValue { - Integer(u128), + Integer(IntegerType, u128), Field(String), Group(String), Boolean(bool), @@ -21,9 +23,9 @@ impl<'ast> InputValue { Ok(InputValue::Boolean(boolean)) } - fn from_number(number: NumberValue<'ast>) -> Result { + fn from_number(integer_type: IntegerType, number: NumberValue<'ast>) -> Result { let integer = number.value.parse::()?; - Ok(InputValue::Integer(integer)) + Ok(InputValue::Integer(integer_type, integer)) } fn from_group(group: GroupValue<'ast>) -> Self { @@ -40,7 +42,7 @@ impl<'ast> InputValue { "bool".to_string(), "implicit number".to_string(), )), - DataType::Integer(_) => InputValue::from_number(implicit.number), + DataType::Integer(integer_type) => InputValue::from_number(integer_type, implicit.number), DataType::Group(_) => Ok(InputValue::Group(implicit.number.value)), DataType::Field(_) => Ok(InputValue::Field(implicit.number.value)), } @@ -49,7 +51,9 @@ impl<'ast> InputValue { fn from_value(data_type: DataType, value: Value<'ast>) -> Result { match (data_type, value) { (DataType::Boolean(_), Value::Boolean(boolean)) => InputValue::from_boolean(boolean), - (DataType::Integer(_), Value::Integer(integer)) => InputValue::from_number(integer.number), + (DataType::Integer(integer_type), Value::Integer(integer)) => { + InputValue::from_number(integer_type, integer.number) + } (DataType::Group(_), Value::Group(group)) => Ok(InputValue::from_group(group)), (DataType::Field(_), Value::Field(field)) => Ok(InputValue::from_field(field)), (data_type, Value::Implicit(implicit)) => InputValue::from_implicit(data_type, implicit), @@ -69,8 +73,8 @@ impl<'ast> InputValue { (Type::Array(array_type), Expression::ArrayInitializer(initializer)) => { InputValue::from_array_initializer(array_type, initializer) } - (Type::Circuit(_), Expression::CircuitInline(_)) => unimplemented!("circuit input values not implemented"), - (Type::Basic(_), Expression::Variable(_)) => unimplemented!("variable inputs not supported"), + (Type::Circuit(_), Expression::CircuitInline(_)) => unimplemented!("circuit input values not supported"), + (Type::Basic(_), Expression::Variable(_)) => unimplemented!("variable input values not supported"), (type_, value) => Err(InputParserError::IncompatibleTypes( type_.to_string(), value.to_string(), @@ -146,15 +150,25 @@ impl<'ast> InputValue { Ok(InputValue::Array(values)) } + + pub(crate) fn to_input_fields(&self) -> Result, InputParserError> { + match self { + InputValue::Boolean(boolean) => Ok(InputFields::from_boolean(boolean)), + InputValue::Integer(type_, number) => InputFields::from_integer(type_, number), + InputValue::Group(_) => unimplemented!(), + InputValue::Field(_) => unimplemented!(), + InputValue::Array(_) => unimplemented!(), + } + } } impl fmt::Display for InputValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - InputValue::Integer(ref integer) => write!(f, "{}", integer), - InputValue::Field(ref field) => write!(f, "{}", field), + InputValue::Boolean(ref boolean) => write!(f, "{}", boolean), + InputValue::Integer(ref type_, ref number) => write!(f, "{}{:?}", number, type_), InputValue::Group(ref group) => write!(f, "{}", group), - InputValue::Boolean(ref bool) => write!(f, "{}", bool), + InputValue::Field(ref field) => write!(f, "{}", field), InputValue::Array(ref array) => { write!(f, "[")?; for (i, e) in array.iter().enumerate() { diff --git a/types/src/inputs/inputs.rs b/types/src/inputs/inputs.rs index 874b188f19..eb3d334f5f 100644 --- a/types/src/inputs/inputs.rs +++ b/types/src/inputs/inputs.rs @@ -1,48 +1,68 @@ use crate::InputValue; use leo_inputs::{common::visibility::Visibility, files::File, InputParserError}; +use snarkos_models::curves::PairingEngine; #[derive(Clone)] pub struct Inputs { - private: Vec>, - //public: Vec<_> + program_inputs: Vec>, + public: Vec, } impl Inputs { pub fn new() -> Self { - Self { private: vec![] } + Self { + program_inputs: vec![], + public: vec![], + } } - pub fn get_private_inputs(&self) -> Vec> { - return self.private.clone(); + pub fn get_inputs(&self) -> Vec> { + self.program_inputs.clone() } - pub fn set_private_inputs(&mut self, inputs: Vec>) { - self.private = inputs; + pub fn set_inputs(&mut self, inputs: Vec>) { + self.program_inputs = inputs; } - pub fn set_private_inputs_size(&mut self, size: usize) { - self.private = vec![None; size]; + pub fn set_inputs_size(&mut self, size: usize) { + self.program_inputs = vec![None; size]; } pub fn from_inputs_file(file: File) -> Result { let mut private = vec![]; + let mut public = vec![]; for section in file.sections.into_iter() { for assignment in section.assignments.into_iter() { + let value = InputValue::from_expression(assignment.parameter.type_, assignment.expression)?; if let Some(Visibility::Public(_)) = assignment.parameter.visibility { - // Collect public parameters here - } else { - // parameter is private by default + // Collect public inputs here - // evaluate expression - let value = InputValue::from_expression(assignment.parameter.type_, assignment.expression)?; - - // push value to vector - private.push(Some(value)); + public.push(value.clone()); } + + // push value to vector + private.push(Some(value)); } } - Ok(Self { private }) + Ok(Self { + program_inputs: private, + public, + }) + } + + pub fn get_public_inputs(&self) -> Result, InputParserError> { + let mut input_vec = vec![]; + + for input in self.public.iter() { + // get fields + let mut input_fields = input.to_input_fields::()?; + + // push fields to input_vec + input_vec.append(&mut input_fields.0) + } + + Ok(input_vec) } } diff --git a/types/src/inputs/mod.rs b/types/src/inputs/mod.rs index 5f93ed25d3..085568ef93 100644 --- a/types/src/inputs/mod.rs +++ b/types/src/inputs/mod.rs @@ -1,5 +1,8 @@ pub mod inputs; pub use inputs::*; +pub mod input_fields; +pub use input_fields::*; + pub mod input_value; pub use input_value::*; diff --git a/types/src/integer.rs b/types/src/integer.rs index a6d056f740..eff0b91dfe 100644 --- a/types/src/integer.rs +++ b/types/src/integer.rs @@ -87,7 +87,7 @@ impl Integer { // Check that the input value is the correct type let integer_option = match integer_value { Some(input) => { - if let InputValue::Integer(integer) = input { + if let InputValue::Integer(_type_, integer) = input { Some(integer) } else { return Err(IntegerError::InvalidInteger(input.to_string()));