Skip to content

Commit

Permalink
get_circuit_sizes not working on first circuit of the program
Browse files Browse the repository at this point in the history
  • Loading branch information
Okm165 committed Apr 27, 2024
1 parent 9138db7 commit 13c8656
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 111 deletions.
11 changes: 5 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,18 @@ authors = ["Bartosz Nowak"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[workspace.dependencies]
acir = "0.41.0"
acvm = "0.41.0"
acvm_blackbox_solver = "0.41.0"
acvm = "0.43.0"
acvm_blackbox_solver = "0.43.0"
base64 = "0.22.0"
bb_rs = {git = "https://github.com/Okm165/aztec-packages.git", branch = "v0.27.0"}
bincode = "1.3.3"
bn254_blackbox_solver = "0.39.0"
bn254_blackbox_solver = "0.43.0"
flate2 = "1.0.28"
hex = "0.4.3"
nargo = { path = "crates/nargo" }
noir_rs = { path = "crates/noir_rs" }
reqwest = { version = "0.12.1", features = ["blocking"] }
serde = "1.0.197"
thiserror = "1.0.58"
serde = "1"
thiserror = "1"
tracing = "0.1"
tracing-subscriber = "0.3"
5 changes: 2 additions & 3 deletions crates/nargo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ 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
acvm.workspace = true
base64.workspace = true
bb_rs.workspace = true
bincode.workspace = true
bn254_blackbox_solver.workspace = true
flate2.workspace = true
hex.workspace = true
reqwest.workspace = true
Expand Down
4 changes: 3 additions & 1 deletion crates/nargo/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ impl NargoError {
ExecutionError::SolvingError(error) => match error {
OpcodeResolutionError::IndexOutOfBounds { .. }
| OpcodeResolutionError::OpcodeNotSolvable(_)
| OpcodeResolutionError::UnsatisfiedConstrain { .. } => None,
| OpcodeResolutionError::UnsatisfiedConstrain { .. }
| OpcodeResolutionError::AcirMainCallAttempted { .. }
| OpcodeResolutionError::AcirCallOutputsMismatch { .. } => None,
OpcodeResolutionError::BrilligFunctionFailed { message, .. } => Some(message),
OpcodeResolutionError::BlackBoxFunctionFailed(_, reason) => Some(reason),
},
Expand Down
164 changes: 113 additions & 51 deletions crates/nargo/src/ops/execute.rs
Original file line number Diff line number Diff line change
@@ -1,61 +1,123 @@
use acir::{circuit::Circuit, native_types::WitnessMap};
use acvm::{
pwg::{ACVMStatus, ErrorLocation, OpcodeResolutionError, ACVM},
BlackBoxFunctionSolver,
};

use crate::errors::{ExecutionError, NargoError};
use acvm::acir::circuit::Program;
use acvm::acir::native_types::WitnessStack;
use acvm::pwg::{ACVMStatus, ErrorLocation, OpcodeNotSolvable, OpcodeResolutionError, ACVM};
use acvm::BlackBoxFunctionSolver;
use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap};

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)
struct ProgramExecutor<'a, B: BlackBoxFunctionSolver> {
functions: &'a [Circuit],
// This gets built as we run through the program looking at each function call
witness_stack: WitnessStack,

blackbox_solver: &'a B,
}

impl<'a, B: BlackBoxFunctionSolver> ProgramExecutor<'a, B> {
pub fn new(functions: &'a [Circuit], blackbox_solver: &'a B) -> Self {
ProgramExecutor {
functions,
witness_stack: WitnessStack::default(),
blackbox_solver,
}
}

pub fn finalize(self) -> WitnessStack {
self.witness_stack
}

pub fn execute_circuit(
&mut self,
circuit: &Circuit,
initial_witness: WitnessMap,
) -> Result<WitnessMap, NargoError> {
let mut acvm = ACVM::new(self.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) => {}
ACVMStatus::RequiresAcirCall(call_info) => {
let acir_to_call = &self.functions[call_info.id as usize];
let initial_witness = call_info.initial_witness;
let call_solved_witness =
self.execute_circuit(acir_to_call, initial_witness)?;
let mut call_resolved_outputs = Vec::new();
for return_witness_index in acir_to_call.return_values.indices() {
if let Some(return_value) =
call_solved_witness.get_index(return_witness_index)
{
call_resolved_outputs.push(*return_value);
} else {
ExecutionError::SolvingError(error)
return Err(ExecutionError::SolvingError(
OpcodeNotSolvable::MissingAssignment(return_witness_index).into(),
)
.into());
}
}
None => ExecutionError::SolvingError(error),
}));
acvm.resolve_pending_acir_call(call_resolved_outputs);
self.witness_stack.push(call_info.id, call_solved_witness);
}
}
ACVMStatus::RequiresForeignCall(_foreign_call) => {}
}

Ok(acvm.finalize())
}
}

pub fn execute_program<B: BlackBoxFunctionSolver>(
program: &Program,
initial_witness: WitnessMap,
blackbox_solver: &B,
) -> Result<WitnessStack, NargoError> {
let main = &program.functions[0];

let mut executor = ProgramExecutor::new(&program.functions, blackbox_solver);
let main_witness = executor.execute_circuit(main, initial_witness)?;
executor.witness_stack.push(0, main_witness);

Ok(acvm.finalize())
Ok(executor.finalize())
}
1 change: 0 additions & 1 deletion crates/noir_rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ authors.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
acir.workspace = true
acvm_blackbox_solver.workspace = true
acvm.workspace = true
base64.workspace = true
Expand Down
15 changes: 8 additions & 7 deletions crates/noir_rs/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use acir::{
native_types::{Witness, WitnessMap},
use acvm::{
acir::native_types::{Witness, WitnessMap},
FieldElement,
};
use prove::prove;
Expand All @@ -10,16 +10,17 @@ pub mod prove;
pub mod srs;
pub mod verify;

const BYTECODE: &str = "H4sIAAAAAAAA/7WUPQ7DIAyFTZNWHXsUm59gtlylqOT+J6iqqqmCiDfMW2CwzGc/mxkArnDWtJ/rfjpcvC/RFnL0RJsyB/QhL0xMgcPLsnOFPceUU8RE3hXaQnIb/lTnwj6RUeS66HHht2dG6KVpeol9Ik1m03j+n4WbwF/Htfd7FfdWrLV9t2V5CJwnD1ZFmBFmTgPyzqC7vCPqnvU9QhAGYkRPsVMGjuUxArP0kcAH+JIvC64FAAA=";
const BYTECODE: &str = "H4sIAAAAAAAA/7WUUQ6DIAyGqTK3192kFdDy5lVmhvc/wTKNmBEke7H8CaEJSfn4Wwpql17XTZ3Vxn2Ku8HB2jD2gQy9sPczO7RuHpiYHLt3z8YEtjz62Y/oyZpAi/NmwV1pLrwmAkGuRo4LN8+g4CVkXuI1kSQzZDW/x7gr8B96rKuJ8UeQ5WDYlPbkcZdOzruEBeRZSGW+5B48C/6caj8JwtRoorZCXq1kh0aNd2v5GqEqNEQNT/GiQP0+ERSY/w0w9QU2ntcLNgYAAA==";

fn main() {
tracing_subscriber::fmt::init();

let mut initial_witness = WitnessMap::new();
initial_witness.insert(Witness(1), FieldElement::zero());
initial_witness.insert(Witness(2), FieldElement::one());
initial_witness.insert(Witness(0), FieldElement::zero());
initial_witness.insert(Witness(1), FieldElement::one());

let (proof, vk) = prove(String::from(BYTECODE), initial_witness).unwrap();
let verdict = verify(String::from(BYTECODE), proof, vk).unwrap();
info!("proof verification verdict: {}", verdict);
// let verdict = verify(String::from(BYTECODE), proof, vk).unwrap();
// info!("proof verification verdict: {}", verdict);
todo!()
}
82 changes: 40 additions & 42 deletions crates/noir_rs/src/prove.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::io::Read;

use acir::{circuit::Circuit, native_types::WitnessMap};
use crate::srs::netsrs::NetSrs;
use acvm::acir::{
circuit::Program,
native_types::{WitnessMap, WitnessStack},
};
use base64::{engine::general_purpose, Engine};
use bb_rs::barretenberg_api::{
acir::{
Expand All @@ -11,52 +13,48 @@ use bb_rs::barretenberg_api::{
};
use bn254_blackbox_solver::Bn254BlackBoxSolver;
use flate2::bufread::GzDecoder;
use nargo::ops::execute::execute_circuit;

use crate::srs::netsrs::NetSrs;
use nargo::ops::execute::execute_program;
use std::io::Read;

pub fn prove(
circuit_bytecode: String,
initial_witness: WitnessMap,
) -> Result<(Vec<u8>, Vec<u8>), String> {
let acir_buffer = general_purpose::STANDARD
let bytecode = 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);

Ok(unsafe {
init_srs(&srs.g1_data, srs.num_points, &srs.g2_data);
let mut acir_ptr = new_acir_composer(subgroup_size);
acir_init_proving_key(&mut acir_ptr, &acir_buffer_uncompressed);
let result = (
acir_create_proof(
&mut acir_ptr,
&acir_buffer_uncompressed,
&serialized_solved_witness,
),
acir_get_verification_key(&mut acir_ptr),
);
delete_acir_composer(acir_ptr);
result
})
let program: Program = Program::deserialize_program(&bytecode).unwrap();

let witness_stack = execute_program(&program, initial_witness, &blackbox_solver).unwrap();
let _serialized_witnesses: Vec<u8> = witness_stack
.try_into()
.expect("could not serialize witness map");

let circuit = bincode::serialize(program.functions.first().unwrap()).unwrap();

let circuit_size = unsafe { get_circuit_sizes(&circuit) };

// 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);

// Ok(unsafe {
// init_srs(&srs.g1_data, srs.num_points, &srs.g2_data);
// let mut acir_ptr = new_acir_composer(subgroup_size);
// acir_init_proving_key(&mut acir_ptr, &acir_buffer_uncompressed);
// let result = (
// acir_create_proof(
// &mut acir_ptr,
// &acir_buffer_uncompressed,
// &serialized_solved_witness,
// ),
// acir_get_verification_key(&mut acir_ptr),
// );
// delete_acir_composer(acir_ptr);
// result
// })
todo!()
}

0 comments on commit 13c8656

Please sign in to comment.