mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-14 02:44:34 +03:00
parse input file before program file
This commit is contained in:
parent
9fc9e16367
commit
82b0b576dd
@ -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);
|
||||
|
@ -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() {
|
||||
|
@ -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"),
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()?;
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
@ -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(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user