Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] Select fee based on consensus height #28473

Open
wants to merge 3 commits into
base: mainnet
Choose a base branch
from
Open
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
49 changes: 30 additions & 19 deletions leo/cli/commands/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,19 +160,24 @@ fn handle_deploy<A: Aleo<Network = N, BaseField = N::Field>, N: Network>(
// Initialize the VM.
let vm = VM::from(store)?;

// Compute the minimum deployment cost.
let (mut total_cost, (storage_cost, synthesis_cost, namespace_cost)) = deployment_cost(&deployment)?;

// Display the deployment cost breakdown using `credit` denomination.
total_cost += command.fee_options.priority_fee;
deploy_cost_breakdown(
name,
total_cost as f64 / 1_000_000.0,
storage_cost as f64 / 1_000_000.0,
synthesis_cost as f64 / 1_000_000.0,
namespace_cost as f64 / 1_000_000.0,
command.fee_options.priority_fee as f64 / 1_000_000.0,
)?;
let base_fee = match command.fee_options.base_fee {
Some(base_fee) => base_fee,
None => {
// Compute the minimum deployment cost.
let (base_fee, (storage_cost, synthesis_cost, namespace_cost)) = deployment_cost(&deployment)?;

// Display the deployment cost breakdown using `credit` denomination.
deploy_cost_breakdown(
name,
base_fee as f64 / 1_000_000.0,
storage_cost as f64 / 1_000_000.0,
synthesis_cost as f64 / 1_000_000.0,
namespace_cost as f64 / 1_000_000.0,
command.fee_options.priority_fee as f64 / 1_000_000.0,
)?;
base_fee
}
};

// Initialize an RNG.
let rng = &mut rand::thread_rng();
Expand All @@ -184,7 +189,7 @@ fn handle_deploy<A: Aleo<Network = N, BaseField = N::Field>, N: Network>(
let fee_authorization = vm.authorize_fee_private(
&private_key,
fee_record,
total_cost,
base_fee,
command.fee_options.priority_fee,
deployment_id,
rng,
Expand All @@ -193,10 +198,16 @@ fn handle_deploy<A: Aleo<Network = N, BaseField = N::Field>, N: Network>(
}
None => {
// Make sure the user has enough public balance to pay for the deployment.
check_balance(&private_key, endpoint, &network.to_string(), context.clone(), total_cost)?;
check_balance(
&private_key,
endpoint,
&network.to_string(),
&context,
base_fee + command.fee_options.priority_fee,
)?;
let fee_authorization = vm.authorize_fee_public(
&private_key,
total_cost,
base_fee,
command.fee_options.priority_fee,
deployment_id,
rng,
Expand Down Expand Up @@ -247,21 +258,21 @@ fn handle_deploy<A: Aleo<Network = N, BaseField = N::Field>, N: Network>(
// A helper function to display a cost breakdown of the deployment.
fn deploy_cost_breakdown(
name: &String,
total_cost: f64,
base_fee: f64,
storage_cost: f64,
synthesis_cost: f64,
namespace_cost: f64,
priority_fee: f64,
) -> Result<()> {
println!("\nBase deployment cost for '{}' is {} credits.\n", name.bold(), total_cost);
println!("\nBase deployment cost for '{}' is {} credits.\n", name.bold(), base_fee);
// Display the cost breakdown in a table.
let data = [
[name, "Cost (credits)"],
["Transaction Storage", &format!("{:.6}", storage_cost)],
["Program Synthesis", &format!("{:.6}", synthesis_cost)],
["Namespace", &format!("{:.6}", namespace_cost)],
["Priority Fee", &format!("{:.6}", priority_fee)],
["Total", &format!("{:.6}", total_cost)],
["Total", &format!("{:.6}", base_fee + priority_fee)],
];
let mut out = Vec::new();
text_tables::render(&mut out, data).map_err(CliError::table_render_failed)?;
Expand Down
77 changes: 57 additions & 20 deletions leo/cli/commands/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ use snarkvm::{
VM,
Value,
execution_cost_v1,
execution_cost_v2,
query::Query as SnarkVMQuery,
store::{
ConsensusStore,
Expand Down Expand Up @@ -211,27 +212,63 @@ fn handle_execute<A: Aleo>(
)?;

// Check the transaction cost.
let (mut total_cost, (storage_cost, finalize_cost)) = if let ExecuteTransaction(_, execution, _) = &transaction
{
// TODO: Update to V2 after block migration.
execution_cost_v1(&vm.process().read(), execution)?
} else {
panic!("All transactions should be of type Execute.")
let base_fee = match command.fee_options.base_fee {
Some(base_fee) => base_fee,
None => {
let (base_fee, (storage_cost, finalize_cost)) =
if let ExecuteTransaction(_, execution, _) = &transaction {
// Attempt to get the height of the latest block to determine which version of the execution cost to use.
if let Ok(height) = get_latest_block_height(endpoint, &network.to_string(), &context) {
if height < A::Network::CONSENSUS_V2_HEIGHT {
execution_cost_v1(&vm.process().read(), execution)?
} else {
execution_cost_v2(&vm.process().read(), execution)?
}
}
// Otherwise, default to the one provided in `fee_options`.
else {
// Get the consensus version from the command.
let version = match command.fee_options.consensus_version {
Some(1) => 1,
None | Some(2) => 2,
Some(version) => {
panic!("Invalid consensus version: {version}. Please specify a valid version.")
}
};
// Print a warning message.
println!("Failed to get the latest block height. Defaulting to V{version}.",);
// Use the provided version.
match version {
1 => execution_cost_v1(&vm.process().read(), execution)?,
2 => execution_cost_v2(&vm.process().read(), execution)?,
_ => unreachable!(),
}
}
} else {
panic!("All transactions should be of type Execute.")
};

// Print the cost breakdown.
execution_cost_breakdown(
&program_name,
base_fee as f64 / 1_000_000.0,
storage_cost as f64 / 1_000_000.0,
finalize_cost as f64 / 1_000_000.0,
command.fee_options.priority_fee as f64 / 1_000_000.0,
)?;
base_fee
}
};

// Print the cost breakdown.
total_cost += command.fee_options.priority_fee;
execution_cost_breakdown(
&program_name,
total_cost as f64 / 1_000_000.0,
storage_cost as f64 / 1_000_000.0,
finalize_cost as f64 / 1_000_000.0,
command.fee_options.priority_fee as f64 / 1_000_000.0,
)?;

// Check if the public balance is sufficient.
if fee_record.is_none() {
check_balance::<A::Network>(&private_key, endpoint, &network.to_string(), context, total_cost)?;
check_balance::<A::Network>(
&private_key,
endpoint,
&network.to_string(),
&context,
base_fee + command.fee_options.priority_fee,
)?;
}

// Broadcast the execution transaction.
Expand Down Expand Up @@ -397,19 +434,19 @@ fn load_program_from_network<N: Network>(
// A helper function to display a cost breakdown of the execution.
fn execution_cost_breakdown(
name: &String,
total_cost: f64,
base_fee: f64,
storage_cost: f64,
finalize_cost: f64,
priority_fee: f64,
) -> Result<()> {
println!("\nBase execution cost for '{}' is {} credits.\n", name.bold(), total_cost);
println!("\nBase execution cost for '{}' is {} credits.\n", name.bold(), base_fee);
// Display the cost breakdown in a table.
let data = [
[name, "Cost (credits)"],
["Transaction Storage", &format!("{:.6}", storage_cost)],
["On-chain Execution", &format!("{:.6}", finalize_cost)],
["Priority Fee", &format!("{:.6}", priority_fee)],
["Total", &format!("{:.6}", total_cost)],
["Total", &format!("{:.6}", base_fee + priority_fee)],
];
let mut out = Vec::new();
text_tables::render(&mut out, data).map_err(CliError::table_render_failed)?;
Expand Down
32 changes: 30 additions & 2 deletions leo/cli/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ pub struct FeeOptions {
pub(crate) yes: bool,
#[clap(long, help = "Performs a dry-run of transaction generation")]
pub(crate) dry_run: bool,
#[clap(long, help = "Base fee in microcredits. Automatically calculated if not provided.")]
pub(crate) base_fee: Option<u64>,
#[clap(long, help = "Priority fee in microcredits. Defaults to 0.", default_value = "0")]
pub(crate) priority_fee: u64,
#[clap(long, help = "Private key to authorize fee expenditure.")]
Expand All @@ -220,6 +222,8 @@ pub struct FeeOptions {
long
)]
record: Option<String>,
#[clap(long, help = "Consensus version to use for the transaction.")]
pub(crate) consensus_version: Option<u8>,
}

/// Parses the record string. If the string is a ciphertext, then attempt to decrypt it. Lifted from snarkOS.
Expand All @@ -241,7 +245,7 @@ fn check_balance<N: Network>(
private_key: &PrivateKey<N>,
endpoint: &str,
network: &str,
context: Context,
context: &Context,
total_cost: u64,
) -> Result<()> {
// Derive the account address.
Expand All @@ -251,7 +255,7 @@ fn check_balance<N: Network>(
endpoint: Some(endpoint.to_string()),
network: Some(network.to_string()),
command: QueryCommands::Program {
command: crate::cli::commands::query::LeoProgram {
command: query::LeoProgram {
name: "credits".to_string(),
mappings: false,
mapping_value: Some(vec!["account".to_string(), address.to_string()]),
Expand All @@ -276,6 +280,30 @@ fn check_balance<N: Network>(
}
}

// A helper function to query for the latest block height.
fn get_latest_block_height(endpoint: &str, network: &str, context: &Context) -> Result<u32> {
// Query the latest block height.
let height = LeoQuery {
endpoint: Some(endpoint.to_string()),
network: Some(network.to_string()),
command: QueryCommands::Block {
command: query::LeoBlock {
id: None,
latest: false,
latest_hash: false,
latest_height: true,
range: None,
transactions: false,
to_height: false,
},
},
}
.execute(Context::new(context.path.clone(), context.home.clone(), true)?)?;
// Parse the height.
let height = height.parse::<u32>().map_err(CliError::string_parse_error)?;
Ok(height)
}

/// Determine if the transaction should be broadcast or displayed to user.
fn handle_broadcast<N: Network>(endpoint: &String, transaction: Transaction<N>, operation: &String) -> Result<()> {
println!("Broadcasting transaction to {}...\n", endpoint.clone());
Expand Down
24 changes: 12 additions & 12 deletions leo/cli/commands/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,26 @@
use super::*;
use snarkvm::prelude::{CanaryV0, MainnetV0, TestnetV0};

mod block;
use block::LeoBlock;
pub mod block;
pub use block::LeoBlock;

pub mod program;
pub use program::LeoProgram;

mod state_root;
use state_root::StateRoot;
pub mod state_root;
pub use state_root::StateRoot;

mod committee;
use committee::LeoCommittee;
pub mod committee;
pub use committee::LeoCommittee;

mod mempool;
use mempool::LeoMempool;
pub mod mempool;
pub use mempool::LeoMempool;

mod peers;
use peers::LeoPeers;
pub mod peers;
pub use peers::LeoPeers;

mod transaction;
use transaction::LeoTransaction;
pub mod transaction;
pub use transaction::LeoTransaction;

mod utils;
use utils::*;
Expand Down
Loading