Skip to content

Commit

Permalink
feat!: Unify ABIs between nargo and yarn-project (AztecProtocol#3989)
Browse files Browse the repository at this point in the history
Changes the output of `nargo` and `noir-wasm` to generate a single
artifact that includes debug information. Compiled contracts now have a
`file_map` at the root of the artifact, and a `debug_symbols` within
each function. For consistency, compiled programs also have `file_map`
and `debug_symbols`. Debug symbols are compressed and base64-encoded, as
they were by the former `noir-compiler` postprocessing. The `debug` json
artifact is no longer emitted.

Removes all code related to generating `yarn-project`-specific ABIs from
noir compiler. Instead, `types` now exposes a `loadContractArtifact`
that renames fields as needed (and use camel instead of snake case), and
is required when loading a noir contract artifact. Autogenerated types
run this automatically.

Since we are no longer post-processing artifacts, the `noir-contracts`
project shape is changed. JSON files live in the `target` folder where
nargo outputs them (this is not configurable), and are loaded by the
autogenerated typescript interfaces from there.

As part of the refactor, moves functions for getting functions debug
info out of `acir-simulator` and into `types`.

**Breaking change**: This removes the need to run `codegen` for using a
compiled contract. However, when creating a new contract object from
aztec.js, a dev needs to call `loadContractArtifact`.

**Future changes**: Type information for a compilation artifact is now
spread all over the place, and duplicated in more than one place. There
are types defined within rust code in Noir as
`[wasm_bindgen(typescript_custom_section)]`, others defined within
typescript code in the `noir_wasm` package, others in `foundation`, and
others in `types`. We should unify it in a single place.

Fixes AztecProtocol#3812

Supersedes AztecProtocol#3906

Noir subrepo has been pushed to
noir-lang/noir#4035 to run the Noir CI
  • Loading branch information
spalladino authored Jan 17, 2024
1 parent bdbe963 commit d083438
Show file tree
Hide file tree
Showing 88 changed files with 706 additions and 795 deletions.
2 changes: 1 addition & 1 deletion boxes/blank-react/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@
"skipLibCheck": true,
"jsx": "react-jsx"
},
"include": ["src", "src/artifacts/Blank.json"]
"include": ["src", "src/contracts/target/*.json"]
}
2 changes: 1 addition & 1 deletion boxes/blank/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@
"skipLibCheck": true,
"jsx": "react-jsx"
},
"include": ["src", "src/artifacts/Blank.json"]
"include": ["src", "src/contracts/target/*.json"]
}
2 changes: 1 addition & 1 deletion boxes/token/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@
"skipLibCheck": true,
"jsx": "react-jsx"
},
"include": ["src", "src/artifacts/Token.json"]
"include": ["src", "src/contracts/target/*.json"]
}
16 changes: 2 additions & 14 deletions docs/docs/dev_docs/contracts/compiling.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,11 @@ aztec-nargo compile

This will output a JSON [artifact](./artifacts.md) for each contract in the project to a `target` folder containing the Noir ABI artifacts.

Before you can use the ABI it currently needs to be validated as being Aztec compatible, and transformed to an Aztec compatible ABI using `aztec-cli codegen`, passing a Noir ABI file or folder, and output location, e.g:

```bash
aztec-cli codegen ./aztec-nargo/output/target/path -o src/artifacts
```

It can be useful to perform this compilation, validation and transformation in one go, so you may wish to chain the commands and perhaps add them to a package.json script. The below assumes your contract is in a folder called `contract` at your project root:

```bash
(cd contract && aztec-nargo compile && aztec-cli codegen target -o ../src/artifacts)
```

### Typescript Interfaces

You can use the codegenerator to autogenerate type-safe typescript classes for each of your contracts. These classes define type-safe methods for deploying and interacting with your contract based on their artifact.
You can use the code generator to autogenerate type-safe typescript classes for each of your contracts. These classes define type-safe methods for deploying and interacting with your contract based on their artifact.

To generate them, include a `--ts` option in the codegen command with a path to the target folder for the typescript files:
To generate them, include a `--ts` option in the `codegen` command with a path to the target folder for the typescript files:

```bash
aztec-cli codegen ./aztec-nargo/output/target/path -o src/artifacts --ts
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/dev_docs/contracts/deploying.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Compile the contract:
aztec-nargo compile
```

Generate the ABI and typescript class:
Generate the typescript class:

```bash
aztec-cli codegen ./aztec-nargo/output/target/path -o src/artifacts --ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ aztec-nargo compile

This will compile the smart contract and create a `target` folder with a `.json` artifact inside.

After compiling, you need to generate the ABI and typescript class. In the same directory, run this:
After compiling, you can generate a typescript class. In the same directory, run this:

```bash
aztec-cli codegen target -o src/artifacts --ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ and the each of the Aztec.nr contracts by going into each folder and running:
aztec-nargo compile
```

And then generate the ABIs and typescript interface:
And then generate the typescript interface:

```bash
aztec-cli codegen ./target/ -o ../../../src/test/fixtures uniswap --ts
Expand Down
11 changes: 2 additions & 9 deletions docs/docs/dev_docs/tutorials/writing_dapp/contract_deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,6 @@ Now run the following from your contract folder (containing Nargo.toml):
aztec-nargo compile
```

Once you have compiled your contracts, you need to generate the ABIs:

```sh
aztec-cli codegen ./target/path -o src/artifacts --ts
```

This should have created an artifact `contracts/token/src/artifacts/Token.json` with the interface and bytecode for your contract.

## Deploy your contracts

Let's now write a script for deploying your contracts to the Sandbox. We'll create a Private eXecution Environment (PXE) client, and then use the `ContractDeployer` class to deploy our contracts, and store the deployment address to a local JSON file.
Expand All @@ -61,7 +53,8 @@ Create a new file `src/deploy.mjs`:
import { writeFileSync } from 'fs';
import { Contract, ContractDeployer, createPXEClient } from '@aztec/aztec.js';
import { getInitialTestAccountsWallets } from '@aztec/accounts/testing';
import TokenContractArtifact from "../contracts/token/target/Token.json" assert { type: "json" };
import TokenContractJson from "../contracts/token/target/token_contract-Token.json" assert { type: "json" };


#include_code dapp-deploy yarn-project/end-to-end/src/sample-dapp/deploy.mjs raw

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ To do this, let's first initialize a new `Contract` instance using `aztec.js` th
// src/contracts.mjs
import { Contract } from "@aztec/aztec.js";
import { readFileSync } from "fs";
import TokenContractArtifact from "../contracts/token/src/artifacts/Token.json" assert { type: "json" };
import TokenContractJson from "../contracts/token/target/token_contract-Token.json" assert { type: "json" };
```

And then add the following code for initializing the `Contract` instances:
Expand Down
10 changes: 4 additions & 6 deletions docs/docs/dev_docs/tutorials/writing_private_voting_contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,18 +193,16 @@ The easiest way to compile the contract is with `aztec-nargo`. Run the following
aztec-nargo compile
```

This will create a new directory called `target` and a JSON artifact inside it. To create the Aztec contract ABI and typescript interface, run:
This will create a new directory called `target` and a JSON artifact inside it. To optionally create a typescript interface, run:

```bash
aztec-cli codegen target -o src/artifacts --ts
```

This will create the ABI called `Voting.json` in `src/artifacts`. If you are getting some errors here you might want to check out the [debugging page](../debugging/main.md).

Once it is compiled you can [deploy](../contracts/deploying.md) it to the sandbox. Ensure your [sandbox is running](../cli/sandbox-reference.md) and run this in the same dir as before:

```bash
aztec-cli deploy ./src/artifacts/Voting.json --args $ADMIN_ADDRESS
aztec-cli deploy ./target/Voting.json --args $ADMIN_ADDRESS
```

The constructor takes an address as an argument to set the admin, so you can use an address that is deployed with the sandbox - check the sandbox terminal or run `aztec-cli get-accounts`.
Expand All @@ -214,7 +212,7 @@ You should see a success message with the contract address. Now we can start cal
Cast a vote like this:

```bash
aztec-cli send cast_vote --contract-artifact ./src/artifacts/Voting.json --contract-address $CONTRACT_ADDRESS --args 1 --private-key $PRIVATE_KEY
aztec-cli send cast_vote --contract-artifact ./target/Voting.json --contract-address $CONTRACT_ADDRESS --args 1 --private-key $PRIVATE_KEY
```

You can get the contract address from the sandbox terminal or the message printed when you deployed the contract. You can also get a private key from the sandbox terminal, or generate one with `aztec-cli generate-private-key`.
Expand All @@ -226,7 +224,7 @@ You can now try running this command again to ensure our nullifier works.
Get the number of votes like this:

```bash
aztec-cli call get_vote --contract-artifact ./src/artifacts/Voting.json --contract-address $CONTRACT_ADDRESS --args 1
aztec-cli call get_vote --contract-artifact ./target/Voting.json --contract-address $CONTRACT_ADDRESS --args 1
```

This should return `1n`.
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/dev_docs/tutorials/writing_token_contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ Run the following command in the directory where your `Nargo.toml` file is locat
aztec-nargo compile
```

Once your contract is compiled, generate the Aztec contract ABI with typescript interface with the following command:
Once your contract is compiled, optionally generate a typescript interface with the following command:

```bash
aztec-cli codegen target -o src/artifacts --ts
Expand Down
8 changes: 6 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
48 changes: 47 additions & 1 deletion noir/compiler/noirc_errors/src/debug_info.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down Expand Up @@ -86,4 +96,40 @@ 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)
}
}
1 change: 1 addition & 0 deletions noir/compiler/wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions noir/compiler/wasm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"test": "yarn test:build_fixtures && yarn test:node && yarn test:browser",
"test:build_fixtures": "./scripts/build-fixtures.sh",
"test:browser": "web-test-runner",
"test:browser:docker": "docker run --rm -v $(cd ../.. && pwd):/usr/src/noir -w /usr/src/noir/compiler/wasm mcr.microsoft.com/playwright:v1.40.0-jammy yarn test:browser",
"test:node": "NODE_NO_WARNINGS=1 mocha --config ./.mocharc.json",
"clean": "rm -rf ./build ./target ./dist public/fixtures/simple/target public/fixtures/with-deps/target",
"nightly:version": "jq --arg new_version \"-$(git rev-parse --short HEAD)$1\" '.version = .version + $new_version' package.json > package-tmp.json && mv package-tmp.json package.json",
Expand All @@ -49,6 +50,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",
Expand Down Expand Up @@ -76,5 +78,8 @@
"url": "^0.11.3",
"webpack": "^5.49.0",
"webpack-cli": "^4.7.2"
},
"dependencies": {
"pako": "^2.1.0"
}
}
Loading

0 comments on commit d083438

Please sign in to comment.