From 381bb162aa22463a2a7dd8c5b0665ab96a7634b9 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Thu, 1 Aug 2024 10:27:36 +0000 Subject: [PATCH 1/5] wip: first version of mega reporter --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 15 ++++++++++----- noir-projects/gates_report.sh | 19 ++++++++++++++++++- .../mega_honk_circuits.json | 4 ++++ 3 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 noir-projects/noir-protocol-circuits/mega_honk_circuits.json diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index a696c6796d37..8beffcb8a34a 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -678,16 +678,16 @@ void prove(const std::string& bytecodePath, const std::string& witnessPath, cons * * @param bytecodePath Path to the file containing the serialized circuit */ -void gateCount(const std::string& bytecodePath, bool honk_recursion) +template void gateCount(const std::string& bytecodePath, bool honk_recursion) { // All circuit reports will be built into the string below std::string functions_string = "{\"functions\": [\n "; auto constraint_systems = get_constraint_systems(bytecodePath, honk_recursion); size_t i = 0; for (auto constraint_system : constraint_systems) { - acir_proofs::AcirComposer acir_composer(0, verbose_logging); - acir_composer.create_circuit(constraint_system, {}, true); - auto circuit_size = acir_composer.get_total_circuit_size(); + auto builder = acir_format::create_circuit( + constraint_system, 0, {}, honk_recursion, std::make_shared(), true); + auto circuit_size = builder.get_total_circuit_size(); // Build individual circuit report std::string gates_per_opcode_str; @@ -1421,7 +1421,12 @@ int main(int argc, char* argv[]) auto tube_vk_path = output_path + "/vk"; return verify_honk(tube_proof_path, tube_vk_path) ? 0 : 1; } else if (command == "gates") { - gateCount(bytecode_path, honk_recursion); + bool mega_honk = flag_present(args, "-m"); + if (mega_honk) { + gateCount(bytecode_path, honk_recursion); + } else { + gateCount(bytecode_path, honk_recursion); + } } else if (command == "verify") { return verify(proof_path, vk_path) ? 0 : 1; } else if (command == "contract") { diff --git a/noir-projects/gates_report.sh b/noir-projects/gates_report.sh index ff638e59ac62..527141cd5ce5 100755 --- a/noir-projects/gates_report.sh +++ b/noir-projects/gates_report.sh @@ -15,11 +15,28 @@ echo "{\"programs\": [" > gates_report.json # Bound for checking where to place last parentheses NUM_ARTIFACTS=$(ls -1q "$PROTOCOL_CIRCUITS_DIR/target"/*.json | wc -l) +MEGA_HONK_CIRCUIT_PATTERNS=$(jq -r '.[]' mega_honk_circuits.json) + ITER="1" for pathname in "$PROTOCOL_CIRCUITS_DIR/target"/*.json; do ARTIFACT_NAME=$(basename -s .json "$pathname") - GATES_INFO=$($BB_BIN gates -h -b "./target/$ARTIFACT_NAME.json") + # Check if the current artifact is a mega honk circuit + IS_MEGA_HONK_CIRCUIT="false" + for pattern in $MEGA_HONK_CIRCUIT_PATTERNS; do + if echo "$ARTIFACT_NAME" | perl -ne "print if /$pattern/"; then + IS_MEGA_HONK_CIRCUIT="true" + break + fi + done + + # If it's mega honk, we need to pass the -m flag + if [ "$IS_MEGA_HONK_CIRCUIT" = "true" ]; then + echo "Processing mega honk circuit: $ARTIFACT_NAME" + GATES_INFO=$($BB_BIN gates -h -b -m "./target/$ARTIFACT_NAME.json") + else + GATES_INFO=$($BB_BIN gates -h -b "./target/$ARTIFACT_NAME.json") + fi MAIN_FUNCTION_INFO=$(echo $GATES_INFO | jq -r '.functions[0] | .name = "main"') echo "{\"package_name\": \"$ARTIFACT_NAME\", \"functions\": [$MAIN_FUNCTION_INFO]" >> gates_report.json diff --git a/noir-projects/noir-protocol-circuits/mega_honk_circuits.json b/noir-projects/noir-protocol-circuits/mega_honk_circuits.json new file mode 100644 index 000000000000..0084e1bfd8cd --- /dev/null +++ b/noir-projects/noir-protocol-circuits/mega_honk_circuits.json @@ -0,0 +1,4 @@ +[ + "private_kernel_reset_[a-z]+$", + "private_kernel_init" +] \ No newline at end of file From 776ec819926a33e09ba18d365168281cd67b2571 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Thu, 1 Aug 2024 12:24:15 +0000 Subject: [PATCH 2/5] feat: Report protocol circuit gates and vks with megabuilder --- noir-projects/gates_report.sh | 5 ++- .../mega_honk_circuits.json | 4 +-- .../scripts/generate_vk_json.js | 33 +++++++++++++++---- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/noir-projects/gates_report.sh b/noir-projects/gates_report.sh index 527141cd5ce5..15e4bff9a4fb 100755 --- a/noir-projects/gates_report.sh +++ b/noir-projects/gates_report.sh @@ -24,7 +24,7 @@ for pathname in "$PROTOCOL_CIRCUITS_DIR/target"/*.json; do # Check if the current artifact is a mega honk circuit IS_MEGA_HONK_CIRCUIT="false" for pattern in $MEGA_HONK_CIRCUIT_PATTERNS; do - if echo "$ARTIFACT_NAME" | perl -ne "print if /$pattern/"; then + if echo "$ARTIFACT_NAME" | grep -qE "$pattern"; then IS_MEGA_HONK_CIRCUIT="true" break fi @@ -32,8 +32,7 @@ for pathname in "$PROTOCOL_CIRCUITS_DIR/target"/*.json; do # If it's mega honk, we need to pass the -m flag if [ "$IS_MEGA_HONK_CIRCUIT" = "true" ]; then - echo "Processing mega honk circuit: $ARTIFACT_NAME" - GATES_INFO=$($BB_BIN gates -h -b -m "./target/$ARTIFACT_NAME.json") + GATES_INFO=$($BB_BIN gates -h -m -b "./target/$ARTIFACT_NAME.json") else GATES_INFO=$($BB_BIN gates -h -b "./target/$ARTIFACT_NAME.json") fi diff --git a/noir-projects/noir-protocol-circuits/mega_honk_circuits.json b/noir-projects/noir-protocol-circuits/mega_honk_circuits.json index 0084e1bfd8cd..812e1aba8b59 100644 --- a/noir-projects/noir-protocol-circuits/mega_honk_circuits.json +++ b/noir-projects/noir-protocol-circuits/mega_honk_circuits.json @@ -1,4 +1,4 @@ [ - "private_kernel_reset_[a-z]+$", - "private_kernel_init" + "private_kernel.*", + "empty_nested" ] \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js b/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js index 8071d782d5ba..db5440409253 100644 --- a/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js +++ b/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js @@ -8,7 +8,11 @@ const { S3 } = require("@aws-sdk/client-s3"); const crypto = require("crypto"); -const BB_BIN_PATH = process.env.BB_BIN || "../../barretenberg/cpp/build/bin/bb"; +const megaHonkPatterns = require("../mega_honk_circuits.json"); + +const BB_BIN_PATH = + process.env.BB_BIN || + path.join(__dirname, "../../../barretenberg/cpp/build/bin/bb"); const BUCKET_NAME = "aztec-ci-artifacts"; const PREFIX = "protocol"; @@ -72,8 +76,15 @@ async function getNewArtifactHash(artifactPath, outputFolder, artifactName) { return artifactHash; } +function isMegaHonkCircuit(artifactName) { + return megaHonkPatterns.some((pattern) => + artifactName.match(new RegExp(pattern)) + ); +} + async function processArtifact(artifactPath, outputFolder) { const artifactName = path.basename(artifactPath, ".json"); + const isMegaHonk = isMegaHonkCircuit(artifactName); const artifactHash = await getNewArtifactHash( artifactPath, @@ -92,7 +103,8 @@ async function processArtifact(artifactPath, outputFolder) { artifactName, outputFolder, artifactPath, - artifactHash + artifactHash, + isMegaHonk ); await writeVKToS3(artifactName, artifactHash, JSON.stringify(vkData)); } else { @@ -109,9 +121,14 @@ async function generateVKData( artifactName, outputFolder, artifactPath, - artifactHash + artifactHash, + isMegaHonk ) { - console.log("Generating new vk for", artifactName); + if (isMegaHonk) { + console.log("Generating new mega honk vk for", artifactName); + } else { + console.log("Generating new vk for", artifactName); + } const binaryVkPath = vkBinaryFileNameForArtifactName( outputFolder, @@ -119,8 +136,12 @@ async function generateVKData( ); const jsonVkPath = vkJsonFileNameForArtifactName(outputFolder, artifactName); - const writeVkCommand = `${BB_BIN_PATH} write_vk_ultra_honk -h -b "${artifactPath}" -o "${binaryVkPath}"`; - const vkAsFieldsCommand = `${BB_BIN_PATH} vk_as_fields_ultra_honk -k "${binaryVkPath}" -o "${jsonVkPath}"`; + const writeVkCommand = `${BB_BIN_PATH} ${ + isMegaHonk ? "write_vk_mega_honk" : "write_vk_ultra_honk" + } -h -b "${artifactPath}" -o "${binaryVkPath}"`; + const vkAsFieldsCommand = `${BB_BIN_PATH} ${ + isMegaHonk ? "vk_as_fields_mega_honk" : "vk_as_fields_ultra_honk" + } -k "${binaryVkPath}" -o "${jsonVkPath}"`; await new Promise((resolve, reject) => { child_process.exec(`${writeVkCommand} && ${vkAsFieldsCommand}`, (err) => { From b306701abb7036f3d0757525abe871a5ec42c742 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Thu, 1 Aug 2024 13:01:58 +0000 Subject: [PATCH 3/5] refactor: Use a different command for mega honk gates --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 9 +++------ noir-projects/gates_report.sh | 7 ++++--- .../scripts/flamegraph.sh | 20 ++++++++++++++++++- .../profiler/src/cli/gates_flamegraph_cmd.rs | 5 +++++ .../tooling/profiler/src/gates_provider.rs | 3 ++- 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 8beffcb8a34a..24c5abaf1e7d 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -1421,12 +1421,9 @@ int main(int argc, char* argv[]) auto tube_vk_path = output_path + "/vk"; return verify_honk(tube_proof_path, tube_vk_path) ? 0 : 1; } else if (command == "gates") { - bool mega_honk = flag_present(args, "-m"); - if (mega_honk) { - gateCount(bytecode_path, honk_recursion); - } else { - gateCount(bytecode_path, honk_recursion); - } + gateCount(bytecode_path, honk_recursion); + } else if (command == "gates_mega_honk") { + gateCount(bytecode_path, honk_recursion); } else if (command == "verify") { return verify(proof_path, vk_path) ? 0 : 1; } else if (command == "contract") { diff --git a/noir-projects/gates_report.sh b/noir-projects/gates_report.sh index 15e4bff9a4fb..8df0443aae46 100755 --- a/noir-projects/gates_report.sh +++ b/noir-projects/gates_report.sh @@ -30,12 +30,13 @@ for pathname in "$PROTOCOL_CIRCUITS_DIR/target"/*.json; do fi done - # If it's mega honk, we need to pass the -m flag + # If it's mega honk, we need to use the gates_mega_honk command if [ "$IS_MEGA_HONK_CIRCUIT" = "true" ]; then - GATES_INFO=$($BB_BIN gates -h -m -b "./target/$ARTIFACT_NAME.json") + GATES_INFO=$($BB_BIN gates_mega_honk -h -b "$pathname") else - GATES_INFO=$($BB_BIN gates -h -b "./target/$ARTIFACT_NAME.json") + GATES_INFO=$($BB_BIN gates -h -b "$pathname") fi + MAIN_FUNCTION_INFO=$(echo $GATES_INFO | jq -r '.functions[0] | .name = "main"') echo "{\"package_name\": \"$ARTIFACT_NAME\", \"functions\": [$MAIN_FUNCTION_INFO]" >> gates_report.json diff --git a/noir-projects/noir-protocol-circuits/scripts/flamegraph.sh b/noir-projects/noir-protocol-circuits/scripts/flamegraph.sh index 55bbcd385042..131fea270ca7 100755 --- a/noir-projects/noir-protocol-circuits/scripts/flamegraph.sh +++ b/noir-projects/noir-protocol-circuits/scripts/flamegraph.sh @@ -71,8 +71,26 @@ fi DEST="$SCRIPT_DIR/../dest" mkdir -p $DEST +MEGA_HONK_CIRCUIT_PATTERNS=$(jq -r '.[]' "$SCRIPT_DIR/../mega_honk_circuits.json") + +# Check if the target circuit is a mega honk circuit. +ARTIFACT_FILE_NAME=$(basename -s .json "$ARTIFACT") + +IS_MEGA_HONK_CIRCUIT="false" +for pattern in $MEGA_HONK_CIRCUIT_PATTERNS; do + if echo "$ARTIFACT_FILE_NAME" | grep -qE "$pattern"; then + IS_MEGA_HONK_CIRCUIT="true" + break + fi +done + # At last, generate the flamegraph. -$PROFILER gates-flamegraph --artifact-path "${ARTIFACT}" --backend-path "$SCRIPT_DIR/../../../barretenberg/cpp/build/bin/bb" --output "$DEST" -- -h +# If it's a mega honk circuit, we need to set the backend_gates_command argument to "gates_mega_honk". +if [ "$IS_MEGA_HONK_CIRCUIT" = "true" ]; then + $PROFILER gates-flamegraph --artifact-path "${ARTIFACT}" --backend-path "$SCRIPT_DIR/../../../barretenberg/cpp/build/bin/bb" --output "$DEST" --backend-gates-command "gates_mega_honk" -- -h +else + $PROFILER gates-flamegraph --artifact-path "${ARTIFACT}" --backend-path "$SCRIPT_DIR/../../../barretenberg/cpp/build/bin/bb" --output "$DEST" -- -h +fi # Serve the file over http if -s is set. if $SERVE; then diff --git a/noir/noir-repo/tooling/profiler/src/cli/gates_flamegraph_cmd.rs b/noir/noir-repo/tooling/profiler/src/cli/gates_flamegraph_cmd.rs index 98e89e420159..f465408a8d88 100644 --- a/noir/noir-repo/tooling/profiler/src/cli/gates_flamegraph_cmd.rs +++ b/noir/noir-repo/tooling/profiler/src/cli/gates_flamegraph_cmd.rs @@ -19,6 +19,10 @@ pub(crate) struct GatesFlamegraphCommand { #[clap(long, short)] backend_path: String, + /// Command to get a gates report from the backend. Defaults to "gates" + #[clap(long, short, default_value = "gates")] + backend_gates_command: String, + #[arg(trailing_var_arg = true, allow_hyphen_values = true)] backend_extra_args: Vec, @@ -32,6 +36,7 @@ pub(crate) fn run(args: GatesFlamegraphCommand) -> eyre::Result<()> { &PathBuf::from(args.artifact_path), &BackendGatesProvider { backend_path: PathBuf::from(args.backend_path), + gates_command: args.backend_gates_command, extra_args: args.backend_extra_args, }, &InfernoFlamegraphGenerator { count_name: "gates".to_string() }, diff --git a/noir/noir-repo/tooling/profiler/src/gates_provider.rs b/noir/noir-repo/tooling/profiler/src/gates_provider.rs index f96b12929871..3f07f3e4be6f 100644 --- a/noir/noir-repo/tooling/profiler/src/gates_provider.rs +++ b/noir/noir-repo/tooling/profiler/src/gates_provider.rs @@ -10,6 +10,7 @@ pub(crate) trait GatesProvider { pub(crate) struct BackendGatesProvider { pub(crate) backend_path: PathBuf, + pub(crate) gates_command: String, pub(crate) extra_args: Vec, } @@ -17,7 +18,7 @@ impl GatesProvider for BackendGatesProvider { fn get_gates(&self, artifact_path: &Path) -> eyre::Result { let mut backend_gates_cmd = Command::new(&self.backend_path); - backend_gates_cmd.arg("gates").arg("-b").arg(artifact_path); + backend_gates_cmd.arg(self.gates_command.clone()).arg("-b").arg(artifact_path); for arg in &self.extra_args { backend_gates_cmd.arg(arg); From 41263082abb74c5ba808194c7cb512efccf87e83 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Thu, 1 Aug 2024 14:06:44 +0000 Subject: [PATCH 4/5] fix: disable megahonk vks until the protocol supports them --- .../noir-protocol-circuits/scripts/generate_vk_json.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js b/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js index db5440409253..8e3c09e7cf37 100644 --- a/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js +++ b/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js @@ -77,9 +77,11 @@ async function getNewArtifactHash(artifactPath, outputFolder, artifactName) { } function isMegaHonkCircuit(artifactName) { - return megaHonkPatterns.some((pattern) => - artifactName.match(new RegExp(pattern)) - ); + // TODO Uncomment when mega honk vks are supported in the protocol + // return megaHonkPatterns.some((pattern) => + // artifactName.match(new RegExp(pattern)) + // ); + return false; } async function processArtifact(artifactPath, outputFolder) { From d44036842869d02b1ff08d1ab63dde1cdbe5f4b7 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Thu, 1 Aug 2024 14:23:26 +0000 Subject: [PATCH 5/5] fix: add proving system to the vk cache key --- .../scripts/generate_vk_json.js | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js b/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js index 8e3c09e7cf37..a4ac5dc4b5b2 100644 --- a/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js +++ b/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js @@ -53,10 +53,25 @@ function getBarretenbergHash() { }); } -async function getNewArtifactHash(artifactPath, outputFolder, artifactName) { +function generateArtifactHash(barretenbergHash, bytecodeHash, isMegaHonk) { + return `${barretenbergHash}-${bytecodeHash}-${ + isMegaHonk ? "mega-honk" : "ultra-honk" + }`; +} + +async function getNewArtifactHash( + artifactPath, + outputFolder, + artifactName, + isMegaHonk +) { const bytecodeHash = await getBytecodeHash(artifactPath); const barretenbergHash = await getBarretenbergHash(); - const artifactHash = `${barretenbergHash}-${bytecodeHash}`; + const artifactHash = generateArtifactHash( + barretenbergHash, + bytecodeHash, + isMegaHonk + ); const vkDataPath = vkDataFileNameForArtifactName(outputFolder, artifactName); try { @@ -91,7 +106,8 @@ async function processArtifact(artifactPath, outputFolder) { const artifactHash = await getNewArtifactHash( artifactPath, outputFolder, - artifactName + artifactName, + isMegaHonk ); if (!artifactHash) { console.log("Reusing on disk vk for", artifactName);