mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-26 11:06:00 +03:00
adds compiler output file and output bytes data structures
This commit is contained in:
parent
ac8c940169
commit
1b99d62de8
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -588,6 +588,7 @@ dependencies = [
|
||||
"pest",
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
"serde",
|
||||
"sha2",
|
||||
"snarkos-curves",
|
||||
"snarkos-dpc",
|
||||
|
@ -25,6 +25,7 @@ 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" }
|
||||
|
||||
|
@ -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::{Inputs, MainInputs, Program};
|
||||
use leo_types::{Inputs, Program};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use snarkos_models::{
|
||||
@ -24,30 +25,36 @@ use std::{fs, marker::PhantomData, path::PathBuf};
|
||||
pub struct Compiler<F: Field + PrimeField, G: GroupType<F>> {
|
||||
package_name: String,
|
||||
main_file_path: PathBuf,
|
||||
outputs_directory: PathBuf,
|
||||
program: Program,
|
||||
program_inputs: Inputs,
|
||||
imported_programs: ImportParser,
|
||||
output: Option<ConstrainedValue<F, G>>,
|
||||
_engine: PhantomData<F>,
|
||||
_group: PhantomData<G>,
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
pub fn new(package_name: String, main_file_path: PathBuf) -> Self {
|
||||
pub fn new(package_name: String, main_file_path: PathBuf, outputs_directory: PathBuf) -> Self {
|
||||
Self {
|
||||
package_name: package_name.clone(),
|
||||
main_file_path,
|
||||
outputs_directory,
|
||||
program: Program::new(package_name),
|
||||
program_inputs: Inputs::new(),
|
||||
imported_programs: ImportParser::new(),
|
||||
output: None,
|
||||
_engine: PhantomData,
|
||||
_group: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// 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) -> Result<Self, CompilerError> {
|
||||
let mut compiler = Self::new(package_name, main_file_path);
|
||||
pub fn parse_program_without_inputs(
|
||||
package_name: String,
|
||||
main_file_path: PathBuf,
|
||||
outputs_directory: PathBuf,
|
||||
) -> Result<Self, CompilerError> {
|
||||
let mut compiler = Self::new(package_name, main_file_path, outputs_directory);
|
||||
|
||||
let program_string = compiler.load_program()?;
|
||||
compiler.parse_program(&program_string)?;
|
||||
@ -60,10 +67,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
pub fn parse_program_with_inputs(
|
||||
package_name: String,
|
||||
main_file_path: PathBuf,
|
||||
outputs_directory: PathBuf,
|
||||
inputs_string: &str,
|
||||
state_string: &str,
|
||||
) -> Result<Self, CompilerError> {
|
||||
let mut compiler = Self::new(package_name, main_file_path);
|
||||
let mut compiler = Self::new(package_name, main_file_path, outputs_directory);
|
||||
|
||||
compiler.parse_inputs(inputs_string, state_string)?;
|
||||
|
||||
@ -106,11 +114,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
Ok(LeoParser::load_file(&self.main_file_path)?)
|
||||
}
|
||||
|
||||
/// Manually set the inputs to the `main` program function.
|
||||
pub fn set_main_inputs(&mut self, program_inputs: MainInputs) {
|
||||
self.program_inputs.set_main_inputs(program_inputs);
|
||||
}
|
||||
|
||||
pub fn checksum(&self) -> Result<String, CompilerError> {
|
||||
// Read in the main file as string
|
||||
let unparsed_file = fs::read_to_string(&self.main_file_path)
|
||||
@ -125,14 +128,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
}
|
||||
|
||||
/// Synthesizes the circuit without program inputs to verify correctness.
|
||||
pub fn compile_constraints<CS: ConstraintSystem<F>>(
|
||||
self,
|
||||
cs: &mut CS,
|
||||
) -> Result<ConstrainedValue<F, G>, CompilerError> {
|
||||
pub fn compile_constraints<CS: ConstraintSystem<F>>(self, cs: &mut CS) -> Result<OutputBytes, CompilerError> {
|
||||
let path = self.main_file_path;
|
||||
let inputs = self.program_inputs.empty();
|
||||
|
||||
generate_constraints(cs, self.program, inputs, &self.imported_programs).map_err(|mut error| {
|
||||
generate_constraints::<F, G, CS>(cs, self.program, inputs, &self.imported_programs).map_err(|mut error| {
|
||||
error.set_path(path);
|
||||
|
||||
error
|
||||
@ -155,11 +155,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -174,7 +175,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compil
|
||||
})?;
|
||||
|
||||
// Write results to file or something
|
||||
log::info!("{}", result);
|
||||
log::info!("Program circuit successfully synthesized!");
|
||||
|
||||
let outputs_file = OutputsFile::new(&self.package_name);
|
||||
outputs_file.write(&self.outputs_directory, result.bytes()).unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,6 +1,14 @@
|
||||
//! Generates R1CS constraints for a compiled Leo program.
|
||||
|
||||
use crate::{errors::CompilerError, new_scope, ConstrainedProgram, ConstrainedValue, GroupType, ImportParser};
|
||||
use crate::{
|
||||
errors::CompilerError,
|
||||
new_scope,
|
||||
ConstrainedProgram,
|
||||
ConstrainedValue,
|
||||
GroupType,
|
||||
ImportParser,
|
||||
OutputBytes,
|
||||
};
|
||||
use leo_types::{Inputs, Program};
|
||||
|
||||
use snarkos_models::{
|
||||
@ -13,8 +21,8 @@ pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: Constrai
|
||||
program: Program,
|
||||
inputs: Inputs,
|
||||
imported_programs: &ImportParser,
|
||||
) -> Result<ConstrainedValue<F, G>, CompilerError> {
|
||||
let mut resolved_program = ConstrainedProgram::new();
|
||||
) -> Result<OutputBytes, CompilerError> {
|
||||
let mut resolved_program = ConstrainedProgram::<F, G>::new();
|
||||
let program_name = program.get_name();
|
||||
let main_function_name = new_scope(program_name.clone(), "main".into());
|
||||
|
||||
|
@ -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),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
}
|
||||
|
@ -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::*;
|
||||
|
||||
|
33
compiler/src/errors/output_bytes.rs
Normal file
33
compiler/src/errors/output_bytes.rs
Normal file
@ -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)
|
||||
}
|
||||
}
|
22
compiler/src/errors/output_file.rs
Normal file
22
compiler/src/errors/output_file.rs
Normal file
@ -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<std::io::Error> for OutputsFileError {
|
||||
fn from(error: std::io::Error) -> Self {
|
||||
OutputsFileError::Crate("std::io", format!("{}", error))
|
||||
}
|
||||
}
|
@ -4,8 +4,8 @@ use crate::{
|
||||
errors::FunctionError,
|
||||
function::check_arguments_length,
|
||||
program::{new_scope, ConstrainedProgram},
|
||||
value::ConstrainedValue,
|
||||
GroupType,
|
||||
OutputBytes,
|
||||
};
|
||||
|
||||
use leo_types::{Expression, Function, Input, Inputs};
|
||||
@ -22,8 +22,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
scope: String,
|
||||
function: Function,
|
||||
inputs: Inputs,
|
||||
) -> Result<ConstrainedValue<F, G>, FunctionError> {
|
||||
) -> Result<OutputBytes, FunctionError> {
|
||||
let function_name = new_scope(scope.clone(), function.get_name());
|
||||
let registers = inputs.get_registers();
|
||||
|
||||
// Make sure we are given the correct number of inputs
|
||||
check_arguments_length(function.inputs.len(), inputs.len(), function.span.clone())?;
|
||||
@ -48,25 +49,25 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
(input_model.identifier, input_value)
|
||||
}
|
||||
Input::Registers(identifier) => {
|
||||
let section = inputs.get_registers();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
let section = inputs.get_state_leaf().values();
|
||||
let value = self.allocate_input_section(cs, identifier.clone(), section)?;
|
||||
|
||||
(identifier, value)
|
||||
@ -82,6 +83,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -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::*;
|
||||
|
||||
|
5
compiler/src/output/mod.rs
Normal file
5
compiler/src/output/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub mod output_file;
|
||||
pub use self::output_file::*;
|
||||
|
||||
pub mod output_bytes;
|
||||
pub use self::output_bytes::*;
|
54
compiler/src/output/output_bytes.rs
Normal file
54
compiler/src/output/output_bytes.rs
Normal file
@ -0,0 +1,54 @@
|
||||
use crate::{errors::OutputBytesError, ConstrainedValue, GroupType};
|
||||
use leo_types::{Registers, Span, REGISTERS_VARIABLE_NAME};
|
||||
|
||||
use snarkos_models::curves::{Field, PrimeField};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Serialized program return output.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct OutputBytes(Vec<u8>);
|
||||
|
||||
impl OutputBytes {
|
||||
pub fn bytes(&self) -> &Vec<u8> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn new_from_constrained_value<F: Field + PrimeField, G: GroupType<F>>(
|
||||
registers: &Registers,
|
||||
value: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<Self, OutputBytesError> {
|
||||
let return_values = match value {
|
||||
ConstrainedValue::Return(values) => values,
|
||||
value => return Err(OutputBytesError::illegal_return(value.to_string(), span)),
|
||||
};
|
||||
let register_values = registers.values();
|
||||
|
||||
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<u8> = vec![];
|
||||
bytes.extend_from_slice(string.as_bytes());
|
||||
|
||||
Ok(Self(bytes))
|
||||
}
|
||||
}
|
61
compiler/src/output/output_file.rs
Normal file
61
compiler/src/output/output_file.rs
Normal file
@ -0,0 +1,61 @@
|
||||
//! 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<String, OutputsFileError> {
|
||||
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);
|
||||
let mut file = File::create(&path)?;
|
||||
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
|
||||
}
|
||||
}
|
2
compiler/tests/boolean/inputs/1field.in
Normal file
2
compiler/tests/boolean/inputs/1field.in
Normal file
@ -0,0 +1,2 @@
|
||||
[main]
|
||||
b: field = 1field;
|
2
compiler/tests/boolean/inputs/true.in
Normal file
2
compiler/tests/boolean/inputs/true.in
Normal file
@ -0,0 +1,2 @@
|
||||
[main]
|
||||
b: bool = true;
|
@ -1,4 +1,4 @@
|
||||
use crate::{get_error, get_output, parse_program, EdwardsConstrainedValue, EdwardsTestCompiler};
|
||||
use crate::{get_error, get_output, parse_program, parse_program_with_inputs, EdwardsConstrainedValue, EdwardsTestCompiler};
|
||||
use leo_compiler::{
|
||||
errors::{BooleanError, CompilerError, ExpressionError, FunctionError, StatementError},
|
||||
ConstrainedValue,
|
||||
@ -56,25 +56,26 @@ fn test_false() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_input_bool_field() {
|
||||
let bytes = include_bytes!("input_bool.leo");
|
||||
let mut program = parse_program(bytes).unwrap();
|
||||
fn test_input_bool_true() {
|
||||
let program_bytes = include_bytes!("input_bool.leo");
|
||||
let input_bytes = include_bytes!("inputs/true.in");
|
||||
|
||||
program.set_main_inputs(vec![Some(InputValue::Field("1field".to_string()))]);
|
||||
let program = parse_program_with_inputs(program_bytes, input_bytes).unwrap();
|
||||
|
||||
fail_boolean(program);
|
||||
output_true(program);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_input_bool_none() {
|
||||
let bytes = include_bytes!("input_bool.leo");
|
||||
let mut program = parse_program(bytes).unwrap();
|
||||
fn test_input_bool_1field() {
|
||||
let program_bytes = include_bytes!("input_bool.leo");
|
||||
let input_bytes = include_bytes!("inputs/1field.in");
|
||||
|
||||
program.set_main_inputs(vec![None]);
|
||||
let program = parse_program_with_inputs(program_bytes, input_bytes).unwrap();
|
||||
|
||||
fail_boolean(program);
|
||||
}
|
||||
|
||||
|
||||
// Boolean not !
|
||||
|
||||
#[test]
|
||||
|
@ -1,49 +1,49 @@
|
||||
pub mod address;
|
||||
pub mod array;
|
||||
pub mod boolean;
|
||||
pub mod circuits;
|
||||
pub mod field;
|
||||
pub mod function;
|
||||
pub mod group;
|
||||
pub mod import;
|
||||
pub mod inputs;
|
||||
pub mod integers;
|
||||
pub mod macros;
|
||||
pub mod mutability;
|
||||
pub mod statements;
|
||||
pub mod syntax;
|
||||
// pub mod address;
|
||||
// pub mod array;
|
||||
// pub mod boolean;
|
||||
// pub mod circuits;
|
||||
// pub mod field;
|
||||
// pub mod function;
|
||||
// pub mod group;
|
||||
// pub mod import;
|
||||
// pub mod inputs;
|
||||
// pub mod integers;
|
||||
// pub mod macros;
|
||||
// pub mod mutability;
|
||||
// pub mod statements;
|
||||
// pub mod syntax;
|
||||
|
||||
use leo_compiler::{
|
||||
compiler::Compiler,
|
||||
constraints::generate_constraints,
|
||||
errors::{CompilerError, FunctionError, StatementError},
|
||||
group::targets::edwards_bls12::EdwardsGroupType,
|
||||
ConstrainedValue,
|
||||
};
|
||||
use leo_types::{InputValue, MainInputs};
|
||||
|
||||
use snarkos_curves::edwards_bls12::Fq;
|
||||
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
|
||||
use snarkos_models::gadgets::r1cs::{ConstraintSynthesizer, TestConstraintSystem};
|
||||
use std::path::PathBuf;
|
||||
|
||||
const EMPTY_FILE: &str = "";
|
||||
|
||||
pub type EdwardsTestCompiler = Compiler<Fq, EdwardsGroupType>;
|
||||
pub type EdwardsConstrainedValue = ConstrainedValue<Fq, EdwardsGroupType>;
|
||||
|
||||
pub(crate) fn get_output(program: EdwardsTestCompiler) -> EdwardsConstrainedValue {
|
||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
||||
let output = program.compile_constraints(&mut cs).unwrap();
|
||||
assert!(cs.is_satisfied());
|
||||
output
|
||||
}
|
||||
pub fn parse_program_with_inputs(
|
||||
program_bytes: &[u8],
|
||||
input_bytes: &[u8],
|
||||
) -> Result<EdwardsTestCompiler, CompilerError> {
|
||||
let mut compiler = new_compiler();
|
||||
|
||||
pub(crate) fn get_error(program: EdwardsTestCompiler) -> CompilerError {
|
||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
||||
program.compile_constraints(&mut cs).unwrap_err()
|
||||
}
|
||||
let program_string = String::from_utf8_lossy(program_bytes);
|
||||
let inputs_string = String::from_utf8_lossy(input_bytes);
|
||||
|
||||
pub(crate) fn fail_enforce(program: EdwardsTestCompiler) {
|
||||
match get_error(program) {
|
||||
CompilerError::FunctionError(FunctionError::StatementError(StatementError::Error(_))) => {}
|
||||
error => panic!("Expected evaluate error, got {}", error),
|
||||
}
|
||||
compiler.parse_inputs(&inputs_string, EMPTY_FILE)?;
|
||||
compiler.parse_program(&program_string)?;
|
||||
|
||||
Ok(compiler)
|
||||
}
|
||||
|
||||
fn new_compiler() -> EdwardsTestCompiler {
|
||||
@ -67,7 +67,32 @@ pub(crate) fn parse_inputs(bytes: &[u8]) -> Result<EdwardsTestCompiler, Compiler
|
||||
let mut compiler = new_compiler();
|
||||
let inputs_string = String::from_utf8_lossy(bytes);
|
||||
|
||||
compiler.parse_inputs(&inputs_string)?;
|
||||
compiler.parse_inputs(&inputs_string, "")?;
|
||||
|
||||
Ok(compiler)
|
||||
}
|
||||
|
||||
pub(crate) fn compile_with_inputs(program: EdwardsTestCompiler) -> EdwardsConstrainedValue {
|
||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
||||
let _output = program.generate_constraints(&mut cs).unwrap();
|
||||
assert!(cs.is_satisfied());
|
||||
}
|
||||
|
||||
pub(crate) fn get_output(program: EdwardsTestCompiler) -> EdwardsConstrainedValue {
|
||||
let mut cs = TestConstraintSystem::<Fq>::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::<Fq>::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),
|
||||
}
|
||||
}
|
||||
|
@ -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, InputsFile, 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};
|
||||
|
||||
@ -11,7 +11,6 @@ use snarkos_algorithms::snark::KeypairAssembly;
|
||||
use snarkos_curves::{bls12_377::Bls12_377, edwards_bls12::Fq};
|
||||
use snarkos_models::gadgets::r1cs::ConstraintSystem;
|
||||
|
||||
use crate::files::StateFile;
|
||||
use clap::ArgMatches;
|
||||
use std::{convert::TryFrom, env::current_dir};
|
||||
|
||||
@ -48,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
|
||||
@ -59,6 +62,7 @@ impl CLI for BuildCommand {
|
||||
let _program = Compiler::<Fq, EdwardsGroupType>::parse_program_without_inputs(
|
||||
package_name.clone(),
|
||||
lib_file_path.clone(),
|
||||
outputs_directory.clone(),
|
||||
)?;
|
||||
|
||||
log::info!("Compiled library file {:?}", lib_file_path);
|
||||
@ -84,6 +88,7 @@ impl CLI for BuildCommand {
|
||||
let program = Compiler::<Fq, EdwardsGroupType>::parse_program_with_inputs(
|
||||
package_name.clone(),
|
||||
main_file_path.clone(),
|
||||
outputs_directory,
|
||||
&inputs_string,
|
||||
&state_string,
|
||||
)?;
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
cli::*,
|
||||
cli_types::*,
|
||||
directories::source::SOURCE_DIRECTORY_NAME,
|
||||
directories::{outputs::OUTPUTS_DIRECTORY_NAME, source::SOURCE_DIRECTORY_NAME},
|
||||
errors::{CLIError, TestError},
|
||||
files::{InputsFile, MainFile, Manifest, StateFile, MAIN_FILE_NAME},
|
||||
};
|
||||
@ -56,6 +56,10 @@ 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)?;
|
||||
|
||||
@ -66,6 +70,7 @@ impl CLI for TestCommand {
|
||||
let program = Compiler::<Fq, EdwardsGroupType>::parse_program_with_inputs(
|
||||
package_name.clone(),
|
||||
main_file_path.clone(),
|
||||
outputs_directory,
|
||||
&inputs_string,
|
||||
&state_string,
|
||||
)?;
|
||||
|
@ -4,10 +4,10 @@ use leo_ast::functions::inputs::Input as AstInput;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
const RECORD_VARIABLE_NAME: &str = "record";
|
||||
const REGISTERS_VARIABLE_NAME: &str = "registers";
|
||||
const STATE_VARIABLE_NAME: &str = "state";
|
||||
const STATE_LEAF_VARIABLE_NAME: &str = "state_leaf";
|
||||
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 {
|
||||
|
@ -1,9 +1,8 @@
|
||||
use crate::{InputValue, MainInputs, Parameter, ProgramInputs, ProgramState};
|
||||
use crate::{InputValue, MainInputs, ProgramInputs, ProgramState, Record, Registers, State, StateLeaf};
|
||||
use leo_inputs::{
|
||||
files::{File, TableOrSection},
|
||||
InputParserError,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct Inputs {
|
||||
@ -72,22 +71,22 @@ impl Inputs {
|
||||
}
|
||||
|
||||
/// Returns the runtime register input values
|
||||
pub fn get_registers(&self) -> HashMap<Parameter, Option<InputValue>> {
|
||||
pub fn get_registers(&self) -> &Registers {
|
||||
self.inputs.get_registers()
|
||||
}
|
||||
|
||||
/// Returns the runtime record input values
|
||||
pub fn get_record(&self) -> HashMap<Parameter, Option<InputValue>> {
|
||||
pub fn get_record(&self) -> &Record {
|
||||
self.state.get_record()
|
||||
}
|
||||
|
||||
/// Returns the runtime state input values
|
||||
pub fn get_state(&self) -> HashMap<Parameter, Option<InputValue>> {
|
||||
pub fn get_state(&self) -> &State {
|
||||
self.state.get_state()
|
||||
}
|
||||
|
||||
/// Returns the runtime state leaf input values
|
||||
pub fn get_state_leaf(&self) -> HashMap<Parameter, Option<InputValue>> {
|
||||
pub fn get_state_leaf(&self) -> &StateLeaf {
|
||||
self.state.get_state_leaf()
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
use crate::{InputValue, MainInputs, Parameter, Registers};
|
||||
use crate::{InputValue, MainInputs, Registers};
|
||||
use leo_inputs::{
|
||||
sections::{Header, Section},
|
||||
InputParserError,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct ProgramInputs {
|
||||
@ -57,7 +56,7 @@ impl ProgramInputs {
|
||||
}
|
||||
|
||||
/// Returns the runtime register input values
|
||||
pub fn get_registers(&self) -> HashMap<Parameter, Option<InputValue>> {
|
||||
self.registers.values()
|
||||
pub fn get_registers(&self) -> &Registers {
|
||||
&self.registers
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
use crate::{InputValue, Parameter, Record, StateLeaf};
|
||||
use crate::{Record, StateLeaf};
|
||||
use leo_inputs::{
|
||||
sections::{Header, Section},
|
||||
InputParserError,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct PrivateState {
|
||||
@ -58,12 +57,12 @@ impl PrivateState {
|
||||
}
|
||||
|
||||
/// Returns the runtime record input values
|
||||
pub fn get_record(&self) -> HashMap<Parameter, Option<InputValue>> {
|
||||
self.record.values()
|
||||
pub fn get_record(&self) -> &Record {
|
||||
&self.record
|
||||
}
|
||||
|
||||
/// Returns the runtime state leaf input values
|
||||
pub fn get_state_leaf(&self) -> HashMap<Parameter, Option<InputValue>> {
|
||||
self.state_leaf.values()
|
||||
pub fn get_state_leaf(&self) -> &StateLeaf {
|
||||
&self.state_leaf
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,9 @@
|
||||
use crate::{InputValue, Parameter, PrivateState, PublicState};
|
||||
use crate::{PrivateState, PublicState, Record, State, StateLeaf};
|
||||
use leo_inputs::{
|
||||
tables::{Table, Visibility},
|
||||
InputParserError,
|
||||
};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct ProgramState {
|
||||
public: PublicState,
|
||||
@ -42,17 +40,17 @@ impl ProgramState {
|
||||
}
|
||||
|
||||
/// Returns the runtime record input values
|
||||
pub fn get_record(&self) -> HashMap<Parameter, Option<InputValue>> {
|
||||
pub fn get_record(&self) -> &Record {
|
||||
self.private.get_record()
|
||||
}
|
||||
|
||||
/// Returns the runtime state input values
|
||||
pub fn get_state(&self) -> HashMap<Parameter, Option<InputValue>> {
|
||||
pub fn get_state(&self) -> &State {
|
||||
self.public.get_state()
|
||||
}
|
||||
|
||||
/// Returns the runtime state leaf input values
|
||||
pub fn get_state_leaf(&self) -> HashMap<Parameter, Option<InputValue>> {
|
||||
pub fn get_state_leaf(&self) -> &StateLeaf {
|
||||
self.private.get_state_leaf()
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,9 @@
|
||||
use crate::{InputValue, Parameter, State};
|
||||
use crate::State;
|
||||
use leo_inputs::{
|
||||
sections::{Header, Section},
|
||||
InputParserError,
|
||||
};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct PublicState {
|
||||
state: State,
|
||||
@ -41,7 +39,7 @@ impl PublicState {
|
||||
}
|
||||
|
||||
/// Returns the runtime state input values
|
||||
pub fn get_state(&self) -> HashMap<Parameter, Option<InputValue>> {
|
||||
self.state.values()
|
||||
pub fn get_state(&self) -> &State {
|
||||
&self.state
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user