Skip to content

Commit

Permalink
chore(dsl): Update backend gateCount command to query a Program in a …
Browse files Browse the repository at this point in the history
…single request (#6228)

Resolves #6168

This PR does a very minor update to simply now go through the entire
list of functions contained inside of a Program and generate a basic
circuit report for each functions. Currently `nargo info` now takes in a
JSON report that it works with instead of an individual printed gate
count. This PR also does some initial work on making a gate report that
is ready for noir-lang/noir-gates-diff. This is yet to be updated but
has most of the initial skeleton needed to get a gates report for an
entire workspace.

Also, once noir-lang/noir#4975 is merged and
synced into this repo we can remove the `bb info` command and rename `bb
gates` -> `bb info`

Nargo info still works as expected:
<img width="662" alt="Screenshot 2024-05-08 at 2 55 32 PM"
src="https://github.com/AztecProtocol/aztec-packages/assets/43554004/dab5e819-18c4-4bbd-a727-d4bf42f7b95c">

---------

Co-authored-by: Tom French <tom@tomfren.ch>
  • Loading branch information
vezenovm and TomAFrench authored May 9, 2024
1 parent eae5822 commit 8079f60
Show file tree
Hide file tree
Showing 20 changed files with 139 additions and 32 deletions.
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 @@ -32,6 +32,7 @@ TEST_F(AcirFormatTests, TestASingleConstraintNoPubInputs)
AcirFormat constraint_system{
.varnum = 4,
.recursive = false,
.num_acir_opcodes = 1,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down Expand Up @@ -149,6 +150,7 @@ TEST_F(AcirFormatTests, TestLogicGateFromNoirCircuit)

AcirFormat constraint_system{ .varnum = 6,
.recursive = false,
.num_acir_opcodes = 7,
.public_inputs = { 1 },
.logic_constraints = { logic_constraint },
.range_constraints = { range_a, range_b },
Expand Down Expand Up @@ -218,6 +220,7 @@ TEST_F(AcirFormatTests, TestSchnorrVerifyPass)
};
AcirFormat constraint_system{ .varnum = 81,
.recursive = false,
.num_acir_opcodes = 75,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = range_constraints,
Expand Down Expand Up @@ -314,6 +317,7 @@ TEST_F(AcirFormatTests, TestSchnorrVerifySmallRange)
AcirFormat constraint_system{
.varnum = 81,
.recursive = false,
.num_acir_opcodes = 75,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = range_constraints,
Expand Down Expand Up @@ -429,6 +433,7 @@ TEST_F(AcirFormatTests, TestVarKeccak)
AcirFormat constraint_system{
.varnum = 36,
.recursive = false,
.num_acir_opcodes = 6,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = { range_a, range_b, range_c, range_d },
Expand Down Expand Up @@ -477,6 +482,7 @@ TEST_F(AcirFormatTests, TestKeccakPermutation)

AcirFormat constraint_system{ .varnum = 51,
.recursive = false,
.num_acir_opcodes = 1,
.public_inputs = {},
.logic_constraints = {},
.range_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
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ TEST_F(BigIntTests, TestBigIntConstraintMultiple)
AcirFormat constraint_system{
.varnum = static_cast<uint32_t>(witness.size() + 1),
.recursive = false,
.num_acir_opcodes = 5,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down Expand Up @@ -238,6 +239,7 @@ TEST_F(BigIntTests, TestBigIntConstraintSimple)
AcirFormat constraint_system{
.varnum = 5,
.recursive = false,
.num_acir_opcodes = 3,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down Expand Up @@ -292,6 +294,7 @@ TEST_F(BigIntTests, TestBigIntConstraintReuse)
AcirFormat constraint_system{
.varnum = static_cast<uint32_t>(witness.size() + 1),
.recursive = false,
.num_acir_opcodes = 5,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down Expand Up @@ -350,6 +353,7 @@ TEST_F(BigIntTests, TestBigIntConstraintReuse2)
AcirFormat constraint_system{
.varnum = static_cast<uint32_t>(witness.size() + 1),
.recursive = false,
.num_acir_opcodes = 5,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down Expand Up @@ -429,6 +433,7 @@ TEST_F(BigIntTests, TestBigIntDIV)
AcirFormat constraint_system{
.varnum = 5,
.recursive = false,
.num_acir_opcodes = 4,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ TEST_F(UltraPlonkRAM, TestBlockConstraint)
AcirFormat constraint_system{
.varnum = static_cast<uint32_t>(num_variables),
.recursive = false,
.num_acir_opcodes = 7,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ TEST_F(EcOperations, TestECOperations)
AcirFormat constraint_system{
.varnum = static_cast<uint32_t>(num_variables + 1),
.recursive = false,
.num_acir_opcodes = 1,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintSucceed)
AcirFormat constraint_system{
.varnum = static_cast<uint32_t>(num_variables),
.recursive = false,
.num_acir_opcodes = 1,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down Expand Up @@ -141,6 +142,7 @@ TEST_F(ECDSASecp256k1, TestECDSACompilesForVerifier)
AcirFormat constraint_system{
.varnum = static_cast<uint32_t>(num_variables),
.recursive = false,
.num_acir_opcodes = 1,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down Expand Up @@ -186,6 +188,7 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintFail)
AcirFormat constraint_system{
.varnum = static_cast<uint32_t>(num_variables),
.recursive = false,
.num_acir_opcodes = 1,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ TEST(ECDSASecp256r1, test_hardcoded)
AcirFormat constraint_system{
.varnum = static_cast<uint32_t>(num_variables),
.recursive = false,
.num_acir_opcodes = 1,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down Expand Up @@ -177,6 +178,7 @@ TEST(ECDSASecp256r1, TestECDSAConstraintSucceed)
AcirFormat constraint_system{
.varnum = static_cast<uint32_t>(num_variables),
.recursive = false,
.num_acir_opcodes = 1,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down Expand Up @@ -227,6 +229,7 @@ TEST(ECDSASecp256r1, TestECDSACompilesForVerifier)
AcirFormat constraint_system{
.varnum = static_cast<uint32_t>(num_variables),
.recursive = false,
.num_acir_opcodes = 1,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down Expand Up @@ -272,6 +275,7 @@ TEST(ECDSASecp256r1, TestECDSAConstraintFail)
AcirFormat constraint_system{
.varnum = static_cast<uint32_t>(num_variables),
.recursive = false,
.num_acir_opcodes = 1,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ TEST_F(Poseidon2Tests, TestPoseidon2Permutation)

AcirFormat constraint_system{ .varnum = 9,
.recursive = false,
.num_acir_opcodes = 1,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ Builder create_inner_circuit()

AcirFormat constraint_system{ .varnum = 6,
.recursive = true,
.num_acir_opcodes = 7,
.public_inputs = { 1, 2 },
.logic_constraints = { logic_constraint },
.range_constraints = { range_a, range_b },
Expand Down Expand Up @@ -241,6 +242,7 @@ Builder create_outer_circuit(std::vector<Builder>& inner_circuits)

AcirFormat constraint_system{ .varnum = static_cast<uint32_t>(witness.size()),
.recursive = false,
.num_acir_opcodes = static_cast<uint32_t>(recursion_constraints.size()),
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ TEST_F(Sha256Tests, TestSha256Compression)

AcirFormat constraint_system{ .varnum = 34,
.recursive = false,
.num_acir_opcodes = 1,
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
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, 123);
assert_eq!(output[0].circuit_size, 125);

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
Loading

0 comments on commit 8079f60

Please sign in to comment.