diff --git a/leo/cli/commands/build.rs b/leo/cli/commands/build.rs index c356836fc4..3b8440b164 100644 --- a/leo/cli/commands/build.rs +++ b/leo/cli/commands/build.rs @@ -211,6 +211,8 @@ fn compile_leo_source_directory( stubs: IndexMap, network: NetworkName, ) -> Result { + tracing::info!("🔨 Compiling '{program_name}.leo'"); + // Create a new instance of the Leo compiler. let mut compiler = Compiler::new( Some(program_name.to_string()), @@ -253,7 +255,6 @@ fn compile_leo_source_directory( if let Some(msg) = warning { tracing::warn!("⚠️ Program '{program_name}' is {msg}."); } - - tracing::info!("✅ Compiled '{program_name}.aleo' into Aleo instructions."); + tracing::info!("✅ Compiled '{program_name}.aleo' into Aleo instructions.\n"); Ok(bytecode) } diff --git a/leo/cli/commands/common/interactive.rs b/leo/cli/commands/common/interactive.rs index fa16365379..a4243bba17 100644 --- a/leo/cli/commands/common/interactive.rs +++ b/leo/cli/commands/common/interactive.rs @@ -35,6 +35,28 @@ pub fn confirm(prompt: &str, skip_confirmation: bool) -> Result { result } +/// Logs a warning and asks the user to confirm an action, with an optional `--yes` override. +/// Unlike `confirm`, this function always logs the warning message regardless of `skip_confirmation`. +pub fn warn_and_confirm(warning: &str, skip_confirmation: bool) -> Result { + // Always log the warning so users are informed of issues even in non-interactive mode. + tracing::warn!("{warning}"); + + if skip_confirmation { + return Ok(true); + } + + let result = Confirm::with_theme(&ColorfulTheme::default()) + .with_prompt("Do you want to continue?") + .default(false) + .interact() + .map_err(|e| CliError::custom(format!("Failed to prompt user: {e}")).into()); + + // Print a newline for better formatting. + println!(); + + result +} + /// Asks the user to confirm a fee. pub fn confirm_fee( fee: &snarkvm::prelude::Fee, diff --git a/leo/cli/commands/upgrade.rs b/leo/cli/commands/upgrade.rs index ba3345b216..0a096c5b84 100644 --- a/leo/cli/commands/upgrade.rs +++ b/leo/cli/commands/upgrade.rs @@ -54,7 +54,7 @@ pub struct LeoUpgrade { pub(crate) env_override: EnvOptions, #[clap(flatten)] pub(crate) extra: ExtraOptions, - #[clap(long, help = "Skips the upgrade of any program that contains one of the given substrings.")] + #[clap(long, help = "Skips the upgrade of any program that contains one of the given substrings.", value_delimiter = ',', num_args = 1..)] pub(crate) skip: Vec, #[clap(flatten)] pub(crate) build_options: BuildOptions, @@ -251,34 +251,35 @@ fn handle_upgrade( let vm = VM::from(ConsensusStore::>::open(StorageMode::Production)?)?; // Load all the programs from the network into the VM. - let programs_and_editions = program_ids - .iter() - .map(|id| { - // Load the program from the network. - let program = leo_package::Program::fetch( - Symbol::intern(&id.name().to_string()), - None, - context.home()?, - network, - &endpoint, - true, - )?; - let ProgramData::Bytecode(bytecode) = program.data else { - panic!("Expected bytecode when fetching a remote program"); - }; - // Parse the program bytecode. - let bytecode = Program::::from_str(&bytecode) - .map_err(|e| CliError::custom(format!("Failed to parse program: {e}")))?; - // Return the bytecode and edition. - // Program::fetch should always set the edition after a successful fetch. - let edition = program.edition.expect("Edition should be set after successful fetch"); - Ok((bytecode, edition)) - }) - .collect::>>()?; - + let mut programs_and_editions = Vec::with_capacity(program_ids.len()); + for id in &program_ids { + // Load the program from the network. + let Ok(program) = leo_package::Program::fetch( + Symbol::intern(&id.name().to_string()), + None, + context.home()?, + network, + &endpoint, + true, + ) else { + warn_and_confirm(&format!("Failed to fetch program {id} from the network."), command.extra.yes)?; + continue; + }; + + let ProgramData::Bytecode(bytecode) = program.data else { + panic!("Expected bytecode when fetching a remote program"); + }; + // Parse the program bytecode. + let bytecode = + Program::::from_str(&bytecode).map_err(|e| CliError::custom(format!("Failed to parse program: {e}")))?; + // Append the bytecode and edition. + // Program::fetch should always set the edition after a successful fetch. + let edition = program.edition.expect("Edition should be set after successful fetch"); + programs_and_editions.push((bytecode, edition)); + } // Check for programs that violate edition/constructor requirements. check_edition_constructor_requirements(&programs_and_editions, consensus_version, "upgrade")?; - + // Add the programs to the VM. vm.process().write().add_programs_with_editions(&programs_and_editions)?; // Print the programs and their editions in the VM. @@ -334,7 +335,9 @@ fn handle_upgrade( all_stats.push(stats); } // Add the program to the VM. - vm.process().write().add_program(&program)?; + if let Err(e) = vm.process().write().add_program(&program) { + warn_and_confirm(&format!("Failed to add program {id} to the VM. Error: {e}"), command.extra.yes)?; + } } // If the `print` option is set, print the deployment transaction to the console. diff --git a/tests/expectations/cli/network_dependency/STDOUT b/tests/expectations/cli/network_dependency/STDOUT index 03b01f19a9..01624b61f9 100644 --- a/tests/expectations/cli/network_dependency/STDOUT +++ b/tests/expectations/cli/network_dependency/STDOUT @@ -1,10 +1,12 @@ DEPLOYMENT 1 + Leo 🔨 Compiling 'test_program1.leo' Leo 1 statements before dead code elimination. Leo 1 statements after dead code elimination. Leo The program checksum is: '[192u8, 225u8, 38u8, 151u8, 139u8, 155u8, 148u8, 209u8, 105u8, 110u8, 246u8, 83u8, 90u8, 243u8, 78u8, 35u8, 155u8, 186u8, 242u8, 17u8, 196u8, 169u8, 179u8, 144u8, 71u8, 227u8, 34u8, 207u8, 121u8, 158u8, 34u8, 25u8]'. Leo Program size: 0.14 KB / 97.66 KB Leo ✅ Compiled 'test_program1.aleo' into Aleo instructions. + 📢 Using the following consensus heights: 0,1,2,3,4,5,6,7,8,9,10,11 To override, pass in `--consensus-heights` or override the environment variable `CONSENSUS_VERSION_HEIGHTS`. @@ -70,12 +72,14 @@ Explored XXXXXX blocks. Transaction accepted. ✅ Deployment confirmed! DEPLOYMENT 2 + Leo 🔨 Compiling 'test_program2.leo' Leo 3 statements before dead code elimination. Leo 3 statements after dead code elimination. Leo The program checksum is: '[206u8, 255u8, 111u8, 48u8, 59u8, 85u8, 122u8, 166u8, 182u8, 205u8, 10u8, 141u8, 58u8, 23u8, 70u8, 232u8, 105u8, 221u8, 83u8, 216u8, 186u8, 14u8, 207u8, 24u8, 13u8, 221u8, 236u8, 0u8, 143u8, 199u8, 151u8, 2u8]'. Leo Program size: 0.19 KB / 97.66 KB Leo ✅ Compiled 'test_program2.aleo' into Aleo instructions. + 📢 Using the following consensus heights: 0,1,2,3,4,5,6,7,8,9,10,11 To override, pass in `--consensus-heights` or override the environment variable `CONSENSUS_VERSION_HEIGHTS`. @@ -145,12 +149,14 @@ Explored XXXXXX blocks. Transaction accepted. ✅ Deployment confirmed! EXECUTION + Leo 🔨 Compiling 'test_program2.leo' Leo 3 statements before dead code elimination. Leo 3 statements after dead code elimination. Leo The program checksum is: '[206u8, 255u8, 111u8, 48u8, 59u8, 85u8, 122u8, 166u8, 182u8, 205u8, 10u8, 141u8, 58u8, 23u8, 70u8, 232u8, 105u8, 221u8, 83u8, 216u8, 186u8, 14u8, 207u8, 24u8, 13u8, 221u8, 236u8, 0u8, 143u8, 199u8, 151u8, 2u8]'. Leo Program size: 0.19 KB / 97.66 KB Leo ✅ Compiled 'test_program2.aleo' into Aleo instructions. + 📢 Using the following consensus heights: 0,1,2,3,4,5,6,7,8,9,10,11 To override, pass in `--consensus-heights` or override the environment variable `CONSENSUS_VERSION_HEIGHTS`. diff --git a/tests/expectations/cli/program_name_mismatch/STDOUT b/tests/expectations/cli/program_name_mismatch/STDOUT index 84f934ab1c..75093bc611 100644 --- a/tests/expectations/cli/program_name_mismatch/STDOUT +++ b/tests/expectations/cli/program_name_mismatch/STDOUT @@ -1,2 +1,3 @@ ⚠️ No network specified, defaulting to 'testnet'. ⚠️ No endpoint specified, defaulting to 'https://api.explorer.provable.com/v1'. + Leo 🔨 Compiling 'foo.leo' diff --git a/tests/expectations/cli/test_add/STDOUT b/tests/expectations/cli/test_add/STDOUT index b41f764382..04ddb8edd6 100644 --- a/tests/expectations/cli/test_add/STDOUT +++ b/tests/expectations/cli/test_add/STDOUT @@ -1,17 +1,21 @@ Leo ✅ Added network dependency `credits.aleo` from network `true`. ⚠️ No network specified, defaulting to 'testnet'. ⚠️ No endpoint specified, defaulting to 'https://api.explorer.provable.com/v1'. + Leo 🔨 Compiling 'some_sample_leo_program.leo' Leo 2 statements before dead code elimination. Leo 2 statements after dead code elimination. Leo The program checksum is: '[208u8, 46u8, 107u8, 120u8, 67u8, 35u8, 254u8, 232u8, 167u8, 173u8, 0u8, 130u8, 249u8, 123u8, 65u8, 159u8, 169u8, 93u8, 168u8, 232u8, 33u8, 125u8, 49u8, 130u8, 118u8, 142u8, 183u8, 31u8, 60u8, 106u8, 136u8, 65u8]'. Leo Program size: 0.18 KB / 97.66 KB Leo ✅ Compiled 'some_sample_leo_program.aleo' into Aleo instructions. + + Leo 🔨 Compiling 'some_sample_leo_program.leo' Leo 2 statements before dead code elimination. Leo 2 statements after dead code elimination. Leo The program checksum is: '[208u8, 46u8, 107u8, 120u8, 67u8, 35u8, 254u8, 232u8, 167u8, 173u8, 0u8, 130u8, 249u8, 123u8, 65u8, 159u8, 169u8, 93u8, 168u8, 232u8, 33u8, 125u8, 49u8, 130u8, 118u8, 142u8, 183u8, 31u8, 60u8, 106u8, 136u8, 65u8]'. Leo Program size: 0.18 KB / 97.66 KB Leo ✅ Compiled 'some_sample_leo_program.aleo' into Aleo instructions. + 📢 Using the following consensus heights: 0,2950000,4800000,6625000,6765000,7600000,8365000,9173000,9800000,10525000,11952000,12669000 To override, pass in `--consensus-heights` or override the environment variable `CONSENSUS_VERSION_HEIGHTS`. @@ -63,12 +67,14 @@ Attempting to determine the consensus version from the latest block height at ht • 3u32 + Leo 🔨 Compiling 'some_sample_leo_program.leo' Leo 2 statements before dead code elimination. Leo 2 statements after dead code elimination. Leo The program checksum is: '[208u8, 46u8, 107u8, 120u8, 67u8, 35u8, 254u8, 232u8, 167u8, 173u8, 0u8, 130u8, 249u8, 123u8, 65u8, 159u8, 169u8, 93u8, 168u8, 232u8, 33u8, 125u8, 49u8, 130u8, 118u8, 142u8, 183u8, 31u8, 60u8, 106u8, 136u8, 65u8]'. Leo Program size: 0.18 KB / 97.66 KB Leo ✅ Compiled 'some_sample_leo_program.aleo' into Aleo instructions. + 📢 Using the following consensus heights: 0,2950000,4800000,6625000,6765000,7600000,8365000,9173000,9800000,10525000,11952000,12669000 To override, pass in `--consensus-heights` or override the environment variable `CONSENSUS_VERSION_HEIGHTS`. diff --git a/tests/expectations/cli/test_command_shortcuts/STDOUT b/tests/expectations/cli/test_command_shortcuts/STDOUT index bc06633e69..6ce62fd9c5 100644 --- a/tests/expectations/cli/test_command_shortcuts/STDOUT +++ b/tests/expectations/cli/test_command_shortcuts/STDOUT @@ -1,17 +1,21 @@ ⚠️ No network specified, defaulting to 'testnet'. ⚠️ No endpoint specified, defaulting to 'https://api.explorer.provable.com/v1'. + Leo 🔨 Compiling 'test_shortcuts.leo' Leo 2 statements before dead code elimination. Leo 2 statements after dead code elimination. Leo The program checksum is: '[243u8, 135u8, 116u8, 66u8, 246u8, 27u8, 131u8, 192u8, 145u8, 195u8, 150u8, 1u8, 217u8, 146u8, 63u8, 42u8, 159u8, 224u8, 25u8, 105u8, 240u8, 197u8, 236u8, 236u8, 115u8, 219u8, 254u8, 62u8, 5u8, 44u8, 74u8, 93u8]'. Leo Program size: 0.19 KB / 97.66 KB Leo ✅ Compiled 'test_shortcuts.aleo' into Aleo instructions. + ⚠️ No network specified, defaulting to 'testnet'. ⚠️ No endpoint specified, defaulting to 'https://api.explorer.provable.com/v1'. + Leo 🔨 Compiling 'test_shortcuts.leo' Leo 2 statements before dead code elimination. Leo 2 statements after dead code elimination. Leo The program checksum is: '[243u8, 135u8, 116u8, 66u8, 246u8, 27u8, 131u8, 192u8, 145u8, 195u8, 150u8, 1u8, 217u8, 146u8, 63u8, 42u8, 159u8, 224u8, 25u8, 105u8, 240u8, 197u8, 236u8, 236u8, 115u8, 219u8, 254u8, 62u8, 5u8, 44u8, 74u8, 93u8]'. Leo Program size: 0.19 KB / 97.66 KB Leo ✅ Compiled 'test_shortcuts.aleo' into Aleo instructions. + ⚠️ No network specified, defaulting to 'testnet'. ⚠️ No valid private key specified, defaulting to 'APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH'. diff --git a/tests/expectations/cli/test_deploy/STDOUT b/tests/expectations/cli/test_deploy/STDOUT index d1e60c46e1..4c0f964d7f 100644 --- a/tests/expectations/cli/test_deploy/STDOUT +++ b/tests/expectations/cli/test_deploy/STDOUT @@ -1,9 +1,11 @@ + Leo 🔨 Compiling 'some_sample_leo_program.leo' Leo 2 statements before dead code elimination. Leo 2 statements after dead code elimination. Leo The program checksum is: '[95u8, 99u8, 136u8, 243u8, 82u8, 169u8, 200u8, 72u8, 133u8, 227u8, 122u8, 161u8, 195u8, 178u8, 69u8, 37u8, 167u8, 114u8, 104u8, 192u8, 161u8, 175u8, 195u8, 180u8, 120u8, 4u8, 192u8, 16u8, 86u8, 199u8, 76u8, 235u8]'. Leo Program size: 0.20 KB / 97.66 KB Leo ✅ Compiled 'some_sample_leo_program.aleo' into Aleo instructions. + 📢 Using the following consensus heights: 0,1,2,3,4,5,6,7,8,9,10,11 To override, pass in `--consensus-heights` or override the environment variable `CONSENSUS_VERSION_HEIGHTS`. diff --git a/tests/expectations/cli/test_simple_build/STDOUT b/tests/expectations/cli/test_simple_build/STDOUT index 024780d122..2942dff16b 100644 --- a/tests/expectations/cli/test_simple_build/STDOUT +++ b/tests/expectations/cli/test_simple_build/STDOUT @@ -1,7 +1,9 @@ ⚠️ No network specified, defaulting to 'testnet'. ⚠️ No endpoint specified, defaulting to 'https://api.explorer.provable.com/v1'. + Leo 🔨 Compiling 'some_sample_leo_program.leo' Leo 2 statements before dead code elimination. Leo 2 statements after dead code elimination. Leo The program checksum is: '[95u8, 99u8, 136u8, 243u8, 82u8, 169u8, 200u8, 72u8, 133u8, 227u8, 122u8, 161u8, 195u8, 178u8, 69u8, 37u8, 167u8, 114u8, 104u8, 192u8, 161u8, 175u8, 195u8, 180u8, 120u8, 4u8, 192u8, 16u8, 86u8, 199u8, 76u8, 235u8]'. Leo Program size: 0.20 KB / 97.66 KB Leo ✅ Compiled 'some_sample_leo_program.aleo' into Aleo instructions. +