diff --git a/crates/nargo/src/package.rs b/crates/nargo/src/package.rs index 6c690fe9caf..16f65d329ba 100644 --- a/crates/nargo/src/package.rs +++ b/crates/nargo/src/package.rs @@ -8,6 +8,7 @@ use crate::constants::{PROVER_INPUT_FILE, VERIFIER_INPUT_FILE}; pub enum PackageType { Library, Binary, + Contract, } impl Display for PackageType { @@ -15,6 +16,7 @@ impl Display for PackageType { match self { Self::Library => write!(f, "lib"), Self::Binary => write!(f, "bin"), + Self::Contract => write!(f, "contract"), } } } @@ -64,6 +66,10 @@ impl Package { self.package_type == PackageType::Binary } + pub fn is_contract(&self) -> bool { + self.package_type == PackageType::Contract + } + pub fn is_library(&self) -> bool { self.package_type == PackageType::Library } diff --git a/crates/nargo_cli/src/cli/compile_cmd.rs b/crates/nargo_cli/src/cli/compile_cmd.rs index 651992f0fd9..b514d771144 100644 --- a/crates/nargo_cli/src/cli/compile_cmd.rs +++ b/crates/nargo_cli/src/cli/compile_cmd.rs @@ -37,10 +37,6 @@ pub(crate) struct CompileCommand { #[arg(long)] include_keys: bool, - /// Compile each contract function used within the program - #[arg(short, long)] - contracts: bool, - /// The name of the package to compile #[clap(long)] package: Option, @@ -60,10 +56,10 @@ pub(crate) fn run( let mut common_reference_string = read_cached_common_reference_string(); - // If contracts is set we're compiling every function in a 'contract' rather than just 'main'. - if args.contracts { - for package in &workspace { - let (mut context, crate_id) = prepare_package(package); + for package in &workspace { + let (mut context, crate_id) = prepare_package(package); + // If `contract` package type, we're compiling every function in a 'contract' rather than just 'main'. + if package.is_contract() { let result = compile_contracts(&mut context, crate_id, &args.compile_options); let contracts = report_errors(result, &context, args.compile_options.deny_warnings)?; @@ -105,9 +101,7 @@ pub(crate) fn run( &circuit_dir, ); } - } - } else { - for package in &workspace { + } else { let (_, program) = compile_package(backend, package, &args.compile_options)?; common_reference_string = diff --git a/crates/nargo_cli/src/cli/init_cmd.rs b/crates/nargo_cli/src/cli/init_cmd.rs index edfb9c3410c..d6ad172ce26 100644 --- a/crates/nargo_cli/src/cli/init_cmd.rs +++ b/crates/nargo_cli/src/cli/init_cmd.rs @@ -16,12 +16,16 @@ pub(crate) struct InitCommand { name: Option, /// Use a library template - #[arg(long, conflicts_with = "bin")] + #[arg(long, conflicts_with = "bin", conflicts_with = "contract")] pub(crate) lib: bool, /// Use a binary template [default] - #[arg(long, conflicts_with = "lib")] + #[arg(long, conflicts_with = "lib", conflicts_with = "contract")] pub(crate) bin: bool, + + /// Use a contract template + #[arg(long, conflicts_with = "lib", conflicts_with = "bin")] + pub(crate) contract: bool, } const BIN_EXAMPLE: &str = r#"fn main(x : Field, y : pub Field) { @@ -37,6 +41,13 @@ fn test_main() { } "#; +const CONTRACT_EXAMPLE: &str = r#"contract Main { + internal fn double(x: Field) -> pub Field { x * 2 } + fn triple(x: Field) -> pub Field { x * 3 } + fn quadruple(x: Field) -> pub Field { double(double(x)) } +} +"#; + const LIB_EXAMPLE: &str = r#"fn my_util(x : Field, y : Field) -> bool { x != y } @@ -60,7 +71,13 @@ pub(crate) fn run( .name .unwrap_or_else(|| config.program_dir.file_name().unwrap().to_str().unwrap().to_owned()); - let package_type = if args.lib { PackageType::Library } else { PackageType::Binary }; + let package_type = if args.lib { + PackageType::Library + } else if args.contract { + PackageType::Contract + } else { + PackageType::Binary + }; initialize_project(config.program_dir, &package_name, package_type); Ok(()) } @@ -88,6 +105,9 @@ compiler_version = "{CARGO_PKG_VERSION}" // This uses the `match` syntax instead of `if` so we get a compile error when we add new package types (which likely need new template files) match package_type { PackageType::Binary => write_to_file(BIN_EXAMPLE.as_bytes(), &src_dir.join("main.nr")), + PackageType::Contract => { + write_to_file(CONTRACT_EXAMPLE.as_bytes(), &src_dir.join("main.nr")) + } PackageType::Library => write_to_file(LIB_EXAMPLE.as_bytes(), &src_dir.join("lib.nr")), }; println!("Project successfully created! It is located at {}", package_dir.display()); diff --git a/crates/nargo_cli/src/cli/new_cmd.rs b/crates/nargo_cli/src/cli/new_cmd.rs index 85e2522a5a5..dbdeddef712 100644 --- a/crates/nargo_cli/src/cli/new_cmd.rs +++ b/crates/nargo_cli/src/cli/new_cmd.rs @@ -17,12 +17,16 @@ pub(crate) struct NewCommand { name: Option, /// Use a library template - #[arg(long, conflicts_with = "bin")] + #[arg(long, conflicts_with = "bin", conflicts_with = "contract")] pub(crate) lib: bool, /// Use a binary template [default] - #[arg(long, conflicts_with = "lib")] + #[arg(long, conflicts_with = "lib", conflicts_with = "contract")] pub(crate) bin: bool, + + /// Use a contract template + #[arg(long, conflicts_with = "lib", conflicts_with = "bin")] + pub(crate) contract: bool, } pub(crate) fn run( @@ -39,7 +43,13 @@ pub(crate) fn run( let package_name = args.name.unwrap_or_else(|| args.path.file_name().unwrap().to_str().unwrap().to_owned()); - let package_type = if args.lib { PackageType::Library } else { PackageType::Binary }; + let package_type = if args.lib { + PackageType::Library + } else if args.contract { + PackageType::Contract + } else { + PackageType::Binary + }; initialize_project(package_dir, &package_name, package_type); Ok(()) } diff --git a/crates/nargo_cli/src/manifest.rs b/crates/nargo_cli/src/manifest.rs index b7b1d6d2d5c..d55c0fbe0c0 100644 --- a/crates/nargo_cli/src/manifest.rs +++ b/crates/nargo_cli/src/manifest.rs @@ -39,6 +39,7 @@ impl PackageConfig { let package_type = match self.package.package_type.as_deref() { Some("lib") => PackageType::Library, Some("bin") => PackageType::Binary, + Some("contract") => PackageType::Contract, Some(invalid) => { return Err(ManifestError::InvalidPackageType( root_dir.join("Nargo.toml"), @@ -63,7 +64,7 @@ impl PackageConfig { PackageType::Library => { root_dir.join("src").join("lib").with_extension(FILE_EXTENSION) } - PackageType::Binary => { + PackageType::Binary | PackageType::Contract => { root_dir.join("src").join("main").with_extension(FILE_EXTENSION) } }; diff --git a/crates/nargo_cli/tests/execution_success/contracts/Nargo.toml b/crates/nargo_cli/tests/execution_success/contracts/Nargo.toml index cca289aa4fd..4abcfab93d3 100644 --- a/crates/nargo_cli/tests/execution_success/contracts/Nargo.toml +++ b/crates/nargo_cli/tests/execution_success/contracts/Nargo.toml @@ -1,6 +1,6 @@ [package] name = "contracts" -type = "bin" +type = "contract" authors = [""] compiler_version = "0.1" diff --git a/crates/noirc_driver/src/lib.rs b/crates/noirc_driver/src/lib.rs index 6b9ab2c996d..2919d2fd3ea 100644 --- a/crates/noirc_driver/src/lib.rs +++ b/crates/noirc_driver/src/lib.rs @@ -179,6 +179,7 @@ pub fn compile_contracts( ) -> Result<(Vec, Warnings), ErrorsAndWarnings> { let warnings = check_crate(context, crate_id, options.deny_warnings)?; + // TODO: We probably want to error if contracts is empty let contracts = context.get_all_contracts(&crate_id); let mut compiled_contracts = vec![]; let mut errors = warnings;