Skip to content

Commit

Permalink
prove&verify definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
Okm165 committed Mar 24, 2024
1 parent ee8dabf commit fc734c1
Show file tree
Hide file tree
Showing 12 changed files with 268 additions and 9 deletions.
17 changes: 14 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["aztec-packages/barretenberg/bb_rs", "crates/noir_rs"]
members = ["aztec-packages/barretenberg/bb_rs", "crates/nargo", "crates/noir_rs"]
resolver = "2"

[workspace.package]
Expand All @@ -10,8 +10,19 @@ authors = ["Bartosz Nowak"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[workspace.dependencies]
thiserror = "1.0.58"
acir = "0.41.0"
acvm = "0.41.0"
acvm_blackbox_solver = "0.41.0"
bn254_blackbox_solver = "0.39.0"
base64 = "0.22.0"
bb_rs = { path = "aztec-packages/barretenberg/bb_rs" }
noir_rs = { path = "crates/noir_rs" }
nargo = { path = "crates/nargo" }
bincode = "1.3.3"
flate2 = "1.0.28"
hex = "0.4.3"
reqwest = { version = "0.12.1", features = ["blocking"] }
serde = "1.0.197"
thiserror = "1.0.58"
tracing = "0.1"
tracing-subscriber = "0.3"
reqwest = { version = "0.12.1", features = ["blocking"] }
23 changes: 23 additions & 0 deletions crates/nargo/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "nargo"
version.workspace = true
edition.workspace = true
authors.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
acir.workspace = true
acvm.workspace = true
acvm_blackbox_solver.workspace = true
bn254_blackbox_solver.workspace = true
base64.workspace = true
bb_rs.workspace = true
bincode.workspace = true
flate2.workspace = true
hex.workspace = true
reqwest.workspace = true
serde.workspace = true
thiserror.workspace = true
tracing-subscriber.workspace = true
tracing.workspace = true
48 changes: 48 additions & 0 deletions crates/nargo/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use acvm::{acir::circuit::OpcodeLocation, pwg::OpcodeResolutionError};

use thiserror::Error;

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

/// ACIR circuit execution error
#[error(transparent)]
ExecutionError(#[from] ExecutionError),
}

impl NargoError {
/// Extracts the user defined failure message from the ExecutionError
/// If one exists.
///
/// We want to extract the user defined error so that we can compare it
/// in tests to expected failure messages
pub fn user_defined_failure_message(&self) -> Option<&str> {
let execution_error = match self {
NargoError::ExecutionError(error) => error,
_ => return None,
};

match execution_error {
ExecutionError::AssertionFailed(message, _) => Some(message),
ExecutionError::SolvingError(error) => match error {
OpcodeResolutionError::IndexOutOfBounds { .. }
| OpcodeResolutionError::OpcodeNotSolvable(_)
| OpcodeResolutionError::UnsatisfiedConstrain { .. } => None,
OpcodeResolutionError::BrilligFunctionFailed { message, .. } => Some(message),
OpcodeResolutionError::BlackBoxFunctionFailed(_, reason) => Some(reason),
},
}
}
}

#[derive(Debug, Error)]
pub enum ExecutionError {
#[error("Failed assertion: '{}'", .0)]
AssertionFailed(String, Vec<OpcodeLocation>),

#[error(transparent)]
SolvingError(#[from] OpcodeResolutionError),
}
2 changes: 2 additions & 0 deletions crates/nargo/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod errors;
pub mod ops;
61 changes: 61 additions & 0 deletions crates/nargo/src/ops/execute.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use acir::{circuit::Circuit, native_types::WitnessMap};
use acvm::{
pwg::{ACVMStatus, ErrorLocation, OpcodeResolutionError, ACVM},
BlackBoxFunctionSolver,
};

use crate::errors::{ExecutionError, NargoError};

pub fn execute_circuit<B: BlackBoxFunctionSolver>(
circuit: &Circuit,
initial_witness: WitnessMap,
blackbox_solver: &B,
) -> Result<WitnessMap, NargoError> {
let mut acvm = ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness);

// This message should be resolved by a nargo foreign call only when we have an unsatisfied assertion.
let assert_message: Option<String> = None;
loop {
let solver_status = acvm.solve();

match solver_status {
ACVMStatus::Solved => break,
ACVMStatus::InProgress => {
unreachable!("Execution should not stop while in `InProgress` state.")
}
ACVMStatus::Failure(error) => {
let call_stack = match &error {
OpcodeResolutionError::UnsatisfiedConstrain {
opcode_location: ErrorLocation::Resolved(opcode_location),
} => Some(vec![*opcode_location]),
OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => {
Some(call_stack.clone())
}
_ => None,
};

return Err(NargoError::ExecutionError(match call_stack {
Some(call_stack) => {
// First check whether we have a runtime assertion message that should be resolved on an ACVM failure
// If we do not have a runtime assertion message, we should check whether the circuit has any hardcoded
// messages associated with a specific `OpcodeLocation`.
// Otherwise return the provided opcode resolution error.
if let Some(assert_message) = assert_message {
ExecutionError::AssertionFailed(assert_message.to_owned(), call_stack)
} else if let Some(assert_message) = circuit.get_assert_message(
*call_stack.last().expect("Call stacks should not be empty"),
) {
ExecutionError::AssertionFailed(assert_message.to_owned(), call_stack)
} else {
ExecutionError::SolvingError(error)
}
}
None => ExecutionError::SolvingError(error),
}));
}
ACVMStatus::RequiresForeignCall(_foreign_call) => {}
}
}

Ok(acvm.finalize())
}
1 change: 1 addition & 0 deletions crates/nargo/src/ops/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod execute;
15 changes: 13 additions & 2 deletions crates/noir_rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,18 @@ authors.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
acir.workspace = true
nargo.workspace = true
acvm.workspace = true
acvm_blackbox_solver.workspace = true
bn254_blackbox_solver.workspace = true
base64.workspace = true
bb_rs.workspace = true
tracing.workspace = true
bincode.workspace = true
flate2.workspace = true
hex.workspace = true
reqwest.workspace = true
serde.workspace = true
thiserror.workspace = true
tracing-subscriber.workspace = true
reqwest.workspace = true
tracing.workspace = true
2 changes: 2 additions & 0 deletions crates/noir_rs/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use tracing_subscriber;

pub mod netsrs;
pub mod prove;
pub mod verify;

fn main() {
tracing_subscriber::fmt::init();
Expand Down
12 changes: 9 additions & 3 deletions crates/noir_rs/src/netsrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ impl NetSrs {
let g1_end: u32 = G1_START + num_points * 64 - 1;

let mut headers = HeaderMap::new();
headers.insert(RANGE, format!("bytes={}-{}", G1_START, g1_end).parse().unwrap());
headers.insert(
RANGE,
format!("bytes={}-{}", G1_START, g1_end).parse().unwrap(),
);

let response = Client::new()
.get(
Expand All @@ -55,7 +58,10 @@ impl NetSrs {
const G2_END: usize = G2_START + 128 - 1;

let mut headers = HeaderMap::new();
headers.insert(RANGE, format!("bytes={}-{}", G2_START, G2_END).parse().unwrap());
headers.insert(
RANGE,
format!("bytes={}-{}", G2_START, G2_END).parse().unwrap(),
);

let response = Client::new()
.get(
Expand All @@ -67,4 +73,4 @@ impl NetSrs {

response.bytes().unwrap().to_vec()
}
}
}
57 changes: 57 additions & 0 deletions crates/noir_rs/src/prove.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use std::io::Read;

use acir::{circuit::Circuit, native_types::WitnessMap};
use base64::{engine::general_purpose, Engine};
use bb_rs::barretenberg_api::{
acir::{acir_create_proof, acir_get_verification_key, get_circuit_sizes, new_acir_composer},
srs::init_srs,
};
use bn254_blackbox_solver::Bn254BlackBoxSolver;
use flate2::bufread::GzDecoder;
use nargo::ops::execute::execute_circuit;

use crate::netsrs::NetSrs;

pub fn prove(
circuit_bytecode: String,
initial_witness: WitnessMap,
) -> Result<(Vec<u8>, Vec<u8>), String> {
let acir_buffer = general_purpose::STANDARD
.decode(circuit_bytecode)
.map_err(|e| e.to_string())?;

let circuit = Circuit::deserialize_circuit(&acir_buffer).map_err(|e| e.to_string())?;

let mut decoder = GzDecoder::new(acir_buffer.as_slice());
let mut acir_buffer_uncompressed = Vec::<u8>::new();
decoder
.read_to_end(&mut acir_buffer_uncompressed)
.map_err(|e| e.to_string())?;

let blackbox_solver = Bn254BlackBoxSolver::new();

let solved_witness =
execute_circuit(&circuit, initial_witness, &blackbox_solver).map_err(|e| e.to_string())?;
let serialized_solved_witness =
bincode::serialize(&solved_witness).map_err(|e| e.to_string())?;

let circuit_size = unsafe { get_circuit_sizes(&acir_buffer_uncompressed) };
let log_value = (circuit_size.total as f64).log2().ceil() as u32;
let subgroup_size = 2u32.pow(log_value);

let srs = NetSrs::new(subgroup_size + 1);
unsafe { init_srs(&srs.data, srs.num_points, &srs.g2_data) };

let mut acir_ptr = unsafe { new_acir_composer(subgroup_size) };

Ok((
unsafe {
acir_create_proof(
&mut acir_ptr,
&acir_buffer_uncompressed,
&serialized_solved_witness,
)
},
unsafe { acir_get_verification_key(&mut acir_ptr) },
))
}
37 changes: 37 additions & 0 deletions crates/noir_rs/src/verify.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::io::Read;

use base64::{engine::general_purpose, Engine};
use bb_rs::barretenberg_api::{
acir::{acir_load_verification_key, acir_verify_proof, get_circuit_sizes, new_acir_composer},
srs::init_srs,
};
use flate2::bufread::GzDecoder;

use crate::netsrs::NetSrs;

pub fn verify(
circuit_bytecode: String,
proof: Vec<u8>,
verification_key: Vec<u8>,
) -> Result<bool, String> {
let acir_buffer = general_purpose::STANDARD
.decode(circuit_bytecode)
.map_err(|e| e.to_string())?;

let mut decoder = GzDecoder::new(acir_buffer.as_slice());
let mut acir_buffer_uncompressed = Vec::<u8>::new();
decoder
.read_to_end(&mut acir_buffer_uncompressed)
.map_err(|e| e.to_string())?;

let circuit_size = unsafe { get_circuit_sizes(&acir_buffer_uncompressed) };
let log_value = (circuit_size.total as f64).log2().ceil() as u32;
let subgroup_size = 2u32.pow(log_value);

let srs = NetSrs::new(subgroup_size + 1);
unsafe { init_srs(&srs.data, srs.num_points, &srs.g2_data) };

let mut acir_ptr = unsafe { new_acir_composer(subgroup_size) };
unsafe { acir_load_verification_key(&mut acir_ptr, &verification_key) };
Ok(unsafe { acir_verify_proof(&mut acir_ptr, &proof) })
}

0 comments on commit fc734c1

Please sign in to comment.