From d9060c63d9e2f54ba11145612adafa37c3bdd2a2 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Thu, 23 Mar 2023 16:22:48 +0000 Subject: [PATCH 01/11] add contract function type and contract method --- crates/noirc_driver/src/contract.rs | 38 ++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/crates/noirc_driver/src/contract.rs b/crates/noirc_driver/src/contract.rs index 85e594e3b99..a80bdc7360b 100644 --- a/crates/noirc_driver/src/contract.rs +++ b/crates/noirc_driver/src/contract.rs @@ -2,10 +2,46 @@ use std::collections::BTreeMap; use crate::CompiledProgram; +/// ContractFunctionType describes the types +/// smart contract functions that are allowed. +/// +/// Note: +/// - All Noir programs in the non-contract context +/// can be seen as `Secret`. +/// - It may be possible to have `unconstrained` +/// functions in regular Noir programs. For now +/// we leave it as a property of only contract functions. +#[derive(serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum ContractFunctionType { + /// This function will be executed in a private + /// context. + Secret, + /// This function will be executed in a public + /// context. + Public, + // / A function which is non-deterministic + // / and does not require any constraint. + Unconstrained, +} +/// Each method in the contract , a contract method, +/// will be compiled as a separate noir program. +/// +/// A contract method unlike a regular Noir program +/// however can have addition properties. +/// One of these being a function type. +#[derive(serde::Serialize, serde::Deserialize)] +pub struct ContractMethod { + pub func_type: ContractFunctionType, + pub function: CompiledProgram, +} + +#[derive(serde::Serialize, serde::Deserialize)] pub struct CompiledContract { /// The name of the contract. pub name: String, /// Each of the contract's functions are compiled into a separate `CompiledProgram` /// stored in this `BTreeMap`. - pub functions: BTreeMap, + #[serde(rename = "methods")] + pub functions: BTreeMap, } From 4a22ee680e2b2127894d05e3ad835bc3057c0abb Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Thu, 23 Mar 2023 16:23:48 +0000 Subject: [PATCH 02/11] when compiling contracts, we explicitly wrap the program as a ContractMethod along with a default FunctionType --- crates/noirc_driver/src/lib.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/noirc_driver/src/lib.rs b/crates/noirc_driver/src/lib.rs index 131a78095e7..7067b45ea75 100644 --- a/crates/noirc_driver/src/lib.rs +++ b/crates/noirc_driver/src/lib.rs @@ -4,6 +4,7 @@ use acvm::Language; use clap::Args; +use contract::ContractMethod; use fm::FileType; use iter_extended::{try_btree_map, try_vecmap}; use noirc_abi::FunctionSignature; @@ -204,13 +205,21 @@ impl Driver { let functions = try_btree_map(&contract.functions, |function| { let function_name = self.function_name(*function).to_owned(); let program = self.compile_no_check(options, *function)?; - Ok((function_name, program)) + Ok(( + function_name, + ContractMethod { + // Note: currently we mark all of the contract methods + // as secret as we do not support public functions. + func_type: contract::ContractFunctionType::Secret, + function: program, + }, + )) })?; Ok(CompiledContract { name: contract.name, functions }) } - /// Returns the FuncId of the 'main' funciton. + /// Returns the FuncId of the 'main' function. /// - Expects check_crate to be called beforehand /// - Panics if no main function is found pub fn main_function(&self) -> Result { From eb6a00cec8d9deac20d8b87610ad27cc8043e2bd Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Thu, 23 Mar 2023 16:27:32 +0000 Subject: [PATCH 03/11] add a `save_contract_to_file` method --- crates/nargo/src/cli/fs/program.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/crates/nargo/src/cli/fs/program.rs b/crates/nargo/src/cli/fs/program.rs index ce7999ed28e..4de97faaf11 100644 --- a/crates/nargo/src/cli/fs/program.rs +++ b/crates/nargo/src/cli/fs/program.rs @@ -1,7 +1,7 @@ use std::path::{Path, PathBuf}; use acvm::{acir::circuit::Circuit, hash_constraint_system}; -use noirc_driver::CompiledProgram; +use noirc_driver::{CompiledContract, CompiledProgram}; use crate::{constants::ACIR_CHECKSUM, errors::CliError}; @@ -11,11 +11,25 @@ pub(crate) fn save_program_to_file>( compiled_program: &CompiledProgram, circuit_name: &str, circuit_dir: P, +) -> PathBuf { + save_build_artifact_to_file(compiled_program, circuit_name, circuit_dir) +} +pub(crate) fn save_contract_to_file>( + compiled_contract: &CompiledContract, + circuit_name: &str, + circuit_dir: P, +) -> PathBuf { + save_build_artifact_to_file(compiled_contract, circuit_name, circuit_dir) +} +fn save_build_artifact_to_file, T: ?Sized + serde::Serialize>( + strukt: &T, + circuit_name: &str, + circuit_dir: P, ) -> PathBuf { create_named_dir(circuit_dir.as_ref(), "target"); let circuit_path = circuit_dir.as_ref().join(circuit_name).with_extension("json"); - write_to_file(&serde_json::to_vec(compiled_program).unwrap(), &circuit_path); + write_to_file(&serde_json::to_vec(strukt).unwrap(), &circuit_path); circuit_path } From f9e719643806c9d2f0391bef3e14ccccdc795fed Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Thu, 23 Mar 2023 16:49:13 +0000 Subject: [PATCH 04/11] add method to save and preprocess contracts --- crates/nargo/src/cli/compile_cmd.rs | 53 ++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/crates/nargo/src/cli/compile_cmd.rs b/crates/nargo/src/cli/compile_cmd.rs index c4938686ed3..37ceb2b78b6 100644 --- a/crates/nargo/src/cli/compile_cmd.rs +++ b/crates/nargo/src/cli/compile_cmd.rs @@ -1,5 +1,5 @@ use acvm::ProofSystemCompiler; -use noirc_driver::{CompileOptions, CompiledProgram, Driver}; +use noirc_driver::{CompileOptions, CompiledContract, CompiledProgram, Driver}; use std::path::Path; use clap::Args; @@ -7,7 +7,7 @@ use clap::Args; use crate::resolver::DependencyResolutionError; use crate::{constants::TARGET_DIR, errors::CliError, resolver::Resolver}; -use super::fs::program::save_program_to_file; +use super::fs::program::{save_contract_to_file, save_program_to_file}; use super::preprocess_cmd::preprocess_with_path; use super::NargoConfig; @@ -34,20 +34,7 @@ pub(crate) fn run(args: CompileCommand, config: NargoConfig) -> Result<(), CliEr let compiled_contracts = driver .compile_contracts(&args.compile_options) .map_err(|_| CliError::CompilationError)?; - - // Flatten each contract into a list of its functions, each being assigned a unique name. - let compiled_programs = compiled_contracts.into_iter().flat_map(|contract| { - let contract_id = format!("{}-{}", args.circuit_name, &contract.name); - contract.functions.into_iter().map(move |(function, program)| { - let program_name = format!("{}-{}", contract_id, function); - (program_name, program) - }) - }); - - for (circuit_name, compiled_program) in compiled_programs { - save_and_preprocess_program(&compiled_program, &circuit_name, &circuit_dir)? - } - Ok(()) + save_and_preprocess_contract(compiled_contracts, &args.circuit_name, &circuit_dir) } else { let program = compile_circuit(&config.program_dir, &args.compile_options)?; save_and_preprocess_program(&program, &args.circuit_name, &circuit_dir) @@ -70,6 +57,40 @@ fn save_and_preprocess_program( Ok(()) } +/// Save a contract to disk along with proving and verification keys. +/// - The contract ABI is saved as one file, which contains all of the +/// methods defined in the contract. +/// - The proving and verification keys are namespaced since the file +/// could contain multiple contracts with the same name. +fn save_and_preprocess_contract( + compiled_contracts: Vec, + circuit_name: &str, + circuit_dir: &Path, +) -> Result<(), CliError> { + for compiled_contract in compiled_contracts { + // Unique identifier for a contract. + let contract_id = format!("{}-{}", circuit_name, &compiled_contract.name); + + // Save contract ABI to file using the contract ID. + save_contract_to_file(&compiled_contract, &contract_id, circuit_dir); + + for (function_name, contract_method) in compiled_contract.functions { + // Create a name which uniquely identifies this contract method + // over multiple contracts. + let uniquely_identifying_program_name = format!("{}-{}", contract_id, function_name); + // Each program in a contract is preprocessed + // Note: This can potentially be quite a long running process + preprocess_with_path( + &uniquely_identifying_program_name, + circuit_dir, + &contract_method.function.circuit, + )?; + } + } + + Ok(()) +} + pub(crate) fn compile_circuit( program_dir: &Path, compile_options: &CompileOptions, From 6d5dacaf99e866f4c0819ef8ffc6b1b20c4c18a9 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Thu, 23 Mar 2023 20:52:28 +0000 Subject: [PATCH 05/11] Update crates/nargo/src/cli/compile_cmd.rs Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- crates/nargo/src/cli/compile_cmd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/nargo/src/cli/compile_cmd.rs b/crates/nargo/src/cli/compile_cmd.rs index 37ceb2b78b6..de974a383d1 100644 --- a/crates/nargo/src/cli/compile_cmd.rs +++ b/crates/nargo/src/cli/compile_cmd.rs @@ -63,7 +63,7 @@ fn save_and_preprocess_program( /// - The proving and verification keys are namespaced since the file /// could contain multiple contracts with the same name. fn save_and_preprocess_contract( - compiled_contracts: Vec, + compiled_contracts: &[CompiledContract], circuit_name: &str, circuit_dir: &Path, ) -> Result<(), CliError> { From 08551704e50d8a0bfb70659193e5200864e15513 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Thu, 23 Mar 2023 21:00:37 +0000 Subject: [PATCH 06/11] use `function` instead of `method` to describe a function in a contract. --- crates/nargo/src/cli/compile_cmd.rs | 10 +++++----- crates/noirc_driver/src/contract.rs | 11 +++++------ crates/noirc_driver/src/lib.rs | 4 ++-- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/crates/nargo/src/cli/compile_cmd.rs b/crates/nargo/src/cli/compile_cmd.rs index de974a383d1..17e0b489f3f 100644 --- a/crates/nargo/src/cli/compile_cmd.rs +++ b/crates/nargo/src/cli/compile_cmd.rs @@ -34,7 +34,7 @@ pub(crate) fn run(args: CompileCommand, config: NargoConfig) -> Result<(), CliEr let compiled_contracts = driver .compile_contracts(&args.compile_options) .map_err(|_| CliError::CompilationError)?; - save_and_preprocess_contract(compiled_contracts, &args.circuit_name, &circuit_dir) + save_and_preprocess_contract(&compiled_contracts, &args.circuit_name, &circuit_dir) } else { let program = compile_circuit(&config.program_dir, &args.compile_options)?; save_and_preprocess_program(&program, &args.circuit_name, &circuit_dir) @@ -59,7 +59,7 @@ fn save_and_preprocess_program( /// Save a contract to disk along with proving and verification keys. /// - The contract ABI is saved as one file, which contains all of the -/// methods defined in the contract. +/// functions defined in the contract. /// - The proving and verification keys are namespaced since the file /// could contain multiple contracts with the same name. fn save_and_preprocess_contract( @@ -74,8 +74,8 @@ fn save_and_preprocess_contract( // Save contract ABI to file using the contract ID. save_contract_to_file(&compiled_contract, &contract_id, circuit_dir); - for (function_name, contract_method) in compiled_contract.functions { - // Create a name which uniquely identifies this contract method + for (function_name, contract_function) in &compiled_contract.functions { + // Create a name which uniquely identifies this contract function // over multiple contracts. let uniquely_identifying_program_name = format!("{}-{}", contract_id, function_name); // Each program in a contract is preprocessed @@ -83,7 +83,7 @@ fn save_and_preprocess_contract( preprocess_with_path( &uniquely_identifying_program_name, circuit_dir, - &contract_method.function.circuit, + &contract_function.function.circuit, )?; } } diff --git a/crates/noirc_driver/src/contract.rs b/crates/noirc_driver/src/contract.rs index a80bdc7360b..c17cedfadaa 100644 --- a/crates/noirc_driver/src/contract.rs +++ b/crates/noirc_driver/src/contract.rs @@ -24,14 +24,14 @@ pub enum ContractFunctionType { // / and does not require any constraint. Unconstrained, } -/// Each method in the contract , a contract method, -/// will be compiled as a separate noir program. +/// Each function in the contract will be compiled +/// as a separate noir program. /// -/// A contract method unlike a regular Noir program +/// A contract function unlike a regular Noir program /// however can have addition properties. /// One of these being a function type. #[derive(serde::Serialize, serde::Deserialize)] -pub struct ContractMethod { +pub struct ContractFunction { pub func_type: ContractFunctionType, pub function: CompiledProgram, } @@ -42,6 +42,5 @@ pub struct CompiledContract { pub name: String, /// Each of the contract's functions are compiled into a separate `CompiledProgram` /// stored in this `BTreeMap`. - #[serde(rename = "methods")] - pub functions: BTreeMap, + pub functions: BTreeMap, } diff --git a/crates/noirc_driver/src/lib.rs b/crates/noirc_driver/src/lib.rs index 7067b45ea75..116c609bf3f 100644 --- a/crates/noirc_driver/src/lib.rs +++ b/crates/noirc_driver/src/lib.rs @@ -4,7 +4,7 @@ use acvm::Language; use clap::Args; -use contract::ContractMethod; +use contract::ContractFunction; use fm::FileType; use iter_extended::{try_btree_map, try_vecmap}; use noirc_abi::FunctionSignature; @@ -207,7 +207,7 @@ impl Driver { let program = self.compile_no_check(options, *function)?; Ok(( function_name, - ContractMethod { + ContractFunction { // Note: currently we mark all of the contract methods // as secret as we do not support public functions. func_type: contract::ContractFunctionType::Secret, From 2a63c5e6f1f022a303b88d2816f2edf58f7cefdc Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Thu, 23 Mar 2023 21:10:51 +0000 Subject: [PATCH 07/11] fix clippy --- crates/nargo/src/cli/compile_cmd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/nargo/src/cli/compile_cmd.rs b/crates/nargo/src/cli/compile_cmd.rs index 17e0b489f3f..1e9bd6be37a 100644 --- a/crates/nargo/src/cli/compile_cmd.rs +++ b/crates/nargo/src/cli/compile_cmd.rs @@ -72,7 +72,7 @@ fn save_and_preprocess_contract( let contract_id = format!("{}-{}", circuit_name, &compiled_contract.name); // Save contract ABI to file using the contract ID. - save_contract_to_file(&compiled_contract, &contract_id, circuit_dir); + save_contract_to_file(compiled_contract, &contract_id, circuit_dir); for (function_name, contract_function) in &compiled_contract.functions { // Create a name which uniquely identifies this contract function From f4c79c7d60de992c4db23b75dcd30d8a1859175c Mon Sep 17 00:00:00 2001 From: jfecher Date: Fri, 24 Mar 2023 12:51:03 +0000 Subject: [PATCH 08/11] Update crates/nargo/src/cli/fs/program.rs Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- crates/nargo/src/cli/fs/program.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/nargo/src/cli/fs/program.rs b/crates/nargo/src/cli/fs/program.rs index 4de97faaf11..ac5c2839f7e 100644 --- a/crates/nargo/src/cli/fs/program.rs +++ b/crates/nargo/src/cli/fs/program.rs @@ -22,7 +22,7 @@ pub(crate) fn save_contract_to_file>( save_build_artifact_to_file(compiled_contract, circuit_name, circuit_dir) } fn save_build_artifact_to_file, T: ?Sized + serde::Serialize>( - strukt: &T, + build_artifact: &T, circuit_name: &str, circuit_dir: P, ) -> PathBuf { From b46e3870c51e5451be6a97437c002562c5d2fb94 Mon Sep 17 00:00:00 2001 From: jfecher Date: Fri, 24 Mar 2023 12:52:15 +0000 Subject: [PATCH 09/11] Update crates/noirc_driver/src/contract.rs Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- crates/noirc_driver/src/contract.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/noirc_driver/src/contract.rs b/crates/noirc_driver/src/contract.rs index c17cedfadaa..3f438355f3b 100644 --- a/crates/noirc_driver/src/contract.rs +++ b/crates/noirc_driver/src/contract.rs @@ -20,8 +20,8 @@ pub enum ContractFunctionType { /// This function will be executed in a public /// context. Public, - // / A function which is non-deterministic - // / and does not require any constraint. + /// A function which is non-deterministic + /// and does not require any constraints. Unconstrained, } /// Each function in the contract will be compiled From b3504b3e0f49ee3bf4ae9f154b6a4561ae5faa50 Mon Sep 17 00:00:00 2001 From: Tom French Date: Fri, 24 Mar 2023 19:06:17 +0000 Subject: [PATCH 10/11] fix: update remaining instance of variable name --- crates/nargo/src/cli/fs/program.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/nargo/src/cli/fs/program.rs b/crates/nargo/src/cli/fs/program.rs index ac5c2839f7e..b50ba4665b7 100644 --- a/crates/nargo/src/cli/fs/program.rs +++ b/crates/nargo/src/cli/fs/program.rs @@ -29,7 +29,7 @@ fn save_build_artifact_to_file, T: ?Sized + serde::Serialize>( create_named_dir(circuit_dir.as_ref(), "target"); let circuit_path = circuit_dir.as_ref().join(circuit_name).with_extension("json"); - write_to_file(&serde_json::to_vec(strukt).unwrap(), &circuit_path); + write_to_file(&serde_json::to_vec(build_artifact).unwrap(), &circuit_path); circuit_path } From 8f9fbf4fec9db6fd3c14d97b38de5e750423e8e3 Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Mon, 27 Mar 2023 11:55:07 +0100 Subject: [PATCH 11/11] Format code --- crates/noirc_driver/src/lib.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/crates/noirc_driver/src/lib.rs b/crates/noirc_driver/src/lib.rs index 116c609bf3f..789ea90ae10 100644 --- a/crates/noirc_driver/src/lib.rs +++ b/crates/noirc_driver/src/lib.rs @@ -204,16 +204,10 @@ impl Driver { ) -> Result { let functions = try_btree_map(&contract.functions, |function| { let function_name = self.function_name(*function).to_owned(); - let program = self.compile_no_check(options, *function)?; - Ok(( - function_name, - ContractFunction { - // Note: currently we mark all of the contract methods - // as secret as we do not support public functions. - func_type: contract::ContractFunctionType::Secret, - function: program, - }, - )) + let function = self.compile_no_check(options, *function)?; + let func_type = contract::ContractFunctionType::Secret; + // Note: currently we mark all of the contract methods as secret as we do not support public functions. + Ok((function_name, ContractFunction { func_type, function })) })?; Ok(CompiledContract { name: contract.name, functions })