Skip to content
Open
Show file tree
Hide file tree
Changes from 7 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
724 changes: 554 additions & 170 deletions Cargo.lock

Large diffs are not rendered by default.

76 changes: 69 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,31 @@ path = "./test-framework"
version = "=3.3.1"

[workspace.dependencies.aleo-std]
version = "1.0.1"
version = "1.0.3"

[workspace.dependencies.aleo-std-storage]
version = "1.0.3"
default-features = false

[workspace.dependencies.anyhow]
version = "1.0"

[workspace.dependencies.axum]
version = "0.8.0"

[workspace.dependencies.axum-extra]
version = "0.10"
features = ["erased-json", "typed-header"]

[workspace.dependencies.base62]
version = "2.2.1"

[workspace.dependencies.colored]
version = "2.0"

[workspace.dependencies.http]
version = "1"

[workspace.dependencies.indexmap]
version = "2.6"
features = [ "serde" ]
Expand All @@ -112,6 +125,12 @@ version = "0.13.0"
[workspace.dependencies.paste]
version = "1.0"

[workspace.dependencies.is-terminal]
version = "0.4"

[workspace.dependencies.parking_lot]
version = "0.12"

[workspace.dependencies.rand]
version = "0.8"
default-features = false
Expand All @@ -121,11 +140,14 @@ version = "0.3.0"
default-features = false

[workspace.dependencies.rayon]
version = "1.11.0"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, are we able to keep using the newer version of rayon rather than downgrading?

version = "0.8"

[workspace.dependencies.regex]
version = "1.11.1"

[workspace.dependencies.reqwest]
version = "0.12.23"

[workspace.dependencies.self_update]
version = "0.41.0"
features = [ "archive-zip", "compression-zip-deflate" ]
Expand All @@ -146,15 +168,29 @@ version = "0.10.9"

[workspace.dependencies.snarkvm]
git = "https://github.com/ProvableHQ/snarkVM.git"
tag = "v4.4.0"
features = [ "test_consensus_heights" ]
rev = "7787e6e"
features = ["dev_skip_checks", "test_consensus_heights", "test_targets"]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to me that this will always disable checks in the devnode.

Can we enable dev_skip_checks only if the Leo build feature flag devnode_skip_checks is enabled, so developers can also use the devnode with checks enabled?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And maybe you can also write some comments giving context to future developers:
// We set test_consensus_heights to give developers freedom to set custom consensus version upgrade heights.
// We set test_targets because the devnode's genesis block was created with the same feature flag


[workspace.dependencies.tempfile]
version = "3.13"

[workspace.dependencies.tokio]
version = "1"
features = ["full"]

[workspace.dependencies.tower-http]
version = "0.6.0"

[workspace.dependencies.tower_governor]
version = "0.7"

[workspace.dependencies.tracing]
version = "0.1"

[workspace.dependencies.tracing-subscriber]
version = "0.3"
features = ["env-filter", "fmt"]

[workspace.dependencies.ureq]
version = "3.0.12"

Expand Down Expand Up @@ -208,6 +244,15 @@ workspace = true
[dependencies.aleo-std]
workspace = true

[dependencies.aleo-std-storage]
workspace = true

[dependencies.axum]
workspace = true

[dependencies.axum-extra]
workspace = true

[dependencies.backtrace]
version = "0.3.74"

Expand Down Expand Up @@ -242,6 +287,9 @@ version = "1.0.5"
[dependencies.indexmap]
workspace = true

[dependencies.is-terminal]
version = "0.4"

[dependencies.itertools]
workspace = true

Expand All @@ -266,6 +314,9 @@ workspace = true
[dependencies.regex]
workspace = true

[dependencies.reqwest]
workspace = true

[dependencies.rpassword]
version = "7.4.0"

Expand All @@ -286,20 +337,31 @@ workspace = true

[dependencies.snarkvm]
workspace = true
features = [ "circuit", "console" ]
features = ["circuit", "console"]

[dependencies.sys-info]
version = "0.9.1"

[dependencies.tempfile]
version = "3.20.0"

[dependencies.tokio]
workspace = true
features = ["full", "rt-multi-thread", "macros"]

[dependencies.tower-http]
workspace = true
features = ["cors", "trace"]

[dependencies.tower_governor]
workspace = true

[dependencies.tracing]
workspace = true

[dependencies.tracing-subscriber]
version = "0.3.18"
features = [ "fmt" ]
version = "0.3.0"
features = ["env-filter","fmt"]

[dependencies.ureq]
workspace = true
Expand Down
11 changes: 10 additions & 1 deletion leo/cli/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ enum Commands {
#[clap(flatten)]
command: LeoDevnet,
},
#[clap(about = "Run a local devnode")]
Devnode {
#[clap(flatten)]
command: LeoDevnode,
},
#[clap(about = "Query live data from the Aleo network")]
Query {
#[clap(flatten)]
Expand Down Expand Up @@ -148,7 +153,10 @@ pub fn run_with_args(cli: CLI) -> Result<()> {
// Initialize the `.env` file.
dotenvy::dotenv().ok();

if !cli.quiet {
// Skip logger initialization for devnode -- it uses it's own logger.
let is_devnode = matches!(&cli.command, Commands::Devnode { .. });

if !cli.quiet && !is_devnode {
// Init logger with optional debug flag.
logger::init_logger("leo", match cli.debug {
false => 1,
Expand All @@ -175,6 +183,7 @@ pub fn run_with_args(cli: CLI) -> Result<()> {
Commands::Clean { command } => command.try_execute(context),
Commands::Deploy { command } => command.try_execute(context),
Commands::Devnet { command } => command.try_execute(context),
Commands::Devnode { command } => command.try_execute(context),
Commands::Run { command } => command.try_execute(context),
Commands::Test { command } => command.try_execute(context),
Commands::Execute { command } => command.try_execute(context),
Expand Down
125 changes: 104 additions & 21 deletions leo/cli/commands/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,22 @@ use aleo_std::StorageMode;
#[cfg(not(feature = "only_testnet"))]
use snarkvm::prelude::{CanaryV0, MainnetV0};
use snarkvm::{
ledger::{query::Query as SnarkVMQuery, store::helpers::memory::BlockMemory},
circuit::{Aleo, AleoTestnetV0},
ledger::{
query::{Query as SnarkVMQuery, QueryTrait},
store::helpers::memory::BlockMemory,
},
prelude::{
Certificate,
ConsensusVersion,
Deployment,
Fee,
Program,
ProgramID,
ProgramOwner,
TestnetV0,
VM,
VerifyingKey,
deployment_cost,
store::{ConsensusStore, helpers::memory::ConsensusMemory},
},
Expand All @@ -56,6 +64,8 @@ pub struct LeoDeploy {
pub(crate) skip: Vec<String>,
#[clap(flatten)]
pub(crate) build_options: BuildOptions,
#[clap(long, help = "Use placeholder certificate and verifying keys during deployment.", default_value = "false")]
pub(crate) skip_deploy_certificate: bool,
}

pub struct Task<N: Network> {
Expand Down Expand Up @@ -92,25 +102,25 @@ impl Command for LeoDeploy {
let network = get_network(&self.env_override.network)?;
// Handle each network with the appropriate parameterization.
match network {
NetworkName::TestnetV0 => handle_deploy::<TestnetV0>(&self, context, network, input),
NetworkName::TestnetV0 => handle_deploy::<TestnetV0, AleoTestnetV0>(&self, context, network, input),
NetworkName::MainnetV0 => {
#[cfg(feature = "only_testnet")]
panic!("Mainnet chosen with only_testnet feature");
#[cfg(not(feature = "only_testnet"))]
handle_deploy::<MainnetV0>(&self, context, network, input)
handle_deploy::<MainnetV0, snarkvm::circuit::AleoV0>(&self, context, network, input)
}
NetworkName::CanaryV0 => {
#[cfg(feature = "only_testnet")]
panic!("Canary chosen with only_testnet feature");
#[cfg(not(feature = "only_testnet"))]
handle_deploy::<CanaryV0>(&self, context, network, input)
handle_deploy::<CanaryV0, snarkvm::circuit::AleoCanaryV0>(&self, context, network, input)
}
}
}
}

// A helper function to handle deployment logic.
fn handle_deploy<N: Network>(
fn handle_deploy<N: Network, A: Aleo<Network = N>>(
command: &LeoDeploy,
context: Context,
network: NetworkName,
Expand Down Expand Up @@ -266,7 +276,7 @@ fn handle_deploy<N: Network>(

// For each of the programs, generate a deployment transaction.
let mut transactions = Vec::new();
for Task { id, program, priority_fee, record, .. } in local {
for Task { id, program, edition, priority_fee, record, .. } in local {
// If the program is a local dependency that is not skipped, generate a deployment transaction.
if !skipped.contains(&id) {
// If the program contains an upgrade config, confirm with the user that they want to proceed.
Expand All @@ -287,27 +297,100 @@ Once it is deployed, it CANNOT be changed.
}
}
println!("📦 Creating deployment transaction for '{}'...\n", id.to_string().bold());
// Generate the transaction.
let transaction =
vm.deploy(&private_key, &program, record, priority_fee.unwrap_or(0), Some(&query), rng)
if command.skip_deploy_certificate {
println!("⚠️ Skipping deployment certificate and verifier key generation as per user request.\n");
assert!(!program.functions().is_empty(), "Program `{}` has no functions", program.id());
// Initialize a vector for the placeholder verifying keys and certificates.
let mut verifying_keys = Vec::with_capacity(program.functions().len());
for function_name in program.functions().keys() {
let (verifying_key, certificate) = {
// Use a placeholder verifying key.
let verifying_key = VerifyingKey::from_str(
"verifier1qygqqqqqqqqqqqyvxgqqqqqqqqq87vsqqqqqqqqqhe7sqqqqqqqqqma4qqqqqqqqqq65yqqqqqqqqqqvqqqqqqqqqqqgtlaj49fmrk2d8slmselaj9tpucgxv6awu6yu4pfcn5xa0yy0tpxpc8wemasjvvxr9248vt3509vpk3u60ejyfd9xtvjmudpp7ljq2csk4yqz70ug3x8xp3xn3ul0yrrw0mvd2g8ju7rts50u3smue03gp99j88f0ky8h6fjlpvh58rmxv53mldmgrxa3fq6spsh8gt5whvsyu2rk4a2wmeyrgvvdf29pwp02srktxnvht3k6ff094usjtllggva2ym75xc4lzuqu9xx8ylfkm3qc7lf7ktk9uu9du5raukh828dzgq26hrarq5ajjl7pz7zk924kekjrp92r6jh9dpp05mxtuffwlmvew84dvnqrkre7lw29mkdzgdxwe7q8z0vnkv2vwwdraekw2va3plu7rkxhtnkuxvce0qkgxcxn5mtg9q2c3vxdf2r7jjse2g68dgvyh85q4mzfnvn07lletrpty3vypus00gfu9m47rzay4mh5w9f03z9zgzgzhkv0mupdqsk8naljqm9tc2qqzhf6yp3mnv2ey89xk7sw9pslzzlkndfd2upzmew4e4vnrkr556kexs9qrykkuhsr260mnrgh7uv0sp2meky0keeukaxgjdsnmy77kl48g3swcvqdjm50ejzr7x04vy7hn7anhd0xeetclxunnl7pd6e52qxdlr3nmutz4zr8f2xqa57a2zkl59a28w842cj4783zpy9hxw03k6vz4a3uu7sm072uqknpxjk8fyq4vxtqd08kd93c2mt40lj9ag35nm4rwcfjayejk57m9qqu83qnkrj3sz90pw808srmf705n2yu6gvqazpvu2mwm8x6mgtlsntxfhr0qas43rqxnccft36z4ygty86390t7vrt08derz8368z8ekn3yywxgp4uq24gm6e58tpp0lcvtpsm3nkwpnmzztx4qvkaf6vk38wg787h8mfpqqqqqqqqqqt49m8x",
)?;
// Use a placeholder certificate.
let certificate = Certificate::from_str(
"certificate1qyqsqqqqqqqqqqxvwszp09v860w62s2l4g6eqf0kzppyax5we36957ywqm2dplzwvvlqg0kwlnmhzfatnax7uaqt7yqqqw0sc4u",
)?;

(verifying_key, certificate)
};
verifying_keys.push((*function_name, (verifying_key, certificate)));
}
// Create the deployment.
let mut deployment =
Deployment::new(edition.unwrap_or(0), program.clone(), verifying_keys, None, None).unwrap();

// Set the program owner.
deployment.set_program_owner_raw(Some(Address::try_from(&private_key)?));

// Compute the checksum of the deployment.
deployment.set_program_checksum_raw(Some(deployment.program().to_checksum()));

// Compute the deployment ID.
let deployment_id = deployment.to_deployment_id()?;

// Construct the owner.
let owner = ProgramOwner::new(&private_key, deployment_id, rng)?;

// Construct the fee authorization.
let (minimum_deployment_cost, _) =
deployment_cost(&vm.process().read(), &deployment, consensus_version)?;
// Authorize the fee.
let fee_authorization = match record {
Some(record) => vm.process().read().authorize_fee_private::<A, _>(
&private_key,
record,
minimum_deployment_cost,
priority_fee.unwrap_or(0),
deployment_id,
rng,
)?,
None => vm.process().read().authorize_fee_public::<A, _>(
&private_key,
minimum_deployment_cost,
priority_fee.unwrap_or(0),
deployment_id,
rng,
)?,
};

// Get the state root.
let state_root = query.current_state_root()?;

// Create a fee transition without a proof.
let fee = Fee::from(fee_authorization.transitions().into_iter().next().unwrap().1, state_root, None)?;

// Create the transaction.
let transaction = Transaction::from_deployment(owner, deployment, fee)?;
// Add the transaction to the transactions vector.
transactions.push((id, transaction));
} else {
// Generate the transaction.
let transaction = vm
.deploy(&private_key, &program, record, priority_fee.unwrap_or(0), Some(&query), rng)
.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");
// Print the deployment stats.
print_deployment_stats(&vm, &id.to_string(), deployment, priority_fee, consensus_version)?;
// Save the transaction.
transactions.push((id, transaction));
// Get the deployment.
let deployment = transaction.deployment().expect("Expected a deployment in the transaction");
// Print the deployment stats.
print_deployment_stats(&vm, &id.to_string(), deployment, priority_fee, consensus_version)?;
// Save the transaction.
transactions.push((id, transaction));
}

if !command.skip_deploy_certificate {
for (program_id, transaction) in transactions.iter() {
// Validate the deployment limits.
let deployment = transaction.deployment().expect("Expected a deployment in the transaction");
validate_deployment_limits(deployment, program_id, &network)?;
}
}
}

// Add the program to the VM.
vm.process().write().add_program(&program)?;
}

for (program_id, transaction) in transactions.iter() {
// Validate the deployment limits.
let deployment = transaction.deployment().expect("Expected a deployment in the transaction");
validate_deployment_limits(deployment, program_id, &network)?;
}

// If the `print` option is set, print the deployment transaction to the console.
// The transaction is printed in JSON format.
if command.action.print {
Expand Down
Loading