mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-27 12:17:35 +03:00
serialize program into bytes file
This commit is contained in:
parent
a85d831eb9
commit
504480b3d7
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -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",
|
||||||
|
@ -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" }
|
||||||
|
@ -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> {
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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
22
leo/errors/files/bytes.rs
Normal 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))
|
||||||
|
}
|
||||||
|
}
|
@ -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
60
leo/files/bytes.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -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::*;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user