1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
// Copyright (C) 2019-2023 Aleo Systems Inc.
// This file is part of the snarkVM library.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use super::*;
/// Runs an Aleo program function
#[derive(Debug, Parser)]
pub struct Run {
/// The function name.
function: Identifier<CurrentNetwork>,
/// The function inputs.
inputs: Vec<Value<CurrentNetwork>>,
}
impl Run {
/// Compiles an Aleo program function with the specified name.
#[allow(clippy::format_in_format_args)]
pub fn parse(self) -> Result<String> {
// Derive the program directory path.
let path = std::env::current_dir()?;
// Load the package.
let package = Package::open(&path)?;
// Load the private key.
let private_key = crate::cli::helpers::dotenv_private_key()?;
// Initialize an RNG.
let rng = &mut rand::thread_rng();
// Execute the request.
let (response, metrics) = package.run::<Aleo, _>(&private_key, self.function, &self.inputs, rng)?;
// Count the number of times a function is called.
let mut program_frequency = HashMap::<String, usize>::new();
for metric in metrics.iter() {
// Prepare the function name string.
let function_name_string = format!("'{}/{}'", metric.program_id, metric.function_name).bold();
// Prepare the function constraints string
let function_constraints_string = format!(
"{function_name_string} - {} constraints",
metric.num_function_constraints.to_formatted_string(LOCALE)
);
// Increment the counter for the function call.
match program_frequency.get_mut(&function_constraints_string) {
Some(counter) => *counter += 1,
None => {
let _ = program_frequency.insert(function_constraints_string, 1);
}
}
}
// Log the metrics.
use num_format::ToFormattedString;
println!("⛓ Constraints\n");
for (function_constraints, counter) in program_frequency {
// Log the constraints
let counter_string = match counter {
1 => "(called 1 time)".to_string().dimmed(),
counter => format!("(called {counter} times)").dimmed(),
};
println!(" • {function_constraints} {counter_string}",)
}
// Log the outputs.
match response.outputs().len() {
0 => (),
1 => println!("\n➡️ Output\n"),
_ => println!("\n➡️ Outputs\n"),
};
for output in response.outputs() {
println!("{}", format!(" • {output}"));
}
println!();
// Prepare the locator.
let locator = Locator::<CurrentNetwork>::from_str(&format!("{}/{}", package.program_id(), self.function))?;
// Prepare the path string.
let path_string = format!("(in \"{}\")", path.display());
Ok(format!("✅ Finished '{}' {}", locator.to_string().bold(), path_string.dimmed()))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
cli::{Command, CLI},
prelude::{Identifier, Value},
};
#[test]
fn clap_snarkvm_run() {
let arg_vec = vec!["snarkvm", "run", "hello", "1u32", "2u32", "foo.aleo"];
let cli = CLI::parse_from(&arg_vec);
if let Command::Run(run) = cli.command {
assert_eq!(run.function, Identifier::try_from(arg_vec[2]).unwrap());
assert_eq!(run.inputs, vec![
Value::try_from(arg_vec[3]).unwrap(),
Value::try_from(arg_vec[4]).unwrap(),
Value::try_from(arg_vec[5]).unwrap()
]);
} else {
panic!("Unexpected result of clap parsing!");
}
}
}