Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Unify ABIs between nargo and yarn-project #3906

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions noir/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions noir/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion noir/acvm-repo/acir/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 4 additions & 1 deletion noir/compiler/noirc_errors/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ fm.workspace = true
chumsky.workspace = true
serde.workspace = true
serde_with = "3.2.0"
tracing.workspace = true
tracing.workspace = true
flate2.workspace = true
serde_json.workspace = true
base64.workspace = true
41 changes: 40 additions & 1 deletion noir/compiler/noirc_errors/src/debug_info.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
use acvm::acir::circuit::OpcodeLocation;
use acvm::compiler::AcirTransformationMap;

use base64::Engine;
use flate2::Compression;
use flate2::read::DeflateDecoder;
use flate2::write::DeflateEncoder;
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)]
Expand Down Expand Up @@ -86,4 +94,35 @@ impl DebugInfo {

counted_opcodes
}

pub fn serialize_compressed_base64_json<S>(debug_info: &DebugInfo, s: S) -> Result<S::Ok, S::Error>
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<DebugInfo, D::Error>
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)
}
}
52 changes: 12 additions & 40 deletions noir/compiler/wasm/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -33,28 +32,25 @@ export type CompiledContract = {
name: string;
functions: Array<any>;
events: Array<any>;
file_map: Record<number, any>;
warnings: Array<any>;
};

export type CompiledProgram = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you rename these types to align with ProgramArtifact and ContractArtifact? I think ideally we should have these be consistent across JS and Rust.

This is a preexisting issue but I think this PR is a good time to make the change tbh.

noir_version: string;
abi: any;
bytecode: string;
}

export type DebugArtifact = {
debug_symbols: Array<any>;
debug_symbols: any;
file_map: Record<number, any>;
warnings: Array<any>;
};
}

export type CompileResult = (
| {
contract: CompiledContract;
debug: DebugArtifact;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we're pulling the warnings out of the artifact, we'll need to include them on the CompileResult so that they can be displayed in JS

}
| {
program: CompiledProgram;
debug: DebugArtifact;
}
);
"#;
Expand All @@ -76,40 +72,25 @@ extern "C" {
impl JsCompileResult {
const CONTRACT_PROP: &'static str = "contract";
const PROGRAM_PROP: &'static str = "program";
const DEBUG_PROP: &'static str = "debug";

pub fn new(resp: CompileResult) -> JsCompileResult {
let obj = JsCompileResult::constructor();
match resp {
CompileResult::Contract { contract, debug } => {
CompileResult::Contract { contract } => {
js_sys::Reflect::set(
&obj,
&JsString::from(JsCompileResult::CONTRACT_PROP),
&<JsValue as JsValueSerdeExt>::from_serde(&contract).unwrap(),
)
.unwrap();

js_sys::Reflect::set(
&obj,
&JsString::from(JsCompileResult::DEBUG_PROP),
&<JsValue as JsValueSerdeExt>::from_serde(&debug).unwrap(),
)
.unwrap();
}
CompileResult::Program { program, debug } => {
CompileResult::Program { program } => {
js_sys::Reflect::set(
&obj,
&JsString::from(JsCompileResult::PROGRAM_PROP),
&<JsValue as JsValueSerdeExt>::from_serde(&program).unwrap(),
)
.unwrap();

js_sys::Reflect::set(
&obj,
&JsString::from(JsCompileResult::DEBUG_PROP),
&<JsValue as JsValueSerdeExt>::from_serde(&debug).unwrap(),
)
.unwrap();
}
};

Expand Down Expand Up @@ -148,8 +129,8 @@ impl PathToFileSourceMap {
}

pub enum CompileResult {
Contract { contract: ContractArtifact, debug: DebugArtifact },
Program { program: ProgramArtifact, debug: DebugArtifact },
Contract { contract: ContractArtifact },
Program { program: ProgramArtifact },
}

#[wasm_bindgen]
Expand Down Expand Up @@ -273,31 +254,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 }
CompileResult::Program { program: program.into() }
}

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,
warnings: contract.warnings,
};

CompileResult::Contract { contract: contract_artifact, debug: debug_artifact }
CompileResult::Contract { contract: contract_artifact }
}

#[cfg(test)]
Expand Down
35 changes: 34 additions & 1 deletion noir/tooling/nargo/src/artifacts/contract.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
use acvm::acir::circuit::Circuit;
use noirc_abi::{Abi, ContractEvent};
use noirc_driver::{ContractFunction, ContractFunctionType};
use noirc_driver::{ContractFunction, ContractFunctionType, CompiledContract};
use serde::{Deserialize, Serialize};
use noirc_evaluator::errors::SsaReport;

use noirc_driver::DebugFile;
use noirc_errors::debug_info::DebugInfo;
use std::collections::BTreeMap;

use fm::FileId;


#[derive(Serialize, Deserialize)]
pub struct ContractArtifact {
Expand All @@ -13,8 +21,26 @@ pub struct ContractArtifact {
pub functions: Vec<ContractFunctionArtifact>,
/// All the events defined inside the contract scope.
pub events: Vec<ContractEvent>,
/// 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<FileId, DebugFile>,
/// Compilation warnings.
pub warnings: Vec<SsaReport>,
Comment on lines +25 to +26
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to store these on the artifact as they're not really relevant after compilation in my mind.

}

impl From<CompiledContract> 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,
warnings: contract.warnings,
}
}
}


/// Each function in the contract will be compiled as a separate noir program.
///
/// A contract function unlike a regular Noir program however can have additional properties.
Expand All @@ -34,6 +60,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<ContractFunction> for ContractFunctionArtifact {
Expand All @@ -44,6 +76,7 @@ impl From<ContractFunction> for ContractFunctionArtifact {
is_internal: func.is_internal,
abi: func.abi,
bytecode: func.bytecode,
debug_symbols: func.debug,
}
}
}
35 changes: 35 additions & 0 deletions noir/tooling/nargo/src/artifacts/program.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
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 noirc_evaluator::errors::SsaReport;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
Expand All @@ -20,6 +26,18 @@ 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<FileId, DebugFile>,

/// Compilation warnings.
pub warnings: Vec<SsaReport>,
Comment on lines +39 to +40
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly here.

}

impl From<CompiledProgram> for ProgramArtifact {
Expand All @@ -29,6 +47,23 @@ impl From<CompiledProgram> for ProgramArtifact {
abi: program.abi,
noir_version: program.noir_version,
bytecode: program.circuit,
debug_symbols: program.debug,
file_map: program.file_map,
warnings: program.warnings,
}
}
}

impl Into<CompiledProgram> 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: self.warnings,
}
}
}
Loading