diff --git a/barretenberg/acir_tests/flows/all_cmds.sh b/barretenberg/acir_tests/flows/all_cmds.sh index a65159351ed..c912613302c 100755 --- a/barretenberg/acir_tests/flows/all_cmds.sh +++ b/barretenberg/acir_tests/flows/all_cmds.sh @@ -2,7 +2,7 @@ set -eu VFLAG=${VERBOSE:+-v} -BFLAG="-b ./target/acir.gz" +BFLAG="-b ./target/program.json" FLAGS="-c $CRS_PATH $VFLAG" # Test we can perform the proof/verify flow. @@ -19,4 +19,4 @@ $BIN contract -k vk $BFLAG -o - | grep "Verification Key Hash" > /dev/null OUTPUT=$($BIN proof_as_fields -k vk -p proof -o - | jq .) [ -n "$OUTPUT" ] || exit 1 OUTPUT=$($BIN vk_as_fields -k vk -o - | jq .) -[ -n "$OUTPUT" ] || exit 1 \ No newline at end of file +[ -n "$OUTPUT" ] || exit 1 diff --git a/barretenberg/acir_tests/flows/prove_and_verify.sh b/barretenberg/acir_tests/flows/prove_and_verify.sh index 091a6d57946..4d905538991 100755 --- a/barretenberg/acir_tests/flows/prove_and_verify.sh +++ b/barretenberg/acir_tests/flows/prove_and_verify.sh @@ -5,4 +5,4 @@ VFLAG=${VERBOSE:+-v} # This is the fastest flow, because it only generates pk/vk once, gate count once, etc. # It may not catch all class of bugs. -$BIN prove_and_verify $VFLAG -c $CRS_PATH -b ./target/acir.gz \ No newline at end of file +$BIN prove_and_verify $VFLAG -c $CRS_PATH -b ./target/program.json diff --git a/barretenberg/acir_tests/flows/prove_and_verify_goblin.sh b/barretenberg/acir_tests/flows/prove_and_verify_goblin.sh index 68a003d685b..23340df80a1 100755 --- a/barretenberg/acir_tests/flows/prove_and_verify_goblin.sh +++ b/barretenberg/acir_tests/flows/prove_and_verify_goblin.sh @@ -3,7 +3,7 @@ set -eu VFLAG=${VERBOSE:+-v} -$BIN prove_and_verify_goblin $VFLAG -c $CRS_PATH -b ./target/acir.gz +$BIN prove_and_verify_goblin $VFLAG -c $CRS_PATH -b ./target/program.json # This command can be used to run all of the tests in sequence with the debugger -# lldb-16 -o run -b -- $BIN prove_and_verify_goblin $VFLAG -c $CRS_PATH -b ./target/acir.gz \ No newline at end of file +# lldb-16 -o run -b -- $BIN prove_and_verify_goblin $VFLAG -c $CRS_PATH -b ./target/program.json diff --git a/barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk.sh b/barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk.sh index a8a72924898..2d79f15c212 100755 --- a/barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk.sh +++ b/barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk.sh @@ -3,4 +3,4 @@ set -eu VFLAG=${VERBOSE:+-v} -$BIN prove_and_verify_goblin_ultra_honk $VFLAG -c $CRS_PATH -b ./target/acir.gz \ No newline at end of file +$BIN prove_and_verify_goblin_ultra_honk $VFLAG -c $CRS_PATH -b ./target/program.json diff --git a/barretenberg/acir_tests/flows/prove_and_verify_ultra_honk.sh b/barretenberg/acir_tests/flows/prove_and_verify_ultra_honk.sh index 7b6f0384796..16f2fd7f398 100755 --- a/barretenberg/acir_tests/flows/prove_and_verify_ultra_honk.sh +++ b/barretenberg/acir_tests/flows/prove_and_verify_ultra_honk.sh @@ -3,4 +3,4 @@ set -eu VFLAG=${VERBOSE:+-v} -$BIN prove_and_verify_ultra_honk $VFLAG -c $CRS_PATH -b ./target/acir.gz \ No newline at end of file +$BIN prove_and_verify_ultra_honk $VFLAG -c $CRS_PATH -b ./target/program.json diff --git a/barretenberg/acir_tests/flows/prove_and_verify_ultra_honk_program.sh b/barretenberg/acir_tests/flows/prove_and_verify_ultra_honk_program.sh index 53c9d08e1a6..65a6e400226 100755 --- a/barretenberg/acir_tests/flows/prove_and_verify_ultra_honk_program.sh +++ b/barretenberg/acir_tests/flows/prove_and_verify_ultra_honk_program.sh @@ -3,4 +3,4 @@ set -eu VFLAG=${VERBOSE:+-v} -$BIN prove_and_verify_ultra_honk_program $VFLAG -c $CRS_PATH -b ./target/acir.gz \ No newline at end of file +$BIN prove_and_verify_ultra_honk_program $VFLAG -c $CRS_PATH -b ./target/program.json diff --git a/barretenberg/acir_tests/flows/prove_then_verify.sh b/barretenberg/acir_tests/flows/prove_then_verify.sh index 9c35b981a1a..08d8ea21057 100755 --- a/barretenberg/acir_tests/flows/prove_then_verify.sh +++ b/barretenberg/acir_tests/flows/prove_then_verify.sh @@ -2,7 +2,7 @@ set -eu VFLAG=${VERBOSE:+-v} -BFLAG="-b ./target/acir.gz" +BFLAG="-b ./target/program.json" FLAGS="-c $CRS_PATH $VFLAG" # Test we can perform the proof/verify flow. diff --git a/barretenberg/acir_tests/flows/prove_then_verify_goblin_ultra_honk.sh b/barretenberg/acir_tests/flows/prove_then_verify_goblin_ultra_honk.sh index 9586e6841eb..fa33cefe5d8 100755 --- a/barretenberg/acir_tests/flows/prove_then_verify_goblin_ultra_honk.sh +++ b/barretenberg/acir_tests/flows/prove_then_verify_goblin_ultra_honk.sh @@ -2,7 +2,7 @@ set -eu VFLAG=${VERBOSE:+-v} -BFLAG="-b ./target/acir.gz" +BFLAG="-b ./target/program.json" FLAGS="-c $CRS_PATH $VFLAG" # Test we can perform the proof/verify flow. diff --git a/barretenberg/acir_tests/flows/prove_then_verify_ultra_honk.sh b/barretenberg/acir_tests/flows/prove_then_verify_ultra_honk.sh index bfb20c27cf0..fd559e256c6 100755 --- a/barretenberg/acir_tests/flows/prove_then_verify_ultra_honk.sh +++ b/barretenberg/acir_tests/flows/prove_then_verify_ultra_honk.sh @@ -2,7 +2,7 @@ set -eu VFLAG=${VERBOSE:+-v} -BFLAG="-b ./target/acir.gz" +BFLAG="-b ./target/program.json" FLAGS="-c $CRS_PATH $VFLAG" # Test we can perform the proof/verify flow. diff --git a/barretenberg/acir_tests/flows/sol.sh b/barretenberg/acir_tests/flows/sol.sh index d95c9039eea..66f7833fb70 100755 --- a/barretenberg/acir_tests/flows/sol.sh +++ b/barretenberg/acir_tests/flows/sol.sh @@ -8,7 +8,7 @@ export PROOF_AS_FIELDS="$(pwd)/proof_fields.json" $BIN prove -o proof $BIN write_vk -o vk $BIN proof_as_fields -k vk -c $CRS_PATH -p $PROOF -$BIN contract -k vk -c $CRS_PATH -b ./target/acir.gz -o Key.sol +$BIN contract -k vk -c $CRS_PATH -b ./target/program.json -o Key.sol # Export the paths to the environment variables for the js test runner export KEY_PATH="$(pwd)/Key.sol" @@ -20,4 +20,4 @@ export BASE_PATH=$(realpath "../../../sol/src/ultra/BaseUltraVerifier.sol") # index.js will start an anvil, on a random port # Deploy the verifier then send a test transaction export TEST_NAME=$(basename $(pwd)) -node ../../sol-test/src/index.js \ No newline at end of file +node ../../sol-test/src/index.js diff --git a/barretenberg/acir_tests/flows/write_contract.sh b/barretenberg/acir_tests/flows/write_contract.sh index 4f483395c58..52669901035 100755 --- a/barretenberg/acir_tests/flows/write_contract.sh +++ b/barretenberg/acir_tests/flows/write_contract.sh @@ -4,4 +4,4 @@ set -eu export TEST_NAME=$(basename $(pwd)) $BIN write_vk -o vk -$BIN contract -k vk -c $CRS_PATH -b ./target/acir.gz -o $TEST_NAME.sol +$BIN contract -k vk -c $CRS_PATH -b ./target/program.json -o $TEST_NAME.sol diff --git a/barretenberg/acir_tests/gen_inner_proof_inputs.sh b/barretenberg/acir_tests/gen_inner_proof_inputs.sh index ade57bcea4f..ea3a2ced8e0 100755 --- a/barretenberg/acir_tests/gen_inner_proof_inputs.sh +++ b/barretenberg/acir_tests/gen_inner_proof_inputs.sh @@ -36,7 +36,7 @@ $BIN vk_as_fields $VFLAG -c $CRS_PATH echo "Generate proof to file..." [ -d "$PROOF_DIR" ] || mkdir $PWD/proofs [ -e "$PROOF_PATH" ] || touch $PROOF_PATH -$BIN prove $VFLAG -c $CRS_PATH -b ./target/acir.gz -o "./proofs/$PROOF_NAME" $RFLAG +$BIN prove $VFLAG -c $CRS_PATH -b ./target/program.json -o "./proofs/$PROOF_NAME" $RFLAG echo "Write proof as fields for recursion..." $BIN proof_as_fields $VFLAG -c $CRS_PATH -p "./proofs/$PROOF_NAME" diff --git a/barretenberg/acir_tests/headless-test/src/index.ts b/barretenberg/acir_tests/headless-test/src/index.ts index 1902e510e87..bb906a6db2d 100644 --- a/barretenberg/acir_tests/headless-test/src/index.ts +++ b/barretenberg/acir_tests/headless-test/src/index.ts @@ -38,9 +38,17 @@ function formatAndPrintLog(message: string): void { } const readBytecodeFile = (path: string): Uint8Array => { - const data = fs.readFileSync(path); - const buffer = gunzipSync(data); - return buffer; + const extension = path.substring(path.lastIndexOf('.') + 1); + + if (extension == 'json') { + const encodedCircuit = JSON.parse(fs.readFileSync(path, 'utf8')); + const decompressed = gunzipSync(Uint8Array.from(atob(encodedCircuit.bytecode), c => c.charCodeAt(0))); + return decompressed; + } + + const encodedCircuit = fs.readFileSync(path); + const decompressed = gunzipSync(encodedCircuit); + return decompressed; }; const readWitnessFile = (path: string): Uint8Array => { diff --git a/barretenberg/acir_tests/run_acir_tests.sh b/barretenberg/acir_tests/run_acir_tests.sh index 88189a43438..0e360a89551 100755 --- a/barretenberg/acir_tests/run_acir_tests.sh +++ b/barretenberg/acir_tests/run_acir_tests.sh @@ -73,7 +73,7 @@ else continue fi - if [[ ! -f ./$TEST_NAME/target/acir.gz || ! -f ./$TEST_NAME/target/witness.gz ]]; then + if [[ ! -f ./$TEST_NAME/target/program.json || ! -f ./$TEST_NAME/target/witness.gz ]]; then echo -e "\033[33mSKIPPED\033[0m (uncompiled)" continue fi diff --git a/barretenberg/cpp/src/barretenberg/bb/get_bytecode.hpp b/barretenberg/cpp/src/barretenberg/bb/get_bytecode.hpp index 2c7af46cfca..84d06a74953 100644 --- a/barretenberg/cpp/src/barretenberg/bb/get_bytecode.hpp +++ b/barretenberg/cpp/src/barretenberg/bb/get_bytecode.hpp @@ -1,11 +1,20 @@ #pragma once #include "exec_pipe.hpp" +#include /** * We can assume for now we're running on a unix like system and use the following to extract the bytecode. */ inline std::vector get_bytecode(const std::string& bytecodePath) { + std::filesystem::path filePath = bytecodePath; + if (filePath.extension() == ".json") { + // Try reading json files as if they are a Nargo build artifact + std::string command = "jq -r '.bytecode' \"" + bytecodePath + "\" | base64 -d | gunzip -c"; + return exec_pipe(command); + } + + // For other extensions, assume file is a raw ACIR program std::string command = "gunzip -c \"" + bytecodePath + "\""; return exec_pipe(command); -} \ No newline at end of file +} diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 674e4e67e92..9b1df668943 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -754,7 +754,7 @@ int main(int argc, char* argv[]) std::string command = args[0]; - std::string bytecode_path = get_option(args, "-b", "./target/acir.gz"); + std::string bytecode_path = get_option(args, "-b", "./target/program.json"); std::string witness_path = get_option(args, "-w", "./target/witness.gz"); std::string proof_path = get_option(args, "-p", "./proofs/proof"); std::string vk_path = get_option(args, "-k", "./target/vk"); diff --git a/barretenberg/ts/src/main.ts b/barretenberg/ts/src/main.ts index 2060523db76..2ac32e23544 100755 --- a/barretenberg/ts/src/main.ts +++ b/barretenberg/ts/src/main.ts @@ -21,6 +21,14 @@ const MAX_CIRCUIT_SIZE = 2 ** 19; const threads = +process.env.HARDWARE_CONCURRENCY! || undefined; function getBytecode(bytecodePath: string) { + const extension = bytecodePath.substring(bytecodePath.lastIndexOf('.') + 1); + + if (extension == 'json') { + const encodedCircuit = JSON.parse(readFileSync(bytecodePath, 'utf8')); + const decompressed = gunzipSync(Buffer.from(encodedCircuit.bytecode, 'base64')); + return decompressed; + } + const encodedCircuit = readFileSync(bytecodePath); const decompressed = gunzipSync(encodedCircuit); return decompressed; diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index 801c0b685a9..d7368f299b8 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -84,10 +84,6 @@ pub struct CompileOptions { #[arg(long, conflicts_with = "deny_warnings")] pub silence_warnings: bool, - /// Output ACIR gzipped bytecode instead of the JSON artefact - #[arg(long, hide = true)] - pub only_acir: bool, - /// Disables the builtin Aztec macros being used in the compiler #[arg(long, hide = true)] pub disable_macros: bool, diff --git a/noir/noir-repo/test_programs/execution_success/unit_value/Nargo.toml b/noir/noir-repo/test_programs/execution_success/unit_value/Nargo.toml index f7e3697a7c1..1f9c4524ec5 100644 --- a/noir/noir-repo/test_programs/execution_success/unit_value/Nargo.toml +++ b/noir/noir-repo/test_programs/execution_success/unit_value/Nargo.toml @@ -1,7 +1,7 @@ [package] -name = "short" +name = "unit_value" type = "bin" authors = [""] compiler_version = ">=0.23.0" -[dependencies] \ No newline at end of file +[dependencies] diff --git a/noir/noir-repo/test_programs/rebuild.sh b/noir/noir-repo/test_programs/rebuild.sh index 51e97278281..4733bad10c3 100755 --- a/noir/noir-repo/test_programs/rebuild.sh +++ b/noir/noir-repo/test_programs/rebuild.sh @@ -16,13 +16,14 @@ process_dir() { if [ -d ./target/ ]; then rm -r ./target/ fi - nargo compile --only-acir && nargo execute witness + nargo execute witness if [ -d "$current_dir/acir_artifacts/$dir_name/target" ]; then rm -r "$current_dir/acir_artifacts/$dir_name/target" fi mkdir $current_dir/acir_artifacts/$dir_name/target + mv ./target/$dir_name.json $current_dir/acir_artifacts/$dir_name/target/program.json mv ./target/*.gz $current_dir/acir_artifacts/$dir_name/target/ cd $current_dir @@ -70,4 +71,4 @@ if [ ! -z "$exit_status" ]; then echo "Rebuild failed!" exit $exit_status fi -echo "Rebuild Succeeded!" \ No newline at end of file +echo "Rebuild Succeeded!" diff --git a/noir/noir-repo/tooling/backend_interface/src/cli/contract.rs b/noir/noir-repo/tooling/backend_interface/src/cli/contract.rs index e83fc1909b6..935b96b3ac4 100644 --- a/noir/noir-repo/tooling/backend_interface/src/cli/contract.rs +++ b/noir/noir-repo/tooling/backend_interface/src/cli/contract.rs @@ -48,15 +48,15 @@ fn contract_command() -> Result<(), BackendError> { let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory_path = temp_directory.path(); - let bytecode_path = temp_directory_path.join("acir.gz"); + let artifact_path = temp_directory_path.join("program.json"); let vk_path = temp_directory_path.join("vk"); let crs_path = backend.backend_directory(); - std::fs::File::create(&bytecode_path).expect("file should be created"); + std::fs::File::create(&artifact_path).expect("file should be created"); let write_vk_command = super::WriteVkCommand { - bytecode_path, + artifact_path, vk_path_output: vk_path.clone(), crs_path: crs_path.clone(), }; diff --git a/noir/noir-repo/tooling/backend_interface/src/cli/gates.rs b/noir/noir-repo/tooling/backend_interface/src/cli/gates.rs index 9e12596bfd7..ce6c6cebfd3 100644 --- a/noir/noir-repo/tooling/backend_interface/src/cli/gates.rs +++ b/noir/noir-repo/tooling/backend_interface/src/cli/gates.rs @@ -10,7 +10,7 @@ use super::string_from_stderr; /// for the given bytecode. pub(crate) struct GatesCommand { pub(crate) crs_path: PathBuf, - pub(crate) bytecode_path: PathBuf, + pub(crate) artifact_path: PathBuf, } #[derive(Deserialize)] @@ -31,7 +31,7 @@ impl GatesCommand { .arg("-c") .arg(self.crs_path) .arg("-b") - .arg(self.bytecode_path) + .arg(self.artifact_path) .output()?; if !output.status.success() { @@ -53,12 +53,12 @@ fn gate_command() -> Result<(), BackendError> { let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory_path = temp_directory.path(); - let bytecode_path = temp_directory_path.join("acir.gz"); + let artifact_path = temp_directory_path.join("program.json"); let crs_path = backend.backend_directory(); - std::fs::File::create(&bytecode_path).expect("file should be created"); + std::fs::File::create(&artifact_path).expect("file should be created"); - let gate_command = GatesCommand { crs_path, bytecode_path }; + let gate_command = GatesCommand { crs_path, artifact_path }; let output = gate_command.run(backend.binary_path())?; // Mock backend always returns zero gates. diff --git a/noir/noir-repo/tooling/backend_interface/src/cli/prove.rs b/noir/noir-repo/tooling/backend_interface/src/cli/prove.rs index c63d8afab54..30a27048b48 100644 --- a/noir/noir-repo/tooling/backend_interface/src/cli/prove.rs +++ b/noir/noir-repo/tooling/backend_interface/src/cli/prove.rs @@ -13,7 +13,7 @@ use super::string_from_stderr; /// The proof will be written to the specified output file. pub(crate) struct ProveCommand { pub(crate) crs_path: PathBuf, - pub(crate) bytecode_path: PathBuf, + pub(crate) artifact_path: PathBuf, pub(crate) witness_path: PathBuf, } @@ -26,7 +26,7 @@ impl ProveCommand { .arg("-c") .arg(self.crs_path) .arg("-b") - .arg(self.bytecode_path) + .arg(self.artifact_path) .arg("-w") .arg(self.witness_path) .arg("-o") @@ -49,14 +49,14 @@ fn prove_command() -> Result<(), BackendError> { let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory_path = temp_directory.path(); - let bytecode_path = temp_directory_path.join("acir.gz"); + let artifact_path = temp_directory_path.join("acir.gz"); let witness_path = temp_directory_path.join("witness.tr"); - std::fs::File::create(&bytecode_path).expect("file should be created"); + std::fs::File::create(&artifact_path).expect("file should be created"); std::fs::File::create(&witness_path).expect("file should be created"); let crs_path = backend.backend_directory(); - let prove_command = ProveCommand { crs_path, bytecode_path, witness_path }; + let prove_command = ProveCommand { crs_path, artifact_path, witness_path }; let proof = prove_command.run(backend.binary_path())?; assert_eq!(proof, "proof".as_bytes()); diff --git a/noir/noir-repo/tooling/backend_interface/src/cli/verify.rs b/noir/noir-repo/tooling/backend_interface/src/cli/verify.rs index 1a4ba50b7de..beea4bbec7d 100644 --- a/noir/noir-repo/tooling/backend_interface/src/cli/verify.rs +++ b/noir/noir-repo/tooling/backend_interface/src/cli/verify.rs @@ -41,25 +41,25 @@ fn verify_command() -> Result<(), BackendError> { let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory_path = temp_directory.path(); - let bytecode_path = temp_directory_path.join("acir.gz"); + let artifact_path = temp_directory_path.join("acir.json"); let witness_path = temp_directory_path.join("witness.tr"); let proof_path = temp_directory_path.join("1_mul.proof"); let vk_path_output = temp_directory_path.join("vk"); let crs_path = backend.backend_directory(); - std::fs::File::create(&bytecode_path).expect("file should be created"); + std::fs::File::create(&artifact_path).expect("file should be created"); std::fs::File::create(&witness_path).expect("file should be created"); let write_vk_command = WriteVkCommand { - bytecode_path: bytecode_path.clone(), + artifact_path: artifact_path.clone(), crs_path: crs_path.clone(), vk_path_output: vk_path_output.clone(), }; write_vk_command.run(backend.binary_path())?; - let prove_command = ProveCommand { crs_path: crs_path.clone(), bytecode_path, witness_path }; + let prove_command = ProveCommand { crs_path: crs_path.clone(), artifact_path, witness_path }; let proof = prove_command.run(backend.binary_path())?; write_to_file(&proof, &proof_path); diff --git a/noir/noir-repo/tooling/backend_interface/src/cli/write_vk.rs b/noir/noir-repo/tooling/backend_interface/src/cli/write_vk.rs index da9fc04cbef..3d51b5a4a8c 100644 --- a/noir/noir-repo/tooling/backend_interface/src/cli/write_vk.rs +++ b/noir/noir-repo/tooling/backend_interface/src/cli/write_vk.rs @@ -7,7 +7,7 @@ use crate::BackendError; /// to write a verification key to a file pub(crate) struct WriteVkCommand { pub(crate) crs_path: PathBuf, - pub(crate) bytecode_path: PathBuf, + pub(crate) artifact_path: PathBuf, pub(crate) vk_path_output: PathBuf, } @@ -21,7 +21,7 @@ impl WriteVkCommand { .arg("-c") .arg(self.crs_path) .arg("-b") - .arg(self.bytecode_path) + .arg(self.artifact_path) .arg("-o") .arg(self.vk_path_output); @@ -42,14 +42,14 @@ fn write_vk_command() -> Result<(), BackendError> { let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory_path = temp_directory.path(); - let bytecode_path = temp_directory_path.join("acir.gz"); + let artifact_path = temp_directory_path.join("program.json"); let vk_path_output = temp_directory.path().join("vk"); let crs_path = backend.backend_directory(); - std::fs::File::create(&bytecode_path).expect("file should be created"); + std::fs::File::create(&artifact_path).expect("file should be created"); - let write_vk_command = WriteVkCommand { bytecode_path, crs_path, vk_path_output }; + let write_vk_command = WriteVkCommand { artifact_path, crs_path, vk_path_output }; write_vk_command.run(backend.binary_path())?; drop(temp_directory); diff --git a/noir/noir-repo/tooling/backend_interface/src/proof_system.rs b/noir/noir-repo/tooling/backend_interface/src/proof_system.rs index ffd46acef0e..49fd57c968f 100644 --- a/noir/noir-repo/tooling/backend_interface/src/proof_system.rs +++ b/noir/noir-repo/tooling/backend_interface/src/proof_system.rs @@ -1,11 +1,8 @@ -use std::fs::File; use std::io::Write; use std::path::Path; +use std::{fs::File, path::PathBuf}; -use acvm::acir::{ - circuit::Program, - native_types::{WitnessMap, WitnessStack}, -}; +use acvm::acir::native_types::{WitnessMap, WitnessStack}; use acvm::FieldElement; use tempfile::tempdir; use tracing::warn; @@ -19,28 +16,20 @@ use crate::{Backend, BackendError}; impl Backend { pub fn get_exact_circuit_sizes( &self, - program: &Program, + artifact_path: PathBuf, ) -> Result, BackendError> { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; - let temp_directory = tempdir().expect("could not create a temporary directory"); - let temp_directory = temp_directory.path().to_path_buf(); - - // Create a temporary file for the circuit - let circuit_path = temp_directory.join("circuit").with_extension("bytecode"); - let serialized_program = Program::serialize_program(program); - write_to_file(&serialized_program, &circuit_path); - - GatesCommand { crs_path: self.crs_directory(), bytecode_path: circuit_path } - .run(binary_path) + GatesCommand { crs_path: self.crs_directory(), artifact_path }.run(binary_path) } #[tracing::instrument(level = "trace", skip_all)] pub fn prove( &self, - program: &Program, + artifact_path: PathBuf, witness_stack: WitnessStack, + num_public_inputs: u32, ) -> Result, BackendError> { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; @@ -54,20 +43,14 @@ impl Backend { let witness_path = temp_directory.join("witness").with_extension("tr"); write_to_file(&serialized_witnesses, &witness_path); - // Create a temporary file for the circuit - // - let bytecode_path = temp_directory.join("program").with_extension("bytecode"); - let serialized_program = Program::serialize_program(program); - write_to_file(&serialized_program, &bytecode_path); - // Create proof and store it in the specified path let proof_with_public_inputs = - ProveCommand { crs_path: self.crs_directory(), bytecode_path, witness_path } + ProveCommand { crs_path: self.crs_directory(), artifact_path, witness_path } .run(binary_path)?; let proof = bb_abstraction_leaks::remove_public_inputs( // TODO(https://github.com/noir-lang/noir/issues/4428) - program.functions[0].public_inputs().0.len(), + num_public_inputs as usize, &proof_with_public_inputs, ); Ok(proof) @@ -78,7 +61,7 @@ impl Backend { &self, proof: &[u8], public_inputs: WitnessMap, - program: &Program, + artifact_path: PathBuf, ) -> Result { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; @@ -92,17 +75,12 @@ impl Backend { let proof_path = temp_directory.join("proof").with_extension("proof"); write_to_file(&proof_with_public_inputs, &proof_path); - // Create a temporary file for the circuit - let bytecode_path = temp_directory.join("program").with_extension("bytecode"); - let serialized_program = Program::serialize_program(program); - write_to_file(&serialized_program, &bytecode_path); - // Create the verification key and write it to the specified path let vk_path = temp_directory.join("vk"); WriteVkCommand { crs_path: self.crs_directory(), - bytecode_path, + artifact_path, vk_path_output: vk_path.clone(), } .run(binary_path)?; @@ -113,7 +91,7 @@ impl Backend { pub fn get_intermediate_proof_artifacts( &self, - program: &Program, + artifact_path: PathBuf, proof: &[u8], public_inputs: WitnessMap, ) -> Result<(Vec, FieldElement, Vec), BackendError> { @@ -123,18 +101,12 @@ impl Backend { let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory = temp_directory.path().to_path_buf(); - // Create a temporary file for the circuit - // - let bytecode_path = temp_directory.join("program").with_extension("bytecode"); - let serialized_program = Program::serialize_program(program); - write_to_file(&serialized_program, &bytecode_path); - // Create the verification key and write it to the specified path let vk_path = temp_directory.join("vk"); WriteVkCommand { crs_path: self.crs_directory(), - bytecode_path, + artifact_path, vk_path_output: vk_path.clone(), } .run(binary_path)?; diff --git a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs index 153ab52c83f..8b26ea07a2f 100644 --- a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs +++ b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs @@ -1,30 +1,25 @@ -use super::proof_system::write_to_file; +use std::path::PathBuf; + use crate::{ cli::{ContractCommand, WriteVkCommand}, Backend, BackendError, }; -use acvm::acir::circuit::Program; use tempfile::tempdir; impl Backend { - pub fn eth_contract(&self, program: &Program) -> Result { + pub fn eth_contract(&self, artifact_path: PathBuf) -> Result { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; let temp_directory = tempdir().expect("could not create a temporary directory"); let temp_directory_path = temp_directory.path().to_path_buf(); - // Create a temporary file for the circuit - let bytecode_path = temp_directory_path.join("program").with_extension("bytecode"); - let serialized_program = Program::serialize_program(program); - write_to_file(&serialized_program, &bytecode_path); - // Create the verification key and write it to the specified path let vk_path = temp_directory_path.join("vk"); WriteVkCommand { crs_path: self.crs_directory(), - bytecode_path, + artifact_path, vk_path_output: vk_path.clone(), } .run(binary_path)?; @@ -35,33 +30,23 @@ impl Backend { #[cfg(test)] mod tests { - use std::collections::BTreeSet; - use acvm::acir::{ - circuit::{Circuit, ExpressionWidth, Opcode, Program, PublicInputs}, - native_types::{Expression, Witness}, - }; + use serde_json::json; + use tempfile::tempdir; - use crate::{get_mock_backend, BackendError}; + use crate::{get_mock_backend, proof_system::write_to_file, BackendError}; #[test] fn test_smart_contract() -> Result<(), BackendError> { - let expression = &(Witness(1) + Witness(2)) - &Expression::from(Witness(3)); - let constraint = Opcode::AssertZero(expression); + let dummy_artifact = json!({"bytecode": ""}); + let artifact_bytes = serde_json::to_vec(&dummy_artifact).unwrap(); - let circuit = Circuit { - current_witness_index: 4, - expression_width: ExpressionWidth::Bounded { width: 4 }, - opcodes: vec![constraint], - private_parameters: BTreeSet::from([Witness(1), Witness(2)]), - public_parameters: PublicInputs::default(), - return_values: PublicInputs::default(), - assert_messages: Default::default(), - recursive: false, - }; - let program = Program { functions: vec![circuit], unconstrained_functions: Vec::new() }; + let temp_directory = tempdir().expect("could not create a temporary directory"); + let temp_directory_path = temp_directory.path(); + let artifact_path = temp_directory_path.join("program.json"); + write_to_file(&artifact_bytes, &artifact_path); - let contract = get_mock_backend()?.eth_contract(&program)?; + let contract = get_mock_backend()?.eth_contract(artifact_path)?; assert!(contract.contains("contract VerifierContract")); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs index 04ed5c2b6b8..6247560f621 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs @@ -7,7 +7,7 @@ use crate::errors::CliError; use clap::Args; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_driver::{CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::graph::CrateName; /// Generates a Solidity verifier smart contract for the program @@ -46,15 +46,15 @@ pub(crate) fn run( let binary_packages = workspace.into_iter().filter(|package| package.is_binary()); for package in binary_packages { let program_artifact_path = workspace.package_build_path(package); - let program: CompiledProgram = read_program_from_file(program_artifact_path)?.into(); + let program = read_program_from_file(&program_artifact_path)?; // TODO(https://github.com/noir-lang/noir/issues/4428): // We do not expect to have a smart contract verifier for a foldable program with multiple circuits. // However, in the future we can expect to possibly have non-inlined ACIR functions during compilation // that will be inlined at a later step such as by the ACVM compiler or by the backend. // Add appropriate handling here once the compiler enables multiple ACIR functions. - assert_eq!(program.program.functions.len(), 1); - let smart_contract_string = backend.eth_contract(&program.program)?; + assert_eq!(program.bytecode.functions.len(), 1); + let smart_contract_string = backend.eth_contract(program_artifact_path)?; let contract_dir = workspace.contracts_directory_path(package); create_named_dir(&contract_dir, "contract"); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs index 8f28e5d9388..ecf2e2e9f53 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -22,7 +22,6 @@ use notify_debouncer_full::new_debouncer; use crate::errors::CliError; -use super::fs::program::only_acir; use super::fs::program::{read_program_from_file, save_contract_to_file, save_program_to_file}; use super::NargoConfig; use rayon::prelude::*; @@ -136,10 +135,9 @@ pub(super) fn compile_workspace_full( .partition(|package| package.is_binary()); // Save build artifacts to disk. - let only_acir = compile_options.only_acir; for (package, program) in binary_packages.into_iter().zip(compiled_programs) { let program = nargo::ops::transform_program(program, compile_options.expression_width); - save_program(program.clone(), &package, &workspace.target_directory_path(), only_acir); + save_program(program.clone(), &package, &workspace.target_directory_path()); } let circuit_dir = workspace.target_directory_path(); for (package, contract) in contract_packages.into_iter().zip(compiled_contracts) { @@ -197,18 +195,9 @@ pub(super) fn compile_workspace( } } -pub(super) fn save_program( - program: CompiledProgram, - package: &Package, - circuit_dir: &Path, - only_acir_opt: bool, -) { - if only_acir_opt { - only_acir(program.program, circuit_dir); - } else { - let program_artifact = ProgramArtifact::from(program.clone()); - save_program_to_file(&program_artifact, &package.name, circuit_dir); - } +pub(super) fn save_program(program: CompiledProgram, package: &Package, circuit_dir: &Path) { + let program_artifact = ProgramArtifact::from(program.clone()); + save_program_to_file(&program_artifact, &package.name, circuit_dir); } fn save_contract(contract: CompiledContract, package: &Package, circuit_dir: &Path) { diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs index 72d686b0b36..ba017651667 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs @@ -1,6 +1,5 @@ use std::path::{Path, PathBuf}; -use acvm::acir::circuit::Program; use nargo::artifacts::{contract::ContractArtifact, program::ProgramArtifact}; use noirc_frontend::graph::CrateName; @@ -17,16 +16,6 @@ pub(crate) fn save_program_to_file>( save_build_artifact_to_file(program_artifact, &circuit_name, circuit_dir) } -/// Writes the bytecode as acir.gz -pub(crate) fn only_acir>(program: Program, circuit_dir: P) -> PathBuf { - create_named_dir(circuit_dir.as_ref(), "target"); - let circuit_path = circuit_dir.as_ref().join("acir").with_extension("gz"); - let bytes = Program::serialize_program(&program); - write_to_file(&bytes, &circuit_path); - - circuit_path -} - pub(crate) fn save_contract_to_file>( compiled_contract: &ContractArtifact, circuit_name: &str, @@ -60,16 +49,3 @@ pub(crate) fn read_program_from_file>( Ok(program) } - -pub(crate) fn read_contract_from_file>( - circuit_path: P, -) -> Result { - let file_path = circuit_path.as_ref().with_extension("json"); - - let input_string = - std::fs::read(&file_path).map_err(|_| FilesystemError::PathNotValid(file_path))?; - let contract = serde_json::from_slice(&input_string) - .map_err(|err| FilesystemError::ProgramSerializationError(err.to_string()))?; - - Ok(contract) -} diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs index f8f645d3c3a..d68aef497f6 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs @@ -1,11 +1,11 @@ -use std::collections::HashMap; +use std::{collections::HashMap, path::PathBuf}; use acvm::acir::circuit::ExpressionWidth; use backend_interface::BackendError; use clap::Args; use iter_extended::vecmap; use nargo::{ - artifacts::{contract::ContractArtifact, debug::DebugArtifact, program::ProgramArtifact}, + artifacts::{debug::DebugArtifact, program::ProgramArtifact}, package::Package, }; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; @@ -20,9 +20,7 @@ use crate::backends::Backend; use crate::errors::CliError; use super::{ - compile_cmd::compile_workspace_full, - fs::program::{read_contract_from_file, read_program_from_file}, - NargoConfig, + compile_cmd::compile_workspace_full, fs::program::read_program_from_file, NargoConfig, }; /// Provides detailed information on each of a program's function (represented by a single circuit) @@ -80,15 +78,6 @@ pub(crate) fn run( }) .collect::>()?; - let compiled_contracts: Vec = workspace - .into_iter() - .filter(|package| package.is_contract()) - .map(|package| { - let contract_artifact_path = workspace.package_build_path(package); - read_contract_from_file(contract_artifact_path) - }) - .collect::>()?; - if args.profile_info { for (_, compiled_program) in &binary_packages { let debug_artifact = DebugArtifact::from(compiled_program.clone()); @@ -97,17 +86,6 @@ pub(crate) fn run( print_span_opcodes(span_opcodes, &debug_artifact); } } - - for compiled_contract in &compiled_contracts { - let debug_artifact = DebugArtifact::from(compiled_contract.clone()); - let functions = &compiled_contract.functions; - for contract_function in functions { - for function_debug in contract_function.debug_symbols.debug_infos.iter() { - let span_opcodes = function_debug.count_span_opcodes(); - print_span_opcodes(span_opcodes, &debug_artifact); - } - } - } } let program_info = binary_packages @@ -116,6 +94,7 @@ pub(crate) fn run( .map(|(package, program)| { count_opcodes_and_gates_in_program( backend, + workspace.package_build_path(&package), program, &package, args.compile_options.expression_width, @@ -123,18 +102,7 @@ pub(crate) fn run( }) .collect::>()?; - let contract_info = compiled_contracts - .into_par_iter() - .map(|contract| { - count_opcodes_and_gates_in_contract( - backend, - contract, - args.compile_options.expression_width, - ) - }) - .collect::>()?; - - let info_report = InfoReport { programs: program_info, contracts: contract_info }; + let info_report = InfoReport { programs: program_info, contracts: Vec::new() }; if args.json { // Expose machine-readable JSON data. @@ -152,23 +120,6 @@ pub(crate) fn run( } program_table.printstd(); } - if !info_report.contracts.is_empty() { - let mut contract_table = table!([ - Fm->"Contract", - Fm->"Function", - Fm->"Expression Width", - Fm->"ACIR Opcodes", - Fm->"Backend Circuit Size" - ]); - for contract_info in info_report.contracts { - let contract_rows: Vec = contract_info.into(); - for row in contract_rows { - contract_table.add_row(row); - } - } - - contract_table.printstd(); - } } Ok(()) @@ -283,15 +234,12 @@ impl From for Vec { fn count_opcodes_and_gates_in_program( backend: &Backend, - mut compiled_program: ProgramArtifact, + program_artifact_path: PathBuf, + compiled_program: ProgramArtifact, package: &Package, expression_width: ExpressionWidth, ) -> Result { - // Unconstrained functions do not matter to a backend circuit count so we clear them - // before sending a serialized program to the backend - compiled_program.bytecode.unconstrained_functions.clear(); - - let program_circuit_sizes = backend.get_exact_circuit_sizes(&compiled_program.bytecode)?; + let program_circuit_sizes = backend.get_exact_circuit_sizes(program_artifact_path)?; let functions = compiled_program .bytecode .functions @@ -309,24 +257,3 @@ fn count_opcodes_and_gates_in_program( Ok(ProgramInfo { package_name: package.name.to_string(), expression_width, functions }) } - -fn count_opcodes_and_gates_in_contract( - backend: &Backend, - contract: ContractArtifact, - expression_width: ExpressionWidth, -) -> Result { - let functions = contract - .functions - .into_par_iter() - .map(|function| -> Result<_, BackendError> { - Ok(FunctionInfo { - name: function.name, - // TODO(https://github.com/noir-lang/noir/issues/4720) - acir_opcodes: function.bytecode.functions[0].opcodes.len(), - circuit_size: backend.get_exact_circuit_sizes(&function.bytecode)?[0].circuit_size, - }) - }) - .collect::>()?; - - Ok(ContractInfo { name: contract.name, expression_width, functions }) -} diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs index 6fb6e7269f7..127c5ac2ebb 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; + use clap::Args; use nargo::constants::{PROVER_INPUT_FILE, VERIFIER_INPUT_FILE}; use nargo::package::Package; @@ -68,12 +70,13 @@ pub(crate) fn run( let binary_packages = workspace.into_iter().filter(|package| package.is_binary()); for package in binary_packages { let program_artifact_path = workspace.package_build_path(package); - let program: CompiledProgram = read_program_from_file(program_artifact_path)?.into(); + let program: CompiledProgram = read_program_from_file(&program_artifact_path)?.into(); let proof = prove_package( backend, package, program, + program_artifact_path, &args.prover_name, &args.verifier_name, args.verify, @@ -86,10 +89,12 @@ pub(crate) fn run( Ok(()) } +#[allow(clippy::too_many_arguments)] fn prove_package( backend: &Backend, package: &Package, compiled_program: CompiledProgram, + program_artifact_path: PathBuf, prover_name: &str, verifier_name: &str, check_proof: bool, @@ -117,11 +122,15 @@ fn prove_package( Format::Toml, )?; - let proof = backend.prove(&compiled_program.program, witness_stack)?; + let proof = backend.prove( + program_artifact_path.clone(), + witness_stack, + compiled_program.program.functions[0].public_inputs().0.len() as u32, + )?; if check_proof { let public_inputs = public_abi.encode(&public_inputs, return_value)?; - let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.program)?; + let valid_proof = backend.verify(&proof, public_inputs, program_artifact_path)?; if !valid_proof { return Err(CliError::InvalidProof("".into())); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs index a7f2772330a..ad1978cabe0 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs @@ -81,7 +81,8 @@ fn verify_package( let proof = load_hex_data(&proof_path)?; - let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.program)?; + let valid_proof = + backend.verify(&proof, public_inputs, workspace.package_build_path(package))?; if valid_proof { Ok(())