Skip to content

Commit

Permalink
chore: standardize backend CLI command functions (#2517)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench authored Sep 1, 2023
1 parent 98a0694 commit 6bfac13
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 142 deletions.
Original file line number Diff line number Diff line change
@@ -1,30 +1,11 @@
// Reference: https://github.com/AztecProtocol/aztec-packages/blob/master/circuits/cpp/barretenberg/cpp/src/barretenberg/bb/main.cpp

mod contract;
mod gates;
mod prove;
mod verify;
mod write_vk;

use std::{io::Cursor, path::PathBuf};
use std::{io::Cursor, path::Path};

use const_format::formatcp;
pub(crate) use contract::ContractCommand;
pub(crate) use gates::GatesCommand;
pub(crate) use prove::ProveCommand;
pub(crate) use verify::VerifyCommand;
pub(crate) use write_vk::WriteVkCommand;

#[derive(Debug, thiserror::Error)]
#[error("Error communicating with barretenberg binary {0}")]
pub(crate) struct CliShimError(String);

const USERNAME: &str = "AztecProtocol";
const REPO: &str = "barretenberg";
const VERSION: &str = "0.4.6";
const TAG: &str = formatcp!("barretenberg-v{}", VERSION);
const DEST_FOLDER: &str = ".nargo/backends/acvm-backend-barretenberg";
const BINARY_NAME: &str = "backend_binary";

const API_URL: &str =
formatcp!("https://github.com/{}/{}/releases/download/{}", USERNAME, REPO, TAG);
Expand All @@ -50,27 +31,13 @@ fn get_bb_download_url() -> String {
format!("{API_URL}/{archive_name}")
}

/// Returns the path to the binary that was set by the `NARGO_BINARIES_PATH` environment variable
fn get_binary_path() -> PathBuf {
match std::env::var("BB_BINARY_PATH") {
Ok(path) => PathBuf::from(path),
Err(_) => dirs::home_dir().unwrap().join(formatcp!("{}/{}", DEST_FOLDER, BINARY_NAME)),
}
}

fn assert_binary_exists() {
if !get_binary_path().exists() {
download_bb_binary()
}
}

fn download_bb_binary() {
pub(crate) fn download_bb_binary(binary_path: &Path) {
use flate2::read::GzDecoder;
use tar::Archive;
use tempfile::tempdir;

// Create directory to place binary in.
std::fs::create_dir_all(get_binary_path().parent().unwrap()).unwrap();
std::fs::create_dir_all(binary_path.parent().unwrap()).unwrap();

// Download sources
let compressed_file: Cursor<Vec<u8>> = download_binary_from_url(&get_bb_download_url())
Expand All @@ -82,10 +49,10 @@ fn download_bb_binary() {

let temp_directory = tempdir().expect("could not create a temporary directory");
archive.unpack(&temp_directory).unwrap();
let binary_path = temp_directory.path().join("bb");
let temp_binary_path = temp_directory.path().join("bb");

// Rename the binary to the desired name
std::fs::copy(binary_path, get_binary_path()).unwrap();
std::fs::copy(temp_binary_path, binary_path).unwrap();

drop(temp_directory);
}
Expand All @@ -100,17 +67,3 @@ fn download_binary_from_url(url: &str) -> Result<Cursor<Vec<u8>>, String> {

Ok(Cursor::new(bytes.to_vec()))
}

#[test]
#[serial_test::serial]
fn no_command_provided_works() {
// This is a simple test to check that the binaries work

assert_binary_exists();

let output =
std::process::Command::new(get_binary_path()).output().expect("Failed to execute command");

let stderr = String::from_utf8_lossy(&output.stderr);
assert_eq!(stderr, "No command provided.\n");
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::path::PathBuf;
use std::path::{Path, PathBuf};

use super::{assert_binary_exists, get_binary_path, CliShimError};
use crate::BackendError;

/// VerifyCommand will call the barretenberg binary
/// to return a solidity library with the verification key
Expand All @@ -17,9 +17,8 @@ pub(crate) struct ContractCommand {
}

impl ContractCommand {
pub(crate) fn run(self) -> Result<(), CliShimError> {
assert_binary_exists();
let mut command = std::process::Command::new(get_binary_path());
pub(crate) fn run(self, binary_path: &Path) -> Result<(), BackendError> {
let mut command = std::process::Command::new(binary_path);

command
.arg("contract")
Expand All @@ -38,7 +37,7 @@ impl ContractCommand {
if output.status.success() {
Ok(())
} else {
Err(CliShimError(String::from_utf8(output.stderr).unwrap()))
Err(BackendError(String::from_utf8(output.stderr).unwrap()))
}
}
}
Expand All @@ -48,14 +47,17 @@ impl ContractCommand {
fn contract_command() {
use tempfile::tempdir;

let backend = crate::get_bb();

let bytecode_path = PathBuf::from("./src/1_mul.bytecode");

let temp_directory = tempdir().expect("could not create a temporary directory");
let temp_directory_path = temp_directory.path();
let crs_path = temp_directory_path.join("crs");
let vk_path = temp_directory_path.join("vk");
let contract_path = temp_directory_path.join("contract");

let crs_path = backend.backend_directory();

let write_vk_command = super::WriteVkCommand {
verbose: true,
bytecode_path,
Expand All @@ -64,10 +66,10 @@ fn contract_command() {
crs_path: crs_path.clone(),
};

assert!(write_vk_command.run().is_ok());
assert!(write_vk_command.run(&backend.binary_path()).is_ok());

let contract_command = ContractCommand { verbose: true, vk_path, crs_path, contract_path };

assert!(contract_command.run().is_ok());
assert!(contract_command.run(&backend.binary_path()).is_ok());
drop(temp_directory);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::path::PathBuf;
use std::path::{Path, PathBuf};

use super::{assert_binary_exists, get_binary_path};
use crate::BackendError;

/// GatesCommand will call the barretenberg binary
/// to return the number of gates needed to create a proof
Expand All @@ -11,9 +11,8 @@ pub(crate) struct GatesCommand {
}

impl GatesCommand {
pub(crate) fn run(self) -> u32 {
assert_binary_exists();
let output = std::process::Command::new(get_binary_path())
pub(crate) fn run(self, binary_path: &Path) -> Result<u32, BackendError> {
let output = std::process::Command::new(binary_path)
.arg("gates")
.arg("-c")
.arg(self.crs_path)
Expand All @@ -23,17 +22,17 @@ impl GatesCommand {
.expect("Failed to execute command");

if !output.status.success() {
panic!(
"gates command encountered an error: {}",
String::from_utf8_lossy(&output.stderr)
);
return Err(BackendError(String::from_utf8(output.stderr).unwrap()));
}
// Note: barretenberg includes the newline, so that subsequent prints to stdout
// are not on the same line as the gates output.

// Ensure we got the expected number of bytes
if output.stdout.len() != 8 {
panic!("Unexpected 8 bytes, received {}", output.stdout.len());
return Err(BackendError(format!(
"Unexpected 8 bytes, received {}",
output.stdout.len()
)));
}

// Convert bytes to u64 in little-endian format
Expand All @@ -48,24 +47,20 @@ impl GatesCommand {
output.stdout[7],
]);

value as u32
Ok(value as u32)
}
}

#[test]
#[serial_test::serial]
fn gate_command() {
use tempfile::tempdir;

let backend = crate::get_bb();
let bytecode_path = PathBuf::from("./src/1_mul.bytecode");

let temp_directory = tempdir().expect("could not create a temporary directory");
let temp_directory_path = temp_directory.path();
let crs_path = temp_directory_path.join("crs");
let crs_path = backend.backend_directory();

let gate_command = GatesCommand { crs_path, bytecode_path };

let output = gate_command.run();
let output = gate_command.run(&backend.binary_path()).unwrap();
assert_eq!(output, 2775);
drop(temp_directory);
}
28 changes: 28 additions & 0 deletions crates/acvm_backend_barretenberg/src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Reference: https://github.com/AztecProtocol/aztec-packages/blob/master/circuits/cpp/barretenberg/cpp/src/barretenberg/bb/main.cpp

mod contract;
mod gates;
mod prove;
mod verify;
mod write_vk;

pub(crate) use contract::ContractCommand;
pub(crate) use gates::GatesCommand;
pub(crate) use prove::ProveCommand;
pub(crate) use verify::VerifyCommand;
pub(crate) use write_vk::WriteVkCommand;

#[test]
#[serial_test::serial]
fn no_command_provided_works() {
// This is a simple test to check that the binaries work

let backend = crate::get_bb();

let output = std::process::Command::new(backend.binary_path())
.output()
.expect("Failed to execute command");

let stderr = String::from_utf8_lossy(&output.stderr);
assert_eq!(stderr, "No command provided.\n");
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::path::PathBuf;
use std::path::{Path, PathBuf};

use super::{assert_binary_exists, get_binary_path, CliShimError};
use crate::BackendError;

/// ProveCommand will call the barretenberg binary
/// to create a proof, given the witness and the bytecode.
Expand All @@ -19,9 +19,8 @@ pub(crate) struct ProveCommand {
}

impl ProveCommand {
pub(crate) fn run(self) -> Result<(), CliShimError> {
assert_binary_exists();
let mut command = std::process::Command::new(get_binary_path());
pub(crate) fn run(self, binary_path: &Path) -> Result<(), BackendError> {
let mut command = std::process::Command::new(binary_path);

command
.arg("prove")
Expand All @@ -42,11 +41,10 @@ impl ProveCommand {
}

let output = command.output().expect("Failed to execute command");

if output.status.success() {
Ok(())
} else {
Err(CliShimError(String::from_utf8(output.stderr).unwrap()))
Err(BackendError(String::from_utf8(output.stderr).unwrap()))
}
}
}
Expand All @@ -56,15 +54,15 @@ impl ProveCommand {
fn prove_command() {
use tempfile::tempdir;

let backend = crate::get_bb();

let bytecode_path = PathBuf::from("./src/1_mul.bytecode");
let witness_path = PathBuf::from("./src/witness.tr");

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

let crs_path = temp_directory_path.join("crs");
let proof_path = temp_directory_path.join("1_mul").with_extension("proof");
let proof_path = temp_directory.path().join("1_mul").with_extension("proof");

let crs_path = backend.backend_directory();
let prove_command = ProveCommand {
verbose: true,
crs_path,
Expand All @@ -74,7 +72,7 @@ fn prove_command() {
proof_path,
};

let proof_created = prove_command.run();
let proof_created = prove_command.run(&backend.binary_path());
assert!(proof_created.is_ok());
drop(temp_directory);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use std::path::PathBuf;

use super::{assert_binary_exists, get_binary_path};
use std::path::{Path, PathBuf};

/// VerifyCommand will call the barretenberg binary
/// to verify a proof
Expand All @@ -13,9 +11,8 @@ pub(crate) struct VerifyCommand {
}

impl VerifyCommand {
pub(crate) fn run(self) -> bool {
assert_binary_exists();
let mut command = std::process::Command::new(get_binary_path());
pub(crate) fn run(self, binary_path: &Path) -> bool {
let mut command = std::process::Command::new(binary_path);

command
.arg("verify")
Expand All @@ -34,6 +31,8 @@ impl VerifyCommand {
}

let output = command.output().expect("Failed to execute command");

// We currently do not distinguish between an invalid proof and an error inside the backend.
output.status.success()
}
}
Expand All @@ -43,18 +42,20 @@ impl VerifyCommand {
fn verify_command() {
use tempfile::tempdir;

use crate::bb::{ProveCommand, WriteVkCommand};
use super::{ProveCommand, WriteVkCommand};

let backend = crate::get_bb();

let bytecode_path = PathBuf::from("./src/1_mul.bytecode");
let witness_path = PathBuf::from("./src/witness.tr");

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

let crs_path = temp_directory_path.join("crs");
let proof_path = temp_directory_path.join("1_mul").with_extension("proof");
let vk_path_output = temp_directory_path.join("vk");

let crs_path = backend.backend_directory();

let write_vk_command = WriteVkCommand {
verbose: true,
bytecode_path: bytecode_path.clone(),
Expand All @@ -63,7 +64,7 @@ fn verify_command() {
vk_path_output: vk_path_output.clone(),
};

let vk_written = write_vk_command.run();
let vk_written = write_vk_command.run(&backend.binary_path());
assert!(vk_written.is_ok());

let prove_command = ProveCommand {
Expand All @@ -74,7 +75,7 @@ fn verify_command() {
witness_path,
proof_path: proof_path.clone(),
};
prove_command.run().unwrap();
prove_command.run(&backend.binary_path()).unwrap();

let verify_command = VerifyCommand {
verbose: true,
Expand All @@ -84,7 +85,7 @@ fn verify_command() {
vk_path: vk_path_output,
};

let verified = verify_command.run();
let verified = verify_command.run(&backend.binary_path());
assert!(verified);
drop(temp_directory);
}
Loading

0 comments on commit 6bfac13

Please sign in to comment.