Skip to content

Commit

Permalink
Merge branch 'master' into program-artifact
Browse files Browse the repository at this point in the history
* master:
  feat: import core logic in cli from `nargo` crate (#1142)
  chore: enforce `clippy::semicolon_if_nothing_returned` linting rule (#1139)
  chore: borrow instead of cloning witness vectors in IR gen (#1127)
  • Loading branch information
TomAFrench committed Apr 12, 2023
2 parents 5f50e7f + 753a272 commit 65d7849
Show file tree
Hide file tree
Showing 56 changed files with 324 additions and 153 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/arena/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![forbid(unsafe_code)]
#![warn(unused_crate_dependencies, unused_extern_crates)]
#![warn(unreachable_pub)]
#![warn(clippy::semicolon_if_nothing_returned)]

// For now we use a wrapper around generational-arena
pub use generational_arena::{Arena, Index};
3 changes: 2 additions & 1 deletion crates/fm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![forbid(unsafe_code)]
#![warn(unused_crate_dependencies, unused_extern_crates)]
#![warn(unreachable_pub)]
#![warn(clippy::semicolon_if_nothing_returned)]

mod file_map;
mod file_reader;
Expand Down Expand Up @@ -136,7 +137,7 @@ mod tests {

let file_id = fm.add_file(&file_path, FileType::Normal).unwrap();

assert!(fm.path(file_id).ends_with("foo"))
assert!(fm.path(file_id).ends_with("foo"));
}
#[test]
fn path_resolve_sub_module() {
Expand Down
1 change: 1 addition & 0 deletions crates/iter-extended/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![forbid(unsafe_code)]
#![warn(unused_crate_dependencies, unused_extern_crates)]
#![warn(unreachable_pub)]
#![warn(clippy::semicolon_if_nothing_returned)]

use std::collections::BTreeMap;

Expand Down
4 changes: 4 additions & 0 deletions crates/nargo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ edition.workspace = true
rustc_version = "0.4.0"

[dependencies]
acvm.workspace = true
noirc_abi.workspace = true
noirc_driver.workspace = true
iter-extended.workspace = true
toml.workspace = true
serde.workspace = true
thiserror.workspace = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,33 @@ use serde::{Deserialize, Serialize};
/// - The ACIR bytecode has had an optimization pass applied to tailor it for the backend.
/// - Proving and verification keys have been pregenerated based on this ACIR.
#[derive(Serialize, Deserialize)]
pub(crate) struct PreprocessedContract {
pub struct PreprocessedContract {
/// The name of the contract.
pub(crate) name: String,
pub name: String,
/// The identifier of the proving backend which this contract has been compiled for.
pub(crate) backend: String,
pub backend: String,
/// Each of the contract's functions are compiled into a separate program stored in this `Vec`.
pub(crate) functions: Vec<PreprocessedContractFunction>,
pub functions: Vec<PreprocessedContractFunction>,
}

/// Each function in the contract will be compiled as a separate noir program.
///
/// A contract function unlike a regular Noir program however can have additional properties.
/// One of these being a function type.
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct PreprocessedContractFunction {
pub(crate) name: String,
pub struct PreprocessedContractFunction {
pub name: String,

pub(crate) function_type: ContractFunctionType,
pub function_type: ContractFunctionType,

pub(crate) abi: Abi,
pub abi: Abi,

#[serde(
serialize_with = "super::serialize_circuit",
deserialize_with = "super::deserialize_circuit"
)]
pub(crate) bytecode: Circuit,
pub bytecode: Circuit,

pub(crate) proving_key: Vec<u8>,
pub(crate) verification_key: Vec<u8>,
pub proving_key: Vec<u8>,
pub verification_key: Vec<u8>,
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
use acvm::acir::circuit::Circuit;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

pub(crate) mod contract;
pub(crate) mod program;
pub mod contract;
pub mod program;

// TODO: move these down into ACVM.
fn serialize_circuit<S>(circuit: &Circuit, s: S) -> Result<S::Ok, S::Error>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ use serde::{Deserialize, Serialize};
/// - The ACIR bytecode has had an optimization pass applied to tailor it for the backend.
/// - Proving and verification keys have been pregenerated based on this ACIR.
#[derive(Serialize, Deserialize, Debug)]
pub(crate) struct PreprocessedProgram {
pub(crate) backend: String,
pub(crate) abi: Abi,
pub struct PreprocessedProgram {
pub backend: String,
pub abi: Abi,

#[serde(
serialize_with = "super::serialize_circuit",
deserialize_with = "super::deserialize_circuit"
)]
pub(crate) bytecode: Circuit,
pub bytecode: Circuit,

pub(crate) proving_key: Vec<u8>,
pub(crate) verification_key: Vec<u8>,
pub proving_key: Vec<u8>,
pub verification_key: Vec<u8>,
}
13 changes: 13 additions & 0 deletions crates/nargo/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use acvm::OpcodeResolutionError;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum NargoError {
/// Error while compiling Noir into ACIR.
#[error("Failed to compile circuit")]
CompilationError,

/// ACIR circuit solving error
#[error(transparent)]
SolvingError(#[from] OpcodeResolutionError),
}
6 changes: 6 additions & 0 deletions crates/nargo/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
#![forbid(unsafe_code)]
#![warn(unused_crate_dependencies, unused_extern_crates)]
#![warn(unreachable_pub)]
#![warn(clippy::semicolon_if_nothing_returned)]

//! Nargo is the package manager for Noir
//! This name was used because it sounds like `cargo` and
//! Noir Package Manager abbreviated is npm, which is already taken.

pub mod artifacts;
mod errors;
pub mod manifest;
pub mod ops;

pub use self::errors::NargoError;
10 changes: 10 additions & 0 deletions crates/nargo/src/ops/codegen_verifier.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use acvm::SmartContract;

use crate::NargoError;

pub fn codegen_verifier(
backend: &impl SmartContract,
verification_key: &[u8],
) -> Result<String, NargoError> {
Ok(backend.eth_contract_from_vk(verification_key))
}
20 changes: 20 additions & 0 deletions crates/nargo/src/ops/execute.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use acvm::PartialWitnessGenerator;
use acvm::{acir::circuit::Circuit, pwg::block::Blocks};
use noirc_abi::WitnessMap;

use crate::NargoError;

pub fn execute_circuit(
backend: &impl PartialWitnessGenerator,
circuit: Circuit,
mut initial_witness: WitnessMap,
) -> Result<WitnessMap, NargoError> {
let mut blocks = Blocks::default();
let (unresolved_opcodes, oracles) =
backend.solve(&mut initial_witness, &mut blocks, circuit.opcodes)?;
if !unresolved_opcodes.is_empty() || !oracles.is_empty() {
todo!("Add oracle support to nargo execute")
}

Ok(initial_witness)
}
11 changes: 11 additions & 0 deletions crates/nargo/src/ops/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pub use self::codegen_verifier::codegen_verifier;
pub use self::execute::execute_circuit;
pub use self::preprocess::{preprocess_contract, preprocess_program};
pub use self::prove::prove;
pub use self::verify::verify_proof;

mod codegen_verifier;
mod execute;
mod preprocess;
mod prove;
mod verify;
57 changes: 57 additions & 0 deletions crates/nargo/src/ops/preprocess.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use acvm::ProofSystemCompiler;
use iter_extended::vecmap;
use noirc_driver::{CompiledContract, CompiledProgram};

use crate::artifacts::{
contract::{PreprocessedContract, PreprocessedContractFunction},
program::PreprocessedProgram,
};

// TODO: pull this from backend.
const BACKEND_IDENTIFIER: &str = "acvm-backend-barretenberg";

pub fn preprocess_program(
backend: &impl ProofSystemCompiler,
compiled_program: CompiledProgram,
) -> PreprocessedProgram {
// TODO: currently `compiled_program`'s bytecode is already optimized for the backend.
// In future we'll need to apply those optimizations here.
let optimized_bytecode = compiled_program.circuit;
let (proving_key, verification_key) = backend.preprocess(&optimized_bytecode);

PreprocessedProgram {
backend: String::from(BACKEND_IDENTIFIER),
abi: compiled_program.abi,
bytecode: optimized_bytecode,
proving_key,
verification_key,
}
}

pub fn preprocess_contract(
backend: &impl ProofSystemCompiler,
compiled_contract: CompiledContract,
) -> PreprocessedContract {
let preprocessed_contract_functions = vecmap(compiled_contract.functions, |func| {
// TODO: currently `func`'s bytecode is already optimized for the backend.
// In future we'll need to apply those optimizations here.
let optimized_bytecode = func.bytecode;
let (proving_key, verification_key) = backend.preprocess(&optimized_bytecode);

PreprocessedContractFunction {
name: func.name,
function_type: func.function_type,
abi: func.abi,

bytecode: optimized_bytecode,
proving_key,
verification_key,
}
});

PreprocessedContract {
name: compiled_contract.name,
backend: String::from(BACKEND_IDENTIFIER),
functions: preprocessed_contract_functions,
}
}
16 changes: 16 additions & 0 deletions crates/nargo/src/ops/prove.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use acvm::acir::circuit::Circuit;
use acvm::ProofSystemCompiler;
use noirc_abi::WitnessMap;

use crate::NargoError;

pub fn prove(
backend: &impl ProofSystemCompiler,
circuit: &Circuit,
solved_witness: WitnessMap,
proving_key: &[u8],
) -> Result<Vec<u8>, NargoError> {
let proof = backend.prove_with_pk(circuit, solved_witness, proving_key);

Ok(proof)
}
17 changes: 17 additions & 0 deletions crates/nargo/src/ops/verify.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use acvm::acir::circuit::Circuit;
use acvm::ProofSystemCompiler;
use noirc_abi::WitnessMap;

use crate::NargoError;

pub fn verify_proof(
backend: &impl ProofSystemCompiler,
circuit: &Circuit,
proof: &[u8],
public_inputs: WitnessMap,
verification_key: &[u8],
) -> Result<bool, NargoError> {
let valid_proof = backend.verify_with_vk(proof, public_inputs, circuit, verification_key);

Ok(valid_proof)
}
6 changes: 4 additions & 2 deletions crates/nargo_cli/src/cli/codegen_verifier_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ pub(crate) struct CodegenVerifierCommand {
}

pub(crate) fn run(args: CodegenVerifierCommand, config: NargoConfig) -> Result<(), CliError> {
let compiled_program = compile_circuit(&config.program_dir, &args.compile_options)?;

let backend = crate::backends::ConcreteBackend;

let compiled_program = compile_circuit(&backend, &config.program_dir, &args.compile_options)?;

// TODO: replace with `nargo::ops::codegen_verifier`
#[allow(deprecated)]
let smart_contract_string = backend.eth_contract_from_cs(compiled_program.circuit);

Expand Down
23 changes: 15 additions & 8 deletions crates/nargo_cli/src/cli/compile_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use std::path::Path;

use clap::Args;

use crate::preprocess::{preprocess_contract, preprocess_program};
use nargo::ops::{preprocess_contract, preprocess_program};

use crate::resolver::DependencyResolutionError;
use crate::{constants::TARGET_DIR, errors::CliError, resolver::Resolver};

Expand All @@ -29,33 +30,39 @@ pub(crate) struct CompileCommand {
pub(crate) fn run(args: CompileCommand, config: NargoConfig) -> Result<(), CliError> {
let circuit_dir = config.program_dir.join(TARGET_DIR);

let backend = crate::backends::ConcreteBackend;

// If contracts is set we're compiling every function in a 'contract' rather than just 'main'.
if args.contracts {
let mut driver = setup_driver(&config.program_dir)?;
let mut driver = setup_driver(&backend, &config.program_dir)?;
let compiled_contracts = driver
.compile_contracts(&args.compile_options)
.map_err(|_| CliError::CompilationError)?;
let preprocessed_contracts = vecmap(compiled_contracts, preprocess_contract);
let preprocessed_contracts =
vecmap(compiled_contracts, |contract| preprocess_contract(&backend, contract));
for contract in preprocessed_contracts {
save_contract_to_file(&contract, &args.circuit_name, &circuit_dir);
}
} else {
let program = compile_circuit(&config.program_dir, &args.compile_options)?;
let preprocessed_program = preprocess_program(program);
let program = compile_circuit(&backend, &config.program_dir, &args.compile_options)?;
let preprocessed_program = preprocess_program(&backend, program);
save_program_to_file(&preprocessed_program, &args.circuit_name, circuit_dir);
}
Ok(())
}

fn setup_driver(program_dir: &Path) -> Result<Driver, DependencyResolutionError> {
let backend = crate::backends::ConcreteBackend;
fn setup_driver(
backend: &impl ProofSystemCompiler,
program_dir: &Path,
) -> Result<Driver, DependencyResolutionError> {
Resolver::resolve_root_manifest(program_dir, backend.np_language())
}

pub(crate) fn compile_circuit(
backend: &impl ProofSystemCompiler,
program_dir: &Path,
compile_options: &CompileOptions,
) -> Result<CompiledProgram, CliError> {
let mut driver = setup_driver(program_dir)?;
let mut driver = setup_driver(backend, program_dir)?;
driver.compile_main(compile_options).map_err(|_| CliError::CompilationError)
}
Loading

0 comments on commit 65d7849

Please sign in to comment.