mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-24 18:52:58 +03:00
Merge pull request #80 from AleoHQ/feature/cli
Add debug flag, improve CLI messages, add num_constraints, add 'leo clean'
This commit is contained in:
commit
d1c5c9e928
@ -53,7 +53,6 @@ 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)?;
|
||||
log::debug!("{}", result);
|
||||
Ok(result)
|
||||
}
|
||||
_ => Err(CompilerError::NoMainFunction),
|
||||
|
@ -15,8 +15,8 @@ circuit PedersenHash {
|
||||
|
||||
// The 'pedersen_hash' main function.
|
||||
function main() -> u32 {
|
||||
let parameters = [0u32; 512];
|
||||
let pedersen = PedersenHash::new(parameters);
|
||||
const parameters = [0u32; 512];
|
||||
const pedersen = PedersenHash::new(parameters);
|
||||
let input: bool[512] = [true; 512];
|
||||
return pedersen.hash(input)
|
||||
}
|
||||
|
15
leo/cli.rs
15
leo/cli.rs
@ -1,4 +1,4 @@
|
||||
use crate::{cli_types::*, errors::CLIError};
|
||||
use crate::{cli_types::*, errors::CLIError, logger};
|
||||
|
||||
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
|
||||
|
||||
@ -66,6 +66,19 @@ pub trait CLI {
|
||||
.subcommands(subcommands)
|
||||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn process(arguments: &ArgMatches) -> Result<(), CLIError> {
|
||||
// Set logging environment
|
||||
match arguments.is_present("debug") {
|
||||
true => logger::init_logger("leo", 2),
|
||||
false => logger::init_logger("leo", 1),
|
||||
}
|
||||
|
||||
let options = Self::parse(arguments)?;
|
||||
let _output = Self::output(options)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn parse(arguments: &ArgMatches) -> Result<Self::Options, CLIError>;
|
||||
|
||||
|
@ -9,6 +9,7 @@ use leo_compiler::{compiler::Compiler, group::edwards_bls12::EdwardsGroupType};
|
||||
|
||||
use snarkos_algorithms::snark::KeypairAssembly;
|
||||
use snarkos_curves::{bls12_377::Bls12_377, edwards_bls12::Fq};
|
||||
use snarkos_models::gadgets::r1cs::ConstraintSystem;
|
||||
|
||||
use clap::ArgMatches;
|
||||
use std::{convert::TryFrom, env::current_dir};
|
||||
@ -51,6 +52,8 @@ impl CLI for BuildCommand {
|
||||
return Err(BuildError::MainFileDoesNotExist(package_path.as_os_str().to_owned()).into());
|
||||
}
|
||||
|
||||
log::info!("Compiling...");
|
||||
|
||||
// Create the outputs directory
|
||||
OutputsDirectory::create(&package_path)?;
|
||||
|
||||
@ -78,6 +81,7 @@ impl CLI for BuildCommand {
|
||||
let temporary_program = program.clone();
|
||||
let output = temporary_program.compile_constraints(&mut cs)?;
|
||||
log::debug!("Compiled constraints - {:#?}", output);
|
||||
log::debug!("Number of constraints - {:#?}", cs.num_constraints());
|
||||
}
|
||||
|
||||
// If a checksum file exists, check if it differs from the new checksum
|
||||
@ -94,9 +98,11 @@ impl CLI for BuildCommand {
|
||||
if checksum_differs {
|
||||
// Write the new checksum to the outputs directory
|
||||
checksum_file.write_to(&path, program_checksum)?;
|
||||
|
||||
log::debug!("Checksum saved ({:?})", path);
|
||||
}
|
||||
|
||||
log::info!("Compiled program in {:?}", main_file_path);
|
||||
log::info!("Compiled program ({:?})", main_file_path);
|
||||
|
||||
Ok((program, checksum_differs))
|
||||
}
|
||||
|
50
leo/commands/clean.rs
Normal file
50
leo/commands/clean.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use crate::{
|
||||
cli::*,
|
||||
cli_types::*,
|
||||
errors::CLIError,
|
||||
files::{ChecksumFile, Manifest, ProofFile, ProvingKeyFile, VerificationKeyFile},
|
||||
};
|
||||
|
||||
use clap::ArgMatches;
|
||||
use std::{convert::TryFrom, env::current_dir};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CleanCommand;
|
||||
|
||||
impl CLI for CleanCommand {
|
||||
type Options = ();
|
||||
type Output = ();
|
||||
|
||||
const ABOUT: AboutType = "Clean the outputs directory";
|
||||
const ARGUMENTS: &'static [ArgumentType] = &[];
|
||||
const FLAGS: &'static [FlagType] = &[];
|
||||
const NAME: NameType = "clean";
|
||||
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<Self::Output, CLIError> {
|
||||
// Get the package name
|
||||
let path = current_dir()?;
|
||||
let package_name = Manifest::try_from(&path)?.get_package_name();
|
||||
|
||||
// Remove the checksum from the outputs directory
|
||||
ChecksumFile::new(&package_name).remove(&path)?;
|
||||
|
||||
// Remove the proving key from the outputs directory
|
||||
ProvingKeyFile::new(&package_name).remove(&path)?;
|
||||
|
||||
// Remove the verification key from the outputs directory
|
||||
VerificationKeyFile::new(&package_name).remove(&path)?;
|
||||
|
||||
// Remove the proof from the outputs directory
|
||||
ProofFile::new(&package_name).remove(&path)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -30,7 +30,7 @@ impl CLI for LoadCommand {
|
||||
let path = current_dir()?;
|
||||
let _package_name = Manifest::try_from(&path)?.get_package_name();
|
||||
|
||||
log::info!("Unimplemented - `leo deploy`");
|
||||
log::info!("Unimplemented - `leo load`");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
pub mod build;
|
||||
pub use self::build::*;
|
||||
|
||||
pub mod clean;
|
||||
pub use self::clean::*;
|
||||
|
||||
pub mod deploy;
|
||||
pub use self::deploy::*;
|
||||
|
||||
|
@ -40,6 +40,8 @@ impl CLI for ProveCommand {
|
||||
let path = current_dir()?;
|
||||
let package_name = Manifest::try_from(&path)?.get_package_name();
|
||||
|
||||
log::info!("Proving...");
|
||||
|
||||
// Fetch program inputs here
|
||||
let inputs_string = InputsFile::new(&package_name).read_from(&path)?;
|
||||
program.parse_inputs(&inputs_string)?;
|
||||
|
@ -52,6 +52,8 @@ impl CLI for SetupCommand {
|
||||
|
||||
// If keys do not exist or the checksum differs, run the program setup
|
||||
if !keys_exist || checksum_differs {
|
||||
log::info!("Setup starting...");
|
||||
|
||||
// Start the timer
|
||||
let start = Instant::now();
|
||||
|
||||
@ -61,18 +63,25 @@ impl CLI for SetupCommand {
|
||||
let prepared_verifying_key = prepare_verifying_key::<Bls12_377>(¶meters.vk);
|
||||
|
||||
// End the timer
|
||||
log::info!("Setup completed in {:?} milliseconds", start.elapsed().as_millis());
|
||||
let end = start.elapsed().as_millis();
|
||||
|
||||
// TODO (howardwu): Convert parameters to a 'proving key' struct for serialization.
|
||||
// Write the proving key file to the outputs directory
|
||||
let mut proving_key = vec![];
|
||||
parameters.write(&mut proving_key)?;
|
||||
ProvingKeyFile::new(&package_name).write_to(&path, &proving_key)?;
|
||||
log::info!("Saving proving key ({:?})", path);
|
||||
|
||||
// Write the proving key file to the outputs directory
|
||||
// Write the verification key file to the outputs directory
|
||||
let mut verification_key = vec![];
|
||||
prepared_verifying_key.write(&mut verification_key)?;
|
||||
VerificationKeyFile::new(&package_name).write_to(&path, &verification_key)?;
|
||||
log::info!("Saving verification key ({:?})", path);
|
||||
|
||||
// Output the setup time
|
||||
log::info!("Setup completed in {:?} milliseconds", end);
|
||||
} else {
|
||||
log::info!("Setup complete");
|
||||
}
|
||||
|
||||
// Read the proving key file from the outputs directory
|
||||
@ -98,7 +107,7 @@ impl CLI for SetupCommand {
|
||||
}
|
||||
}
|
||||
|
||||
log::info!("Completed program setup");
|
||||
log::info!("Program setup complete");
|
||||
|
||||
Ok((program, parameters, prepared_verifying_key))
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ impl CLI for UnloadCommand {
|
||||
let path = current_dir()?;
|
||||
let _package_name = Manifest::try_from(&path)?.get_package_name();
|
||||
|
||||
log::info!("Unimplemented - `leo deploy`");
|
||||
log::info!("Unimplemented - `leo unload`");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -11,6 +11,9 @@ pub enum ChecksumFileError {
|
||||
#[error("Cannot read from the provided file path - {:?}", _0)]
|
||||
FileReadError(PathBuf),
|
||||
|
||||
#[error("Cannot remove the provided file - {:?}", _0)]
|
||||
FileRemovalError(PathBuf),
|
||||
|
||||
#[error("writing: {}", _0)]
|
||||
Writing(io::Error),
|
||||
}
|
||||
|
@ -11,6 +11,9 @@ pub enum ProofFileError {
|
||||
#[error("Cannot read from the provided file path - {:?}", _0)]
|
||||
FileReadError(PathBuf),
|
||||
|
||||
#[error("Cannot remove the provided file - {:?}", _0)]
|
||||
FileRemovalError(PathBuf),
|
||||
|
||||
#[error("writing: {}", _0)]
|
||||
Writing(io::Error),
|
||||
}
|
||||
|
@ -11,6 +11,9 @@ pub enum ProvingKeyFileError {
|
||||
#[error("Cannot read from the provided file path - {:?}", _0)]
|
||||
FileReadError(PathBuf),
|
||||
|
||||
#[error("Cannot remove the provided file - {:?}", _0)]
|
||||
FileRemovalError(PathBuf),
|
||||
|
||||
#[error("writing: {}", _0)]
|
||||
Writing(io::Error),
|
||||
}
|
||||
|
@ -11,6 +11,9 @@ pub enum VerificationKeyFileError {
|
||||
#[error("Cannot read from the provided file path - {:?}", _0)]
|
||||
FileReadError(PathBuf),
|
||||
|
||||
#[error("Cannot remove the provided file - {:?}", _0)]
|
||||
FileRemovalError(PathBuf),
|
||||
|
||||
#[error("Verification key file was corrupted")]
|
||||
IncorrectVerificationKey,
|
||||
|
||||
|
@ -42,11 +42,21 @@ impl ChecksumFile {
|
||||
let mut file = File::create(&path)?;
|
||||
file.write_all(checksum.as_bytes())?;
|
||||
|
||||
log::info!("Checksum stored to {:?}", path);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Removes the checksum at the given path if it exists. Returns `true` on success,
|
||||
/// `false` if the file doesn't exist, and `Error` if the file system fails during operation.
|
||||
pub fn remove(&self, path: &PathBuf) -> Result<bool, ChecksumFileError> {
|
||||
let path = self.setup_file_path(path);
|
||||
if !path.exists() {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
fs::remove_file(&path).map_err(|_| ChecksumFileError::FileRemovalError(path.clone()))?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn setup_file_path(&self, path: &PathBuf) -> PathBuf {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() {
|
||||
|
@ -43,11 +43,23 @@ impl ProofFile {
|
||||
let mut file = File::create(&path)?;
|
||||
file.write_all(proof)?;
|
||||
|
||||
log::info!("Proof stored to {:?}", path);
|
||||
log::info!("Proof stored ({:?})", path);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Removes the proof at the given path if it exists. Returns `true` on success,
|
||||
/// `false` if the file doesn't exist, and `Error` if the file system fails during operation.
|
||||
pub fn remove(&self, path: &PathBuf) -> Result<bool, ProofFileError> {
|
||||
let path = self.setup_file_path(path);
|
||||
if !path.exists() {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
fs::remove_file(&path).map_err(|_| ProofFileError::FileRemovalError(path.clone()))?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn setup_file_path(&self, path: &PathBuf) -> PathBuf {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() {
|
||||
|
@ -42,11 +42,21 @@ impl ProvingKeyFile {
|
||||
let mut file = File::create(&path)?;
|
||||
file.write_all(proving_key)?;
|
||||
|
||||
log::info!("Proving key stored to {:?}", path);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Removes the proving key at the given path if it exists. Returns `true` on success,
|
||||
/// `false` if the file doesn't exist, and `Error` if the file system fails during operation.
|
||||
pub fn remove(&self, path: &PathBuf) -> Result<bool, ProvingKeyFileError> {
|
||||
let path = self.setup_file_path(path);
|
||||
if !path.exists() {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
fs::remove_file(&path).map_err(|_| ProvingKeyFileError::FileRemovalError(path.clone()))?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn setup_file_path(&self, path: &PathBuf) -> PathBuf {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() {
|
||||
|
@ -42,11 +42,21 @@ impl VerificationKeyFile {
|
||||
let mut file = File::create(&path)?;
|
||||
file.write_all(verification_key)?;
|
||||
|
||||
log::info!("Verification key stored to {:?}", path);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Removes the verification key at the given path if it exists. Returns `true` on success,
|
||||
/// `false` if the file doesn't exist, and `Error` if the file system fails during operation.
|
||||
pub fn remove(&self, path: &PathBuf) -> Result<bool, VerificationKeyFileError> {
|
||||
let path = self.setup_file_path(path);
|
||||
if !path.exists() {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
fs::remove_file(&path).map_err(|_| VerificationKeyFileError::FileRemovalError(path.clone()))?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn setup_file_path(&self, path: &PathBuf) -> PathBuf {
|
||||
let mut path = path.to_owned();
|
||||
if path.is_dir() {
|
||||
|
@ -3,33 +3,18 @@ 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(),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn colored_string(level: log::Level, message: &str) -> colored::ColoredString {
|
||||
match level {
|
||||
log::Level::Error => message.bold().red(),
|
||||
log::Level::Warn => message.bold().yellow(),
|
||||
log::Level::Info => message.bold().blue(),
|
||||
log::Level::Info => message.bold().cyan(),
|
||||
log::Level::Debug => message.bold().magenta(),
|
||||
log::Level::Trace => message.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 {
|
||||
@ -46,8 +31,7 @@ pub fn init_logger(app_name: &'static str, verbosity: usize) {
|
||||
|
||||
writeln!(
|
||||
buf,
|
||||
"{:>5}{:>5} {}",
|
||||
level_string(record.level()),
|
||||
"{:>5} {}",
|
||||
colored_string(record.level(), app_name),
|
||||
record.args().to_string().replace("\n", &padding)
|
||||
)
|
||||
|
63
leo/main.rs
63
leo/main.rs
@ -1,11 +1,9 @@
|
||||
use leo::{cli::*, commands::*, errors::CLIError, logger};
|
||||
use leo::{cli::*, commands::*, errors::CLIError};
|
||||
|
||||
use clap::{App, AppSettings};
|
||||
use clap::{App, AppSettings, Arg};
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn main() -> Result<(), CLIError> {
|
||||
logger::init_logger("leo", 1);
|
||||
|
||||
let arguments = App::new("leo")
|
||||
.version("v0.1.0")
|
||||
.about("Leo compiler and package manager")
|
||||
@ -16,46 +14,41 @@ fn main() -> Result<(), CLIError> {
|
||||
AppSettings::DisableVersion,
|
||||
AppSettings::SubcommandRequiredElseHelp,
|
||||
])
|
||||
.args(&[Arg::with_name("debug")
|
||||
.short("d")
|
||||
.long("debug")
|
||||
.help("Enables debugging mode")
|
||||
.global(true)])
|
||||
.subcommands(vec![
|
||||
NewCommand::new().display_order(0),
|
||||
InitCommand::new().display_order(1),
|
||||
BuildCommand::new().display_order(2),
|
||||
LoadCommand::new().display_order(3),
|
||||
UnloadCommand::new().display_order(4),
|
||||
SetupCommand::new().display_order(5),
|
||||
ProveCommand::new().display_order(6),
|
||||
RunCommand::new().display_order(7),
|
||||
PublishCommand::new().display_order(8),
|
||||
DeployCommand::new().display_order(9),
|
||||
TestCommand::new().display_order(10),
|
||||
TestCommand::new().display_order(3),
|
||||
LoadCommand::new().display_order(4),
|
||||
UnloadCommand::new().display_order(5),
|
||||
SetupCommand::new().display_order(6),
|
||||
ProveCommand::new().display_order(7),
|
||||
RunCommand::new().display_order(8),
|
||||
PublishCommand::new().display_order(9),
|
||||
DeployCommand::new().display_order(10),
|
||||
CleanCommand::new().display_order(11),
|
||||
])
|
||||
.set_term_width(0)
|
||||
.get_matches();
|
||||
|
||||
match arguments.subcommand() {
|
||||
("new", Some(arguments)) => NewCommand::output(NewCommand::parse(arguments)?),
|
||||
("init", Some(arguments)) => InitCommand::output(InitCommand::parse(arguments)?),
|
||||
("build", Some(arguments)) => {
|
||||
BuildCommand::output(BuildCommand::parse(arguments)?)?;
|
||||
Ok(())
|
||||
}
|
||||
("load", Some(arguments)) => LoadCommand::output(LoadCommand::parse(arguments)?),
|
||||
("unload", Some(arguments)) => UnloadCommand::output(UnloadCommand::parse(arguments)?),
|
||||
("setup", Some(arguments)) => {
|
||||
SetupCommand::output(SetupCommand::parse(arguments)?)?;
|
||||
Ok(())
|
||||
}
|
||||
("prove", Some(arguments)) => {
|
||||
ProveCommand::output(ProveCommand::parse(arguments)?)?;
|
||||
Ok(())
|
||||
}
|
||||
("run", Some(arguments)) => RunCommand::output(RunCommand::parse(arguments)?),
|
||||
("publish", Some(arguments)) => PublishCommand::output(PublishCommand::parse(arguments)?),
|
||||
("deploy", Some(arguments)) => DeployCommand::output(DeployCommand::parse(arguments)?),
|
||||
("test", Some(arguments)) => {
|
||||
TestCommand::output(TestCommand::parse(arguments)?)?;
|
||||
Ok(())
|
||||
}
|
||||
("new", Some(arguments)) => NewCommand::process(arguments),
|
||||
("init", Some(arguments)) => InitCommand::process(arguments),
|
||||
("build", Some(arguments)) => BuildCommand::process(arguments),
|
||||
("test", Some(arguments)) => TestCommand::process(arguments),
|
||||
("load", Some(arguments)) => LoadCommand::process(arguments),
|
||||
("unload", Some(arguments)) => UnloadCommand::process(arguments),
|
||||
("setup", Some(arguments)) => SetupCommand::process(arguments),
|
||||
("prove", Some(arguments)) => ProveCommand::process(arguments),
|
||||
("run", Some(arguments)) => RunCommand::process(arguments),
|
||||
("publish", Some(arguments)) => PublishCommand::process(arguments),
|
||||
("deploy", Some(arguments)) => DeployCommand::process(arguments),
|
||||
("clean", Some(arguments)) => CleanCommand::process(arguments),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user