serialize program into bytes file

This commit is contained in:
collin 2020-06-24 21:05:11 -07:00
parent a85d831eb9
commit 504480b3d7
11 changed files with 154 additions and 8 deletions

1
Cargo.lock generated
View File

@ -511,6 +511,7 @@ dependencies = [
name = "leo-compiler" name = "leo-compiler"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bincode",
"hex", "hex",
"leo-ast", "leo-ast",
"leo-inputs", "leo-inputs",

View File

@ -14,6 +14,7 @@ snarkos-errors = { path = "../../snarkOS/errors", version = "0.8.0", default-fea
snarkos-gadgets = { path = "../../snarkOS/gadgets", version = "0.8.0", default-features = false } snarkos-gadgets = { path = "../../snarkOS/gadgets", version = "0.8.0", default-features = false }
snarkos-models = { path = "../../snarkOS/models", version = "0.8.0", default-features = false } snarkos-models = { path = "../../snarkOS/models", version = "0.8.0", default-features = false }
bincode = { version = "1.0" }
hex = { version = "0.4.2" } hex = { version = "0.4.2" }
log = { version = "0.4" } log = { version = "0.4" }
pest = { version = "2.0" } pest = { version = "2.0" }

View File

@ -40,15 +40,15 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
} }
} }
pub fn init(package_name: String, main_file_path: PathBuf) -> Result<Self, CompilerError> { pub fn new_from_path(package_name: String, main_file_path: PathBuf) -> Result<Self, CompilerError> {
let mut program = Self::new(package_name); let mut compiler = Self::new(package_name);
program.set_path(main_file_path); compiler.set_path(main_file_path);
// Generate the abstract syntax tree and assemble the program // Generate the abstract syntax tree and assemble the program
let program_string = program.load_program()?; let program_string = compiler.load_program()?;
program.parse_program(&program_string)?; compiler.parse_program(&program_string)?;
Ok(program) Ok(compiler)
} }
pub fn set_path(&mut self, main_file_path: PathBuf) { pub fn set_path(&mut self, main_file_path: PathBuf) {
@ -116,6 +116,23 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
Ok(()) Ok(())
} }
pub fn to_bytes(&self) -> Result<Vec<u8>, CompilerError> {
Ok(bincode::serialize(&self.program)?)
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, CompilerError> {
let program: Program = bincode::deserialize(bytes)?;
Ok(Self {
package_name: program.name.clone(),
main_file_path: PathBuf::new(),
program,
program_inputs: Inputs::new(),
output: None,
_engine: PhantomData,
})
}
} }
impl<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compiler<F, G> { impl<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compiler<F, G> {

View File

@ -2,6 +2,7 @@ use crate::errors::{FunctionError, ImportError};
use leo_ast::ParserError; use leo_ast::ParserError;
use leo_inputs::InputParserError; use leo_inputs::InputParserError;
use bincode::Error as SerdeError;
use std::path::PathBuf; use std::path::PathBuf;
#[derive(Debug, Error)] #[derive(Debug, Error)]
@ -26,6 +27,9 @@ pub enum CompilerError {
#[error("{}", _0)] #[error("{}", _0)]
ParserError(#[from] ParserError), ParserError(#[from] ParserError),
#[error("{}", _0)]
SerdeError(#[from] SerdeError),
} }
impl CompilerError { impl CompilerError {

View File

@ -10,6 +10,7 @@ use leo_compiler::{compiler::Compiler, group::edwards_bls12::EdwardsGroupType};
use snarkos_algorithms::snark::KeypairAssembly; use snarkos_algorithms::snark::KeypairAssembly;
use snarkos_curves::{bls12_377::Bls12_377, edwards_bls12::Fq}; use snarkos_curves::{bls12_377::Bls12_377, edwards_bls12::Fq};
use crate::files::BytesFile;
use clap::ArgMatches; use clap::ArgMatches;
use std::{convert::TryFrom, env::current_dir}; use std::{convert::TryFrom, env::current_dir};
@ -59,8 +60,32 @@ impl CLI for BuildCommand {
main_file_path.push(SOURCE_DIRECTORY_NAME); main_file_path.push(SOURCE_DIRECTORY_NAME);
main_file_path.push(MAIN_FILE_NAME); main_file_path.push(MAIN_FILE_NAME);
// Check if the program bytes exist
let existing_bytes = BytesFile::new(&package_name).exists_at(&path);
let program = if existing_bytes {
// Load the program ast from stored bytes
let bytes = BytesFile::new(&package_name).read_from(&path)?;
let mut program = Compiler::<Fq, EdwardsGroupType>::from_bytes(bytes.as_slice())?;
program.set_path(main_file_path.clone());
program
} else {
// Load the program at `main_file_path`
let program =
Compiler::<Fq, EdwardsGroupType>::new_from_path(package_name.clone(), main_file_path.clone())?;
// Store the program ast as bytes
let bytes = program.to_bytes()?;
BytesFile::new(&package_name).write_to(&path, bytes)?;
program
};
// Compute the current program checksum // Compute the current program checksum
let program = Compiler::<Fq, EdwardsGroupType>::init(package_name.clone(), main_file_path.clone())?;
let program_checksum = program.checksum()?; let program_checksum = program.checksum()?;
// Generate the program on the constraint system and verify correctness // Generate the program on the constraint system and verify correctness

View File

@ -57,7 +57,7 @@ impl CLI for TestCommand {
main_file_path.push(MAIN_FILE_NAME); main_file_path.push(MAIN_FILE_NAME);
// Compute the current program checksum // Compute the current program checksum
let program = Compiler::<Fq, EdwardsGroupType>::init(package_name.clone(), main_file_path.clone())?; let program = Compiler::<Fq, EdwardsGroupType>::new_from_path(package_name.clone(), main_file_path.clone())?;
// Generate the program on the constraint system and verify correctness // Generate the program on the constraint system and verify correctness
{ {

View File

@ -5,6 +5,9 @@ pub enum CLIError {
#[error("{}", _0)] #[error("{}", _0)]
BuildError(BuildError), BuildError(BuildError),
#[error("{}", _0)]
BytesFileError(BytesFileError),
#[error("{}: {}", _0, _1)] #[error("{}: {}", _0, _1)]
Crate(&'static str, String), Crate(&'static str, String),
@ -54,6 +57,13 @@ pub enum CLIError {
VerificationKeyFileError(VerificationKeyFileError), VerificationKeyFileError(VerificationKeyFileError),
} }
impl From<BytesFileError> for CLIError {
fn from(error: BytesFileError) -> Self {
log::error!("{}\n", error);
CLIError::BytesFileError(error)
}
}
impl From<BuildError> for CLIError { impl From<BuildError> for CLIError {
fn from(error: BuildError) -> Self { fn from(error: BuildError) -> Self {
log::error!("{}\n", error); log::error!("{}\n", error);

22
leo/errors/files/bytes.rs Normal file
View File

@ -0,0 +1,22 @@
use std::{io, path::PathBuf};
#[derive(Debug, Error)]
pub enum BytesFileError {
#[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 BytesFileError {
fn from(error: std::io::Error) -> Self {
BytesFileError::Crate("std::io", format!("{}", error))
}
}

View File

@ -1,3 +1,6 @@
pub mod bytes;
pub use self::bytes::*;
pub mod checksum; pub mod checksum;
pub use self::checksum::*; pub use self::checksum::*;

60
leo/files/bytes.rs Normal file
View File

@ -0,0 +1,60 @@
//! The program bytes file.
use crate::{directories::outputs::OUTPUTS_DIRECTORY_NAME, errors::BytesFileError};
use serde::Deserialize;
use std::{
fs::{self, File},
io::Write,
path::PathBuf,
};
pub static BYTES_FILE_EXTENSION: &str = ".bytes";
#[derive(Deserialize)]
pub struct BytesFile {
pub package_name: String,
}
impl BytesFile {
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 program bytes from the given file path if it exists.
pub fn read_from(&self, path: &PathBuf) -> Result<Vec<u8>, BytesFileError> {
let path = self.setup_file_path(path);
Ok(fs::read(&path).map_err(|_| BytesFileError::FileReadError(path.clone()))?)
}
/// Writes the given program bytes to a file.
pub fn write_to(&self, path: &PathBuf, bytes: Vec<u8>) -> Result<(), BytesFileError> {
let path = self.setup_file_path(path);
let mut file = File::create(&path)?;
file.write_all(bytes.as_slice())?;
log::info!("program bytes stored to {:?}", path);
Ok(())
}
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, BYTES_FILE_EXTENSION)));
}
path
}
}

View File

@ -1,3 +1,6 @@
pub mod bytes;
pub use self::bytes::*;
pub mod checksum; pub mod checksum;
pub use self::checksum::*; pub use self::checksum::*;