Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(dsl): Update backend gateCount command to query a Program in a single request #6228

Merged
merged 23 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
746cf0f
update bb gateCount command to take in a program in a single request
vezenovm May 6, 2024
9fd25ef
Merge branch 'master' into mv/program-gate-count
vezenovm May 6, 2024
48ac058
rename and diff cleanup
vezenovm May 6, 2024
af66ca1
Merge remote-tracking branch 'origin/mv/program-gate-count' into mv/p…
vezenovm May 6, 2024
54bc28f
cargo clippy
vezenovm May 7, 2024
989f41a
update gate command test
vezenovm May 7, 2024
eb57f08
remove accidentally committed method
vezenovm May 7, 2024
6b97812
Merge branch 'master' into mv/program-gate-count
vezenovm May 7, 2024
0a3d833
Merge branch 'master' into mv/program-gate-count
vezenovm May 7, 2024
ce96f48
return json from gateCount and adapt nargo info to use it, also initi…
vezenovm May 8, 2024
1b2c761
remove earthfile changes and unnecessary imports
vezenovm May 8, 2024
77e65ce
update issue on gates report script
vezenovm May 8, 2024
577d462
merge conflicts w/ master
vezenovm May 8, 2024
2066168
revert only acir naming changes
vezenovm May 8, 2024
5139163
cleanup bb main and fix noir backend_interface gates test
vezenovm May 8, 2024
3bb1ae7
clippy
vezenovm May 8, 2024
312171e
merge conflicts
vezenovm May 8, 2024
ec4d253
bring back serde to backend_interface
vezenovm May 8, 2024
33ad378
add field to AcirFormat for gcc build?
vezenovm May 8, 2024
b85c5eb
Merge branch 'master' into mv/program-gate-count
TomAFrench May 8, 2024
e527d25
chore: fix tests
TomAFrench May 8, 2024
ca9b94c
chore: update test
TomAFrench May 8, 2024
aeaf948
Merge branch 'master' into mv/program-gate-count
TomAFrench May 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 31 additions & 7 deletions barretenberg/cpp/src/barretenberg/bb/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,19 +296,43 @@ void prove(const std::string& bytecodePath, const std::string& witnessPath, cons
* @brief Computes the number of Barretenberg specific gates needed to create a proof for the specific ACIR circuit
*
* Communication:
* - stdout: The number of gates is written to stdout
* - stdout: A JSON string of the number of ACIR opcodes and final backend circuit size
*
* @param bytecodePath Path to the file containing the serialized circuit
*/
void gateCount(const std::string& bytecodePath)
{
auto constraint_system = get_constraint_system(bytecodePath);
acir_proofs::AcirComposer acir_composer(0, verbose);
acir_composer.create_circuit(constraint_system);
auto gate_count = acir_composer.get_total_circuit_size();
// All circuit reports will be built into the string below
std::string functions_string = "{\"functions\": [\n ";
auto constraint_systems = get_constraint_systems(bytecodePath);
size_t i = 0;
for (auto constraint_system : constraint_systems) {
acir_proofs::AcirComposer acir_composer(0, verbose);
acir_composer.create_circuit(constraint_system);
auto circuit_size = acir_composer.get_total_circuit_size();

// Build individual circuit report
auto result_string = format("{\n \"acir_opcodes\": ",
constraint_system.num_acir_opcodes,
",\n \"circuit_size\": ",
circuit_size,
"\n }");

// Attach a comma if we still circuit reports to generate
if (i != (constraint_systems.size() - 1)) {
result_string = format(result_string, ",");
}

writeUint64AsRawBytesToStdout(static_cast<uint64_t>(gate_count));
vinfo("gate count: ", gate_count);
functions_string = format(functions_string, result_string);

i++;
}
functions_string = format(functions_string, "\n]}");

const char* jsonData = functions_string.c_str();
size_t length = strlen(jsonData);
std::vector<uint8_t> data(jsonData, jsonData + length);
writeRawBytesToStdout(data);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ struct AcirFormat {
// to be able to verify SNARKs on Ethereum.
bool recursive;

uint32_t num_acir_opcodes;

std::vector<uint32_t> public_inputs;

std::vector<LogicConstraint> logic_constraints;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ AcirFormat circuit_serde_to_acir_format(Program::Circuit const& circuit)
// `varnum` is the true number of variables, thus we add one to the index which starts at zero
af.varnum = circuit.current_witness_index + 1;
af.recursive = circuit.recursive;
af.num_acir_opcodes = static_cast<uint32_t>(circuit.opcodes.size());
af.public_inputs = join({ map(circuit.public_parameters.value, [](auto e) { return e.value; }),
map(circuit.return_values.value, [](auto e) { return e.value; }) });
std::map<uint32_t, BlockConstraint> block_id_to_block_constraint;
Expand Down
39 changes: 39 additions & 0 deletions noir-projects/gates_report.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
set -eu

# TODO(https://github.com/noir-lang/noir/issues/4962): This script is still yet to be integrated with noir-lang/noir-gates-diff
# The script needs some slight updating as `nargo info` expects a complete JSON object, while this script expects a single object field
# representing a list of circuit reports for a program.
# The ACIR tests in barretenberg also expect every target bytecode to have the name `acir.gz` while this script expects the same name of the package
echo "Compile noir-protocol-circuits for gates report..."
cd noir-protocol-circuits
PROTOCOL_CIRCUITS_DIR=$PWD

# Compile programs into artifacts that the backend expects
NARGO=${NARGO:-../../noir/noir-repo/target/release/nargo}
$NARGO compile --only-acir

BB_BIN=${BB_BIN:-../../barretenberg/cpp/build/bin/bb}

echo "{\"programs\": [" > gates_report.json

# Bound for checking where to place last parentheses
NUM_ARTIFACTS=$(ls -1q "$PROTOCOL_CIRCUITS_DIR/target"/*.gz | wc -l)

ITER="1"
for pathname in "$PROTOCOL_CIRCUITS_DIR/target"/*.gz; do
ARTIFACT_NAME=$(basename -s .gz "$pathname")

echo "{\"package_name\": \"$ARTIFACT_NAME\"," >> gates_report.json
$BB_BIN gates -b "./target/$ARTIFACT_NAME.gz" >> gates_report.json

if (($ITER == $NUM_ARTIFACTS)); then
echo "}" >> gates_report.json
else
echo "}, " >> gates_report.json
fi

ITER=$(( $ITER + 1 ))
done

echo "]}" >> gates_report.json
1 change: 1 addition & 0 deletions noir/noir-repo/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 noir/noir-repo/tooling/backend_interface/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ license.workspace = true
acvm.workspace = true
dirs.workspace = true
thiserror.workspace = true
serde.workspace = true
serde_json.workspace = true
bb_abstraction_leaks.workspace = true
tracing.workspace = true
Expand Down
32 changes: 19 additions & 13 deletions noir/noir-repo/tooling/backend_interface/src/cli/gates.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use serde::Deserialize;
use std::path::{Path, PathBuf};

use crate::BackendError;
Expand All @@ -12,8 +13,19 @@ pub(crate) struct GatesCommand {
pub(crate) bytecode_path: PathBuf,
}

#[derive(Deserialize)]
struct GatesResponse {
functions: Vec<CircuitReport>,
}

#[derive(Deserialize)]
pub struct CircuitReport {
pub acir_opcodes: u32,
pub circuit_size: u32,
}

impl GatesCommand {
pub(crate) fn run(self, binary_path: &Path) -> Result<u32, BackendError> {
pub(crate) fn run(self, binary_path: &Path) -> Result<Vec<CircuitReport>, BackendError> {
let output = std::process::Command::new(binary_path)
.arg("gates")
.arg("-c")
Expand All @@ -25,19 +37,11 @@ impl GatesCommand {
if !output.status.success() {
return Err(BackendError::CommandFailed(string_from_stderr(&output.stderr)));
}
// Note: barretenberg includes the newline, so that subsequent prints to stdout
// are not on the same line as the gates output.

const EXPECTED_BYTES: usize = 8;
let gates_bytes: [u8; EXPECTED_BYTES] =
output.stdout.as_slice().try_into().map_err(|_| {
BackendError::UnexpectedNumberOfBytes(EXPECTED_BYTES, output.stdout.clone())
})?;

// Convert bytes to u64 in little-endian format
let value = u64::from_le_bytes(gates_bytes);
let gates_info: GatesResponse =
serde_json::from_slice(&output.stdout).expect("Backend should return valid json");

Ok(value as u32)
Ok(gates_info.functions)
}
}

Expand All @@ -58,7 +62,9 @@ fn gate_command() -> Result<(), BackendError> {

let output = gate_command.run(backend.binary_path())?;
// Mock backend always returns zero gates.
assert_eq!(output, 0);
assert_eq!(output.len(), 1);
assert_eq!(output[0].acir_opcodes, 0);
assert_eq!(output[0].circuit_size, 0);

Ok(())
}
2 changes: 2 additions & 0 deletions noir/noir-repo/tooling/backend_interface/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ pub(crate) use version::VersionCommand;
pub(crate) use vk_as_fields::VkAsFieldsCommand;
pub(crate) use write_vk::WriteVkCommand;

pub(crate) use gates::CircuitReport;

#[test]
fn no_command_provided_works() -> Result<(), crate::BackendError> {
// This is a simple test to check that the binaries work
Expand Down
9 changes: 6 additions & 3 deletions noir/noir-repo/tooling/backend_interface/src/proof_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@ use tempfile::tempdir;
use tracing::warn;

use crate::cli::{
GatesCommand, ProofAsFieldsCommand, ProveCommand, VerifyCommand, VkAsFieldsCommand,
WriteVkCommand,
CircuitReport, GatesCommand, ProofAsFieldsCommand, ProveCommand, VerifyCommand,
VkAsFieldsCommand, WriteVkCommand,
};
use crate::{Backend, BackendError};

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

Expand Down
21 changes: 11 additions & 10 deletions noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashMap;

use acvm::acir::circuit::{ExpressionWidth, Program};
use acvm::acir::circuit::ExpressionWidth;
use backend_interface::BackendError;
use clap::Args;
use iter_extended::vecmap;
Expand Down Expand Up @@ -287,24 +287,25 @@ impl From<ContractInfo> for Vec<Row> {

fn count_opcodes_and_gates_in_program(
backend: &Backend,
compiled_program: CompiledProgram,
mut compiled_program: CompiledProgram,
package: &Package,
expression_width: ExpressionWidth,
) -> Result<ProgramInfo, CliError> {
// Unconstrained functions do not matter to a backend circuit count so we clear them
// before sending a serialized program to the backend
compiled_program.program.unconstrained_functions.clear();

let program_circuit_sizes = backend.get_exact_circuit_sizes(&compiled_program.program)?;
let functions = compiled_program
.program
.functions
.into_par_iter()
.enumerate()
.map(|(i, function)| -> Result<_, BackendError> {
.map(|(i, _)| -> Result<_, BackendError> {
Ok(FunctionInfo {
name: compiled_program.names[i].clone(),
acir_opcodes: function.opcodes.len(),
// Unconstrained functions do not matter to a backend circuit count so we pass nothing here
circuit_size: backend.get_exact_circuit_size(&Program {
functions: vec![function],
unconstrained_functions: Vec::new(),
})?,
acir_opcodes: program_circuit_sizes[i].acir_opcodes as usize,
circuit_size: program_circuit_sizes[i].circuit_size,
})
})
.collect::<Result<_, _>>()?;
Expand All @@ -325,7 +326,7 @@ fn count_opcodes_and_gates_in_contract(
name: function.name,
// TODO(https://github.com/noir-lang/noir/issues/4720)
acir_opcodes: function.bytecode.functions[0].opcodes.len(),
circuit_size: backend.get_exact_circuit_size(&function.bytecode)?,
circuit_size: backend.get_exact_circuit_sizes(&function.bytecode)?[0].circuit_size,
})
})
.collect::<Result<_, _>>()?;
Expand Down
Loading