111 std::string
name =
"Barretenberg\nYour favo(u)rite zkSNARK library written in C++, a perfectly good computer "
112 "programming language.";
116 name +=
"\nAztec Virtual Machine (AVM): enabled";
118 name +=
"\nAztec Virtual Machine (AVM): disabled";
120#ifdef ENABLE_AVM_TRANSPILER
121 name +=
"\nAVM Transpiler: enabled";
123 name +=
"\nAVM Transpiler: disabled";
125#ifdef STARKNET_GARAGA_FLAVORS
126 name +=
"\nStarknet Garaga Extensions: enabled";
128 name +=
"\nStarknet Garaga Extensions: disabled";
130 CLI::App app{
name };
131 argv = app.ensure_utf8(argv);
141 app.require_subcommand(0, 1);
145 std::filesystem::path bytecode_path{
"./target/program.json" };
146 std::filesystem::path witness_path{
"./target/witness.gz" };
147 std::filesystem::path ivc_inputs_path{
"./ivc-inputs.msgpack" };
148 std::filesystem::path output_path{
151 std::filesystem::path public_inputs_path{
"./target/public_inputs" };
152 std::filesystem::path proof_path{
"./target/proof" };
153 std::filesystem::path vk_path{
"./target/vk" };
155 flags.oracle_hash_type =
"poseidon2";
157 flags.include_gates_per_opcode =
false;
163 bool show_extended_help =
false;
164 for (
int i = 1; i < argc; ++i) {
165 if (std::string(argv[i]) ==
"--help-extended") {
166 show_extended_help =
true;
171 const std::string advanced_group = show_extended_help ?
"Advanced Options (Aztec/Power Users)" :
"";
172 const std::string aztec_internal_group = show_extended_help ?
"Aztec Internal Commands" :
"";
174 const auto add_output_path_option = [&](CLI::App* subcommand,
auto& _output_path) {
175 return subcommand->add_option(
"--output_path, -o",
177 "Directory to write files or path of file to write, depending on subcommand.");
181 const auto add_help_extended_flag = [&](CLI::App* subcommand) {
182 subcommand->add_flag(
"--help-extended",
"Show all options including advanced ones.");
189 const auto add_ipa_accumulation_flag = [&](CLI::App* subcommand) {
191 ->add_flag(
"--ipa_accumulation",
192 flags.ipa_accumulation,
193 "Accumulate/Aggregate IPA (Inner Product Argument) claims")
194 ->group(advanced_group);
197 const auto add_scheme_option = [&](CLI::App* subcommand) {
202 "The type of proof to be constructed. This can specify a proving system, an accumulation scheme, or a "
203 "particular type of circuit to be constructed and proven for some implicit scheme.")
204 ->envname(
"BB_SCHEME")
205 ->default_val(
"ultra_honk")
206 ->check(CLI::IsMember({
"chonk",
"avm",
"ultra_honk" }).
name(
"is_member"))
207 ->
group(advanced_group);
210 const auto add_crs_path_option = [&](CLI::App* subcommand) {
212 ->add_option(
"--crs_path, -c",
214 "Path CRS directory. Missing CRS files will be retrieved from the internet.")
215 ->check(CLI::ExistingDirectory)
216 ->group(advanced_group);
219 const auto add_oracle_hash_option = [&](CLI::App* subcommand) {
223 flags.oracle_hash_type,
224 "The hash function used by the prover as random oracle standing in for a verifier's challenge "
225 "generation. Poseidon2 is to be used for proofs that are intended to be verified inside of a "
226 "circuit. Keccak is optimized for verification in an Ethereum smart contract, where Keccak "
227 "has a privileged position due to the existence of an EVM precompile. Starknet is optimized "
228 "for verification in a Starknet smart contract, which can be generated using the Garaga library. "
229 "Prefer using --verifier_target instead.")
230 ->check(CLI::IsMember({
"poseidon2",
"keccak",
"starknet" }).
name(
"is_member"))
231 ->
group(advanced_group);
234 const auto add_verifier_target_option = [&](CLI::App* subcommand) {
236 ->add_option(
"--verifier_target, -t",
237 flags.verifier_target,
238 "Target verification environment. Determines hash function and ZK settings.\n"
241 " evm Ethereum/Solidity (keccak, ZK)\n"
242 " evm-no-zk Ethereum/Solidity without ZK\n"
243 " noir-recursive Noir circuits (poseidon2, ZK)\n"
244 " noir-recursive-no-zk Noir circuits without ZK\n"
245 " noir-rollup Rollup with IPA (poseidon2, ZK)\n"
246 " noir-rollup-no-zk Rollup without ZK\n"
247 " starknet Starknet via Garaga (ZK)\n"
248 " starknet-no-zk Starknet without ZK")
249 ->envname(
"BB_VERIFIER_TARGET")
250 ->check(CLI::IsMember({
"evm",
253 "noir-recursive-no-zk",
257 "starknet-no-zk" }));
260 const auto add_write_vk_flag = [&](CLI::App* subcommand) {
261 return subcommand->add_flag(
"--write_vk", flags.write_vk,
"Write the provided circuit's verification key");
264 const auto remove_zk_option = [&](CLI::App* subcommand) {
266 ->add_flag(
"--disable_zk",
268 "Use a non-zk version of --scheme. Prefer using --verifier_target *-no-zk variants instead.")
269 ->group(advanced_group);
272 const auto add_bytecode_path_option = [&](CLI::App* subcommand) {
273 subcommand->add_option(
"--bytecode_path, -b", bytecode_path,
"Path to ACIR bytecode generated by Noir.")
277 const auto add_witness_path_option = [&](CLI::App* subcommand) {
278 subcommand->add_option(
"--witness_path, -w", witness_path,
"Path to partial witness generated by Noir.")
282 const auto add_ivc_inputs_path_options = [&](CLI::App* subcommand) {
285 "--ivc_inputs_path", ivc_inputs_path,
"For IVC, path to input stack with bytecode and witnesses.")
286 ->group(advanced_group);
289 const auto add_public_inputs_path_option = [&](CLI::App* subcommand) {
290 return subcommand->add_option(
291 "--public_inputs_path, -i", public_inputs_path,
"Path to public inputs.") ;
294 const auto add_proof_path_option = [&](CLI::App* subcommand) {
295 return subcommand->add_option(
296 "--proof_path, -p", proof_path,
"Path to a proof.") ;
299 const auto add_vk_path_option = [&](CLI::App* subcommand) {
300 return subcommand->add_option(
"--vk_path, -k", vk_path,
"Path to a verification key.")
304 const auto add_verbose_flag = [&](CLI::App* subcommand) {
305 return subcommand->add_flag(
"--verbose, --verbose_logging, -v", flags.verbose,
"Output all logs to stderr.")
306 ->group(advanced_group);
309 const auto add_debug_flag = [&](CLI::App* subcommand) {
310 return subcommand->add_flag(
"--debug_logging, -d", flags.debug,
"Output debug logs to stderr.")
311 ->group(advanced_group);
314 const auto add_include_gates_per_opcode_flag = [&](CLI::App* subcommand) {
315 return subcommand->add_flag(
"--include_gates_per_opcode",
316 flags.include_gates_per_opcode,
317 "Include gates_per_opcode in the output of the gates command.");
320 const auto add_slow_low_memory_flag = [&](CLI::App* subcommand) {
322 ->add_flag(
"--slow_low_memory", flags.slow_low_memory,
"Enable low memory mode (can be 2x slower or more).")
323 ->group(advanced_group);
326 const auto add_storage_budget_option = [&](CLI::App* subcommand) {
328 ->add_option(
"--storage_budget",
329 flags.storage_budget,
330 "Storage budget for FileBackedMemory (e.g. '500m', '2g'). When exceeded, falls "
331 "back to RAM (requires --slow_low_memory).")
332 ->group(advanced_group);
335 const auto add_vk_policy_option = [&](CLI::App* subcommand) {
337 ->add_option(
"--vk_policy",
339 "Policy for handling verification keys. 'default' uses the provided VK as-is, 'check' "
340 "verifies the provided VK matches the computed VK (throws error on mismatch), 'recompute' "
341 "always ignores the provided VK and treats it as nullptr, 'rewrite' checks the VK and "
342 "rewrites the input file with the correct VK if there's a mismatch (for check command).")
343 ->check(CLI::IsMember({
"default",
"check",
"recompute",
"rewrite" }).
name(
"is_member"))
344 ->
group(advanced_group);
347 const auto add_circuit_kind_option = [&](CLI::App* subcommand) {
349 ->add_option(
"--circuit_kind",
351 "Chonk-only: which Mega flavor to derive the VK against. One of: "
352 "'app' (MegaAppFlavor), 'kernel' (MegaKernelFlavor), 'hiding' (MegaZKFlavor "
353 "for the IVC hiding kernel). Required for `bb write_vk --scheme chonk` — the "
354 "caller must know the kind because it determines the VK shape.")
355 ->check(CLI::IsMember({
"app",
"kernel",
"hiding" }).
name(
"is_member"))
356 ->
group(advanced_group);
359 const auto add_optimized_solidity_verifier_flag = [&](CLI::App* subcommand) {
360 return subcommand->add_flag(
361 "--optimized", flags.optimized_solidity_verifier,
"Use the optimized Solidity verifier.");
364 const auto add_output_format_option = [&](CLI::App* subcommand) {
366 ->add_option(
"--output_format",
368 "Output format for proofs and verification keys: 'binary' (default) or 'json'.\n"
369 "JSON format includes metadata like bb_version, scheme, and verifier_target.")
370 ->check(CLI::IsMember({
"binary",
"json" }).
name(
"is_member"));
373 bool print_bench =
false;
374 const auto add_print_bench_flag = [&](CLI::App* subcommand) {
377 "--print_bench", print_bench,
"Pretty print op counts to standard error in a human-readable format.")
378 ->group(advanced_group);
381 std::string bench_out;
382 const auto add_bench_out_option = [&](CLI::App* subcommand) {
383 return subcommand->add_option(
"--bench_out", bench_out,
"Path to write the op counts in a json.")
384 ->group(advanced_group);
386 std::string bench_out_hierarchical;
387 const auto add_bench_out_hierarchical_option = [&](CLI::App* subcommand) {
389 ->add_option(
"--bench_out_hierarchical",
390 bench_out_hierarchical,
391 "Path to write the hierarchical benchmark data (op counts and timings with "
392 "parent-child relationships) as json.")
393 ->group(advanced_group);
395 std::string memory_profile_out;
396 const auto add_memory_profile_out_option = [&](CLI::App* subcommand) {
398 ->add_option(
"--memory_profile_out",
400 "Path to write memory profile data (polynomial breakdown by category, RSS "
401 "checkpoints, CRS size) as json.")
402 ->group(advanced_group);
405 std::string trace_out_perfetto;
406 const auto add_trace_out_perfetto_option = [&](CLI::App* subcommand) {
408 ->add_option(
"--trace_out_perfetto",
410 "Path to write a Chrome Trace Event Format JSON of every instrumented "
411 "BB_BENCH scope (per-call timeline). Drop the file into ui.perfetto.dev "
412 "or chrome://tracing.")
413 ->group(advanced_group);
415 std::string trace_out_perfetto_aggregate;
416 const auto add_trace_out_perfetto_aggregate_option = [&](CLI::App* subcommand) {
418 ->add_option(
"--trace_out_perfetto_aggregate",
419 trace_out_perfetto_aggregate,
420 "Path to write a synthesized Chrome Trace Event Format JSON derived from the "
421 "aggregate stats. Smaller than --trace_out_perfetto but lossy about individual "
423 ->group(advanced_group);
429 add_verbose_flag(&app);
430 add_debug_flag(&app);
431 add_crs_path_option(&app);
436 app.set_version_flag(
"--version",
BB_VERSION,
"Print the version string.");
441 app.add_flag(
"--help-extended",
"Show all options including advanced and Aztec-specific commands.");
446 std::filesystem::path acir_roundtrip_output_path;
447 CLI::App* acir_roundtrip_cmd =
448 app.add_subcommand(
"acir_roundtrip",
449 "[Internal testing] Deserialize an ACIR program from bytecode (msgpack), "
450 "re-serialize it back to msgpack, and write it to an output JSON file "
451 "in nargo-compatible format. Functional equivalence should then be verified "
452 "externally (e.g. by proving with the roundtripped bytecode).");
454 acir_roundtrip_cmd->group(aztec_internal_group);
455 add_bytecode_path_option(acir_roundtrip_cmd);
457 ->add_option(
"--output_path,-o", acir_roundtrip_output_path,
"Output path for the roundtripped bytecode JSON.")
463 CLI::App* check = app.add_subcommand(
465 "A debugging tool to quickly check whether a witness satisfies a circuit The "
466 "function constructs the execution trace and iterates through it row by row, applying the "
467 "polynomial relations defining the gate types. For Chonk, we check the VKs in the folding stack.");
469 add_help_extended_flag(check);
470 add_scheme_option(check);
471 add_bytecode_path_option(check);
472 add_witness_path_option(check);
473 add_ivc_inputs_path_options(check);
474 add_vk_policy_option(check);
479 CLI::App* gates = app.add_subcommand(
"gates",
480 "Construct a circuit from the given bytecode (in particular, expand black box "
481 "functions) and return the gate count information.");
483 add_help_extended_flag(gates);
484 add_scheme_option(gates);
485 add_verbose_flag(gates);
486 add_bytecode_path_option(gates);
487 add_include_gates_per_opcode_flag(gates);
488 add_verifier_target_option(gates);
489 add_oracle_hash_option(gates);
490 add_ipa_accumulation_flag(gates);
495 CLI::App* prove = app.add_subcommand(
"prove",
"Generate a proof.");
497 add_help_extended_flag(prove);
498 add_scheme_option(prove);
499 add_bytecode_path_option(prove);
500 add_witness_path_option(prove);
501 add_output_path_option(prove, output_path);
502 add_ivc_inputs_path_options(prove);
503 add_vk_path_option(prove);
504 add_vk_policy_option(prove);
505 add_verbose_flag(prove);
506 add_debug_flag(prove);
507 add_crs_path_option(prove);
508 add_verifier_target_option(prove);
509 add_oracle_hash_option(prove);
510 add_write_vk_flag(prove);
511 add_ipa_accumulation_flag(prove);
512 remove_zk_option(prove);
513 add_slow_low_memory_flag(prove);
514 add_print_bench_flag(prove);
515 add_bench_out_option(prove);
516 add_bench_out_hierarchical_option(prove);
517 add_memory_profile_out_option(prove);
518 add_trace_out_perfetto_option(prove);
519 add_trace_out_perfetto_aggregate_option(prove);
520 add_storage_budget_option(prove);
521 add_output_format_option(prove);
523 prove->add_flag(
"--verify",
"Verify the proof natively, resulting in a boolean output. Useful for testing.");
529 app.add_subcommand(
"write_vk",
530 "Write the verification key of a circuit. The circuit is constructed using "
531 "quickly generated but invalid witnesses (which must be supplied in Barretenberg in order "
532 "to expand ACIR black box opcodes), and no proof is constructed.");
534 add_help_extended_flag(write_vk);
535 add_scheme_option(write_vk);
536 add_bytecode_path_option(write_vk);
537 add_output_path_option(write_vk, output_path);
538 add_ivc_inputs_path_options(write_vk);
540 add_verbose_flag(write_vk);
541 add_debug_flag(write_vk);
542 add_crs_path_option(write_vk);
543 add_verifier_target_option(write_vk);
544 add_oracle_hash_option(write_vk);
545 add_ipa_accumulation_flag(write_vk);
546 remove_zk_option(write_vk);
547 add_output_format_option(write_vk);
548 add_circuit_kind_option(write_vk);
553 CLI::App* verify = app.add_subcommand(
"verify",
"Verify a proof.");
555 add_help_extended_flag(verify);
556 add_public_inputs_path_option(verify);
557 add_proof_path_option(verify);
558 add_vk_path_option(verify);
560 add_verbose_flag(verify);
561 add_debug_flag(verify);
562 add_scheme_option(verify);
563 add_crs_path_option(verify);
564 add_verifier_target_option(verify);
565 add_oracle_hash_option(verify);
566 remove_zk_option(verify);
567 add_ipa_accumulation_flag(verify);
572 std::filesystem::path batch_verify_proofs_dir{
"./proofs" };
573 CLI::App* batch_verify =
574 app.add_subcommand(
"batch_verify",
"Batch-verify multiple Chonk proofs with batched IPA SRS MSMs.");
576 add_help_extended_flag(batch_verify);
577 add_scheme_option(batch_verify);
578 batch_verify->add_option(
"--proofs_dir", batch_verify_proofs_dir,
"Directory containing proof_N/vk_N pairs.");
579 add_verbose_flag(batch_verify);
580 add_debug_flag(batch_verify);
581 add_crs_path_option(batch_verify);
586 CLI::App* proof_stats =
587 app.add_subcommand(
"proof_stats",
"Output proof statistics (compressed size, number of public inputs).");
589 add_help_extended_flag(proof_stats);
590 add_scheme_option(proof_stats);
591 add_proof_path_option(proof_stats);
592 add_output_path_option(proof_stats, output_path);
593 add_verbose_flag(proof_stats);
598 CLI::App* write_solidity_verifier =
599 app.add_subcommand(
"write_solidity_verifier",
600 "Write a Solidity smart contract suitable for verifying proofs of circuit "
601 "satisfiability for the circuit with verification key at vk_path. Not all "
602 "hash types are implemented due to efficiency concerns.");
604 add_help_extended_flag(write_solidity_verifier);
605 add_scheme_option(write_solidity_verifier);
606 add_vk_path_option(write_solidity_verifier);
607 add_output_path_option(write_solidity_verifier, output_path);
609 add_verbose_flag(write_solidity_verifier);
610 add_verifier_target_option(write_solidity_verifier);
611 remove_zk_option(write_solidity_verifier);
612 add_crs_path_option(write_solidity_verifier);
613 add_optimized_solidity_verifier_flag(write_solidity_verifier);
615 std::filesystem::path avm_inputs_path{
"./target/avm_inputs.bin" };
616 const auto add_avm_inputs_option = [&](CLI::App* subcommand) {
617 return subcommand->add_option(
"--avm-inputs", avm_inputs_path,
"");
619 std::filesystem::path avm_public_inputs_path{
"./target/avm_public_inputs.bin" };
620 const auto add_avm_public_inputs_option = [&](CLI::App* subcommand) {
621 return subcommand->add_option(
"--avm-public-inputs", avm_public_inputs_path,
"");
627 CLI::App* avm_simulate_command = app.add_subcommand(
"avm_simulate",
"Simulate AVM execution.");
628 avm_simulate_command->group(aztec_internal_group);
629 add_verbose_flag(avm_simulate_command);
630 add_debug_flag(avm_simulate_command);
631 add_avm_inputs_option(avm_simulate_command);
636 CLI::App* avm_prove_command = app.add_subcommand(
"avm_prove",
"Generate an AVM proof.");
637 avm_prove_command->group(aztec_internal_group);
638 add_verbose_flag(avm_prove_command);
639 add_debug_flag(avm_prove_command);
640 add_crs_path_option(avm_prove_command);
641 std::filesystem::path avm_prove_output_path{
"./proofs" };
642 add_output_path_option(avm_prove_command, avm_prove_output_path);
643 add_avm_inputs_option(avm_prove_command);
648 CLI::App* avm_write_vk_command = app.add_subcommand(
"avm_write_vk",
"Write AVM verification key.");
649 avm_write_vk_command->group(aztec_internal_group);
650 add_verbose_flag(avm_write_vk_command);
651 add_debug_flag(avm_write_vk_command);
652 add_crs_path_option(avm_write_vk_command);
653 std::filesystem::path avm_write_vk_output_path{
"./keys" };
654 add_output_path_option(avm_write_vk_command, avm_write_vk_output_path);
659 CLI::App* avm_check_circuit_command = app.add_subcommand(
"avm_check_circuit",
"Check AVM circuit satisfiability.");
660 avm_check_circuit_command->group(aztec_internal_group);
661 add_verbose_flag(avm_check_circuit_command);
662 add_debug_flag(avm_check_circuit_command);
663 add_crs_path_option(avm_check_circuit_command);
664 add_avm_inputs_option(avm_check_circuit_command);
669 CLI::App* avm_verify_command = app.add_subcommand(
"avm_verify",
"Verify an AVM proof.");
670 avm_verify_command->group(aztec_internal_group);
671 add_verbose_flag(avm_verify_command);
672 add_debug_flag(avm_verify_command);
673 add_crs_path_option(avm_verify_command);
674 add_avm_public_inputs_option(avm_verify_command);
675 add_proof_path_option(avm_verify_command);
680 CLI::App* aztec_process = app.add_subcommand(
682 "Process Aztec contract artifacts: transpile and generate verification keys for all private functions.\n"
683 "If input is a directory (and no output specified), recursively processes all artifacts found in the "
685 "Multiple -i flags can be specified when no -o flag is present for parallel processing.");
686 aztec_process->group(aztec_internal_group);
688 std::vector<std::string> artifact_input_paths;
689 std::string artifact_output_path;
690 bool force_regenerate =
false;
692 aztec_process->add_option(
"-i,--input",
693 artifact_input_paths,
694 "Input artifact JSON path or directory to search (optional, defaults to current "
695 "directory). Can be specified multiple times when no -o flag is present.");
696 aztec_process->add_option(
698 artifact_output_path,
699 "Output artifact JSON path (optional, same as input if not specified). Cannot be used with multiple -i flags.");
700 aztec_process->add_flag(
"-f,--force", force_regenerate,
"Force regeneration of verification keys");
701 add_verbose_flag(aztec_process);
702 add_debug_flag(aztec_process);
707 CLI::App* cache_paths_command =
708 aztec_process->add_subcommand(
"cache_paths",
709 "Output cache paths for verification keys in an artifact.\n"
710 "Format: <hash>:<cache_path>:<function_name> (one per line).");
712 std::string cache_paths_input;
713 cache_paths_command->add_option(
"input", cache_paths_input,
"Input artifact JSON path (required).")->required();
714 add_verbose_flag(cache_paths_command);
715 add_debug_flag(cache_paths_command);
720 CLI::App* msgpack_command = app.add_subcommand(
"msgpack",
"Msgpack API interface.");
723 CLI::App* msgpack_schema_command =
724 msgpack_command->add_subcommand(
"schema",
"Output a msgpack schema encoded as JSON to stdout.");
725 add_verbose_flag(msgpack_schema_command);
728 CLI::App* msgpack_curve_constants_command =
729 msgpack_command->add_subcommand(
"curve_constants",
"Output curve constants as msgpack to stdout.");
730 add_verbose_flag(msgpack_curve_constants_command);
733 CLI::App* msgpack_run_command =
734 msgpack_command->add_subcommand(
"run",
"Execute msgpack API commands from stdin or file.");
735 add_verbose_flag(msgpack_run_command);
736 std::string msgpack_input_file;
737 msgpack_run_command->add_option(
738 "-i,--input", msgpack_input_file,
"Input file containing msgpack buffers (defaults to stdin)");
739 size_t request_ring_size = 1024 * 1024;
742 "--request-ring-size", request_ring_size,
"Request ring buffer size for shared memory IPC (default: 1MB)")
743 ->check(CLI::PositiveNumber);
744 size_t response_ring_size = 1024 * 1024;
746 ->add_option(
"--response-ring-size",
748 "Response ring buffer size for shared memory IPC (default: 1MB)")
749 ->check(CLI::PositiveNumber);
752 ->add_option(
"--max-clients",
754 "Maximum concurrent clients for socket IPC servers (default: 1, only used for .sock files)")
755 ->check(CLI::PositiveNumber);
764 if (show_extended_help) {
771 if (!flags.verifier_target.empty()) {
775 if (active_sub !=
nullptr) {
777 auto get_option_count = [](CLI::App* sub,
const std::string&
name) ->
size_t {
779 return sub->get_option(
name)->count();
780 }
catch (
const CLI::OptionNotFound&) {
785 if (get_option_count(active_sub,
"--oracle_hash") > 0) {
786 throw_or_abort(
"Cannot use --verifier_target with --oracle_hash. "
787 "The --verifier_target flag sets oracle_hash automatically.");
789 if (get_option_count(active_sub,
"--disable_zk") > 0) {
791 "Use a '-no-zk' variant of --verifier_target instead (e.g., 'evm-no-zk').");
793 if (get_option_count(active_sub,
"--ipa_accumulation") > 0) {
794 throw_or_abort(
"Cannot use --verifier_target with --ipa_accumulation. "
795 "Use '--verifier_target noir-rollup' for IPA accumulation.");
800 if (flags.verifier_target ==
"evm") {
801 flags.oracle_hash_type =
"keccak";
802 }
else if (flags.verifier_target ==
"evm-no-zk") {
803 flags.oracle_hash_type =
"keccak";
804 flags.disable_zk =
true;
805 }
else if (flags.verifier_target ==
"noir-recursive") {
806 flags.oracle_hash_type =
"poseidon2";
807 }
else if (flags.verifier_target ==
"noir-recursive-no-zk") {
808 flags.oracle_hash_type =
"poseidon2";
809 flags.disable_zk =
true;
810 }
else if (flags.verifier_target ==
"noir-rollup") {
811 flags.oracle_hash_type =
"poseidon2";
812 flags.ipa_accumulation =
true;
813 }
else if (flags.verifier_target ==
"noir-rollup-no-zk") {
814 flags.oracle_hash_type =
"poseidon2";
815 flags.ipa_accumulation =
true;
816 flags.disable_zk =
true;
817 }
else if (flags.verifier_target ==
"starknet") {
818 flags.oracle_hash_type =
"starknet";
819 }
else if (flags.verifier_target ==
"starknet-no-zk") {
820 flags.oracle_hash_type =
"starknet";
821 flags.disable_zk =
true;
823 vinfo(
"verifier_target '",
824 flags.verifier_target,
825 "' -> oracle_hash_type='",
826 flags.oracle_hash_type,
829 ", ipa_accumulation=",
830 flags.ipa_accumulation);
836 if ((prove->parsed() || write_vk->parsed()) && output_path !=
"-") {
838 std::filesystem::create_directories(output_path);
842 }
else if (flags.verbose) {
846#if !defined(__wasm__) || defined(ENABLE_WASM_BENCH)
847 if (!flags.storage_budget.empty()) {
850 if (!memory_profile_out.empty()) {
852 vinfo(
"Memory profiling enabled via --memory_profile_out");
854 if (print_bench || !bench_out.empty() || !bench_out_hierarchical.empty() || !trace_out_perfetto.empty() ||
855 !trace_out_perfetto_aggregate.empty()) {
857 vinfo(
"BB_BENCH enabled via --print_bench / --bench_out / --trace_out_perfetto");
859 if (!trace_out_perfetto.empty()) {
861 vinfo(
"Per-call BB_BENCH event capture enabled via --trace_out_perfetto");
873 const auto execute_non_prove_command = [&](
API& api) {
874 if (check->parsed()) {
875 api.check(flags, bytecode_path, witness_path);
878 if (gates->parsed()) {
879 api.gates(flags, bytecode_path);
882 if (write_vk->parsed()) {
883 api.write_vk(flags, bytecode_path, output_path);
886 if (verify->parsed()) {
887 const bool verified = api.verify(flags, public_inputs_path, proof_path, vk_path);
888 vinfo(
"verified: ", verified);
889 return verified ? 0 : 1;
891 if (write_solidity_verifier->parsed()) {
893 if (!flags.verifier_target.empty() && flags.verifier_target !=
"evm" &&
894 flags.verifier_target !=
"evm-no-zk") {
895 throw_or_abort(
"write_solidity_verifier requires --verifier_target to be 'evm' or 'evm-no-zk', got '" +
896 flags.verifier_target +
"'");
898 api.write_solidity_verifier(flags, output_path, vk_path);
901 auto subcommands = app.get_subcommands();
902 const std::string message = std::string(
"No handler for subcommand ") + subcommands[0]->get_name();
909 if (acir_roundtrip_cmd->parsed()) {
915 if (msgpack_schema_command->parsed()) {
919 if (msgpack_curve_constants_command->parsed()) {
923 if (msgpack_run_command->parsed()) {
924 return execute_msgpack_run(msgpack_input_file, max_clients, request_ring_size, response_ring_size);
926 if (aztec_process->parsed()) {
928 throw_or_abort(
"Aztec artifact processing is not supported in WASM builds.");
931 if (cache_paths_command->parsed()) {
936 if (!artifact_output_path.empty() && artifact_input_paths.size() > 1) {
937 throw_or_abort(
"Cannot specify --output when multiple --input flags are provided.");
941 if (artifact_input_paths.empty()) {
942 artifact_input_paths.push_back(
".");
946 if (artifact_input_paths.size() > 1) {
948 for (
const auto& input : artifact_input_paths) {
949 if (std::filesystem::is_directory(input)) {
950 throw_or_abort(
"When using multiple --input flags, all inputs must be files, not directories.");
955 std::atomic<bool> all_success =
true;
956 std::vector<std::string> failures;
957 std::mutex failures_mutex;
959 parallel_for(artifact_input_paths.size(), [&](
size_t i) {
960 const auto& input = artifact_input_paths[i];
961 if (!process_aztec_artifact(input, input, force_regenerate)) {
963 std::lock_guard<std::mutex> lock(failures_mutex);
964 failures.push_back(input);
969 info(
"Failed to process ", failures.size(),
" artifact(s)");
972 info(
"Successfully processed ", artifact_input_paths.size(),
" artifact(s)");
977 std::string input = artifact_input_paths[0];
980 if (std::filesystem::is_directory(input)) {
982 if (!artifact_output_path.empty()) {
984 "Cannot specify --output when input is a directory. Artifacts are updated in-place.");
991 std::string output = artifact_output_path.empty() ? input : artifact_output_path;
996 else if (avm_prove_command->parsed()) {
998 avm_prove(avm_inputs_path, avm_prove_output_path);
999 }
else if (avm_check_circuit_command->parsed()) {
1001 }
else if (avm_verify_command->parsed()) {
1002 return avm_verify(proof_path, avm_public_inputs_path) ? 0 : 1;
1003 }
else if (avm_simulate_command->parsed()) {
1005 }
else if (avm_write_vk_command->parsed()) {
1007 }
else if (flags.scheme ==
"chonk") {
1009 if (prove->parsed()) {
1010 if (!std::filesystem::exists(ivc_inputs_path)) {
1011 throw_or_abort(
"The prove command for Chonk expect a valid file passed with --ivc_inputs_path "
1012 "<ivc-inputs.msgpack> (default ./ivc-inputs.msgpack)");
1014 api.
prove(flags, ivc_inputs_path, output_path);
1015#if !defined(__wasm__) || defined(ENABLE_WASM_BENCH)
1017 vinfo(
"Printing BB_BENCH results...");
1021 if (!bench_out.empty()) {
1022 std::ofstream file(bench_out);
1025 if (!bench_out_hierarchical.empty()) {
1026 std::ofstream file(bench_out_hierarchical);
1029 if (!trace_out_perfetto.empty()) {
1030 std::ofstream file(trace_out_perfetto);
1032 vinfo(
"Perfetto per-call trace written to ", trace_out_perfetto);
1034 if (!trace_out_perfetto_aggregate.empty()) {
1035 std::ofstream file(trace_out_perfetto_aggregate);
1037 vinfo(
"Perfetto aggregate trace written to ", trace_out_perfetto_aggregate);
1040 if (!memory_profile_out.empty()) {
1041 std::ofstream file(memory_profile_out);
1043 vinfo(
"Memory profile written to ", memory_profile_out);
1047 if (check->parsed()) {
1048 if (!std::filesystem::exists(ivc_inputs_path)) {
1049 throw_or_abort(
"The check command for Chonk expect a valid file passed with --ivc_inputs_path "
1050 "<ivc-inputs.msgpack> (default ./ivc-inputs.msgpack)");
1054 if (batch_verify->parsed()) {
1055 const bool verified = api.
batch_verify(flags, batch_verify_proofs_dir);
1056 vinfo(
"batch verified: ", verified);
1057 return verified ? 0 : 1;
1059 if (proof_stats->parsed()) {
1063 return execute_non_prove_command(api);
1064 }
else if (flags.scheme ==
"ultra_honk") {
1066 if (prove->parsed()) {
1067 api.
prove(flags, bytecode_path, witness_path, vk_path, output_path);
1068#if !defined(__wasm__) || defined(ENABLE_WASM_BENCH)
1072 if (!bench_out.empty()) {
1073 std::ofstream file(bench_out);
1076 if (!bench_out_hierarchical.empty()) {
1077 std::ofstream file(bench_out_hierarchical);
1080 if (!trace_out_perfetto.empty()) {
1081 std::ofstream file(trace_out_perfetto);
1083 vinfo(
"Perfetto per-call trace written to ", trace_out_perfetto);
1085 if (!trace_out_perfetto_aggregate.empty()) {
1086 std::ofstream file(trace_out_perfetto_aggregate);
1088 vinfo(
"Perfetto aggregate trace written to ", trace_out_perfetto_aggregate);
1093 return execute_non_prove_command(api);
1098 }
catch (std::runtime_error
const& err) {
1099#ifndef BB_NO_EXCEPTIONS