108 std::string name =
"Barretenberg\nYour favo(u)rite zkSNARK library written in C++, a perfectly good computer "
109 "programming language.";
113 name +=
"\nAztec Virtual Machine (AVM): enabled";
115 name +=
"\nAztec Virtual Machine (AVM): disabled";
117#ifdef ENABLE_AVM_TRANSPILER
118 name +=
"\nAVM Transpiler: enabled";
120 name +=
"\nAVM Transpiler: disabled";
122#ifdef STARKNET_GARAGA_FLAVORS
123 name +=
"\nStarknet Garaga Extensions: enabled";
125 name +=
"\nStarknet Garaga Extensions: disabled";
127 CLI::App app{ name };
128 argv = app.ensure_utf8(argv);
138 app.require_subcommand(0, 1);
142 std::filesystem::path bytecode_path{
"./target/program.json" };
143 std::filesystem::path witness_path{
"./target/witness.gz" };
144 std::filesystem::path ivc_inputs_path{
"./ivc-inputs.msgpack" };
145 std::filesystem::path output_path{
148 std::filesystem::path public_inputs_path{
"./target/public_inputs" };
149 std::filesystem::path proof_path{
"./target/proof" };
150 std::filesystem::path vk_path{
"./target/vk" };
152 flags.oracle_hash_type =
"poseidon2";
154 flags.include_gates_per_opcode =
false;
160 bool show_extended_help =
false;
161 for (
int i = 1; i < argc; ++i) {
162 if (std::string(argv[i]) ==
"--help-extended") {
163 show_extended_help =
true;
168 const std::string advanced_group = show_extended_help ?
"Advanced Options (Aztec/Power Users)" :
"";
169 const std::string aztec_internal_group = show_extended_help ?
"Aztec Internal Commands" :
"";
171 const auto add_output_path_option = [&](CLI::App* subcommand,
auto& _output_path) {
172 return subcommand->add_option(
"--output_path, -o",
174 "Directory to write files or path of file to write, depending on subcommand.");
178 const auto add_help_extended_flag = [&](CLI::App* subcommand) {
179 subcommand->add_flag(
"--help-extended",
"Show all options including advanced ones.");
186 const auto add_ipa_accumulation_flag = [&](CLI::App* subcommand) {
188 ->add_flag(
"--ipa_accumulation",
189 flags.ipa_accumulation,
190 "Accumulate/Aggregate IPA (Inner Product Argument) claims")
191 ->group(advanced_group);
194 const auto add_scheme_option = [&](CLI::App* subcommand) {
199 "The type of proof to be constructed. This can specify a proving system, an accumulation scheme, or a "
200 "particular type of circuit to be constructed and proven for some implicit scheme.")
201 ->envname(
"BB_SCHEME")
202 ->default_val(
"ultra_honk")
203 ->check(CLI::IsMember({
"chonk",
"avm",
"ultra_honk" }).name(
"is_member"))
204 ->
group(advanced_group);
207 const auto add_crs_path_option = [&](CLI::App* subcommand) {
209 ->add_option(
"--crs_path, -c",
211 "Path CRS directory. Missing CRS files will be retrieved from the internet.")
212 ->check(CLI::ExistingDirectory)
213 ->group(advanced_group);
216 const auto add_oracle_hash_option = [&](CLI::App* subcommand) {
220 flags.oracle_hash_type,
221 "The hash function used by the prover as random oracle standing in for a verifier's challenge "
222 "generation. Poseidon2 is to be used for proofs that are intended to be verified inside of a "
223 "circuit. Keccak is optimized for verification in an Ethereum smart contract, where Keccak "
224 "has a privileged position due to the existence of an EVM precompile. Starknet is optimized "
225 "for verification in a Starknet smart contract, which can be generated using the Garaga library. "
226 "Prefer using --verifier_target instead.")
227 ->check(CLI::IsMember({
"poseidon2",
"keccak",
"starknet" }).name(
"is_member"))
228 ->
group(advanced_group);
231 const auto add_verifier_target_option = [&](CLI::App* subcommand) {
233 ->add_option(
"--verifier_target, -t",
234 flags.verifier_target,
235 "Target verification environment. Determines hash function and ZK settings.\n"
236 " evm: Ethereum/Solidity verification (keccak, ZK)\n"
237 " evm-no-zk: Ethereum/Solidity without zero-knowledge\n"
238 " noir-recursive: Recursive verification in Noir circuits (poseidon2, ZK)\n"
239 " noir-recursive-no-zk: Recursive verification without ZK\n"
240 " noir-rollup: Rollup circuits with IPA accumulation (poseidon2, ZK)\n"
241 " noir-rollup-no-zk: Rollup circuits without ZK\n"
242 " starknet: Starknet verification via Garaga (ZK)\n"
243 " starknet-no-zk: Starknet without zero-knowledge")
244 ->envname(
"BB_VERIFIER_TARGET")
245 ->check(CLI::IsMember({
"evm",
248 "noir-recursive-no-zk",
252 "starknet-no-zk" }));
255 const auto add_write_vk_flag = [&](CLI::App* subcommand) {
256 return subcommand->add_flag(
"--write_vk", flags.write_vk,
"Write the provided circuit's verification key");
259 const auto remove_zk_option = [&](CLI::App* subcommand) {
261 ->add_flag(
"--disable_zk",
263 "Use a non-zk version of --scheme. Prefer using --verifier_target *-no-zk variants instead.")
264 ->group(advanced_group);
267 const auto add_bytecode_path_option = [&](CLI::App* subcommand) {
268 subcommand->add_option(
"--bytecode_path, -b", bytecode_path,
"Path to ACIR bytecode generated by Noir.")
272 const auto add_witness_path_option = [&](CLI::App* subcommand) {
273 subcommand->add_option(
"--witness_path, -w", witness_path,
"Path to partial witness generated by Noir.")
277 const auto add_ivc_inputs_path_options = [&](CLI::App* subcommand) {
280 "--ivc_inputs_path", ivc_inputs_path,
"For IVC, path to input stack with bytecode and witnesses.")
281 ->group(advanced_group);
284 const auto add_public_inputs_path_option = [&](CLI::App* subcommand) {
285 return subcommand->add_option(
286 "--public_inputs_path, -i", public_inputs_path,
"Path to public inputs.") ;
289 const auto add_proof_path_option = [&](CLI::App* subcommand) {
290 return subcommand->add_option(
291 "--proof_path, -p", proof_path,
"Path to a proof.") ;
294 const auto add_vk_path_option = [&](CLI::App* subcommand) {
295 return subcommand->add_option(
"--vk_path, -k", vk_path,
"Path to a verification key.")
299 const auto add_verifier_type_option = [&](CLI::App* subcommand) {
301 ->add_option(
"--verifier_type",
303 "Is a verification key for use a standalone single circuit verifier (e.g. a SNARK or folding "
304 "recursive verifier) or is it for an ivc verifier? `standalone` produces a verification key "
305 "is sufficient for verifying proofs about a single circuit (including the non-encsapsulated "
306 "use case where an IVC scheme is manually constructed via recursive UltraHonk proof "
307 "verification). `standalone_hiding` is similar to `standalone` but is used for the last step "
308 "where the structured trace is not utilized. `ivc` produces a verification key for verifying "
309 "the stack of run though a dedicated ivc verifier class (currently the only option is the "
311 ->check(CLI::IsMember({
"standalone",
"standalone_hiding",
"ivc" }).name(
"is_member"))
312 ->
group(advanced_group);
315 const auto add_verbose_flag = [&](CLI::App* subcommand) {
316 return subcommand->add_flag(
"--verbose, --verbose_logging, -v", flags.verbose,
"Output all logs to stderr.")
317 ->group(advanced_group);
320 const auto add_debug_flag = [&](CLI::App* subcommand) {
321 return subcommand->add_flag(
"--debug_logging, -d", flags.debug,
"Output debug logs to stderr.")
322 ->group(advanced_group);
325 const auto add_include_gates_per_opcode_flag = [&](CLI::App* subcommand) {
326 return subcommand->add_flag(
"--include_gates_per_opcode",
327 flags.include_gates_per_opcode,
328 "Include gates_per_opcode in the output of the gates command.");
331 const auto add_slow_low_memory_flag = [&](CLI::App* subcommand) {
333 ->add_flag(
"--slow_low_memory", flags.slow_low_memory,
"Enable low memory mode (can be 2x slower or more).")
334 ->group(advanced_group);
337 const auto add_storage_budget_option = [&](CLI::App* subcommand) {
339 ->add_option(
"--storage_budget",
340 flags.storage_budget,
341 "Storage budget for FileBackedMemory (e.g. '500m', '2g'). When exceeded, falls "
342 "back to RAM (requires --slow_low_memory).")
343 ->group(advanced_group);
346 const auto add_vk_policy_option = [&](CLI::App* subcommand) {
348 ->add_option(
"--vk_policy",
350 "Policy for handling verification keys. 'default' uses the provided VK as-is, 'check' "
351 "verifies the provided VK matches the computed VK (throws error on mismatch), 'recompute' "
352 "always ignores the provided VK and treats it as nullptr, 'rewrite' checks the VK and "
353 "rewrites the input file with the correct VK if there's a mismatch (for check command).")
354 ->check(CLI::IsMember({
"default",
"check",
"recompute",
"rewrite" }).name(
"is_member"))
355 ->
group(advanced_group);
358 const auto add_optimized_solidity_verifier_flag = [&](CLI::App* subcommand) {
359 return subcommand->add_flag(
360 "--optimized", flags.optimized_solidity_verifier,
"Use the optimized Solidity verifier.");
363 bool print_bench =
false;
364 const auto add_print_bench_flag = [&](CLI::App* subcommand) {
367 "--print_bench", print_bench,
"Pretty print op counts to standard error in a human-readable format.")
368 ->group(advanced_group);
371 std::string bench_out;
372 const auto add_bench_out_option = [&](CLI::App* subcommand) {
373 return subcommand->add_option(
"--bench_out", bench_out,
"Path to write the op counts in a json.")
374 ->group(advanced_group);
376 std::string bench_out_hierarchical;
377 const auto add_bench_out_hierarchical_option = [&](CLI::App* subcommand) {
379 ->add_option(
"--bench_out_hierarchical",
380 bench_out_hierarchical,
381 "Path to write the hierarchical benchmark data (op counts and timings with "
382 "parent-child relationships) as json.")
383 ->group(advanced_group);
389 add_verbose_flag(&app);
390 add_debug_flag(&app);
391 add_crs_path_option(&app);
396 app.set_version_flag(
"--version",
BB_VERSION,
"Print the version string.");
401 app.add_flag(
"--help-extended",
"Show all options including advanced and Aztec-specific commands.");
406 CLI::App* check = app.add_subcommand(
408 "A debugging tool to quickly check whether a witness satisfies a circuit The "
409 "function constructs the execution trace and iterates through it row by row, applying the "
410 "polynomial relations defining the gate types. For Chonk, we check the VKs in the folding stack.");
412 add_help_extended_flag(check);
413 add_scheme_option(check);
414 add_bytecode_path_option(check);
415 add_witness_path_option(check);
416 add_ivc_inputs_path_options(check);
417 add_vk_policy_option(check);
422 CLI::App* gates = app.add_subcommand(
"gates",
423 "Construct a circuit from the given bytecode (in particular, expand black box "
424 "functions) and return the gate count information.");
426 add_help_extended_flag(gates);
427 add_scheme_option(gates);
428 add_verbose_flag(gates);
429 add_bytecode_path_option(gates);
430 add_include_gates_per_opcode_flag(gates);
431 add_verifier_target_option(gates);
432 add_oracle_hash_option(gates);
433 add_ipa_accumulation_flag(gates);
438 CLI::App* prove = app.add_subcommand(
"prove",
"Generate a proof.");
440 add_help_extended_flag(prove);
441 add_scheme_option(prove);
442 add_bytecode_path_option(prove);
443 add_witness_path_option(prove);
444 add_output_path_option(prove, output_path);
445 add_ivc_inputs_path_options(prove);
446 add_vk_path_option(prove);
447 add_vk_policy_option(prove);
448 add_verbose_flag(prove);
449 add_debug_flag(prove);
450 add_crs_path_option(prove);
451 add_verifier_target_option(prove);
452 add_oracle_hash_option(prove);
453 add_write_vk_flag(prove);
454 add_ipa_accumulation_flag(prove);
455 remove_zk_option(prove);
456 add_slow_low_memory_flag(prove);
457 add_print_bench_flag(prove);
458 add_bench_out_option(prove);
459 add_bench_out_hierarchical_option(prove);
460 add_storage_budget_option(prove);
462 prove->add_flag(
"--verify",
"Verify the proof natively, resulting in a boolean output. Useful for testing.");
468 app.add_subcommand(
"write_vk",
469 "Write the verification key of a circuit. The circuit is constructed using "
470 "quickly generated but invalid witnesses (which must be supplied in Barretenberg in order "
471 "to expand ACIR black box opcodes), and no proof is constructed.");
473 add_help_extended_flag(write_vk);
474 add_scheme_option(write_vk);
475 add_bytecode_path_option(write_vk);
476 add_output_path_option(write_vk, output_path);
477 add_ivc_inputs_path_options(write_vk);
479 add_verbose_flag(write_vk);
480 add_debug_flag(write_vk);
481 add_crs_path_option(write_vk);
482 add_verifier_target_option(write_vk);
483 add_oracle_hash_option(write_vk);
484 add_ipa_accumulation_flag(write_vk);
485 add_verifier_type_option(write_vk)->default_val(
"standalone");
486 remove_zk_option(write_vk);
491 CLI::App* verify = app.add_subcommand(
"verify",
"Verify a proof.");
493 add_help_extended_flag(verify);
494 add_public_inputs_path_option(verify);
495 add_proof_path_option(verify);
496 add_vk_path_option(verify);
498 add_verbose_flag(verify);
499 add_debug_flag(verify);
500 add_scheme_option(verify);
501 add_crs_path_option(verify);
502 add_verifier_target_option(verify);
503 add_oracle_hash_option(verify);
504 remove_zk_option(verify);
505 add_ipa_accumulation_flag(verify);
510 CLI::App* write_solidity_verifier =
511 app.add_subcommand(
"write_solidity_verifier",
512 "Write a Solidity smart contract suitable for verifying proofs of circuit "
513 "satisfiability for the circuit with verification key at vk_path. Not all "
514 "hash types are implemented due to efficiency concerns.");
516 add_help_extended_flag(write_solidity_verifier);
517 add_scheme_option(write_solidity_verifier);
518 add_vk_path_option(write_solidity_verifier);
519 add_output_path_option(write_solidity_verifier, output_path);
521 add_verbose_flag(write_solidity_verifier);
522 add_verifier_target_option(write_solidity_verifier);
523 remove_zk_option(write_solidity_verifier);
524 add_crs_path_option(write_solidity_verifier);
525 add_optimized_solidity_verifier_flag(write_solidity_verifier);
527 std::filesystem::path avm_inputs_path{
"./target/avm_inputs.bin" };
528 const auto add_avm_inputs_option = [&](CLI::App* subcommand) {
529 return subcommand->add_option(
"--avm-inputs", avm_inputs_path,
"");
531 std::filesystem::path avm_public_inputs_path{
"./target/avm_public_inputs.bin" };
532 const auto add_avm_public_inputs_option = [&](CLI::App* subcommand) {
533 return subcommand->add_option(
"--avm-public-inputs", avm_public_inputs_path,
"");
539 CLI::App* avm_simulate_command = app.add_subcommand(
"avm_simulate",
"Simulate AVM execution.");
540 avm_simulate_command->group(aztec_internal_group);
541 add_verbose_flag(avm_simulate_command);
542 add_debug_flag(avm_simulate_command);
543 add_avm_inputs_option(avm_simulate_command);
548 CLI::App* avm_prove_command = app.add_subcommand(
"avm_prove",
"Generate an AVM proof.");
549 avm_prove_command->group(aztec_internal_group);
550 add_verbose_flag(avm_prove_command);
551 add_debug_flag(avm_prove_command);
552 add_crs_path_option(avm_prove_command);
553 std::filesystem::path avm_prove_output_path{
"./proofs" };
554 add_output_path_option(avm_prove_command, avm_prove_output_path);
555 add_avm_inputs_option(avm_prove_command);
560 CLI::App* avm_write_vk_command = app.add_subcommand(
"avm_write_vk",
"Write AVM verification key.");
561 avm_write_vk_command->group(aztec_internal_group);
562 add_verbose_flag(avm_write_vk_command);
563 add_debug_flag(avm_write_vk_command);
564 add_crs_path_option(avm_write_vk_command);
565 std::filesystem::path avm_write_vk_output_path{
"./keys" };
566 add_output_path_option(avm_write_vk_command, avm_write_vk_output_path);
571 CLI::App* avm_check_circuit_command = app.add_subcommand(
"avm_check_circuit",
"Check AVM circuit satisfiability.");
572 avm_check_circuit_command->group(aztec_internal_group);
573 add_verbose_flag(avm_check_circuit_command);
574 add_debug_flag(avm_check_circuit_command);
575 add_crs_path_option(avm_check_circuit_command);
576 add_avm_inputs_option(avm_check_circuit_command);
581 CLI::App* avm_verify_command = app.add_subcommand(
"avm_verify",
"Verify an AVM proof.");
582 avm_verify_command->group(aztec_internal_group);
583 add_verbose_flag(avm_verify_command);
584 add_debug_flag(avm_verify_command);
585 add_crs_path_option(avm_verify_command);
586 add_avm_public_inputs_option(avm_verify_command);
587 add_proof_path_option(avm_verify_command);
592 CLI::App* aztec_process = app.add_subcommand(
594 "Process Aztec contract artifacts: transpile and generate verification keys for all private functions.\n"
595 "If input is a directory (and no output specified), recursively processes all artifacts found in the "
597 "Multiple -i flags can be specified when no -o flag is present for parallel processing.");
598 aztec_process->group(aztec_internal_group);
600 std::vector<std::string> artifact_input_paths;
601 std::string artifact_output_path;
602 bool force_regenerate =
false;
604 aztec_process->add_option(
"-i,--input",
605 artifact_input_paths,
606 "Input artifact JSON path or directory to search (optional, defaults to current "
607 "directory). Can be specified multiple times when no -o flag is present.");
608 aztec_process->add_option(
610 artifact_output_path,
611 "Output artifact JSON path (optional, same as input if not specified). Cannot be used with multiple -i flags.");
612 aztec_process->add_flag(
"-f,--force", force_regenerate,
"Force regeneration of verification keys");
613 add_verbose_flag(aztec_process);
614 add_debug_flag(aztec_process);
619 CLI::App* cache_paths_command =
620 aztec_process->add_subcommand(
"cache_paths",
621 "Output cache paths for verification keys in an artifact.\n"
622 "Format: <hash>:<cache_path>:<function_name> (one per line).");
624 std::string cache_paths_input;
625 cache_paths_command->add_option(
"input", cache_paths_input,
"Input artifact JSON path (required).")->required();
626 add_verbose_flag(cache_paths_command);
627 add_debug_flag(cache_paths_command);
632 CLI::App* msgpack_command = app.add_subcommand(
"msgpack",
"Msgpack API interface.");
635 CLI::App* msgpack_schema_command =
636 msgpack_command->add_subcommand(
"schema",
"Output a msgpack schema encoded as JSON to stdout.");
637 add_verbose_flag(msgpack_schema_command);
640 CLI::App* msgpack_curve_constants_command =
641 msgpack_command->add_subcommand(
"curve_constants",
"Output curve constants as msgpack to stdout.");
642 add_verbose_flag(msgpack_curve_constants_command);
645 CLI::App* msgpack_run_command =
646 msgpack_command->add_subcommand(
"run",
"Execute msgpack API commands from stdin or file.");
647 add_verbose_flag(msgpack_run_command);
648 std::string msgpack_input_file;
649 msgpack_run_command->add_option(
650 "-i,--input", msgpack_input_file,
"Input file containing msgpack buffers (defaults to stdin)");
651 size_t request_ring_size = 1024 * 1024;
654 "--request-ring-size", request_ring_size,
"Request ring buffer size for shared memory IPC (default: 1MB)")
655 ->check(CLI::PositiveNumber);
656 size_t response_ring_size = 1024 * 1024;
658 ->add_option(
"--response-ring-size",
660 "Response ring buffer size for shared memory IPC (default: 1MB)")
661 ->check(CLI::PositiveNumber);
664 ->add_option(
"--max-clients",
666 "Maximum concurrent clients for socket IPC servers (default: 1, only used for .sock files)")
667 ->check(CLI::PositiveNumber);
676 if (show_extended_help) {
683 if (!flags.verifier_target.empty()) {
687 if (active_sub !=
nullptr) {
689 auto get_option_count = [](CLI::App* sub,
const std::string& name) ->
size_t {
691 return sub->get_option(name)->count();
692 }
catch (
const CLI::OptionNotFound&) {
697 if (get_option_count(active_sub,
"--oracle_hash") > 0) {
698 throw_or_abort(
"Cannot use --verifier_target with --oracle_hash. "
699 "The --verifier_target flag sets oracle_hash automatically.");
701 if (get_option_count(active_sub,
"--disable_zk") > 0) {
703 "Use a '-no-zk' variant of --verifier_target instead (e.g., 'evm-no-zk').");
705 if (get_option_count(active_sub,
"--ipa_accumulation") > 0) {
706 throw_or_abort(
"Cannot use --verifier_target with --ipa_accumulation. "
707 "Use '--verifier_target noir-rollup' for IPA accumulation.");
712 if (flags.verifier_target ==
"evm") {
713 flags.oracle_hash_type =
"keccak";
714 }
else if (flags.verifier_target ==
"evm-no-zk") {
715 flags.oracle_hash_type =
"keccak";
716 flags.disable_zk =
true;
717 }
else if (flags.verifier_target ==
"noir-recursive") {
718 flags.oracle_hash_type =
"poseidon2";
719 }
else if (flags.verifier_target ==
"noir-recursive-no-zk") {
720 flags.oracle_hash_type =
"poseidon2";
721 flags.disable_zk =
true;
722 }
else if (flags.verifier_target ==
"noir-rollup") {
723 flags.oracle_hash_type =
"poseidon2";
724 flags.ipa_accumulation =
true;
725 }
else if (flags.verifier_target ==
"noir-rollup-no-zk") {
726 flags.oracle_hash_type =
"poseidon2";
727 flags.ipa_accumulation =
true;
728 flags.disable_zk =
true;
729 }
else if (flags.verifier_target ==
"starknet") {
730 flags.oracle_hash_type =
"starknet";
731 }
else if (flags.verifier_target ==
"starknet-no-zk") {
732 flags.oracle_hash_type =
"starknet";
733 flags.disable_zk =
true;
735 vinfo(
"verifier_target '",
736 flags.verifier_target,
737 "' -> oracle_hash_type='",
738 flags.oracle_hash_type,
741 ", ipa_accumulation=",
742 flags.ipa_accumulation);
748 if ((prove->parsed() || write_vk->parsed()) && output_path !=
"-") {
750 std::filesystem::create_directories(output_path);
755#if !defined(__wasm__) || defined(ENABLE_WASM_BENCH)
756 if (!flags.storage_budget.empty()) {
759 if (print_bench || !bench_out.empty() || !bench_out_hierarchical.empty()) {
761 vinfo(
"BB_BENCH enabled via --print_bench or --bench_out");
773 const auto execute_non_prove_command = [&](
API& api) {
774 if (check->parsed()) {
775 api.check(flags, bytecode_path, witness_path);
778 if (gates->parsed()) {
779 api.gates(flags, bytecode_path);
782 if (write_vk->parsed()) {
783 api.write_vk(flags, bytecode_path, output_path);
786 if (verify->parsed()) {
787 const bool verified = api.verify(flags, public_inputs_path, proof_path, vk_path);
788 vinfo(
"verified: ", verified);
789 return verified ? 0 : 1;
791 if (write_solidity_verifier->parsed()) {
793 if (!flags.verifier_target.empty() && flags.verifier_target !=
"evm" &&
794 flags.verifier_target !=
"evm-no-zk") {
795 throw_or_abort(
"write_solidity_verifier requires --verifier_target to be 'evm' or 'evm-no-zk', got '" +
796 flags.verifier_target +
"'");
798 api.write_solidity_verifier(flags, output_path, vk_path);
801 auto subcommands = app.get_subcommands();
802 const std::string message = std::string(
"No handler for subcommand ") + subcommands[0]->get_name();
809 if (msgpack_schema_command->parsed()) {
813 if (msgpack_curve_constants_command->parsed()) {
817 if (msgpack_run_command->parsed()) {
818 return execute_msgpack_run(msgpack_input_file, max_clients, request_ring_size, response_ring_size);
820 if (aztec_process->parsed()) {
822 throw_or_abort(
"Aztec artifact processing is not supported in WASM builds.");
825 if (cache_paths_command->parsed()) {
830 if (!artifact_output_path.empty() && artifact_input_paths.size() > 1) {
831 throw_or_abort(
"Cannot specify --output when multiple --input flags are provided.");
835 if (artifact_input_paths.empty()) {
836 artifact_input_paths.push_back(
".");
840 if (artifact_input_paths.size() > 1) {
842 for (
const auto& input : artifact_input_paths) {
843 if (std::filesystem::is_directory(input)) {
844 throw_or_abort(
"When using multiple --input flags, all inputs must be files, not directories.");
849 std::atomic<bool> all_success =
true;
850 std::vector<std::string> failures;
851 std::mutex failures_mutex;
853 parallel_for(artifact_input_paths.size(), [&](
size_t i) {
854 const auto& input = artifact_input_paths[i];
855 if (!process_aztec_artifact(input, input, force_regenerate)) {
857 std::lock_guard<std::mutex> lock(failures_mutex);
858 failures.push_back(input);
863 info(
"Failed to process ", failures.size(),
" artifact(s)");
866 info(
"Successfully processed ", artifact_input_paths.size(),
" artifact(s)");
871 std::string input = artifact_input_paths[0];
874 if (std::filesystem::is_directory(input)) {
876 if (!artifact_output_path.empty()) {
878 "Cannot specify --output when input is a directory. Artifacts are updated in-place.");
885 std::string output = artifact_output_path.empty() ? input : artifact_output_path;
890 else if (avm_prove_command->parsed()) {
892 avm_prove(avm_inputs_path, avm_prove_output_path);
893 }
else if (avm_check_circuit_command->parsed()) {
895 }
else if (avm_verify_command->parsed()) {
896 return avm_verify(proof_path, avm_public_inputs_path) ? 0 : 1;
897 }
else if (avm_simulate_command->parsed()) {
899 }
else if (avm_write_vk_command->parsed()) {
901 }
else if (flags.scheme ==
"chonk") {
903 if (prove->parsed()) {
904 if (!std::filesystem::exists(ivc_inputs_path)) {
905 throw_or_abort(
"The prove command for Chonk expect a valid file passed with --ivc_inputs_path "
906 "<ivc-inputs.msgpack> (default ./ivc-inputs.msgpack)");
908 api.
prove(flags, ivc_inputs_path, output_path);
909#if !defined(__wasm__) || defined(ENABLE_WASM_BENCH)
911 vinfo(
"Printing BB_BENCH results...");
915 if (!bench_out.empty()) {
916 std::ofstream file(bench_out);
919 if (!bench_out_hierarchical.empty()) {
920 std::ofstream file(bench_out_hierarchical);
926 if (check->parsed()) {
927 if (!std::filesystem::exists(ivc_inputs_path)) {
928 throw_or_abort(
"The check command for Chonk expect a valid file passed with --ivc_inputs_path "
929 "<ivc-inputs.msgpack> (default ./ivc-inputs.msgpack)");
933 return execute_non_prove_command(api);
934 }
else if (flags.scheme ==
"ultra_honk") {
936 if (prove->parsed()) {
937 api.
prove(flags, bytecode_path, witness_path, vk_path, output_path);
938#if !defined(__wasm__) || defined(ENABLE_WASM_BENCH)
942 if (!bench_out.empty()) {
943 std::ofstream file(bench_out);
946 if (!bench_out_hierarchical.empty()) {
947 std::ofstream file(bench_out_hierarchical);
953 return execute_non_prove_command(api);
958 }
catch (std::runtime_error
const& err) {
959#ifndef BB_NO_EXCEPTIONS