Skip to content

Commit

Permalink
feat: switch bb over to read ACIR from nargo artifacts
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench committed May 8, 2024
1 parent 9192882 commit 67aafd7
Show file tree
Hide file tree
Showing 13 changed files with 399 additions and 429 deletions.
4 changes: 2 additions & 2 deletions barretenberg/cpp/src/barretenberg/bb/get_bytecode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
*/
inline std::vector<uint8_t> get_bytecode(const std::string& bytecodePath)
{
std::string command = "gunzip -c \"" + bytecodePath + "\"";
std::string command = "jq -r '.bytecode' \"" + bytecodePath + "\" | base64 -d | gunzip -c";
return exec_pipe(command);
}
}
6 changes: 3 additions & 3 deletions noir/noir-repo/tooling/backend_interface/src/cli/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ fn contract_command() -> Result<(), BackendError> {

let temp_directory = tempdir().expect("could not create a temporary directory");
let temp_directory_path = temp_directory.path();
let bytecode_path = temp_directory_path.join("acir.gz");
let artifact_path = temp_directory_path.join("program.json");
let vk_path = temp_directory_path.join("vk");

let crs_path = backend.backend_directory();

std::fs::File::create(&bytecode_path).expect("file should be created");
std::fs::File::create(&artifact_path).expect("file should be created");

let write_vk_command = super::WriteVkCommand {
bytecode_path,
artifact_path,
vk_path_output: vk_path.clone(),
crs_path: crs_path.clone(),
};
Expand Down
10 changes: 5 additions & 5 deletions noir/noir-repo/tooling/backend_interface/src/cli/gates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use super::string_from_stderr;
/// for the given bytecode.
pub(crate) struct GatesCommand {
pub(crate) crs_path: PathBuf,
pub(crate) bytecode_path: PathBuf,
pub(crate) artifact_path: PathBuf,
}

impl GatesCommand {
Expand All @@ -19,7 +19,7 @@ impl GatesCommand {
.arg("-c")
.arg(self.crs_path)
.arg("-b")
.arg(self.bytecode_path)
.arg(self.artifact_path)
.output()?;

if !output.status.success() {
Expand Down Expand Up @@ -49,12 +49,12 @@ fn gate_command() -> Result<(), BackendError> {

let temp_directory = tempdir().expect("could not create a temporary directory");
let temp_directory_path = temp_directory.path();
let bytecode_path = temp_directory_path.join("acir.gz");
let artifact_path = temp_directory_path.join("program.json");
let crs_path = backend.backend_directory();

std::fs::File::create(&bytecode_path).expect("file should be created");
std::fs::File::create(&artifact_path).expect("file should be created");

let gate_command = GatesCommand { crs_path, bytecode_path };
let gate_command = GatesCommand { crs_path, artifact_path };

let output = gate_command.run(backend.binary_path())?;
// Mock backend always returns zero gates.
Expand Down
10 changes: 5 additions & 5 deletions noir/noir-repo/tooling/backend_interface/src/cli/prove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use super::string_from_stderr;
/// The proof will be written to the specified output file.
pub(crate) struct ProveCommand {
pub(crate) crs_path: PathBuf,
pub(crate) bytecode_path: PathBuf,
pub(crate) artifact_path: PathBuf,
pub(crate) witness_path: PathBuf,
}

Expand All @@ -26,7 +26,7 @@ impl ProveCommand {
.arg("-c")
.arg(self.crs_path)
.arg("-b")
.arg(self.bytecode_path)
.arg(self.artifact_path)
.arg("-w")
.arg(self.witness_path)
.arg("-o")
Expand All @@ -49,14 +49,14 @@ fn prove_command() -> Result<(), BackendError> {

let temp_directory = tempdir().expect("could not create a temporary directory");
let temp_directory_path = temp_directory.path();
let bytecode_path = temp_directory_path.join("acir.gz");
let artifact_path = temp_directory_path.join("acir.gz");
let witness_path = temp_directory_path.join("witness.tr");

std::fs::File::create(&bytecode_path).expect("file should be created");
std::fs::File::create(&artifact_path).expect("file should be created");
std::fs::File::create(&witness_path).expect("file should be created");

let crs_path = backend.backend_directory();
let prove_command = ProveCommand { crs_path, bytecode_path, witness_path };
let prove_command = ProveCommand { crs_path, artifact_path, witness_path };

let proof = prove_command.run(backend.binary_path())?;
assert_eq!(proof, "proof".as_bytes());
Expand Down
8 changes: 4 additions & 4 deletions noir/noir-repo/tooling/backend_interface/src/cli/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,25 +41,25 @@ fn verify_command() -> Result<(), BackendError> {

let temp_directory = tempdir().expect("could not create a temporary directory");
let temp_directory_path = temp_directory.path();
let bytecode_path = temp_directory_path.join("acir.gz");
let artifact_path = temp_directory_path.join("acir.json");
let witness_path = temp_directory_path.join("witness.tr");
let proof_path = temp_directory_path.join("1_mul.proof");
let vk_path_output = temp_directory_path.join("vk");

let crs_path = backend.backend_directory();

std::fs::File::create(&bytecode_path).expect("file should be created");
std::fs::File::create(&artifact_path).expect("file should be created");
std::fs::File::create(&witness_path).expect("file should be created");

let write_vk_command = WriteVkCommand {
bytecode_path: bytecode_path.clone(),
artifact_path: artifact_path.clone(),
crs_path: crs_path.clone(),
vk_path_output: vk_path_output.clone(),
};

write_vk_command.run(backend.binary_path())?;

let prove_command = ProveCommand { crs_path: crs_path.clone(), bytecode_path, witness_path };
let prove_command = ProveCommand { crs_path: crs_path.clone(), artifact_path, witness_path };
let proof = prove_command.run(backend.binary_path())?;

write_to_file(&proof, &proof_path);
Expand Down
10 changes: 5 additions & 5 deletions noir/noir-repo/tooling/backend_interface/src/cli/write_vk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::BackendError;
/// to write a verification key to a file
pub(crate) struct WriteVkCommand {
pub(crate) crs_path: PathBuf,
pub(crate) bytecode_path: PathBuf,
pub(crate) artifact_path: PathBuf,
pub(crate) vk_path_output: PathBuf,
}

Expand All @@ -21,7 +21,7 @@ impl WriteVkCommand {
.arg("-c")
.arg(self.crs_path)
.arg("-b")
.arg(self.bytecode_path)
.arg(self.artifact_path)
.arg("-o")
.arg(self.vk_path_output);

Expand All @@ -42,14 +42,14 @@ fn write_vk_command() -> Result<(), BackendError> {

let temp_directory = tempdir().expect("could not create a temporary directory");
let temp_directory_path = temp_directory.path();
let bytecode_path = temp_directory_path.join("acir.gz");
let artifact_path = temp_directory_path.join("program.json");
let vk_path_output = temp_directory.path().join("vk");

let crs_path = backend.backend_directory();

std::fs::File::create(&bytecode_path).expect("file should be created");
std::fs::File::create(&artifact_path).expect("file should be created");

let write_vk_command = WriteVkCommand { bytecode_path, crs_path, vk_path_output };
let write_vk_command = WriteVkCommand { artifact_path, crs_path, vk_path_output };

write_vk_command.run(backend.binary_path())?;
drop(temp_directory);
Expand Down
49 changes: 12 additions & 37 deletions noir/noir-repo/tooling/backend_interface/src/proof_system.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::{fs::File, path::PathBuf};

use acvm::acir::{
circuit::{ExpressionWidth, Program},
circuit::ExpressionWidth,
native_types::{WitnessMap, WitnessStack},
};
use acvm::FieldElement;
Expand All @@ -17,20 +17,11 @@ use crate::cli::{
use crate::{Backend, BackendError};

impl Backend {
pub fn get_exact_circuit_size(&self, program: &Program) -> Result<u32, BackendError> {
pub fn get_exact_circuit_size(&self, artifact_path: PathBuf) -> Result<u32, BackendError> {
let binary_path = self.assert_binary_exists()?;
self.assert_correct_version()?;

let temp_directory = tempdir().expect("could not create a temporary directory");
let temp_directory = temp_directory.path().to_path_buf();

// Create a temporary file for the circuit
let circuit_path = temp_directory.join("circuit").with_extension("bytecode");
let serialized_program = Program::serialize_program(program);
write_to_file(&serialized_program, &circuit_path);

GatesCommand { crs_path: self.crs_directory(), bytecode_path: circuit_path }
.run(binary_path)
GatesCommand { crs_path: self.crs_directory(), artifact_path }.run(binary_path)
}

pub fn get_backend_info(&self) -> Result<ExpressionWidth, BackendError> {
Expand All @@ -55,8 +46,9 @@ impl Backend {
#[tracing::instrument(level = "trace", skip_all)]
pub fn prove(
&self,
program: &Program,
artifact_path: PathBuf,
witness_stack: WitnessStack,
num_public_inputs: u32,
) -> Result<Vec<u8>, BackendError> {
let binary_path = self.assert_binary_exists()?;
self.assert_correct_version()?;
Expand All @@ -70,20 +62,14 @@ impl Backend {
let witness_path = temp_directory.join("witness").with_extension("tr");
write_to_file(&serialized_witnesses, &witness_path);

// Create a temporary file for the circuit
//
let bytecode_path = temp_directory.join("program").with_extension("bytecode");
let serialized_program = Program::serialize_program(program);
write_to_file(&serialized_program, &bytecode_path);

// Create proof and store it in the specified path
let proof_with_public_inputs =
ProveCommand { crs_path: self.crs_directory(), bytecode_path, witness_path }
ProveCommand { crs_path: self.crs_directory(), artifact_path, witness_path }
.run(binary_path)?;

let proof = bb_abstraction_leaks::remove_public_inputs(
// TODO(https://github.com/noir-lang/noir/issues/4428)
program.functions[0].public_inputs().0.len(),
num_public_inputs as usize,
&proof_with_public_inputs,
);
Ok(proof)
Expand All @@ -94,7 +80,7 @@ impl Backend {
&self,
proof: &[u8],
public_inputs: WitnessMap,
program: &Program,
artifact_path: PathBuf,
) -> Result<bool, BackendError> {
let binary_path = self.assert_binary_exists()?;
self.assert_correct_version()?;
Expand All @@ -108,17 +94,12 @@ impl Backend {
let proof_path = temp_directory.join("proof").with_extension("proof");
write_to_file(&proof_with_public_inputs, &proof_path);

// Create a temporary file for the circuit
let bytecode_path = temp_directory.join("program").with_extension("bytecode");
let serialized_program = Program::serialize_program(program);
write_to_file(&serialized_program, &bytecode_path);

// Create the verification key and write it to the specified path
let vk_path = temp_directory.join("vk");

WriteVkCommand {
crs_path: self.crs_directory(),
bytecode_path,
artifact_path,
vk_path_output: vk_path.clone(),
}
.run(binary_path)?;
Expand All @@ -129,7 +110,7 @@ impl Backend {

pub fn get_intermediate_proof_artifacts(
&self,
program: &Program,
artifact_path: PathBuf,
proof: &[u8],
public_inputs: WitnessMap,
) -> Result<(Vec<FieldElement>, FieldElement, Vec<FieldElement>), BackendError> {
Expand All @@ -139,18 +120,12 @@ impl Backend {
let temp_directory = tempdir().expect("could not create a temporary directory");
let temp_directory = temp_directory.path().to_path_buf();

// Create a temporary file for the circuit
//
let bytecode_path = temp_directory.join("program").with_extension("bytecode");
let serialized_program = Program::serialize_program(program);
write_to_file(&serialized_program, &bytecode_path);

// Create the verification key and write it to the specified path
let vk_path = temp_directory.join("vk");

WriteVkCommand {
crs_path: self.crs_directory(),
bytecode_path,
artifact_path,
vk_path_output: vk_path.clone(),
}
.run(binary_path)?;
Expand Down
43 changes: 14 additions & 29 deletions noir/noir-repo/tooling/backend_interface/src/smart_contract.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,25 @@
use super::proof_system::write_to_file;
use std::path::PathBuf;

use crate::{
cli::{ContractCommand, WriteVkCommand},
Backend, BackendError,
};
use acvm::acir::circuit::Program;
use tempfile::tempdir;

impl Backend {
pub fn eth_contract(&self, program: &Program) -> Result<String, BackendError> {
pub fn eth_contract(&self, artifact_path: PathBuf) -> Result<String, BackendError> {
let binary_path = self.assert_binary_exists()?;
self.assert_correct_version()?;

let temp_directory = tempdir().expect("could not create a temporary directory");
let temp_directory_path = temp_directory.path().to_path_buf();

// Create a temporary file for the circuit
let bytecode_path = temp_directory_path.join("program").with_extension("bytecode");
let serialized_program = Program::serialize_program(program);
write_to_file(&serialized_program, &bytecode_path);

// Create the verification key and write it to the specified path
let vk_path = temp_directory_path.join("vk");

WriteVkCommand {
crs_path: self.crs_directory(),
bytecode_path,
artifact_path,
vk_path_output: vk_path.clone(),
}
.run(binary_path)?;
Expand All @@ -35,33 +30,23 @@ impl Backend {

#[cfg(test)]
mod tests {
use std::collections::BTreeSet;

use acvm::acir::{
circuit::{Circuit, ExpressionWidth, Opcode, Program, PublicInputs},
native_types::{Expression, Witness},
};
use serde_json::json;
use tempfile::tempdir;

use crate::{get_mock_backend, BackendError};
use crate::{get_mock_backend, proof_system::write_to_file, BackendError};

#[test]
fn test_smart_contract() -> Result<(), BackendError> {
let expression = &(Witness(1) + Witness(2)) - &Expression::from(Witness(3));
let constraint = Opcode::AssertZero(expression);
let dummy_artifact = json!({"bytecode": ""});
let artifact_bytes = serde_json::to_vec(&dummy_artifact).unwrap();

let circuit = Circuit {
current_witness_index: 4,
expression_width: ExpressionWidth::Bounded { width: 4 },
opcodes: vec![constraint],
private_parameters: BTreeSet::from([Witness(1), Witness(2)]),
public_parameters: PublicInputs::default(),
return_values: PublicInputs::default(),
assert_messages: Default::default(),
recursive: false,
};
let program = Program { functions: vec![circuit], unconstrained_functions: Vec::new() };
let temp_directory = tempdir().expect("could not create a temporary directory");
let temp_directory_path = temp_directory.path();
let artifact_path = temp_directory_path.join("program.json");
write_to_file(&artifact_bytes, &artifact_path);

let contract = get_mock_backend()?.eth_contract(&program)?;
let contract = get_mock_backend()?.eth_contract(artifact_path)?;

assert!(contract.contains("contract VerifierContract"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@ pub(crate) fn run(
let binary_packages = workspace.into_iter().filter(|package| package.is_binary());
for package in binary_packages {
let program_artifact_path = workspace.package_build_path(package);
let program: CompiledProgram = read_program_from_file(program_artifact_path)?.into();
let program: CompiledProgram = read_program_from_file(&program_artifact_path)?.into();

// TODO(https://github.com/noir-lang/noir/issues/4428):
// We do not expect to have a smart contract verifier for a foldable program with multiple circuits.
// However, in the future we can expect to possibly have non-inlined ACIR functions during compilation
// that will be inlined at a later step such as by the ACVM compiler or by the backend.
// Add appropriate handling here once the compiler enables multiple ACIR functions.
assert_eq!(program.program.functions.len(), 1);
let smart_contract_string = backend.eth_contract(&program.program)?;
let smart_contract_string = backend.eth_contract(program_artifact_path)?;

let contract_dir = workspace.contracts_directory_path(package);
create_named_dir(&contract_dir, "contract");
Expand Down
Loading

0 comments on commit 67aafd7

Please sign in to comment.