Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 58 additions & 57 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ version = "0.10.9"
[workspace.dependencies.snarkvm]
#version = "4.2.0"
git = "http://github.com/ProvableHQ/snarkVM.git"
rev = "eb44d39" # testnet-v4.3.0
rev = "7009257" # staging
features = ["test_consensus_heights"]

[workspace.dependencies.tempfile]
Expand Down
41 changes: 19 additions & 22 deletions errors/src/common/formatted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,20 +214,19 @@ fn print_code_line(
)?;
}
// Multi-line highlight: only print underline on last line
else if multiline {
if let (Some(first), Some(last)) = (first_line, last_line) {
if line_num - first_line.unwrap() == last - first {
let underline_len = (end - start).max(1);
writeln!(
f,
"{INDENT} | {:start$}{} {}",
label.color.color_and_bold("|", use_colors), // vertical pointer
label.color.color_and_bold(&"_".repeat(underline_len), use_colors), // underline
label.color.color_and_bold(&label.msg, use_colors), // message
start = start
)?;
}
}
else if multiline
&& let (Some(first), Some(last)) = (first_line, last_line)
&& line_num - first_line.unwrap() == last - first
{
let underline_len = (end - start).max(1);
writeln!(
f,
"{INDENT} | {:start$}{} {}",
label.color.color_and_bold("|", use_colors), // vertical pointer
label.color.color_and_bold(&"_".repeat(underline_len), use_colors), // underline
label.color.color_and_bold(&label.msg, use_colors), // message
start = start
)?;
}

Ok(())
Expand Down Expand Up @@ -376,16 +375,14 @@ impl fmt::Display for Formatted {
}

// If this was a multi-line highlight, print the final underline + message
if multiline {
if let (Some(_), Some(last)) = (first_line, last_line) {
// Start column: first highlighted character on the last line
let start_col = line_spans[last].0;
if multiline && let (Some(_), Some(last)) = (first_line, last_line) {
// Start column: first highlighted character on the last line
let start_col = line_spans[last].0;

// End column: last highlighted character on the last line
let end_col = line_spans[last].1;
// End column: last highlighted character on the last line
let end_col = line_spans[last].1;

print_multiline_underline(f, start_col, end_col, &label)?;
}
print_multiline_underline(f, start_col, end_col, &label)?;
}

// Update the previous last line to track gaps for the next label
Expand Down
4 changes: 3 additions & 1 deletion leo/cli/commands/common/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ pub fn get_consensus_version(
Some(9) => Ok(ConsensusVersion::V9),
Some(10) => Ok(ConsensusVersion::V10),
Some(11) => Ok(ConsensusVersion::V11),
Some(12) => Ok(ConsensusVersion::V12),
// If none is provided, then attempt to query the current block height and use it to determine the version.
None => {
println!("Attempting to determine the consensus version from the latest block height at {endpoint}...");
Expand Down Expand Up @@ -309,6 +310,7 @@ pub fn number_to_consensus_version(index: usize) -> ConsensusVersion {
9 => ConsensusVersion::V9,
10 => ConsensusVersion::V10,
11 => ConsensusVersion::V11,
12 => ConsensusVersion::V12,
_ => panic!("Invalid consensus version: {index}"),
}
}
Expand Down Expand Up @@ -425,6 +427,6 @@ mod test {

#[test]
fn test_latest_consensus_version() {
assert_eq!(ConsensusVersion::latest(), ConsensusVersion::V11); // If this fails, update the test and any code that matches on `ConsensusVersion`.
assert_eq!(ConsensusVersion::latest(), ConsensusVersion::V12); // If this fails, update the test and any code that matches on `ConsensusVersion`.
}
}
125 changes: 123 additions & 2 deletions leo/cli/commands/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use leo_ast::NetworkName;
use leo_package::{Package, ProgramData, fetch_program_from_network};

use aleo_std::StorageMode;
use rand::CryptoRng;
#[cfg(not(feature = "only_testnet"))]
use snarkvm::prelude::{CanaryV0, MainnetV0};
use snarkvm::{
Expand All @@ -30,11 +31,17 @@ use snarkvm::{
Deployment,
Program,
ProgramID,
Rng,
TestnetV0,
VM,
cost_in_microcredits_v1,
cost_in_microcredits_v2,
cost_in_microcredits_v3,
deployment_cost,
execution_cost_for_authorization,
store::{ConsensusStore, helpers::memory::ConsensusMemory},
},
synthesizer::program::StackTrait,
};

use colored::*;
Expand Down Expand Up @@ -256,6 +263,8 @@ fn handle_deploy<N: Network>(
// Specify the query
let query = SnarkVMQuery::<N, BlockMemory<N>>::from(
endpoint
.replace("v1", "")
.replace("v2", "")
.parse::<Uri>()
.map_err(|e| CliError::custom(format!("Failed to parse endpoint URI '{endpoint}': {e}")))?,
);
Expand Down Expand Up @@ -289,13 +298,17 @@ Once it is deployed, it CANNOT be changed.
.map_err(|e| CliError::custom(format!("Failed to generate deployment transaction: {e}")))?;
// Get the deployment.
let deployment = transaction.deployment().expect("Expected a deployment in the transaction");
// Add the program to the VM before printing stats and validating limits.
// This is needed to invoke the correct program methods.
vm.process().write().add_program(&program)?;
// Print the deployment stats.
print_deployment_stats(&vm, &id.to_string(), deployment, priority_fee, consensus_version)?;
// Save the transaction.
transactions.push((id, transaction));
} else {
// Add the program to the VM directly.
vm.process().write().add_program(&program)?;
}
// Add the program to the VM.
vm.process().write().add_program(&program)?;
}

for (program_id, transaction) in transactions.iter() {
Expand Down Expand Up @@ -629,7 +642,115 @@ pub(crate) fn print_deployment_stats<N: Network>(
println!(" {:22}{}{:.6}", "Priority Fee:".cyan(), "".yellow(), prio_fee_cr);
println!(" {:22}{}{:.6}", "Total Fee:".cyan(), "".yellow(), total_fee_cr);

// --- Individual function costs ─────────────────────────────────────────────
for function_cost in calculate_function_costs(vm, deployment, consensus_version, &mut rand::thread_rng())? {
println!("\n{}", format!("🔍 Function '{}' Cost Breakdown", function_cost.name).bold());
println!(
" {:22}{}",
"Variables:".cyan(),
function_cost.num_variables.to_formatted_string(&Locale::en).yellow()
);
println!(
" {:22}{}",
"Constraints:".cyan(),
function_cost.num_constraints.to_formatted_string(&Locale::en).yellow()
);
if let Some(execution_cost) = function_cost.execution_cost {
println!(
" {:22}{}{:.6}",
"Total Execution Cost:".cyan(),
"".yellow(),
execution_cost as f64 / 1_000_000.0
);
println!(
" {:22}{}{:.6}",
"|- Finalize Cost:".cyan(),
"".yellow(),
function_cost.finalize_cost as f64 / 1_000_000.0
);
println!(
" {:22}{}{:.6}",
"|- Storage Cost:".cyan(),
"".yellow(),
(execution_cost - function_cost.finalize_cost) as f64 / 1_000_000.0
);
} else {
println!(" {:22}{}", "Total Execution Cost:".cyan(), "Undetermined".dimmed());
println!(
" {:22}{}{:.6}",
"|- Finalize Cost:".cyan(),
"".yellow(),
function_cost.finalize_cost as f64 / 1_000_000.0
);
}
}

// ── Footer rule ───────────────────────────────────────────────────────
println!("{}", "──────────────────────────────────────────────".dimmed());
Ok(())
}

pub(crate) struct FunctionCosts {
pub name: String,
pub num_variables: u64,
pub num_constraints: u64,
pub finalize_cost: u64,
pub execution_cost: Option<u64>,
}

/// Calculate individual function costs.
pub(crate) fn calculate_function_costs<N: Network, R: Rng + CryptoRng>(
vm: &VM<N, ConsensusMemory<N>>,
deployment: &Deployment<N>,
consensus_version: ConsensusVersion,
rng: &mut R,
) -> Result<Vec<FunctionCosts>> {
// Get the stack for the program.
let stack = vm.process().read().get_stack(deployment.program().id())?;

// Initialize the function costs.
let mut function_costs = Vec::new();

for (function_name, (key, _)) in deployment.verifying_keys() {
let name = function_name.to_string();

// Get the number of variables.
let num_variables = key.num_variables();
// Get the number of constraints.
let num_constraints = key.circuit_info.num_constraints as u64;
// Get the finalize cost.
let finalize_cost = if consensus_version >= ConsensusVersion::V10 {
cost_in_microcredits_v3(&stack, function_name)?
} else if consensus_version >= ConsensusVersion::V2 {
cost_in_microcredits_v2(&stack, function_name)?
} else {
cost_in_microcredits_v1(&stack, function_name)?
};

// Sample an authorization and attempt to get the execution cost.
// Note. `authorize` may fail on some functions, so this is a best-effort attempt.
let private_key = PrivateKey::new(rng)?;
let address = Address::try_from(&private_key)?;
let input_types = deployment.program().get_function(function_name)?.input_types();
let inputs = input_types
.into_iter()
.map(|ty| {
stack
.sample_value(&address, &ty.into(), rng)
.map_err(|e| CliError::custom(format!("Failed to sample value: {e}")).into())
})
.collect::<Result<Vec<_>>>()?;
let execution_cost =
match vm.authorize(&private_key, deployment.program().id(), function_name, inputs.iter(), rng) {
Err(_) => None,
Ok(authorization) => {
Some(execution_cost_for_authorization(&vm.process().read(), &authorization, consensus_version)?.0)
}
};

// Return the function cost.
function_costs.push(FunctionCosts { name, num_variables, num_constraints, finalize_cost, execution_cost });
}

Ok(function_costs)
}
2 changes: 2 additions & 0 deletions leo/cli/commands/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ fn handle_execute<A: Aleo>(
// Specify the query.
let query = SnarkVMQuery::<A::Network, BlockMemory<A::Network>>::from(
endpoint
.replace("v1", "")
.replace("v2", "")
.parse::<Uri>()
.map_err(|e| CliError::custom(format!("Failed to parse endpoint URI '{endpoint}': {e}")))?,
);
Expand Down
10 changes: 8 additions & 2 deletions leo/cli/commands/upgrade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,8 @@ fn handle_upgrade<N: Network>(
// Specify the query.
let query = SnarkVMQuery::<N, BlockMemory<N>>::from(
endpoint
.replace("v1", "")
.replace("v2", "")
.parse::<Uri>()
.map_err(|e| CliError::custom(format!("Failed to parse endpoint URI '{endpoint}': {e}")))?,
);
Expand All @@ -296,15 +298,19 @@ fn handle_upgrade<N: Network>(
.map_err(|e| CliError::custom(format!("Failed to generate deployment transaction: {e}")))?;
// Get the deployment.
let deployment = transaction.deployment().expect("Expected a deployment in the transaction");
// Add the program to the VM before printing stats and validating limits.
// This is needed to invoke the correct program methods.
vm.process().write().add_program(&program)?;
// Print the deployment stats.
print_deployment_stats(&vm, &id.to_string(), deployment, priority_fee, consensus_version)?;
// Validate the deployment limits.
validate_deployment_limits(deployment, &id, &network)?;
// Save the transaction.
transactions.push((id, transaction));
} else {
// Directly add the program to the VM.
vm.process().write().add_program(&program)?;
}
// Add the program to the VM.
vm.process().write().add_program(&program)?;
}

// If the `print` option is set, print the deployment transaction to the console.
Expand Down
8 changes: 4 additions & 4 deletions tests/expectations/execution/array_of_optionals.out
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ warnings:
{
"transitions": [
{
"id": "au1shvprqelfulztvj6nu93wtsct889nydtjsyx83u6jycfxdvyavpslkt77s",
"id": "au1qm0edyl2ur5qkcvu9zdaf29fe8yqzpeggqcd9p6286xt4fu36cysfy3jxa",
"program": "test.aleo",
"function": "main",
"inputs": [],
"outputs": [],
"tpk": "8127437964174420753776014445241514262944089371814894523276400046876569529123group",
"tcm": "6937436789184964112497960141706902359272983420587345267067261189483875442560field",
"scm": "7589774827963503497792246887384001964125015972546989106273956620737268256834field"
"tpk": "1647326534570190869526511692036029835793485304762551878523730212444022003462group",
"tcm": "8361131198643110274357598539107535843638807303278926921741138461546277258380field",
"scm": "6315535954879828455724059116063075109428767135722148385521563079514769136604field"
}
],
"global_state_root": "sr1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gk0xu"
Expand Down
Loading