This commit is contained in:
Pranav Gaddamadugu 2024-05-29 10:12:20 -07:00
parent 2cc2177158
commit 8964a194a4
11 changed files with 81 additions and 56 deletions

View File

@ -229,4 +229,11 @@ create_messages!(
msg: format!("Invalid network name: {network}"),
help: Some("Valid network names are `testnet` and `mainnet`.".to_string()),
}
@backtraced
invalid_example {
args: (example: impl Display),
msg: format!("Invalid Leo example: {example}"),
help: Some("Valid Leo examples are `lottery`, `tictactoe`, and `token`.".to_string()),
}
);

View File

@ -54,7 +54,7 @@ enum Commands {
},
#[clap(about = "Create a new Leo example package in a new directory")]
Example {
#[clap(subcommand)]
#[clap(flatten)]
command: Example,
},
#[clap(about = "Run a program with input variables")]
@ -329,7 +329,7 @@ mod test_helpers {
let new = CLI {
debug: false,
quiet: false,
command: Commands::New { command: New { name: name.to_string(), network: "mainnet".to_string() } },
command: Commands::New { command: New { name: name.to_string(), network: NETWORK.to_string() } },
path: Some(project_directory.clone()),
home: None,
};
@ -397,7 +397,7 @@ function external_nested_function:
command: Add {
name: "nested_example_layer_0".to_string(),
local: None,
network: "mainnet".to_string(),
network: NETWORK.to_string(),
clear: false,
},
},
@ -430,7 +430,7 @@ function external_nested_function:
let create_grandparent_project = CLI {
debug: false,
quiet: false,
command: Commands::New { command: New { name: "grandparent".to_string(), network: "mainnet".to_string() } },
command: Commands::New { command: New { name: "grandparent".to_string(), network: NETWORK.to_string() } },
path: Some(grandparent_directory.clone()),
home: None,
};
@ -438,7 +438,7 @@ function external_nested_function:
let create_parent_project = CLI {
debug: false,
quiet: false,
command: Commands::New { command: New { name: "parent".to_string(), network: "mainnet".to_string() } },
command: Commands::New { command: New { name: "parent".to_string(), network: NETWORK.to_string() } },
path: Some(parent_directory.clone()),
home: None,
};
@ -446,7 +446,7 @@ function external_nested_function:
let create_child_project = CLI {
debug: false,
quiet: false,
command: Commands::New { command: New { name: "child".to_string(), network: "mainnet".to_string() } },
command: Commands::New { command: New { name: "child".to_string(), network: NETWORK.to_string() } },
path: Some(child_directory.clone()),
home: None,
};
@ -491,7 +491,7 @@ program child.aleo {
command: Add {
name: "parent".to_string(),
local: Some(parent_directory.clone()),
network: "mainnet".to_string(),
network: NETWORK.to_string(),
clear: false,
},
},
@ -506,7 +506,7 @@ program child.aleo {
command: Add {
name: "child".to_string(),
local: Some(child_directory.clone()),
network: "mainnet".to_string(),
network: NETWORK.to_string(),
clear: false,
},
},
@ -521,7 +521,7 @@ program child.aleo {
command: Add {
name: "child".to_string(),
local: Some(child_directory.clone()),
network: "mainnet".to_string(),
network: NETWORK.to_string(),
clear: false,
},
},
@ -561,7 +561,7 @@ program child.aleo {
let create_outer_project = CLI {
debug: false,
quiet: false,
command: Commands::New { command: New { name: "outer".to_string(), network: "mainnet".to_string() } },
command: Commands::New { command: New { name: "outer".to_string(), network: NETWORK.to_string() } },
path: Some(outer_directory.clone()),
home: None,
};
@ -569,7 +569,7 @@ program child.aleo {
let create_inner_1_project = CLI {
debug: false,
quiet: false,
command: Commands::New { command: New { name: "inner_1".to_string(), network: "mainnet".to_string() } },
command: Commands::New { command: New { name: "inner_1".to_string(), network: NETWORK.to_string() } },
path: Some(inner_1_directory.clone()),
home: None,
};
@ -577,7 +577,7 @@ program child.aleo {
let create_inner_2_project = CLI {
debug: false,
quiet: false,
command: Commands::New { command: New { name: "inner_2".to_string(), network: "mainnet".to_string() } },
command: Commands::New { command: New { name: "inner_2".to_string(), network: NETWORK.to_string() } },
path: Some(inner_2_directory.clone()),
home: None,
};
@ -645,7 +645,7 @@ program outer.aleo {
command: Add {
name: "inner_1".to_string(),
local: Some(inner_1_directory.clone()),
network: "mainnet".to_string(),
network: NETWORK.to_string(),
clear: false,
},
},
@ -660,7 +660,7 @@ program outer.aleo {
command: Add {
name: "inner_2".to_string(),
local: Some(inner_2_directory.clone()),
network: "mainnet".to_string(),
network: NETWORK.to_string(),
clear: false,
},
},
@ -699,7 +699,7 @@ program outer.aleo {
let create_outer_project = CLI {
debug: false,
quiet: false,
command: Commands::New { command: New { name: "outer_2".to_string(), network: "mainnet".to_string() } },
command: Commands::New { command: New { name: "outer_2".to_string(), network: NETWORK.to_string() } },
path: Some(outer_directory.clone()),
home: None,
};
@ -707,7 +707,7 @@ program outer.aleo {
let create_inner_1_project = CLI {
debug: false,
quiet: false,
command: Commands::New { command: New { name: "inner_1".to_string(), network: "mainnet".to_string() } },
command: Commands::New { command: New { name: "inner_1".to_string(), network: NETWORK.to_string() } },
path: Some(inner_1_directory.clone()),
home: None,
};
@ -715,7 +715,7 @@ program outer.aleo {
let create_inner_2_project = CLI {
debug: false,
quiet: false,
command: Commands::New { command: New { name: "inner_2".to_string(), network: "mainnet".to_string() } },
command: Commands::New { command: New { name: "inner_2".to_string(), network: NETWORK.to_string() } },
path: Some(inner_2_directory.clone()),
home: None,
};
@ -814,7 +814,7 @@ program outer_2.aleo {
command: Add {
name: "inner_1".to_string(),
local: Some(inner_1_directory.clone()),
network: "mainnet".to_string(),
network: NETWORK.to_string(),
clear: false,
},
},
@ -829,7 +829,7 @@ program outer_2.aleo {
command: Add {
name: "inner_2".to_string(),
local: Some(inner_2_directory.clone()),
network: "mainnet".to_string(),
network: NETWORK.to_string(),
clear: false,
},
},

View File

@ -360,21 +360,21 @@ mod tests {
#[test]
fn test_signature_raw() {
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".parse().unwrap();
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".to_string();
let message = "Hello, world!".to_string();
assert!(sign_message::<CurrentNetwork>(message, None, true, Some(key), None).is_ok());
}
#[test]
fn test_signature() {
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".parse().unwrap();
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".to_string();
let message = "5field".to_string();
assert!(sign_message::<CurrentNetwork>(message, None, false, Some(key), None).is_ok());
}
#[test]
fn test_signature_fail() {
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".parse().unwrap();
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".to_string();
let message = "not a literal value".to_string();
assert!(sign_message::<CurrentNetwork>(message, None, false, Some(key), None).is_err());
}
@ -382,7 +382,7 @@ mod tests {
#[test]
fn test_seeded_signature_raw() {
let seed = Some(38868010450269069);
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".parse().unwrap();
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".to_string();
let message = "Hello, world!".to_string();
let expected = "sign175pmqldmkqw2nwp7wz7tfmpyqdnvzaq06mh8t2g22frsmrdtuvpf843p0wzazg27rwrjft8863vwn5a5cqgr97ldw69cyq53l0zlwqhesm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qkevd26g";
let actual = sign_message::<CurrentNetwork>(message, seed, true, Some(key), None).unwrap();
@ -392,7 +392,7 @@ mod tests {
#[test]
fn test_seeded_signature() {
let seed = Some(38868010450269069);
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".parse().unwrap();
let key = "APrivateKey1zkp61PAYmrYEKLtRWeWhUoDpFnGLNuHrCciSqN49T86dw3p".to_string();
let message = "5field".to_string();
let expected = "sign1ad29myqy8gv6xve2r6tuly39m63l2mpfpyvqkwdl2umxqek6q5qxmy63zmhjx75x90sqxq69u5ntzp25kp59e0hp4hj8l8085sg7vqlesm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qk7v46re";
let actual = sign_message::<CurrentNetwork>(message, seed, false, Some(key), None).unwrap();
@ -402,20 +402,20 @@ mod tests {
#[test]
fn test_verify_raw() {
// test signature of "Hello, world!"
let address = "aleo1zecnqchckrzw7dlsyf65g6z5le2rmys403ecwmcafrag0e030yxqrnlg8j".parse().unwrap();
let address = "aleo1zecnqchckrzw7dlsyf65g6z5le2rmys403ecwmcafrag0e030yxqrnlg8j".to_string();
let signature = "sign1nnvrjlksrkxdpwsrw8kztjukzhmuhe5zf3srk38h7g32u4kqtqpxn3j5a6k8zrqcfx580a96956nsjvluzt64cqf54pdka9mgksfqp8esm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qkwsnaqq".to_string();
let message = "Hello, world!".to_string();
assert!(verify_message::<CurrentNetwork>(address, signature, message, true).is_ok());
assert!(verify_message::<CurrentNetwork>(address.clone(), signature, message, true).is_ok());
// test signature of "Hello, world!" against the message "Different Message"
let signature = "sign1nnvrjlksrkxdpwsrw8kztjukzhmuhe5zf3srk38h7g32u4kqtqpxn3j5a6k8zrqcfx580a96956nsjvluzt64cqf54pdka9mgksfqp8esm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qkwsnaqq".to_string();
let message = "Different Message".to_string();
assert!(verify_message::<CurrentNetwork>(address, signature, message, true).is_err());
assert!(verify_message::<CurrentNetwork>(address.clone(), signature, message, true).is_err());
// test signature of "Hello, world!" against the wrong address
let signature = "sign1nnvrjlksrkxdpwsrw8kztjukzhmuhe5zf3srk38h7g32u4kqtqpxn3j5a6k8zrqcfx580a96956nsjvluzt64cqf54pdka9mgksfqp8esm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qkwsnaqq".to_string();
let message = "Hello, world!".to_string();
let wrong_address = "aleo1uxl69laseuv3876ksh8k0nd7tvpgjt6ccrgccedpjk9qwyfensxst9ftg5".parse().unwrap();
let wrong_address = "aleo1uxl69laseuv3876ksh8k0nd7tvpgjt6ccrgccedpjk9qwyfensxst9ftg5".to_string();
assert!(verify_message::<CurrentNetwork>(wrong_address, signature, message, true).is_err());
// test a valid signature of "Different Message"
@ -427,20 +427,20 @@ mod tests {
#[test]
fn test_verify() {
// test signature of 5u8
let address = "aleo1zecnqchckrzw7dlsyf65g6z5le2rmys403ecwmcafrag0e030yxqrnlg8j".parse().unwrap();
let address = "aleo1zecnqchckrzw7dlsyf65g6z5le2rmys403ecwmcafrag0e030yxqrnlg8j".to_string();
let signature = "sign1j7swjfnyujt2vme3ulu88wdyh2ddj85arh64qh6c6khvrx8wvsp8z9wtzde0sahqj2qwz8rgzt803c0ceega53l4hks2mf5sfsv36qhesm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qkdetews".to_string();
let message = "5field".to_string();
assert!(verify_message::<CurrentNetwork>(address, signature, message, false).is_ok());
assert!(verify_message::<CurrentNetwork>(address.clone(), signature, message, false).is_ok());
// test signature of 5u8 against the message 10u8
let signature = "sign1j7swjfnyujt2vme3ulu88wdyh2ddj85arh64qh6c6khvrx8wvsp8z9wtzde0sahqj2qwz8rgzt803c0ceega53l4hks2mf5sfsv36qhesm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qkdetews".to_string();
let message = "10field".to_string();
assert!(verify_message::<CurrentNetwork>(address, signature, message, false).is_err());
assert!(verify_message::<CurrentNetwork>(address.clone(), signature, message, false).is_err());
// test signature of 5u8 against the wrong address
let signature = "sign1j7swjfnyujt2vme3ulu88wdyh2ddj85arh64qh6c6khvrx8wvsp8z9wtzde0sahqj2qwz8rgzt803c0ceega53l4hks2mf5sfsv36qhesm5elrqqunzqzmac7kzutl6zk7mqht3c0m9kg4hklv7h2js0qmxavwnpuwyl4lzldl6prs4qeqy9wxyp8y44nnydg3h8sg6ue99qkdetews".to_string();
let message = "5field".to_string();
let wrong_address = "aleo1uxl69laseuv3876ksh8k0nd7tvpgjt6ccrgccedpjk9qwyfensxst9ftg5".parse().unwrap();
let wrong_address = "aleo1uxl69laseuv3876ksh8k0nd7tvpgjt6ccrgccedpjk9qwyfensxst9ftg5".to_string();
assert!(verify_message::<CurrentNetwork>(wrong_address, signature, message, false).is_err());
// test a valid signature of 10u8

View File

@ -21,8 +21,8 @@ use std::fs;
/// Initialize a new Leo example.
#[derive(Parser, Debug)]
pub struct Example {
#[clap(name = "EXAMPLE", help = "The example to initialize.")]
pub(crate) example: ExampleVariant,
#[clap(name = "NAME", help = "The example to initialize.")]
pub(crate) name: String,
#[clap(short = 'n', long, help = "Name of the network to use", default_value = "mainnet")]
pub(crate) network: String,
}
@ -32,8 +32,8 @@ impl Command for Example {
type Output = ();
fn prelude(&self, context: Context) -> Result<Self::Input> {
// Run leo new EXAMPLE_NAME
(New { name: self.example.name(), network: self.network }).execute(context)
// Run leo new <name> --network <network>
(New { name: self.name.clone(), network: self.network.clone() }).execute(context)
}
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output>
@ -42,22 +42,26 @@ impl Command for Example {
{
let package_dir = context.dir()?;
// Parse the example variant.
let example_variant =
ExampleVariant::try_from(self.name.as_str()).map_err(|_| CliError::invalid_example(self.name.as_str()))?;
// Write the main file.
let main_file_path = package_dir.join("src").join("main.leo");
fs::write(main_file_path, self.example.main_file_string()).map_err(CliError::failed_to_write_file)?;
fs::write(main_file_path, example_variant.main_file_string()).map_err(CliError::failed_to_write_file)?;
// Write the README file.
let readme_file_path = package_dir.join("README.md");
let readme_file_path_string = readme_file_path.display().to_string();
fs::write(readme_file_path, self.example.readme_file_string()).map_err(CliError::failed_to_write_file)?;
fs::write(readme_file_path, example_variant.readme_file_string()).map_err(CliError::failed_to_write_file)?;
// Write the run.sh file.
let run_file_path = package_dir.join("run.sh");
fs::write(run_file_path, self.example.run_file_string()).map_err(CliError::failed_to_write_file)?;
fs::write(run_file_path, example_variant.run_file_string()).map_err(CliError::failed_to_write_file)?;
tracing::info!(
"🚀 To run the '{}' program follow the instructions at {}",
self.example.name().bold(),
example_variant.name().bold(),
readme_file_path_string
);
@ -121,3 +125,16 @@ impl ExampleVariant {
}
}
}
impl TryFrom<&str> for ExampleVariant {
type Error = ();
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
match value {
"lottery" => Ok(Self::Lottery),
"tictactoe" => Ok(Self::TicTacToe),
"token" => Ok(Self::Token),
_ => Err(()),
}
}
}

View File

@ -64,14 +64,14 @@ impl Command for Execute {
// Parse the network.
let network = NetworkName::try_from(self.compiler_options.network.as_str())?;
match network {
NetworkName::MainnetV0 => handle_execute::<MainnetV0>(&self, context),
NetworkName::TestnetV0 => handle_execute::<TestnetV0>(&self, context),
NetworkName::MainnetV0 => handle_execute::<MainnetV0>(self, context),
NetworkName::TestnetV0 => handle_execute::<TestnetV0>(self, context),
}
}
}
// A helper function to handle the `execute` command.
fn handle_execute<N: Network>(command: &Execute, context: Context) -> Result<<Execute as Command>::Output> {
fn handle_execute<N: Network>(command: Execute, context: Context) -> Result<<Execute as Command>::Output> {
// If the `broadcast` flag is set, then broadcast the transaction.
if command.broadcast {
// Get the program name.

View File

@ -15,6 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use super::*;
use snarkvm::prelude::{MainnetV0, TestnetV0};
use leo_retriever::NetworkName;
@ -44,15 +45,22 @@ impl Command for New {
let network = NetworkName::try_from(self.network.as_str())?;
// Derive the location of the parent directory to the project.
let mut package_path = context.parent_dir()?;
let package_path = context.parent_dir()?;
// Change the cwd to the Leo package directory to initialize all files.
std::env::set_current_dir(&package_path)
.map_err(|err| PackageError::failed_to_set_cwd(package_path.display(), err))?;
// Open the program manifest.
let manifest = context.open_manifest()?;
// Note that this has the side effect of create the appropriate directories and files.
match network {
NetworkName::MainnetV0 => {
context.open_manifest::<MainnetV0>()?;
}
NetworkName::TestnetV0 => {
context.open_manifest::<TestnetV0>()?;
}
}
// Initialize the package.
match network {

View File

@ -14,10 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use super::*;
use leo_errors::{LeoError, Result, UtilError};
use leo_package::package::Package;
// A valid hash is 61 characters long, with preface "ab1" and all characters lowercase or numbers.

View File

@ -16,7 +16,6 @@
use super::*;
use leo_retriever::{Dependency, Manifest};
use std::path::PathBuf;
/// Remove a dependency from the current package.
#[derive(Parser, Debug)]

View File

@ -54,14 +54,14 @@ impl Command for Run {
// Parse the network.
let network = NetworkName::try_from(self.compiler_options.network.as_str())?;
match network {
NetworkName::MainnetV0 => handle_run::<MainnetV0>(&self, context),
NetworkName::TestnetV0 => handle_run::<TestnetV0>(&self, context),
NetworkName::MainnetV0 => handle_run::<MainnetV0>(self, context),
NetworkName::TestnetV0 => handle_run::<TestnetV0>(self, context),
}
}
}
// A helper function to handle the run command.
fn handle_run<N: Network>(command: &Run, context: Context) -> Result<<Run as Command>::Output> {
fn handle_run<N: Network>(command: Run, context: Context) -> Result<<Run as Command>::Output> {
let mut inputs = command.inputs;
// Compose the `run` command.

View File

@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use super::*;
use aleo_std;
use leo_errors::{CliError, PackageError, Result};
use leo_package::build::{BuildDirectory, BUILD_DIRECTORY_NAME};

View File

@ -14,8 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
pub use super::*;
pub mod context;
pub mod logger;
pub mod updater;