From 8165b2c2d3bc1e12948d3c5dd8fcf1b90659ba43 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Thu, 17 Sep 2026 20:08:47 +0000 Subject: [PATCH] fix(circuits): bench each protocol circuit under the scheme its VK uses bench_cmds selected the bb scheme for each artifact by grepping its name against ivc_patterns, an array that no longer exists: the chonk patterns are read into ivc_kernel_patterns and ivc_app_patterns. An unset array expands to one empty line, and an empty pattern in a grep -f file matches every input, so every artifact was benched with --scheme chonk. bb rejects that for the rollup circuits ("Rollup Honk proof type not supported on MegaBuilder"), and run_bench.sh piped the failure into jq without pipefail, so each rollup bench passed in zero seconds and wrote an empty bench file. The rollup gate series have been absent from the bench since. VK generation and the bench now classify a circuit through one function, circuit_kind, and each turns the kind into its own bb flags. run_bench.sh fails on a bb error instead of hiding it, and uses the bb the build keys the circuits with, so the public tx-base circuit, which verifies an AVM proof, measures under bb-avm rather than failing under the non-AVM binary. The classifier only runs in the build for a VK that misses the cache, so a test pins the flavor each circuit family lands on, keyed on the script and the pattern files it reads. --- .../fnd/noir-protocol-circuits/bootstrap.sh | 70 +++++++++++++------ .../scripts/circuit_kind.test.sh | 40 +++++++++++ .../scripts/run_bench.sh | 7 +- 3 files changed, 93 insertions(+), 24 deletions(-) create mode 100755 noir-projects/fnd/noir-protocol-circuits/scripts/circuit_kind.test.sh diff --git a/noir-projects/fnd/noir-protocol-circuits/bootstrap.sh b/noir-projects/fnd/noir-protocol-circuits/bootstrap.sh index aab5cb88bf42..bb3cd20e290a 100755 --- a/noir-projects/fnd/noir-protocol-circuits/bootstrap.sh +++ b/noir-projects/fnd/noir-protocol-circuits/bootstrap.sh @@ -38,8 +38,27 @@ export ivc_kernel_regex=$(IFS="|"; echo "${ivc_kernel_patterns[*]}") export ivc_app_regex=$(IFS="|"; echo "${ivc_app_patterns[*]}") export hiding_kernel_regex=$(IFS="|"; echo "${ivc_hiding_pattern[*]}") export rollup_honk_regex=$(IFS="|"; echo "${rollup_honk_patterns[*]}") -# Combined ivc regex (kernel + app) kept for callers that just want "is this a chonk circuit?". -export ivc_regex="${ivc_kernel_regex}|${ivc_app_regex}" + +# Classifies a circuit artifact by name: the three chonk circuit kinds, the two ultra-honk rollup +# configurations, and plain ultra_honk for everything else. Every place that picks bb flags for a +# circuit derives them from this, so the VKs the build writes and the bench that measures the same +# circuits cannot disagree on its scheme. +function circuit_kind { + local name=$1 + if echo "$name" | grep -qE "${hiding_kernel_regex}"; then + echo hiding + elif echo "$name" | grep -qE "${ivc_kernel_regex}"; then + echo kernel + elif echo "$name" | grep -qE "${ivc_app_regex}"; then + echo app + elif echo "$name" | grep -qE "${rollup_honk_regex}"; then + echo rollup_honk + elif echo "$name" | grep -qE "rollup_root"; then + echo rollup_root + else + echo ultra_honk + fi +} function on_exit { rm -f joblog.txt @@ -110,19 +129,17 @@ function generate_vk { local outdir=$(mktemp -d) trap "rm -rf $outdir" EXIT function write_vk { - if echo "$name" | grep -qE "${hiding_kernel_regex}"; then - $BB write_vk --scheme chonk --circuit_kind hiding -b - -o $outdir - elif echo "$name" | grep -qE "${ivc_kernel_regex}"; then - $BB write_vk --scheme chonk --circuit_kind kernel -b - -o $outdir - elif echo "$name" | grep -qE "${ivc_app_regex}"; then - $BB write_vk --scheme chonk --circuit_kind app -b - -o $outdir - elif echo "$name" | grep -qE "${rollup_honk_regex}"; then - $BB write_vk --scheme ultra_honk --ipa_accumulation -b - -o $outdir - elif echo "$name" | grep -qE "rollup_root"; then - $BB write_vk --scheme ultra_honk --oracle_hash keccak -b - -o $outdir - else - $BB write_vk --scheme ultra_honk -b - -o $outdir - fi + local kind=$(circuit_kind "$name") + case $kind in + hiding|kernel|app) + $BB write_vk --scheme chonk --circuit_kind $kind -b - -o $outdir ;; + rollup_honk) + $BB write_vk --scheme ultra_honk --ipa_accumulation -b - -o $outdir ;; + rollup_root) + $BB write_vk --scheme ultra_honk --oracle_hash keccak -b - -o $outdir ;; + *) + $BB write_vk --scheme ultra_honk -b - -o $outdir ;; + esac } echo_stderr "Generating vk for function: $name..." @@ -180,7 +197,7 @@ function check_pinned_vk { fi } -export -f hex_to_fields_json compile generate_vk check_pinned_vk +export -f hex_to_fields_json circuit_kind compile generate_vk check_pinned_vk function build { set -eu @@ -268,6 +285,15 @@ function test_cmds { local scripts_hash=$(hash_str $(cache_content_hash "^noir-projects/fnd/noir-protocol-circuits/scripts/")) echo "$scripts_hash node --test noir-projects/fnd/noir-protocol-circuits/scripts/generate_reset_config.test.js" fi + # The mock circuits reuse this script; the classifier test lives with the real circuits only. + if [ -f ./scripts/circuit_kind.test.sh ]; then + local classifier_hash=$(hash_str $(cache_content_hash \ + "^noir-projects/fnd/noir-protocol-circuits/bootstrap.sh" \ + "^noir-projects/fnd/noir-protocol-circuits/scripts/circuit_kind.test.sh" \ + "^noir-projects/fnd/chonk_circuits.json" \ + "^noir-projects/fnd/rollup_honk_circuits.json")) + echo "$classifier_hash noir-projects/fnd/noir-protocol-circuits/scripts/circuit_kind.test.sh" + fi # We don't blindly execute all circuits as some will have no `Prover.toml`. circuits_to_execute=" private-kernel-init @@ -306,13 +332,11 @@ function bench_cmds { prefix="$circuits_hash noir-projects/fnd/noir-protocol-circuits/scripts/run_bench.sh" for artifact in ./target/*.json; do [[ "$artifact" =~ _simulated ]] && continue - if echo "$artifact" | grep -qEf <(printf '%s\n' "${ivc_patterns[@]}"); then - echo "$prefix $artifact --scheme chonk" - elif echo "$artifact" | grep -qEf <(printf '%s\n' "${rollup_honk_patterns[@]}"); then - echo "$prefix $artifact --scheme ultra_honk --ipa_accumulation" - else - echo "$prefix $artifact --scheme ultra_honk" - fi + case $(circuit_kind "$(basename "$artifact" .json)") in + hiding|kernel|app) echo "$prefix $artifact --scheme chonk" ;; + rollup_honk) echo "$prefix $artifact --scheme ultra_honk --ipa_accumulation" ;; + *) echo "$prefix $artifact --scheme ultra_honk" ;; + esac done } diff --git a/noir-projects/fnd/noir-protocol-circuits/scripts/circuit_kind.test.sh b/noir-projects/fnd/noir-protocol-circuits/scripts/circuit_kind.test.sh new file mode 100755 index 000000000000..df1beaccfb42 --- /dev/null +++ b/noir-projects/fnd/noir-protocol-circuits/scripts/circuit_kind.test.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# Pins the scheme each protocol circuit is keyed and benched under. The build only runs the +# classifier for a VK that misses the cache, so without this a change to the pattern files or to +# circuit_kind that moves a circuit onto another flavor surfaces on the next cold-cache build. +set -euo pipefail +cd "$(dirname "$0")/.." + +failed=0 +check() { + local name=$1 expected=$2 actual + actual=$(./bootstrap.sh circuit_kind "$name") + if [ "$actual" == "$expected" ]; then + echo "ok $name -> $actual" + else + echo "FAIL $name -> $actual (expected $expected)" + failed=1 + fi +} + +check hiding_kernel_to_rollup hiding +check hiding_kernel_to_public hiding +check private_kernel_init kernel +check private_kernel_inner kernel +check private_kernel_reset kernel +check private_kernel_reset_4_4_4_4_4_4_0_0_0 kernel +check private_kernel_reset_tail_to_public kernel +check app_creator app +check chonk_verifier_public rollup_honk +check rollup_tx_base_private rollup_honk +check rollup_block_root rollup_honk +check rollup_checkpoint_merge rollup_honk +check rollup_root rollup_root +check inbox_parity_4 ultra_honk +# The mock circuits share this script and must land on the same flavors as the circuits they mock. +check mock_hiding hiding +check mock_private_kernel_init kernel +check mock_rollup_tx_merge rollup_honk +check mock_rollup_root rollup_root + +exit $failed diff --git a/noir-projects/fnd/noir-protocol-circuits/scripts/run_bench.sh b/noir-projects/fnd/noir-protocol-circuits/scripts/run_bench.sh index fd85b862a34a..79a471052b9e 100755 --- a/noir-projects/fnd/noir-protocol-circuits/scripts/run_bench.sh +++ b/noir-projects/fnd/noir-protocol-circuits/scripts/run_bench.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +set -euo pipefail cd $(dirname $0)/.. @@ -8,8 +9,12 @@ shift circuit_name=$(basename $artifact .json) +# The same bb the build keys the circuits with: the AVM-enabled one by default, which the public +# tx-base circuit needs because it verifies an AVM proof. +BB=${BB:-$(../../../barretenberg/cpp/scripts/find-bb)} + mkdir -p ./bench-out -../../../barretenberg/cpp/build/bin/bb gates -b $artifact "$@" | +$BB gates -b $artifact "$@" | jq --arg name $circuit_name '[ { name: ($name + "_opcodes"), unit: "opcodes", value: .functions[0].acir_opcodes }, { name: ($name + "_gates"), unit: "gates", value: .functions[0].circuit_size }