parse input file before program file

This commit is contained in:
collin 2020-07-28 20:46:26 -07:00
parent 9fc9e16367
commit 82b0b576dd
17 changed files with 443 additions and 228 deletions

View File

@ -9,7 +9,7 @@ use crate::{
};
use leo_ast::LeoParser;
use leo_inputs::LeoInputsParser;
use leo_types::{InputValue, Inputs, Program};
use leo_types::{InputValue, Inputs, MainInputs, Program};
use snarkos_errors::gadgets::SynthesisError;
use snarkos_models::{
@ -44,11 +44,18 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
}
}
pub fn new_from_path(package_name: String, main_file_path: PathBuf) -> Result<Self, CompilerError> {
pub fn new_from_path(
package_name: String,
main_file_path: PathBuf,
inputs_string: &str,
) -> Result<Self, CompilerError> {
let mut compiler = Self::new(package_name);
compiler.set_path(main_file_path);
// Generate the abstract syntax tree and assemble the program
// Generate the inputs file abstract syntax tree
compiler.parse_inputs(inputs_string)?;
// Generate the program abstract syntax tree and assemble the program
let program_string = compiler.load_program()?;
compiler.parse_program(&program_string)?;
@ -59,8 +66,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
self.main_file_path = main_file_path
}
pub fn set_inputs(&mut self, program_inputs: Vec<Option<InputValue>>) {
self.program_inputs.set_inputs(program_inputs);
pub fn set_inputs(&mut self, program_inputs: MainInputs) {
self.program_inputs.set_main_inputs(program_inputs);
}
pub fn checksum(&self) -> Result<String, CompilerError> {
@ -81,7 +88,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
cs: &mut CS,
) -> Result<ConstrainedValue<F, G>, CompilerError> {
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| {
error.set_path(path);
@ -91,7 +98,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
}
pub fn compile_test_constraints(self, cs: &mut TestConstraintSystem<F>) -> Result<(), CompilerError> {
generate_test_constraints::<F, G>(cs, self.program, &self.imported_programs)
generate_test_constraints::<F, G>(cs, self.program, self.program_inputs, &self.imported_programs)
}
fn load_program(&mut self) -> Result<String, CompilerError> {
@ -107,7 +114,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
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);
@ -118,11 +124,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
pub fn parse_inputs(&mut self, inputs_string: &str) -> Result<(), CompilerError> {
let syntax_tree = LeoInputsParser::parse_file(&inputs_string)?;
self.program_inputs
.parse_program_input_file(syntax_tree, self.program.expected_inputs.clone())?;
// Check number/order of parameters here
// self.program_inputs = Inputs::from_inputs_file(syntax_tree, self.program.expected_inputs.clone())?;
self.program_inputs.parse_file(syntax_tree)?;
Ok(())
}
@ -135,8 +137,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
let program: Program = bincode::deserialize(bytes)?;
let mut program_inputs = Inputs::new();
program_inputs.set_inputs_size(program.expected_inputs.len());
Ok(Self {
package_name: program.name.clone(),
main_file_path: PathBuf::new(),
@ -151,16 +151,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
impl<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compiler<F, G> {
fn generate_constraints<CS: ConstraintSystem<F>>(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| {
log::error!("{}", e);
SynthesisError::Unsatisfiable
})?;
let result = generate_constraints::<_, G, _>(cs, self.program, self.program_inputs, &self.imported_programs)
.map_err(|e| {
log::error!("{}", e);
SynthesisError::Unsatisfiable
})?;
// Write results to file or something
log::info!("{}", result);

View File

@ -1,7 +1,7 @@
//! Generates R1CS constraints for a compiled Leo program.
use crate::{errors::CompilerError, new_scope, ConstrainedProgram, ConstrainedValue, GroupType, ImportParser};
use leo_types::{InputValue, Program};
use leo_types::{Inputs, Program};
use snarkos_models::{
curves::{Field, PrimeField},
@ -11,7 +11,7 @@ use snarkos_models::{
pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
cs: &mut CS,
program: Program,
parameters: Vec<Option<InputValue>>,
inputs: Inputs,
imported_programs: &ImportParser,
) -> Result<ConstrainedValue<F, G>, CompilerError> {
let mut resolved_program = ConstrainedProgram::new();
@ -26,7 +26,7 @@ pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, 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 +36,7 @@ pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: Constrai
pub fn generate_test_constraints<F: Field + PrimeField, G: GroupType<F>>(
cs: &mut TestConstraintSystem<F>,
program: Program,
inputs: Inputs,
imported_programs: &ImportParser,
) -> Result<(), CompilerError> {
let mut resolved_program = ConstrainedProgram::<F, G>::new();
@ -54,7 +55,7 @@ pub fn generate_test_constraints<F: Field + PrimeField, G: GroupType<F>>(
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() {

View File

@ -25,24 +25,24 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn allocate_main_function_input<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
_type: Type,
type_: Type,
name: String,
input_value: Option<InputValue>,
input_option: Option<InputValue>,
span: Span,
) -> Result<ConstrainedValue<F, G>, 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"),
}
}

View File

@ -8,7 +8,7 @@ use crate::{
GroupType,
};
use leo_types::{Expression, Function, Input, InputValue};
use leo_types::{Expression, Function, Input, Inputs};
use snarkos_models::{
curves::{Field, PrimeField},
@ -21,7 +21,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
cs: &mut CS,
scope: String,
function: Function,
inputs: Vec<Option<InputValue>>,
inputs: Inputs,
) -> Result<ConstrainedValue<F, G>, FunctionError> {
let function_name = new_scope(scope.clone(), function.get_name());
@ -30,24 +30,38 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
// 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()) {
if let Input::FunctionInput(input_model) = input_model {
let input_value = self.allocate_main_function_input(
cs,
input_model.type_,
input_model.identifier.name.clone(),
input_option,
function.span.clone(),
)?;
let mut seen = 0;
for (i, input_model) in function.inputs.clone().into_iter().enumerate() {
match input_model {
Input::FunctionInput(input_model) => {
let name = input_model.identifier.name.clone();
let input_option = inputs.get(&name);
let input_value = self.allocate_main_function_input(
cs,
input_model.type_,
name.clone(),
input_option,
function.span.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);
// 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);
input_variables.push(Expression::Identifier(input_model.identifier));
} else {
println!("main function input model {}", input_model);
// println!("main function input option {}", input_option.to_)
input_variables.push(Expression::Identifier(input_model.identifier));
}
Input::Registers => {
seen += 1;
}
Input::Record => {
seen += 1;
}
Input::State => {
seen += 1;
}
Input::StateLeaf => {
seen += 1;
}
}
}

View File

@ -3,7 +3,7 @@ use crate::{
cli_types::*,
directories::{source::SOURCE_DIRECTORY_NAME, OutputsDirectory},
errors::CLIError,
files::{ChecksumFile, LibFile, MainFile, Manifest, LIB_FILE_NAME, MAIN_FILE_NAME},
files::{ChecksumFile, InputsFile, LibFile, MainFile, Manifest, LIB_FILE_NAME, MAIN_FILE_NAME},
};
use leo_compiler::{compiler::Compiler, group::targets::edwards_bls12::EdwardsGroupType};
@ -41,6 +41,9 @@ impl CLI for BuildCommand {
let manifest = Manifest::try_from(&path)?;
let package_name = manifest.get_package_name();
// Load the inputs file at `package_name`
let inputs_string = InputsFile::new(&package_name).read_from(&path)?;
// Sanitize the package path to the root directory
let mut package_path = path.clone();
if package_path.is_file() {
@ -55,8 +58,11 @@ impl CLI for BuildCommand {
lib_file_path.push(LIB_FILE_NAME);
// Compile the library file but do not output
let _program =
Compiler::<Fq, EdwardsGroupType>::new_from_path(package_name.clone(), lib_file_path.clone())?;
let _program = Compiler::<Fq, EdwardsGroupType>::new_from_path(
package_name.clone(),
lib_file_path.clone(),
&inputs_string,
)?;
log::info!("Compiled library file {:?}", lib_file_path);
};
@ -72,8 +78,11 @@ impl CLI for BuildCommand {
main_file_path.push(MAIN_FILE_NAME);
// Load the program at `main_file_path`
let program =
Compiler::<Fq, EdwardsGroupType>::new_from_path(package_name.clone(), main_file_path.clone())?;
let program = Compiler::<Fq, EdwardsGroupType>::new_from_path(
package_name.clone(),
main_file_path.clone(),
&inputs_string,
)?;
// Compute the current program checksum
let program_checksum = program.checksum()?;

View File

@ -42,9 +42,9 @@ 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)?;
// Fetch main 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();

View File

@ -10,6 +10,7 @@ use leo_compiler::{compiler::Compiler, group::targets::edwards_bls12::EdwardsGro
use snarkos_curves::edwards_bls12::Fq;
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
use crate::files::InputsFile;
use clap::ArgMatches;
use std::{convert::TryFrom, env::current_dir};
@ -40,6 +41,9 @@ impl CLI for TestCommand {
let manifest = Manifest::try_from(&path)?;
let package_name = manifest.get_package_name();
// Load the inputs file at `package_name`
let inputs_string = InputsFile::new(&package_name).read_from(&path)?;
// Sanitize the package path to the root directory
let mut package_path = path.clone();
if package_path.is_file() {
@ -57,7 +61,11 @@ impl CLI for TestCommand {
main_file_path.push(MAIN_FILE_NAME);
// Compute the current program checksum
let program = Compiler::<Fq, EdwardsGroupType>::new_from_path(package_name.clone(), main_file_path.clone())?;
let program = Compiler::<Fq, EdwardsGroupType>::new_from_path(
package_name.clone(),
main_file_path.clone(),
&inputs_string,
)?;
// Generate the program on the constraint system and verify correctness
{

View File

@ -1,10 +1,10 @@
use crate::{Input, InputValue, ProgramInputs, ProgramState};
use crate::{Input, InputValue, MainInputs, ProgramInputs, ProgramState};
use leo_inputs::{
files::{File, TableOrSection},
InputParserError,
};
#[derive(Clone)]
#[derive(Clone, PartialEq, Eq)]
pub struct Inputs {
inputs: ProgramInputs,
state: ProgramState,
@ -18,34 +18,40 @@ impl Inputs {
}
}
pub fn get_inputs(&self) -> Vec<Option<InputValue>> {
self.inputs.main.0.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<Option<InputValue>>) {
self.inputs.main.0 = inputs;
pub fn len(&self) -> usize {
self.inputs.len() + self.state.len()
}
pub fn set_inputs_size(&mut self, size: usize) {
self.inputs.main.0 = vec![None; size];
pub fn set_main_inputs(&mut self, inputs: MainInputs) {
self.inputs.main = inputs;
}
pub fn parse_program_input_file(
&mut self,
file: File,
expected_inputs: Vec<Input>,
) -> Result<(), InputParserError> {
pub fn parse_file(&mut self, file: File) -> Result<(), InputParserError> {
for entry in file.entries.into_iter() {
match entry {
TableOrSection::Section(section) => {
self.inputs.store_definitions(section, &expected_inputs)?;
self.inputs.store_definitions(section)?;
}
TableOrSection::Table(table) => {
self.state.store_definitions(table, &expected_inputs)?;
self.state.store_definitions(table)?;
}
}
}
Ok(())
}
/// Returns the main function input value with the given `name`
pub fn get(&self, name: &String) -> Option<InputValue> {
self.inputs.get(name)
}
}

View File

@ -1,50 +1,74 @@
use crate::{Input, InputValue};
use leo_inputs::{definitions::Definition, InputParserError};
use std::collections::HashMap;
#[derive(Clone, PartialEq, Eq)]
pub struct MainInputs(pub Vec<Option<InputValue>>);
pub struct MainInputs {
inputs: HashMap<String, Option<InputValue>>,
}
impl MainInputs {
pub fn new() -> Self {
Self(vec![])
Self { inputs: HashMap::new() }
}
pub fn len(&self) -> usize {
self.inputs.len()
}
/// 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 }
}
/// Stores main input assignments that match expected main function inputs
pub fn store_definitions(
&mut self,
definitions: Vec<Definition>,
expected_inputs: &Vec<Input>,
) -> Result<(), InputParserError> {
let mut program_inputs = vec![];
pub fn store_definitions(&mut self, definitions: Vec<Definition>) -> Result<(), InputParserError> {
// for definition in definitions {
//
// }
for definition in definitions {
// find input with matching name
let matched_input = expected_inputs.clone().into_iter().find(|input| {
// only look at program inputs
match input {
Input::FunctionInput(function_input) => {
// name match
function_input.identifier.name.eq(&definition.parameter.variable.value)
// type match
&& function_input.type_.to_string().eq(&definition.parameter.type_.to_string())
}
_ => false,
}
});
match matched_input {
Some(_) => {
let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
// push value to main inputs
program_inputs.push(Some(value));
}
None => return Err(InputParserError::InputNotFound(definition.parameter.variable.value)),
}
}
self.0 = program_inputs;
// let mut program_inputs = vec![];
//
// for definition in definitions {
// // find input with matching name
// let matched_input = expected_inputs.clone().into_iter().find(|input| {
// // only look at program inputs
// match input {
// Input::FunctionInput(function_input) => {
// // name match
// function_input.identifier.name.eq(&definition.parameter.variable.value)
// // type match
// && function_input.type_.to_string().eq(&definition.parameter.type_.to_string())
// }
// _ => false,
// }
// });
//
// match matched_input {
// Some(_) => {
// let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
//
// // push value to main inputs
// program_inputs.push(Some(value));
// }
// None => return Err(InputParserError::InputNotFound(definition.parameter.variable.value)),
// }
// }
//
// self.0 = program_inputs;
Ok(())
}
/// Returns main function input at `index`
pub fn get(&self, name: &String) -> Option<InputValue> {
self.inputs.get(name).unwrap().clone()
}
}

View File

@ -1,4 +1,4 @@
use crate::{Input, MainInputs, Registers};
use crate::{Input, InputValue, MainInputs, Registers};
use leo_inputs::{
sections::{Header, Section},
InputParserError,
@ -7,7 +7,7 @@ use leo_inputs::{
#[derive(Clone, PartialEq, Eq)]
pub struct ProgramInputs {
pub main: MainInputs,
pub registers: Registers,
registers: Registers,
}
impl ProgramInputs {
@ -18,15 +18,38 @@ impl ProgramInputs {
}
}
pub fn store_definitions(
&mut self,
section: Section,
expected_inputs: &Vec<Input>,
) -> Result<(), InputParserError> {
/// 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
}
pub fn store_definitions(&mut self, section: Section) -> Result<(), InputParserError> {
match section.header {
Header::Main(_main) => self.main.store_definitions(section.definitions, &expected_inputs),
Header::Registers(_registers) => self.registers.store_definitions(section.definitions, &expected_inputs),
Header::Main(_main) => self.main.store_definitions(section.definitions),
Header::Registers(_registers) => self.registers.store_definitions(section.definitions),
header => Err(InputParserError::input_section_header(header)),
}
}
pub fn get(&self, name: &String) -> Option<InputValue> {
self.main.get(name)
}
}

View File

@ -1,37 +1,61 @@
use crate::{Input, InputValue};
use leo_inputs::{definitions::Definition, InputParserError};
use std::collections::HashMap;
#[derive(Clone, PartialEq, Eq)]
pub struct Registers(Vec<Option<InputValue>>);
pub struct Registers {
is_present: bool,
values: HashMap<String, Option<InputValue>>,
}
impl Registers {
pub fn new() -> Self {
Self(vec![])
Self {
is_present: false,
values: HashMap::new(),
}
}
/// Stores register input definitions if the main function input contains the `registers` variable.
pub fn store_definitions(
&mut self,
definitions: Vec<Definition>,
expected_inputs: &Vec<Input>,
) -> Result<(), InputParserError> {
// if the main function does not contain the `registers` variable
// then do not parse registers
if !expected_inputs.contains(&Input::Registers) {
return Ok(());
}
/// 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();
let mut register_inputs = vec![];
values.iter_mut().for_each(|(_name, value)| {
*value = None;
});
// store all registers
for definition in definitions {
let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
Self { is_present, values }
}
// push value to register inputs
register_inputs.push(Some(value));
}
/// Returns `true` if the `registers` variable is passed as input to the main function
pub fn is_present(&self) -> bool {
self.is_present
}
self.0 = register_inputs;
/// Stores register input definitions.
/// This function is called if the main function input contains the `registers` variable.
pub fn store_definitions(&mut self, definitions: Vec<Definition>) -> Result<(), InputParserError> {
self.is_present = true;
// // if the main function does not contain the `registers` variable
// // then do not parse registers
// if !expected_inputs.contains(&Input::Registers) {
// return Ok(());
// }
//
// let mut register_inputs = vec![];
//
// // store all registers
// for definition in definitions {
// let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
//
// // push value to register inputs
// register_inputs.push(Some(value));
// }
//
// self.values = register_inputs;
Ok(())
}

View File

@ -18,17 +18,36 @@ impl PrivateState {
}
}
pub fn store_definitions(
&mut self,
sections: Vec<Section>,
expected_inputs: &Vec<Input>,
) -> Result<(), InputParserError> {
/// 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
}
pub fn store_definitions(&mut self, sections: Vec<Section>) -> Result<(), InputParserError> {
for section in sections {
match section.header {
Header::Record(_state) => self.record.store_definitions(section.definitions, expected_inputs)?,
Header::StateLeaf(_state_leaf) => self
.state_leaf
.store_definitions(section.definitions, expected_inputs)?,
Header::Record(_state) => self.record.store_definitions(section.definitions)?,
Header::StateLeaf(_state_leaf) => self.state_leaf.store_definitions(section.definitions)?,
header => return Err(InputParserError::private_section(header)),
}
}

View File

@ -1,37 +1,60 @@
use crate::{Input, InputValue};
use leo_inputs::{definitions::Definition, InputParserError};
use std::collections::HashMap;
#[derive(Clone, PartialEq, Eq)]
pub struct Record(Vec<Option<InputValue>>);
pub struct Record {
is_present: bool,
values: HashMap<String, Option<InputValue>>,
}
impl Record {
pub fn new() -> Self {
Self(vec![])
Self {
is_present: false,
values: HashMap::new(),
}
}
/// Stores record input definitions if the main function input contains the `record` variable.
pub fn store_definitions(
&mut self,
definitions: Vec<Definition>,
expected_inputs: &Vec<Input>,
) -> Result<(), InputParserError> {
// if the main function does not contain the `record` variable
// then do not parse record definitions
if !expected_inputs.contains(&Input::Record) {
return Ok(());
}
/// 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();
let mut record_inputs = vec![];
values.iter_mut().for_each(|(_name, value)| {
*value = None;
});
// store all definitions
for definition in definitions {
let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
Self { is_present, values }
}
// push value to register inputs
record_inputs.push(Some(value));
}
/// Returns `true` if the `record` variable is passed as input to the main function.
pub fn is_present(&self) -> bool {
self.is_present
}
self.0 = record_inputs;
/// Stores record input definitions.
/// This function is called if the main function input contains the `record` variable.
pub fn store_definitions(&mut self, definitions: Vec<Definition>) -> Result<(), InputParserError> {
self.is_present = true;
// // if the main function does not contain the `record` variable
// // then do not parse record definitions
// if !expected_inputs.contains(&Input::Record) {
// return Ok(());
// }
//
// let mut record_inputs = vec![];
//
// // store all definitions
// for definition in definitions {
// let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
//
// // push value to register inputs
// record_inputs.push(Some(value));
// }
//
// self.0 = record_inputs;
Ok(())
}

View File

@ -1,37 +1,61 @@
use crate::{Input, InputValue};
use leo_inputs::{definitions::Definition, InputParserError};
use std::collections::HashMap;
#[derive(Clone, PartialEq, Eq)]
pub struct StateLeaf(Vec<Option<InputValue>>);
pub struct StateLeaf {
is_present: bool,
values: HashMap<String, Option<InputValue>>,
}
impl StateLeaf {
pub fn new() -> Self {
Self(vec![])
Self {
is_present: false,
values: HashMap::new(),
}
}
/// Stores state_leaf input definitions if the main function input contains the `state_leaf` variable.
pub fn store_definitions(
&mut self,
definitions: Vec<Definition>,
expected_inputs: &Vec<Input>,
) -> Result<(), InputParserError> {
// if the main function does not contain the `state_leaf` variable
// then do not parse state_leaf definitions
if !expected_inputs.contains(&Input::StateLeaf) {
return Ok(());
}
/// 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();
let mut state_leaf_inputs = vec![];
values.iter_mut().for_each(|(_name, value)| {
*value = None;
});
// store all definitions
for definition in definitions {
let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
Self { is_present, values }
}
// push value to register inputs
state_leaf_inputs.push(Some(value));
}
/// Returns `true` if the `state_leaf` variable is passed as input to the main function
pub fn is_present(&self) -> bool {
self.is_present
}
self.0 = state_leaf_inputs;
/// Stores state leaf input definitions.
/// This function is called if the main function input contains the `state_leaf` variable.
pub fn store_definitions(&mut self, definitions: Vec<Definition>) -> Result<(), InputParserError> {
self.is_present = true;
// // if the main function does not contain the `state_leaf` variable
// // then do not parse state_leaf definitions
// if !expected_inputs.contains(&Input::StateLeaf) {
// return Ok(());
// }
//
// let mut state_leaf_inputs = vec![];
//
// // store all definitions
// for definition in definitions {
// let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
//
// // push value to register inputs
// state_leaf_inputs.push(Some(value));
// }
//
// self.0 = state_leaf_inputs;
Ok(())
}

View File

@ -6,8 +6,8 @@ use leo_inputs::{
#[derive(Clone, PartialEq, Eq)]
pub struct ProgramState {
pub public: PublicState,
pub private: PrivateState,
public: PublicState,
private: PrivateState,
}
impl ProgramState {
@ -18,10 +18,23 @@ impl ProgramState {
}
}
pub fn store_definitions(&mut self, table: Table, expected_inputs: &Vec<Input>) -> Result<(), InputParserError> {
/// 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()
}
pub fn store_definitions(&mut self, table: Table) -> Result<(), InputParserError> {
match table.visibility {
Visibility::Private(_private) => self.private.store_definitions(table.sections, &expected_inputs),
Visibility::Public(_public) => self.public.store_definitions(table.sections, &expected_inputs),
Visibility::Private(_private) => self.private.store_definitions(table.sections),
Visibility::Public(_public) => self.public.store_definitions(table.sections),
}
}
}

View File

@ -14,14 +14,22 @@ impl PublicState {
Self { state: State::new() }
}
pub fn store_definitions(
&mut self,
sections: Vec<Section>,
expected_inputs: &Vec<Input>,
) -> Result<(), InputParserError> {
pub fn len(&self) -> usize {
if self.state.is_present() { 1usize } else { 0usize }
}
/// 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 store_definitions(&mut self, sections: Vec<Section>) -> Result<(), InputParserError> {
for section in sections {
match section.header {
Header::State(_state) => self.state.store_definitions(section.definitions, expected_inputs)?,
Header::State(_state) => self.state.store_definitions(section.definitions)?,
header => return Err(InputParserError::public_section(header)),
}
}

View File

@ -1,37 +1,61 @@
use crate::{Input, InputValue};
use leo_inputs::{definitions::Definition, InputParserError};
use std::collections::HashMap;
#[derive(Clone, PartialEq, Eq)]
pub struct State(Vec<Option<InputValue>>);
pub struct State {
is_present: bool,
values: HashMap<String, Option<InputValue>>,
}
impl State {
pub fn new() -> Self {
Self(vec![])
Self {
is_present: false,
values: HashMap::new(),
}
}
/// Stores state input definitions if the main function input contains the `state` variable.
pub fn store_definitions(
&mut self,
definitions: Vec<Definition>,
expected_inputs: &Vec<Input>,
) -> Result<(), InputParserError> {
// if the main function does not contain the `state` variable
// then do not parse state definitions
if !expected_inputs.contains(&Input::State) {
return Ok(());
}
/// 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();
let mut state_inputs = vec![];
values.iter_mut().for_each(|(_name, value)| {
*value = None;
});
// store all registers
for definition in definitions {
let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
Self { is_present, values }
}
// push value to register inputs
state_inputs.push(Some(value));
}
/// Returns `true` if the `state` variable is passed as input to the main function
pub fn is_present(&self) -> bool {
self.is_present
}
self.0 = state_inputs;
/// Stores state input definitions.
/// This function is called if the main function input contains the `state` variable.
pub fn store_definitions(&mut self, definitions: Vec<Definition>) -> Result<(), InputParserError> {
self.is_present = true;
// // if the main function does not contain the `state` variable
// // then do not parse state definitions
// if !expected_inputs.contains(&Input::State) {
// return Ok(());
// }
//
// let mut state_inputs = vec![];
//
// // store all definitions
// for definition in definitions {
// let value = InputValue::from_expression(definition.parameter.type_, definition.expression)?;
//
// // push value to register inputs
// state_inputs.push(Some(value));
// }
//
// self.values = state_inputs;
Ok(())
}