From b87561a813574e47864b7001e73b9a995c28381c Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Tue, 9 Jan 2024 16:14:05 -0300 Subject: [PATCH] Update nargo and noir-wasm --- noir/Cargo.lock | 8 +- noir/Cargo.toml | 1 + noir/acvm-repo/acir/Cargo.toml | 2 +- noir/compiler/noirc_errors/Cargo.toml | 5 +- noir/compiler/noirc_errors/src/debug_info.rs | 48 +++++++++++- noir/compiler/wasm/Cargo.toml | 1 + noir/compiler/wasm/package.json | 4 + noir/compiler/wasm/src/compile.rs | 70 +++++++----------- noir/compiler/wasm/src/types/noir_artifact.ts | 41 +++++----- .../compiler/node/compile_with_deps.test.ts | 72 ++++++++++++++++-- noir/tooling/nargo/src/artifacts/contract.rs | 29 +++++++- noir/tooling/nargo/src/artifacts/program.rs | 30 ++++++++ noir/tooling/nargo_cli/src/cli/compile_cmd.rs | 74 ++----------------- noir/tooling/nargo_cli/src/cli/fs/program.rs | 24 +----- noir/yarn.lock | 16 ++++ 15 files changed, 255 insertions(+), 170 deletions(-) diff --git a/noir/Cargo.lock b/noir/Cargo.lock index 438d74b1b2d..f6ca8463782 100644 --- a/noir/Cargo.lock +++ b/noir/Cargo.lock @@ -1664,9 +1664,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", @@ -2871,6 +2871,7 @@ dependencies = [ "nargo", "noirc_driver", "noirc_errors", + "noirc_evaluator", "noirc_frontend", "rust-embed", "serde", @@ -2938,11 +2939,14 @@ name = "noirc_errors" version = "0.22.0" dependencies = [ "acvm", + "base64 0.21.2", "chumsky", "codespan", "codespan-reporting", + "flate2", "fm", "serde", + "serde_json", "serde_with", "tracing", ] diff --git a/noir/Cargo.toml b/noir/Cargo.toml index 05139934c62..f0fc7249efc 100644 --- a/noir/Cargo.toml +++ b/noir/Cargo.toml @@ -123,6 +123,7 @@ num-traits = "0.2" similar-asserts = "1.5.0" tempfile = "3.6.0" jsonrpc = { version = "0.16.0", features = ["minreq_http"] } +flate2 = "1.0.24" tracing = "0.1.40" tracing-web = "0.1.3" diff --git a/noir/acvm-repo/acir/Cargo.toml b/noir/acvm-repo/acir/Cargo.toml index a0877120a58..b44c64dd838 100644 --- a/noir/acvm-repo/acir/Cargo.toml +++ b/noir/acvm-repo/acir/Cargo.toml @@ -17,7 +17,7 @@ acir_field.workspace = true brillig.workspace = true serde.workspace = true thiserror.workspace = true -flate2 = "1.0.24" +flate2.workspace = true bincode.workspace = true base64.workspace = true diff --git a/noir/compiler/noirc_errors/Cargo.toml b/noir/compiler/noirc_errors/Cargo.toml index 02e97b2c670..935137ba2fc 100644 --- a/noir/compiler/noirc_errors/Cargo.toml +++ b/noir/compiler/noirc_errors/Cargo.toml @@ -15,4 +15,7 @@ fm.workspace = true chumsky.workspace = true serde.workspace = true serde_with = "3.2.0" -tracing.workspace = true \ No newline at end of file +tracing.workspace = true +flate2.workspace = true +serde_json.workspace = true +base64.workspace = true \ No newline at end of file diff --git a/noir/compiler/noirc_errors/src/debug_info.rs b/noir/compiler/noirc_errors/src/debug_info.rs index ee40ced19bf..a15119943c1 100644 --- a/noir/compiler/noirc_errors/src/debug_info.rs +++ b/noir/compiler/noirc_errors/src/debug_info.rs @@ -1,14 +1,24 @@ use acvm::acir::circuit::OpcodeLocation; use acvm::compiler::AcirTransformationMap; +use base64::Engine; +use flate2::read::DeflateDecoder; +use flate2::write::DeflateEncoder; +use flate2::Compression; +use serde::Deserializer; +use serde::Serializer; use serde_with::serde_as; use serde_with::DisplayFromStr; use std::collections::BTreeMap; use std::collections::HashMap; +use std::io::Read; +use std::io::Write; use std::mem; use crate::Location; -use serde::{Deserialize, Serialize}; +use serde::{ + de::Error as DeserializationError, ser::Error as SerializationError, Deserialize, Serialize, +}; #[serde_as] #[derive(Default, Debug, Clone, Deserialize, Serialize)] @@ -86,4 +96,40 @@ impl DebugInfo { counted_opcodes } + + pub fn serialize_compressed_base64_json( + debug_info: &DebugInfo, + s: S, + ) -> Result + where + S: Serializer, + { + let json_str = serde_json::to_string(debug_info).map_err(S::Error::custom)?; + + let mut encoder = DeflateEncoder::new(Vec::new(), Compression::default()); + encoder.write_all(json_str.as_bytes()).map_err(S::Error::custom)?; + let compressed_data = encoder.finish().map_err(S::Error::custom)?; + + let encoded_b64 = base64::prelude::BASE64_STANDARD.encode(&compressed_data); + s.serialize_str(&encoded_b64) + } + + pub fn deserialize_compressed_base64_json<'de, D>( + deserializer: D, + ) -> Result + where + D: Deserializer<'de>, + { + let encoded_b64: String = Deserialize::deserialize(deserializer)?; + + let compressed_data = + base64::prelude::BASE64_STANDARD.decode(&encoded_b64).map_err(D::Error::custom)?; + + let mut decoder = DeflateDecoder::new(&compressed_data[..]); + let mut decompressed_data = Vec::new(); + decoder.read_to_end(&mut decompressed_data).map_err(D::Error::custom)?; + + let json_str = String::from_utf8(decompressed_data).map_err(D::Error::custom)?; + serde_json::from_str(&json_str).map_err(D::Error::custom) + } } diff --git a/noir/compiler/wasm/Cargo.toml b/noir/compiler/wasm/Cargo.toml index 7af26269106..a20efeeed8a 100644 --- a/noir/compiler/wasm/Cargo.toml +++ b/noir/compiler/wasm/Cargo.toml @@ -18,6 +18,7 @@ nargo.workspace = true noirc_driver.workspace = true noirc_frontend.workspace = true noirc_errors.workspace = true +noirc_evaluator.workspace = true wasm-bindgen.workspace = true serde.workspace = true js-sys.workspace = true diff --git a/noir/compiler/wasm/package.json b/noir/compiler/wasm/package.json index 4a71d8aa77d..7cdf78b0ffd 100644 --- a/noir/compiler/wasm/package.json +++ b/noir/compiler/wasm/package.json @@ -48,6 +48,7 @@ "@types/mocha": "^10.0.6", "@types/mocha-each": "^2", "@types/node": "^20.10.5", + "@types/pako": "^2", "@types/path-browserify": "^1", "@types/readable-stream": "^4", "@types/sinon": "^17", @@ -75,5 +76,8 @@ "url": "^0.11.3", "webpack": "^5.49.0", "webpack-cli": "^4.7.2" + }, + "dependencies": { + "pako": "^2.1.0" } } diff --git a/noir/compiler/wasm/src/compile.rs b/noir/compiler/wasm/src/compile.rs index 54fdccf1369..c94392adf83 100644 --- a/noir/compiler/wasm/src/compile.rs +++ b/noir/compiler/wasm/src/compile.rs @@ -3,7 +3,6 @@ use gloo_utils::format::JsValueSerdeExt; use js_sys::{JsString, Object}; use nargo::artifacts::{ contract::{ContractArtifact, ContractFunctionArtifact}, - debug::DebugArtifact, program::ProgramArtifact, }; use noirc_driver::{ @@ -11,6 +10,7 @@ use noirc_driver::{ prepare_dependency, CompileOptions, CompiledContract, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, }; +use noirc_evaluator::errors::SsaReport; use noirc_frontend::{ graph::{CrateId, CrateName}, hir::Context, @@ -28,35 +28,30 @@ export type DependencyGraph = { library_dependencies: Readonly>; } -export type CompiledContract = { +export type ContractArtifact = { noir_version: string; name: string; functions: Array; events: Array; + file_map: Record; }; -export type CompiledProgram = { +export type ProgramArtifact = { noir_version: string; + hash: number; abi: any; bytecode: string; + debug_symbols: any; + file_map: Record; } -export type DebugArtifact = { - debug_symbols: Array; - file_map: Record; - warnings: Array; -}; +type WarningsCompileResult = { warnings: Array; }; -export type CompileResult = ( - | { - contract: CompiledContract; - debug: DebugArtifact; - } - | { - program: CompiledProgram; - debug: DebugArtifact; - } -); +export type ContractCompileResult = { contract: CompiledContract; } & WarningsCompileResult; + +export type ProgramCompileResult = { program: CompiledProgram; } & WarningsCompileResult; + +export type CompileResult = ContractCompileResult | ProgramCompileResult; "#; #[wasm_bindgen] @@ -76,38 +71,36 @@ extern "C" { impl JsCompileResult { const CONTRACT_PROP: &'static str = "contract"; const PROGRAM_PROP: &'static str = "program"; - const DEBUG_PROP: &'static str = "debug"; + const WARNINGS_PROP: &'static str = "warnings"; pub fn new(resp: CompileResult) -> JsCompileResult { let obj = JsCompileResult::constructor(); match resp { - CompileResult::Contract { contract, debug } => { + CompileResult::Contract { contract, warnings } => { js_sys::Reflect::set( &obj, &JsString::from(JsCompileResult::CONTRACT_PROP), &::from_serde(&contract).unwrap(), ) .unwrap(); - js_sys::Reflect::set( &obj, - &JsString::from(JsCompileResult::DEBUG_PROP), - &::from_serde(&debug).unwrap(), + &JsString::from(JsCompileResult::WARNINGS_PROP), + &::from_serde(&warnings).unwrap(), ) .unwrap(); } - CompileResult::Program { program, debug } => { + CompileResult::Program { program, warnings } => { js_sys::Reflect::set( &obj, &JsString::from(JsCompileResult::PROGRAM_PROP), &::from_serde(&program).unwrap(), ) .unwrap(); - js_sys::Reflect::set( &obj, - &JsString::from(JsCompileResult::DEBUG_PROP), - &::from_serde(&debug).unwrap(), + &JsString::from(JsCompileResult::WARNINGS_PROP), + &::from_serde(&warnings).unwrap(), ) .unwrap(); } @@ -148,8 +141,8 @@ impl PathToFileSourceMap { } pub enum CompileResult { - Contract { contract: ContractArtifact, debug: DebugArtifact }, - Program { program: ProgramArtifact, debug: DebugArtifact }, + Contract { contract: ContractArtifact, warnings: Vec }, + Program { program: ProgramArtifact, warnings: Vec }, } #[wasm_bindgen] @@ -273,31 +266,22 @@ fn add_noir_lib(context: &mut Context, library_name: &CrateName) -> CrateId { } pub(crate) fn generate_program_artifact(program: CompiledProgram) -> CompileResult { - let debug_artifact = DebugArtifact { - debug_symbols: vec![program.debug.clone()], - file_map: program.file_map.clone(), - warnings: program.warnings.clone(), - }; - - CompileResult::Program { program: program.into(), debug: debug_artifact } + let warnings = program.warnings.clone(); + CompileResult::Program { program: program.into(), warnings } } pub(crate) fn generate_contract_artifact(contract: CompiledContract) -> CompileResult { - let debug_artifact = DebugArtifact { - debug_symbols: contract.functions.iter().map(|function| function.debug.clone()).collect(), - file_map: contract.file_map, - warnings: contract.warnings, - }; let functions = contract.functions.into_iter().map(ContractFunctionArtifact::from).collect(); - + let contract_artifact = ContractArtifact { noir_version: String::from(NOIR_ARTIFACT_VERSION_STRING), name: contract.name, functions, events: contract.events, + file_map: contract.file_map, }; - CompileResult::Contract { contract: contract_artifact, debug: debug_artifact } + CompileResult::Contract { contract: contract_artifact, warnings: contract.warnings } } #[cfg(test)] diff --git a/noir/compiler/wasm/src/types/noir_artifact.ts b/noir/compiler/wasm/src/types/noir_artifact.ts index f2147cfbeda..4b9e4b1b79c 100644 --- a/noir/compiler/wasm/src/types/noir_artifact.ts +++ b/noir/compiler/wasm/src/types/noir_artifact.ts @@ -49,6 +49,8 @@ export interface NoirFunctionEntry { abi: Abi; /** The bytecode of the function in base64. */ bytecode: string; + /** The debug information, compressed and base64 encoded. */ + debug_symbols: string; } /** @@ -57,12 +59,16 @@ export interface NoirFunctionEntry { export interface CompiledContract { /** The name of the contract. */ name: string; + /** Version of noir used for the build. */ + noir_version: string; /** Compilation backend. */ backend: string; /** The functions of the contract. */ functions: NoirFunctionEntry[]; /** The events of the contract */ events: EventAbi[]; + /** The map of file ID to the source code and path of the file. */ + file_map: DebugFileMap; } /** @@ -73,12 +79,14 @@ export interface CompiledCircuit { hash?: number; /** Compilation backend. */ backend: string; - /** - * The ABI of the function. - */ + /** * The ABI of the function. */ abi: Abi; /** The bytecode of the circuit in base64. */ bytecode: string; + /** The debug information, compressed and base64 encoded. */ + debug_symbols: string; + /** The map of file ID to the source code and path of the file. */ + file_map: DebugFileMap; } /** @@ -142,19 +150,8 @@ export type DebugFileMap = Record< } >; -/** - * The debug metadata of an Noir contract. - */ -export interface DebugMetadata { - /** - * The debug information for each function. - */ - debug_symbols: DebugInfo[]; - /** - * The map of file ID to the source code and path of the file. - */ - file_map: DebugFileMap; -} +/** Compilation warning */ +export type Warning = unknown; /** * The compilation artifacts of a given contract. @@ -165,10 +162,8 @@ export interface ContractCompilationArtifacts { */ contract: CompiledContract; - /** - * The artifact that contains the debug metadata about the contract. - */ - debug?: DebugMetadata; + /** Compilation warnings. */ + warnings: Warning[]; } /** @@ -184,10 +179,8 @@ export interface ProgramCompilationArtifacts { */ program: CompiledCircuit; - /** - * The artifact that contains the debug metadata about the contract. - */ - debug?: DebugMetadata; + /** Compilation warnings. */ + warnings: Warning[]; } /** diff --git a/noir/compiler/wasm/test/compiler/node/compile_with_deps.test.ts b/noir/compiler/wasm/test/compiler/node/compile_with_deps.test.ts index 546ec03c183..4b2a27294b1 100644 --- a/noir/compiler/wasm/test/compiler/node/compile_with_deps.test.ts +++ b/noir/compiler/wasm/test/compiler/node/compile_with_deps.test.ts @@ -1,10 +1,12 @@ import { join, resolve } from 'path'; import { getPaths } from '../../shared'; +import { inflate } from 'pako'; import { expect } from 'chai'; import { readFile } from 'fs/promises'; import { compile, createFileManager } from '@noir-lang/noir_wasm'; -import { CompiledContract } from '../../../src/types/noir_artifact'; +import { CompiledContract, DebugFileMap, DebugInfo } from '../../../src/types/noir_artifact'; +import { ContractCompilationArtifacts, NoirFunctionEntry } from 'dist/types/src/types/noir_artifact'; const basePath = resolve(join(__dirname, '../../')); const { contractProjectPath, contractExpectedArtifact } = getPaths(basePath); @@ -13,14 +15,68 @@ describe('noir-compiler', () => { it('both nargo and noir_wasm should compile identically', async () => { const fm = createFileManager(contractProjectPath); const nargoArtifact = JSON.parse((await readFile(contractExpectedArtifact)).toString()) as CompiledContract; - nargoArtifact.functions.sort((a, b) => a.name.localeCompare(b.name)); + const [nargoDebugInfos, nargoFileMap] = deleteDebugMetadata(nargoArtifact); + normalizeVersion(nargoArtifact); + const noirWasmArtifact = await compile(fm); - if (!('contract' in noirWasmArtifact)) { - throw new Error('Compilation failed'); - } - const noirWasmContract = noirWasmArtifact.contract; + const noirWasmContract = (noirWasmArtifact as ContractCompilationArtifacts).contract; expect(noirWasmContract).not.to.be.undefined; - noirWasmContract.functions.sort((a, b) => a.name.localeCompare(b.name)); + const [noirWasmDebugInfos, norWasmFileMap] = deleteDebugMetadata(noirWasmContract); + normalizeVersion(noirWasmContract); + + // We first compare both contracts without considering debug info expect(nargoArtifact).to.deep.eq(noirWasmContract); - }); + + // Compare the file maps, ignoring keys, since those depend in the order in which files are visited, + // which may change depending on the file manager implementation. Also ignores paths, since the base + // path is reported differently between nargo and noir-wasm. + expect(getSources(nargoFileMap)).to.have.members(getSources(norWasmFileMap)); + + // Compare the debug symbol information, ignoring the actual ids used for file identifiers. + // Debug symbol info looks like the following, what we need is to ignore the 'file' identifiers + // {"locations":{"0":[{"span":{"start":141,"end":156},"file":39},{"span":{"start":38,"end":76},"file":38},{"span":{"start":824,"end":862},"file":23}]}} + expect(nargoDebugInfos).to.deep.eq(noirWasmDebugInfos); + }).timeout(5000); }); + +/** Remove commit identifier from version, which may not match depending on cached nargo and noir-wasm */ +function normalizeVersion(contract: CompiledContract) { + contract.noir_version = contract.noir_version.replace(/\+.+$/, ''); +} + +/** Decompresses and decodes the debug symbols */ +function inflateDebugSymbols(debugSymbols: string) { + return JSON.parse(inflate(Buffer.from(debugSymbols, 'base64'), { to: 'string', raw: true })); +} + +/** Extracts the debug symbols from all functions, decodes them, removes their file identifiers, and deletes them from the artifact. */ +function extractDebugInfos(fns: NoirFunctionEntry[]) { + return fns.map((fn) => { + const debugSymbols = inflateDebugSymbols(fn.debug_symbols); + delete (fn as Partial).debug_symbols; + clearFileIdentifiers(debugSymbols); + return debugSymbols; + }); +} + +/** Deletes all debug info from a contract and returns it. */ +function deleteDebugMetadata(contract: CompiledContract) { + contract.functions.sort((a, b) => a.name.localeCompare(b.name)); + const fileMap = contract.file_map; + delete (contract as Partial).file_map; + return [extractDebugInfos(contract.functions), fileMap]; +} + +/** Clears file identifiers from a set of debug symbols. */ +function clearFileIdentifiers(debugSymbols: DebugInfo) { + for (const loc of Object.values(debugSymbols.locations)) { + for (const span of loc) { + span.file = 0; + } + } +} + +/** Returns list of sources from file map, dropping paths along the way, since they don't match depending on the file manager. */ +function getSources(fileMap: DebugFileMap) { + return Object.values(fileMap).map((file) => file.source); +} diff --git a/noir/tooling/nargo/src/artifacts/contract.rs b/noir/tooling/nargo/src/artifacts/contract.rs index 04699126762..d928b09fcb9 100644 --- a/noir/tooling/nargo/src/artifacts/contract.rs +++ b/noir/tooling/nargo/src/artifacts/contract.rs @@ -1,8 +1,14 @@ use acvm::acir::circuit::Circuit; use noirc_abi::{Abi, ContractEvent}; -use noirc_driver::{ContractFunction, ContractFunctionType}; +use noirc_driver::{CompiledContract, ContractFunction, ContractFunctionType}; use serde::{Deserialize, Serialize}; +use noirc_driver::DebugFile; +use noirc_errors::debug_info::DebugInfo; +use std::collections::BTreeMap; + +use fm::FileId; + #[derive(Serialize, Deserialize)] pub struct ContractArtifact { /// Version of noir used to compile this contract @@ -13,6 +19,20 @@ pub struct ContractArtifact { pub functions: Vec, /// All the events defined inside the contract scope. pub events: Vec, + /// Map of file Id to the source code so locations in debug info can be mapped to source code they point to. + pub file_map: BTreeMap, +} + +impl From for ContractArtifact { + fn from(contract: CompiledContract) -> Self { + ContractArtifact { + noir_version: contract.noir_version, + name: contract.name, + functions: contract.functions.into_iter().map(ContractFunctionArtifact::from).collect(), + events: contract.events, + file_map: contract.file_map, + } + } } /// Each function in the contract will be compiled as a separate noir program. @@ -34,6 +54,12 @@ pub struct ContractFunctionArtifact { deserialize_with = "Circuit::deserialize_circuit_base64" )] pub bytecode: Circuit, + + #[serde( + serialize_with = "DebugInfo::serialize_compressed_base64_json", + deserialize_with = "DebugInfo::deserialize_compressed_base64_json" + )] + pub debug_symbols: DebugInfo, } impl From for ContractFunctionArtifact { @@ -44,6 +70,7 @@ impl From for ContractFunctionArtifact { is_internal: func.is_internal, abi: func.abi, bytecode: func.bytecode, + debug_symbols: func.debug, } } } diff --git a/noir/tooling/nargo/src/artifacts/program.rs b/noir/tooling/nargo/src/artifacts/program.rs index 96e63e6fe50..b1db5f31728 100644 --- a/noir/tooling/nargo/src/artifacts/program.rs +++ b/noir/tooling/nargo/src/artifacts/program.rs @@ -1,6 +1,11 @@ +use std::collections::BTreeMap; + use acvm::acir::circuit::Circuit; +use fm::FileId; use noirc_abi::Abi; use noirc_driver::CompiledProgram; +use noirc_driver::DebugFile; +use noirc_errors::debug_info::DebugInfo; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] @@ -20,6 +25,15 @@ pub struct ProgramArtifact { deserialize_with = "Circuit::deserialize_circuit_base64" )] pub bytecode: Circuit, + + #[serde( + serialize_with = "DebugInfo::serialize_compressed_base64_json", + deserialize_with = "DebugInfo::deserialize_compressed_base64_json" + )] + pub debug_symbols: DebugInfo, + + /// Map of file Id to the source code so locations in debug info can be mapped to source code they point to. + pub file_map: BTreeMap, } impl From for ProgramArtifact { @@ -29,6 +43,22 @@ impl From for ProgramArtifact { abi: program.abi, noir_version: program.noir_version, bytecode: program.circuit, + debug_symbols: program.debug, + file_map: program.file_map, + } + } +} + +impl Into for ProgramArtifact { + fn into(self) -> CompiledProgram { + CompiledProgram { + hash: self.hash, + abi: self.abi, + noir_version: self.noir_version, + circuit: self.bytecode, + debug: self.debug_symbols, + file_map: self.file_map, + warnings: vec![], } } } diff --git a/noir/tooling/nargo_cli/src/cli/compile_cmd.rs b/noir/tooling/nargo_cli/src/cli/compile_cmd.rs index 31105ebe68f..924116861f4 100644 --- a/noir/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/noir/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -1,10 +1,8 @@ use std::path::Path; use acvm::ExpressionWidth; + use fm::FileManager; -use iter_extended::vecmap; -use nargo::artifacts::contract::{ContractArtifact, ContractFunctionArtifact}; -use nargo::artifacts::debug::DebugArtifact; use nargo::artifacts::program::ProgramArtifact; use nargo::errors::CompileError; use nargo::insert_all_files_for_workspace_into_file_manager; @@ -15,6 +13,7 @@ use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelec use noirc_driver::file_manager_with_stdlib; use noirc_driver::NOIR_ARTIFACT_VERSION_STRING; use noirc_driver::{CompilationResult, CompileOptions, CompiledContract, CompiledProgram}; + use noirc_frontend::graph::CrateName; use clap::Args; @@ -23,10 +22,7 @@ use crate::backends::Backend; use crate::errors::CliError; use super::fs::program::only_acir; -use super::fs::program::{ - read_debug_artifact_from_file, read_program_from_file, save_contract_to_file, - save_debug_artifact_to_file, save_program_to_file, -}; +use super::fs::program::{read_program_from_file, save_contract_to_file, save_program_to_file}; use super::NargoConfig; use rayon::prelude::*; @@ -170,24 +166,8 @@ fn compile_program( let (mut context, crate_id) = prepare_package(file_manager, package); let program_artifact_path = workspace.package_build_path(package); - let mut debug_artifact_path = program_artifact_path.clone(); - debug_artifact_path.set_file_name(format!("debug_{}.json", package.name)); - let cached_program = if let (Ok(program_artifact), Ok(mut debug_artifact)) = ( - read_program_from_file(program_artifact_path), - read_debug_artifact_from_file(debug_artifact_path), - ) { - Some(CompiledProgram { - hash: program_artifact.hash, - circuit: program_artifact.bytecode, - abi: program_artifact.abi, - noir_version: program_artifact.noir_version, - debug: debug_artifact.debug_symbols.remove(0), - file_map: debug_artifact.file_map, - warnings: debug_artifact.warnings, - }) - } else { - None - }; + let cached_program: Option = + read_program_from_file(program_artifact_path).map(|p| p.into()).ok(); let force_recompile = cached_program.as_ref().map_or(false, |p| p.noir_version != NOIR_ARTIFACT_VERSION_STRING); @@ -244,51 +224,13 @@ pub(super) fn save_program( } else { save_program_to_file(&program_artifact, &package.name, circuit_dir); } - - let debug_artifact = DebugArtifact { - debug_symbols: vec![program.debug], - file_map: program.file_map, - warnings: program.warnings, - }; - let circuit_name: String = (&package.name).into(); - save_debug_artifact_to_file(&debug_artifact, &circuit_name, circuit_dir); } fn save_contract(contract: CompiledContract, package: &Package, circuit_dir: &Path) { - // TODO(#1389): I wonder if it is incorrect for nargo-core to know anything about contracts. - // As can be seen here, It seems like a leaky abstraction where ContractFunctions (essentially CompiledPrograms) - // are compiled via nargo-core and then the ContractArtifact is constructed here. - // This is due to EACH function needing it's own CRS, PKey, and VKey from the backend. - let debug_artifact = DebugArtifact { - debug_symbols: contract.functions.iter().map(|function| function.debug.clone()).collect(), - file_map: contract.file_map, - warnings: contract.warnings, - }; - - let functions = vecmap(contract.functions, |func| ContractFunctionArtifact { - name: func.name, - function_type: func.function_type, - is_internal: func.is_internal, - abi: func.abi, - bytecode: func.bytecode, - }); - - let contract_artifact = ContractArtifact { - noir_version: contract.noir_version, - name: contract.name, - functions, - events: contract.events, - }; - + let contract_name = contract.name.clone(); save_contract_to_file( - &contract_artifact, - &format!("{}-{}", package.name, contract_artifact.name), - circuit_dir, - ); - - save_debug_artifact_to_file( - &debug_artifact, - &format!("{}-{}", package.name, contract_artifact.name), + &contract.into(), + &format!("{}-{}", package.name, contract_name), circuit_dir, ); } diff --git a/noir/tooling/nargo_cli/src/cli/fs/program.rs b/noir/tooling/nargo_cli/src/cli/fs/program.rs index 1d2f012736e..1fb57ae6685 100644 --- a/noir/tooling/nargo_cli/src/cli/fs/program.rs +++ b/noir/tooling/nargo_cli/src/cli/fs/program.rs @@ -1,9 +1,7 @@ use std::path::{Path, PathBuf}; use acvm::acir::circuit::Circuit; -use nargo::artifacts::{ - contract::ContractArtifact, debug::DebugArtifact, program::ProgramArtifact, -}; +use nargo::artifacts::{contract::ContractArtifact, program::ProgramArtifact}; use noirc_frontend::graph::CrateName; use crate::errors::FilesystemError; @@ -40,15 +38,6 @@ pub(crate) fn save_contract_to_file>( save_build_artifact_to_file(compiled_contract, circuit_name, circuit_dir) } -pub(crate) fn save_debug_artifact_to_file>( - debug_artifact: &DebugArtifact, - circuit_name: &str, - circuit_dir: P, -) -> PathBuf { - let artifact_name = format!("debug_{circuit_name}"); - save_build_artifact_to_file(debug_artifact, &artifact_name, circuit_dir) -} - fn save_build_artifact_to_file, T: ?Sized + serde::Serialize>( build_artifact: &T, artifact_name: &str, @@ -74,14 +63,3 @@ pub(crate) fn read_program_from_file>( Ok(program) } - -pub(crate) fn read_debug_artifact_from_file>( - debug_artifact_path: P, -) -> Result { - let input_string = std::fs::read(&debug_artifact_path) - .map_err(|_| FilesystemError::PathNotValid(debug_artifact_path.as_ref().into()))?; - let program = serde_json::from_slice(&input_string) - .map_err(|err| FilesystemError::ProgramSerializationError(err.to_string()))?; - - Ok(program) -} diff --git a/noir/yarn.lock b/noir/yarn.lock index f4e0ce7df36..7ec790dc23c 100644 --- a/noir/yarn.lock +++ b/noir/yarn.lock @@ -4530,6 +4530,7 @@ __metadata: "@types/mocha": ^10.0.6 "@types/mocha-each": ^2 "@types/node": ^20.10.5 + "@types/pako": ^2 "@types/path-browserify": ^1 "@types/readable-stream": ^4 "@types/sinon": ^17 @@ -4546,6 +4547,7 @@ __metadata: memfs: ^4.6.0 mocha: ^10.2.0 mocha-each: ^2.0.1 + pako: ^2.1.0 path-browserify: ^1.0.1 process: ^0.11.10 readable-stream: ^4.4.2 @@ -6197,6 +6199,13 @@ __metadata: languageName: node linkType: hard +"@types/pako@npm:^2": + version: 2.0.3 + resolution: "@types/pako@npm:2.0.3" + checksum: 0746dd5d29eccf5b2e6cceb3ccb093851219e78bd2e2e20d25757e247987139e061e5d4ba37cb5295493f06e3c683c74f8876011cd8a3f3748a09244fbc841d9 + languageName: node + linkType: hard + "@types/parse-json@npm:^4.0.0": version: 4.0.2 resolution: "@types/parse-json@npm:4.0.2" @@ -17099,6 +17108,13 @@ __metadata: languageName: node linkType: hard +"pako@npm:^2.1.0": + version: 2.1.0 + resolution: "pako@npm:2.1.0" + checksum: 71666548644c9a4d056bcaba849ca6fd7242c6cf1af0646d3346f3079a1c7f4a66ffec6f7369ee0dc88f61926c10d6ab05da3e1fca44b83551839e89edd75a3e + languageName: node + linkType: hard + "param-case@npm:^3.0.4": version: 3.0.4 resolution: "param-case@npm:3.0.4"