mirror of
https://github.com/AleoHQ/leo.git
synced 2024-09-11 15:05:33 +03:00
Adds command
This commit is contained in:
parent
dcb5f542a8
commit
18768bbec7
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -613,8 +613,11 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"colored",
|
||||
"env_logger",
|
||||
"failure",
|
||||
"from-pest",
|
||||
"leo-program",
|
||||
"log",
|
||||
"rand 0.7.3",
|
||||
"rand_core 0.5.1",
|
||||
"serde",
|
||||
|
@ -16,6 +16,8 @@ path = "leo/main.rs"
|
||||
members = [ "benchmark", "program" ]
|
||||
|
||||
[dependencies]
|
||||
leo-program = { path = "./program", version = "0.1.0" }
|
||||
|
||||
snarkos-algorithms = { path = "../snarkOS/algorithms", version = "0.8.0" }
|
||||
snarkos-curves = { path = "../snarkOS/curves", version = "0.8.0" }
|
||||
snarkos-errors = { path = "../snarkOS/errors", version = "0.8.0" }
|
||||
@ -24,8 +26,10 @@ snarkos-models = { path = "../snarkOS/models", version = "0.8.0" }
|
||||
|
||||
clap = { version = "2.33.0" }
|
||||
colored = { version = "1.9" }
|
||||
env_logger = { version = "0.7" }
|
||||
failure = { version = "0.1.5" }
|
||||
from-pest = { version = "0.3.1" }
|
||||
log = { version = "0.4" }
|
||||
rand = { version = "0.7" }
|
||||
rand_core = { version = "0.5.1" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
@ -56,8 +56,9 @@ impl CLI for InitCommand {
|
||||
// Create the inputs directory
|
||||
InputsDirectory::create(&path)?;
|
||||
|
||||
// Create the main file in the source directory
|
||||
// Verify the main file does not exist
|
||||
if !MainFile::exists_at(&path) {
|
||||
// Create the main file in the source directory
|
||||
MainFile::new(&package_name).write_to(&path)?;
|
||||
}
|
||||
|
||||
|
@ -1,2 +1,5 @@
|
||||
pub mod init;
|
||||
pub use self::init::*;
|
||||
|
||||
pub mod run;
|
||||
pub use self::run::*;
|
||||
|
135
leo/commands/run.rs
Normal file
135
leo/commands/run.rs
Normal file
@ -0,0 +1,135 @@
|
||||
use crate::{cli::*, cli_types::*};
|
||||
use crate::compiler::Compiler;
|
||||
use crate::directories::{OutputsDirectory, source::SOURCE_DIRECTORY_NAME};
|
||||
use crate::errors::{CLIError, RunError};
|
||||
use crate::files::{MainFile, MAIN_FILE_NAME};
|
||||
use crate::manifest::Manifest;
|
||||
|
||||
use snarkos_curves::bls12_377::Fr;
|
||||
|
||||
use clap::ArgMatches;
|
||||
use std::convert::TryFrom;
|
||||
use std::env::current_dir;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RunCommand;
|
||||
|
||||
impl CLI for RunCommand {
|
||||
type Options = ();
|
||||
|
||||
const NAME: NameType = "run";
|
||||
const ABOUT: AboutType = "Run a program with inputs (include -h for more options)";
|
||||
const FLAGS: &'static [FlagType] = &[];
|
||||
const OPTIONS: &'static [OptionType] = &[];
|
||||
const SUBCOMMANDS: &'static [SubCommandType] = &[];
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn parse(_arguments: &ArgMatches) -> Result<Self::Options, CLIError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn output(_options: Self::Options) -> Result<(), CLIError> {
|
||||
let path = current_dir()?;
|
||||
let _manifest = Manifest::try_from(&path)?;
|
||||
|
||||
// Sanitize the package path to the root directory
|
||||
let mut package_path = path.clone();
|
||||
if package_path.is_file() {
|
||||
package_path.pop();
|
||||
}
|
||||
|
||||
// Verify the main file exists
|
||||
if !MainFile::exists_at(&package_path) {
|
||||
return Err(RunError::MainFileDoesNotExist(package_path.as_os_str().to_owned()).into());
|
||||
}
|
||||
|
||||
// Create the outputs directory
|
||||
OutputsDirectory::create(&package_path)?;
|
||||
|
||||
// Construct the path to the main file in the source directory
|
||||
let mut main_file_path = package_path.clone();
|
||||
main_file_path.push(SOURCE_DIRECTORY_NAME);
|
||||
main_file_path.push(MAIN_FILE_NAME);
|
||||
|
||||
log::debug!("Compiling program located in {:?}", main_file_path);
|
||||
|
||||
fn run(main_file_path: PathBuf) {
|
||||
|
||||
use snarkos_algorithms::snark::{create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof};
|
||||
use snarkos_curves::bls12_377::Bls12_377;
|
||||
|
||||
use rand::thread_rng;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
let mut setup = Duration::new(0, 0);
|
||||
let mut proving = Duration::new(0, 0);
|
||||
let mut verifying = Duration::new(0, 0);
|
||||
|
||||
let rng = &mut thread_rng();
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
let params = {
|
||||
let circuit = Compiler::<Fr>::init(main_file_path.clone());
|
||||
generate_random_parameters::<Bls12_377, _, _>(circuit, rng).unwrap()
|
||||
};
|
||||
|
||||
let prepared_verifying_key = prepare_verifying_key::<Bls12_377>(¶ms.vk);
|
||||
|
||||
setup += start.elapsed();
|
||||
|
||||
let start = Instant::now();
|
||||
let proof = {
|
||||
let circuit = Compiler::<Fr>::init(main_file_path);
|
||||
create_random_proof(circuit, ¶ms, rng).unwrap()
|
||||
};
|
||||
|
||||
proving += start.elapsed();
|
||||
|
||||
// let _inputs: Vec<_> = [1u32; 1].to_vec();
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
let is_success = verify_proof(&prepared_verifying_key, &proof, &[]).unwrap();
|
||||
|
||||
verifying += start.elapsed();
|
||||
|
||||
println!(" ");
|
||||
println!(" Setup time : {:?} milliseconds", setup.as_millis());
|
||||
println!(" Prover time : {:?} milliseconds", proving.as_millis());
|
||||
println!(
|
||||
" Verifier time : {:?} milliseconds",
|
||||
verifying.as_millis()
|
||||
);
|
||||
println!(" Verifier output : {}", is_success);
|
||||
println!(" ");
|
||||
}
|
||||
|
||||
run(main_file_path);
|
||||
|
||||
// let source_files = SourceDirectory::files(&package_path)?;
|
||||
// BuildDirectory::create(&circuit_path).map_err(Error::BuildDirectory)?;
|
||||
// DataDirectory::create(&circuit_path).map_err(Error::DataDirectory)?;
|
||||
|
||||
// Compiler::build(
|
||||
// self.verbosity,
|
||||
// &self.witness,
|
||||
// &self.public_data,
|
||||
// &self.circuit,
|
||||
// &source_file_paths,
|
||||
// )
|
||||
// .map_err(Error::Compiler)?;
|
||||
//
|
||||
// VirtualMachine::run(
|
||||
// self.verbosity,
|
||||
// &self.circuit,
|
||||
// &self.witness,
|
||||
// &self.public_data,
|
||||
// )
|
||||
// .map_err(Error::VirtualMachine)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
50
leo/compiler.rs
Normal file
50
leo/compiler.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use leo_program::{self, ast};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
gadgets::r1cs::{ConstraintSynthesizer, ConstraintSystem},
|
||||
};
|
||||
|
||||
use from_pest::FromPest;
|
||||
use std::{
|
||||
fs,
|
||||
marker::PhantomData,
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
pub struct Compiler<F: Field + PrimeField> {
|
||||
main_file_path: PathBuf,
|
||||
_engine: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField> Compiler<F> {
|
||||
pub fn init(main_file_path: PathBuf) -> Self {
|
||||
Self { main_file_path, _engine: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField> ConstraintSynthesizer<F> for Compiler<F> {
|
||||
fn generate_constraints<CS: ConstraintSystem<F>>(
|
||||
self,
|
||||
cs: &mut CS,
|
||||
) -> Result<(), SynthesisError> {
|
||||
// Read in the main file as string
|
||||
let unparsed_file = fs::read_to_string(&self.main_file_path).expect("cannot read file");
|
||||
|
||||
// Parse the file using leo.pest
|
||||
let mut file = ast::parse(&unparsed_file).expect("unsuccessful parse");
|
||||
|
||||
// Build the abstract syntax tree
|
||||
let syntax_tree = ast::File::from_pest(&mut file).expect("infallible");
|
||||
// println!("{:#?}", syntax_tree);
|
||||
|
||||
let program = leo_program::Program::<'_, F>::from(syntax_tree);
|
||||
println!(" compiled: {:#?}", program);
|
||||
|
||||
let program = program.name("simple".into());
|
||||
leo_program::ResolvedProgram::generate_constraints(cs, program);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
pub mod inputs;
|
||||
pub use self::inputs::*;
|
||||
|
||||
pub mod outputs;
|
||||
pub use self::outputs::*;
|
||||
|
||||
pub mod source;
|
||||
pub use self::source::*;
|
||||
|
34
leo/directories/outputs.rs
Normal file
34
leo/directories/outputs.rs
Normal file
@ -0,0 +1,34 @@
|
||||
use crate::errors::OutputsDirectoryError;
|
||||
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub(crate) static OUTPUTS_DIRECTORY_NAME: &str = "outputs/";
|
||||
|
||||
pub struct OutputsDirectory;
|
||||
|
||||
impl OutputsDirectory {
|
||||
/// Creates a directory at the provided path with the default directory name.
|
||||
pub fn create(path: &PathBuf) -> Result<(), OutputsDirectoryError> {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() && !path.ends_with(OUTPUTS_DIRECTORY_NAME) {
|
||||
path.push(PathBuf::from(OUTPUTS_DIRECTORY_NAME));
|
||||
}
|
||||
|
||||
fs::create_dir_all(&path).map_err(OutputsDirectoryError::Creating)
|
||||
}
|
||||
|
||||
/// Removes the directory at the provided path.
|
||||
pub fn remove(path: &PathBuf) -> Result<(), OutputsDirectoryError> {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() && !path.ends_with(OUTPUTS_DIRECTORY_NAME) {
|
||||
path.push(PathBuf::from(OUTPUTS_DIRECTORY_NAME));
|
||||
}
|
||||
|
||||
if path.exists() {
|
||||
fs::remove_dir_all(&path).map_err(OutputsDirectoryError::Removing)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use crate::errors::{InitError, InputsDirectoryError, MainFileError, ManifestError, SourceDirectoryError};
|
||||
use crate::errors::{InitError, InputsDirectoryError, MainFileError, ManifestError, OutputsDirectoryError, RunError, SourceDirectoryError};
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum CLIError {
|
||||
@ -18,6 +18,12 @@ pub enum CLIError {
|
||||
#[fail(display = "{}", _0)]
|
||||
ManifestError(ManifestError),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
OutputsDirectoryError(OutputsDirectoryError),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
RunError(RunError),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
SourceDirectoryError(SourceDirectoryError),
|
||||
|
||||
@ -47,6 +53,18 @@ impl From<ManifestError> for CLIError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OutputsDirectoryError> for CLIError {
|
||||
fn from(error: OutputsDirectoryError) -> Self {
|
||||
CLIError::OutputsDirectoryError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RunError> for CLIError {
|
||||
fn from(error: RunError) -> Self {
|
||||
CLIError::RunError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SourceDirectoryError> for CLIError {
|
||||
fn from(error: SourceDirectoryError) -> Self {
|
||||
CLIError::SourceDirectoryError(error)
|
||||
|
@ -1,2 +1,5 @@
|
||||
pub mod init;
|
||||
pub use self::init::*;
|
||||
|
||||
pub mod run;
|
||||
pub use self::run::*;
|
||||
|
33
leo/errors/commands/run.rs
Normal file
33
leo/errors/commands/run.rs
Normal file
@ -0,0 +1,33 @@
|
||||
use crate::errors::ManifestError;
|
||||
|
||||
use std::ffi::OsString;
|
||||
use std::io;
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum RunError {
|
||||
|
||||
#[fail(display = "root directory {:?} creating: {}", _0, _1)]
|
||||
CreatingRootDirectory(OsString, io::Error),
|
||||
|
||||
#[fail(display = "directory {:?} does not exist", _0)]
|
||||
DirectoryDoesNotExist(OsString),
|
||||
|
||||
#[fail(display = "main file {:?} does not exist", _0)]
|
||||
MainFileDoesNotExist(OsString),
|
||||
|
||||
#[fail(display = "{}", _0)]
|
||||
ManifestError(ManifestError),
|
||||
|
||||
#[fail(display = "package at path {:?} already exists", _0)]
|
||||
PackageAlreadyExists(OsString),
|
||||
|
||||
#[fail(display = "package name is missing - {:?}", _0)]
|
||||
ProjectNameInvalid(OsString),
|
||||
|
||||
}
|
||||
|
||||
impl From<ManifestError> for RunError {
|
||||
fn from(error: ManifestError) -> Self {
|
||||
RunError::ManifestError(error)
|
||||
}
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
pub mod inputs;
|
||||
pub use self::inputs::*;
|
||||
|
||||
pub mod outputs;
|
||||
pub use self::outputs::*;
|
||||
|
||||
pub mod source;
|
||||
pub use self::source::*;
|
||||
|
30
leo/errors/directory/outputs.rs
Normal file
30
leo/errors/directory/outputs.rs
Normal file
@ -0,0 +1,30 @@
|
||||
use std::{ffi::OsString, fs::FileType, io};
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum OutputsDirectoryError {
|
||||
|
||||
#[fail(display = "creating: {}", _0)]
|
||||
Creating(io::Error),
|
||||
|
||||
#[fail(display = "file entry getting: {}", _0)]
|
||||
GettingFileEntry(io::Error),
|
||||
|
||||
#[fail(display = "file {:?} extension getting", _0)]
|
||||
GettingFileExtension(OsString),
|
||||
|
||||
#[fail(display = "file {:?} type getting: {}", _0, _1)]
|
||||
GettingFileType(OsString, io::Error),
|
||||
|
||||
#[fail(display = "invalid file {:?} extension: {:?}", _0, _1)]
|
||||
InvalidFileExtension(OsString, OsString),
|
||||
|
||||
#[fail(display = "invalid file {:?} type: {:?}", _0, _1)]
|
||||
InvalidFileType(OsString, FileType),
|
||||
|
||||
#[fail(display = "reading: {}", _0)]
|
||||
Reading(io::Error),
|
||||
|
||||
#[fail(display = "removing: {}", _0)]
|
||||
Removing(io::Error),
|
||||
|
||||
}
|
@ -8,7 +8,7 @@ use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub static FILE_NAME_DEFAULT: &str = "main.leo";
|
||||
pub static MAIN_FILE_NAME: &str = "main.leo";
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct MainFile {
|
||||
@ -26,7 +26,7 @@ impl MainFile {
|
||||
if !path.ends_with(SOURCE_DIRECTORY_NAME) {
|
||||
path.push(PathBuf::from(SOURCE_DIRECTORY_NAME));
|
||||
}
|
||||
path.push(PathBuf::from(FILE_NAME_DEFAULT));
|
||||
path.push(PathBuf::from(MAIN_FILE_NAME));
|
||||
}
|
||||
path.exists()
|
||||
}
|
||||
@ -37,7 +37,7 @@ impl MainFile {
|
||||
if !path.ends_with(SOURCE_DIRECTORY_NAME) {
|
||||
path.push(PathBuf::from(SOURCE_DIRECTORY_NAME));
|
||||
}
|
||||
path.push(PathBuf::from(FILE_NAME_DEFAULT));
|
||||
path.push(PathBuf::from(MAIN_FILE_NAME));
|
||||
}
|
||||
|
||||
let mut file = File::create(&path)?;
|
||||
|
@ -5,7 +5,9 @@ extern crate failure;
|
||||
pub mod cli;
|
||||
pub mod cli_types;
|
||||
pub mod commands;
|
||||
pub mod compiler;
|
||||
pub mod directories;
|
||||
pub mod errors;
|
||||
pub mod files;
|
||||
pub mod logger;
|
||||
pub mod manifest;
|
||||
|
45
leo/logger.rs
Normal file
45
leo/logger.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use colored::Colorize;
|
||||
use std::io::Write;
|
||||
|
||||
const LEVEL_NAME_LENGTH: usize = 10;
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn level_string(level: log::Level) -> colored::ColoredString {
|
||||
match level {
|
||||
log::Level::Error => "ERROR".bold().red(),
|
||||
log::Level::Warn => "WARN".bold().yellow(),
|
||||
log::Level::Info => "INFO".bold().blue(),
|
||||
log::Level::Debug => "DEBUG".bold().magenta(),
|
||||
log::Level::Trace => "TRACE".bold(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize logger with custom format and verbosity.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `verbosity` - Verbosity level. 0 for `Warn`, 1 for `Info`, 2 for `Debug`, more for `Trace`
|
||||
pub fn init_logger(app_name: &'static str, verbosity: usize) {
|
||||
env_logger::builder()
|
||||
.filter_level(match verbosity {
|
||||
0 => log::LevelFilter::Warn,
|
||||
1 => log::LevelFilter::Info,
|
||||
2 => log::LevelFilter::Debug,
|
||||
_ => log::LevelFilter::Trace,
|
||||
})
|
||||
.format(move |buf, record| {
|
||||
let mut padding = String::from("\n");
|
||||
for _ in 0..(app_name.len() + LEVEL_NAME_LENGTH + 4) {
|
||||
padding.push(' ');
|
||||
}
|
||||
|
||||
writeln!(
|
||||
buf,
|
||||
"[{:>5} {:>5}] {}",
|
||||
level_string(record.level()),
|
||||
app_name,
|
||||
record.args().to_string().replace("\n", &padding)
|
||||
)
|
||||
})
|
||||
.init();
|
||||
}
|
10
leo/main.rs
10
leo/main.rs
@ -110,13 +110,15 @@
|
||||
// //
|
||||
// }
|
||||
|
||||
use leo::{cli::*, commands::*};
|
||||
use leo::{cli::*, commands::*, logger};
|
||||
use leo::errors::CLIError;
|
||||
|
||||
use clap::{App, AppSettings};
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn main() -> Result<(), CLIError> {
|
||||
logger::init_logger("leo", 3);
|
||||
|
||||
let arguments = App::new("leo")
|
||||
.version("v0.1.0")
|
||||
.about("Leo compiler and package manager")
|
||||
@ -129,15 +131,15 @@ fn main() -> Result<(), CLIError> {
|
||||
])
|
||||
.subcommands(vec![
|
||||
InitCommand::new(),
|
||||
RunCommand::new(),
|
||||
])
|
||||
.set_term_width(0)
|
||||
.get_matches();
|
||||
|
||||
|
||||
match arguments.subcommand() {
|
||||
("init", Some(arguments)) => {
|
||||
InitCommand::output(InitCommand::parse(arguments)?)
|
||||
},
|
||||
("init", Some(arguments)) => InitCommand::output(InitCommand::parse(arguments)?),
|
||||
("run", Some(arguments)) => RunCommand::output(RunCommand::parse(arguments)?),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
function main() -> (u32) {
|
||||
a = 1 + 1
|
||||
return a
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
struct Point {
|
||||
u32 x
|
||||
u32 y
|
||||
}
|
Loading…
Reference in New Issue
Block a user