diff --git a/.circleci/config.yml b/.circleci/config.yml index 139ec59e247..5091985d8a6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -712,7 +712,7 @@ jobs: - *setup_env - run: name: "Test" - command: ./scripts/cond_run_script end-to-end $JOB_NAME ./scripts/run_tests_local e2e_zk_token_contract.test.ts + command: ./scripts/cond_run_script end-to-end $JOB_NAME ./scripts/run_tests_local e2e_private_token_contract.test.ts working_directory: yarn-project/end-to-end e2e-block-building: diff --git a/bootstrap_docker.sh b/bootstrap_docker.sh index a55b82a8ebe..d4df940ff47 100755 --- a/bootstrap_docker.sh +++ b/bootstrap_docker.sh @@ -38,5 +38,5 @@ build_local $TARGET_PROJECT $ONLY_TARGET if [ -z "$TARGET_PROJECT" ]; then echo echo "Success! You could now run e.g.:" - echo " docker run -ti --rm aztecprotocol/end-to-end:latest e2e_zk_token_contract.test" + echo " docker run -ti --rm aztecprotocol/end-to-end:latest e2e_private_token_contract.test" fi \ No newline at end of file diff --git a/circuits/cpp/barretenberg/cpp/bin-test/Nargo.toml b/circuits/cpp/barretenberg/cpp/bin-test/Nargo.toml index 670888e37cd..4f58c0383aa 100644 --- a/circuits/cpp/barretenberg/cpp/bin-test/Nargo.toml +++ b/circuits/cpp/barretenberg/cpp/bin-test/Nargo.toml @@ -1,4 +1,5 @@ [package] +name = "" authors = [""] compiler_version = "0.6.0" diff --git a/docs/docs/dev_docs/contracts/abi.md b/docs/docs/dev_docs/contracts/abi.md index e69de29bb2d..d5fbe20bc04 100644 --- a/docs/docs/dev_docs/contracts/abi.md +++ b/docs/docs/dev_docs/contracts/abi.md @@ -0,0 +1,18 @@ +Discuss: +- Public Inputs ABIs for functions. +- Args & args hashes +- return values and return values hashes +- etc. + + +## Limitations + +### Num reads and writes + +### Num function calls + +### Num logs + +### Num key pair validations + +### No gas or fees yet \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/concepts.md b/docs/docs/dev_docs/contracts/concepts.md deleted file mode 100644 index 8eaf513c77a..00000000000 --- a/docs/docs/dev_docs/contracts/concepts.md +++ /dev/null @@ -1,162 +0,0 @@ -# Concepts [OLD BY MIKE, TO SPLIT] - - - - -Here, we outline all of the Noir Contract language concepts and keywords. - -## `contract` - -```rust -contract MyContract { - - constructor() {} - - fn my_function_1(x: Field, y: Field) -> Field { - x + y - } - - fn my_function_2(x: Field, y: Field) -> Field { - x * y - } -} -``` - -- A dev can declare a `contract`; a scope which encapsulates a collection of functions and state variables. -- Functions within this scope are said to belong to that contract. -- No external functions (i.e. functions which cannot be inlined) are allowed outside a contract scope. All external functions belong to a contract. -- Contracts are named using PascalCase. -- There is no `main()` function within a contract scope (as opposed to a 'regular noir' program). This is because more than one function may be called and proven (as opposed to inlined by the compiler). That is to say, a developer might want to be able to generate a proof for more than one function in a contract's scope. - -## Noir Contract stdlib - -On top of 'regular Noir's' stdlib, we provide a stdlib for writing Noir Contracts. The Noir Contract stdlib contains structs and abstractions which remove the need to understand the low-level Aztec protocol. - -### State Variables - -#### `PublicState` - -#### `Map` - -#### Private State - -##### UTXO trees - -##### Notes - -##### Custom Notes - -##### `UTXO` - -##### `UTXOSet` - - - -## Functions - -### Public vs Private - -Naming things is hard. - -The words 'public' and 'private' are perfect for describing Aztec's features -- the ability to hide and/or reveal state variables and function execution. - -But those words are also overloaded: -- In smart contract languages, `public` and `private` can be used to describe how a function may be called. -- In many other languages, `public` and `private` describe the accessibility of class methods and members. -- In 'regular Noir', `pub` is used to declare that a parameter or return variable is a 'public input' to the circuit. - -So, whilst 'public' and 'private' are used liberally when describing features of the Aztec network (and indeed in the Aztec codebase), we've avoided using those words anywhere in Noir Contract syntax. - -Instead, we seem to use `open` instead of `public` (why not!) and `secret` for private stuff. Maybe we should use `open` and `closed`. Seems better. - -### `constructor` - -- A special `constructor` function MUST be declared within a contract's scope. -- A constructor doesn't have a name, because its purpose is clear: to initialise state. -- In Aztec terminology, a constructor is always a 'private function' (i.e. it cannot be an `open` function). -- A constructor behaves almost identically to any other function. It's just important for Aztec to be able to identify this function as special: it may only be called once, and will not be deployed as part of the contract. - -### secret functions - -### `open` functions - -### `unconstrained` functions - - - -## Calling functions - -### Inlining - -### Importing Contracts - -### Constrained --> Unconstrained - -E.g. `get()` - -### Oracle calls - -### Private --> Private - -### Public --> Public - -### Private --> Public - -### `internal` keyword - -### Public --> Private - -### Recursive function calls - -### L1 --> L2 - -### L2 --> L1 - -### Delegatecall - -Talk a about the dangers of delegatecall too! - - - -## Events - -### Constraining events - -### Unencrypted Events - -### Encrypted Events - -### Costs - -Explain L1 cost to emit an event. - - - -## Access Control - -### msg_sender - -### slow updates tree (TBC!!!) - - - - - - - -## Limitations - -### Num reads and writes - -### Num function calls - -### Num logs - -### Num key pair validations - -### No gas or fees yet - - -## Future Improvements - -See the Noir Dogfooding retro doc. \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/constrain.md b/docs/docs/dev_docs/contracts/constrain.md index e69de29bb2d..f32c4c11348 100644 --- a/docs/docs/dev_docs/contracts/constrain.md +++ b/docs/docs/dev_docs/contracts/constrain.md @@ -0,0 +1,2 @@ +Not sure what this one's for? +`assert`? \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/contract.md b/docs/docs/dev_docs/contracts/contract.md new file mode 100644 index 00000000000..60062cdbcf3 --- /dev/null +++ b/docs/docs/dev_docs/contracts/contract.md @@ -0,0 +1,26 @@ +# `contract` + +A contract is a collection of persistent [state variables](#state-variables), and [functions](#functions) which may modify these persistent states. Functions and states within a contract's scope are said to belong to that contract. A contract can only access and modify its own state. If a contract wishes to access or modify another contract's state, it must make a [call](#calling-functions) to an external function of that other contract. For anything to happen on the Aztec network, an external function of a contract needs to be called. + +A contract may be declared and given a name using the `contract` keyword (see snippet below). By convention, contracts are named in `PascalCase`. + +```rust title="contract keyword" +// highlight-next-line +contract MyContract { + + // Functions and state variables belonging to this contract are not shown here. + +} +``` + + +> A note for vanilla Noir devs: There is no [`main()`](https://noir-lang.org/getting_started/breakdown/#mainnr) function within a Noir Contract scope. This is because more than one function of a contract may be called and proven as external (as opposed to inlined by the compiler). + +## Structure of a contract + +- Private state variables +- Public state variables +- Private functions +- Public functions +- Encrypted events +- Unencrypted events \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/control_structure.md b/docs/docs/dev_docs/contracts/control_structure.md index b769854fbe9..d4ce598c4dc 100644 --- a/docs/docs/dev_docs/contracts/control_structure.md +++ b/docs/docs/dev_docs/contracts/control_structure.md @@ -2,6 +2,12 @@ title: Control Structures --- +:::danger +Question: this feels like the wrong title for a section about how to call functions. 'Control structure' in my mind is "if/else", "for", "while". + +Can we not put "how to call functions" in the [functions](./functions.md) section? +::: + # Function Calls ## Private Function Calls diff --git a/docs/docs/dev_docs/contracts/deploying.md b/docs/docs/dev_docs/contracts/deploying.md index e69de29bb2d..d1f57537c6d 100644 --- a/docs/docs/dev_docs/contracts/deploying.md +++ b/docs/docs/dev_docs/contracts/deploying.md @@ -0,0 +1 @@ +See sandbox section? \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/events.md b/docs/docs/dev_docs/contracts/events.md index e69de29bb2d..f6a0c5666e7 100644 --- a/docs/docs/dev_docs/contracts/events.md +++ b/docs/docs/dev_docs/contracts/events.md @@ -0,0 +1,17 @@ +## Events + +### Constraining events + +### Unencrypted Events + +### Encrypted Events + +### Costs + +Explain L1 cost to emit an event. + +## Processing events + +### Decrypting + +### Stev \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/functions.md b/docs/docs/dev_docs/contracts/functions.md index e69de29bb2d..e76052ffeb1 100644 --- a/docs/docs/dev_docs/contracts/functions.md +++ b/docs/docs/dev_docs/contracts/functions.md @@ -0,0 +1,50 @@ +# Functions + +## `constructor` + +- A special `constructor` function MUST be declared within a contract's scope. +- A constructor doesn't have a name, because its purpose is clear: to initialise state. +- In Aztec terminology, a constructor is always a 'private function' (i.e. it cannot be an `open` function). +- A constructor behaves almost identically to any other function. It's just important for Aztec to be able to identify this function as special: it may only be called once, and will not be deployed as part of the contract. + +## secret functions + +## `open` functions + +## `unconstrained` functions + + + +# Calling functions + +## Inlining + +## Importing Contracts + +### Contract Interface + +## Constrained --> Unconstrained + +E.g. `get()` + +## Oracle calls + +## Private --> Private + +## Public --> Public + +## Private --> Public + +## `internal` keyword + +## Public --> Private + +## Recursive function calls + +## L1 --> L2 + +## L2 --> L1 + +## Delegatecall + +Talk a about the dangers of delegatecall too! \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/globals.md b/docs/docs/dev_docs/contracts/globals.md index e69de29bb2d..f90edd0d8de 100644 --- a/docs/docs/dev_docs/contracts/globals.md +++ b/docs/docs/dev_docs/contracts/globals.md @@ -0,0 +1,4 @@ +- timestamp +- block number +- chain id +- version \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/layout.md b/docs/docs/dev_docs/contracts/layout.md index e69de29bb2d..2b08b584216 100644 --- a/docs/docs/dev_docs/contracts/layout.md +++ b/docs/docs/dev_docs/contracts/layout.md @@ -0,0 +1,15 @@ +# Layout +## Directory structure + +Here's a common layout for a basic Noir Contract project: + +``` title="layout of an aztec contract project" +─── my_aztec_contract_project + ├── src + │ ├── main.nr <-- your contract + │ └── storage.nr <-- state variable declarations (by convention) + └── Nargo.toml <-- package and dependency management +``` + + +> See the vanilla Noir docs for [more info on packages](https://noir-lang.org/modules_packages_crates/crates_and_packages). \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/main.md b/docs/docs/dev_docs/contracts/main.md index 3750c0d661b..9bb76be3b42 100644 --- a/docs/docs/dev_docs/contracts/main.md +++ b/docs/docs/dev_docs/contracts/main.md @@ -11,9 +11,9 @@ We've extended the Noir language to understand the notion of an **'Aztec smart c - A **Noir Contract** is just an Aztec smart contract, written in Noir syntax. -> Throughout these docs, we'll refer to "regular Noir" as being the version of Noir without the Noir Contract syntax. - - +:::info +Throughout these docs, we'll refer to "Vanilla Noir" as being the version of Noir without the Noir Contract syntax. +::: # Getting started @@ -31,13 +31,28 @@ There are a number of tools to make writing Noir Contracts more pleasant. See [h Download an Aztec Box. (Josh / Ze to build :) ). +@Josh what's the best way to enable a 'one-command' creation of a noir project? (akin to https://noir-lang.org/getting_started/hello_world). I wonder if @aztec/cli should have this functionality? + +@Josh I wonder if @aztec/cli would be a good place to hold 'Aztec Boxes'? +- `aztec-cli unbox` +- `aztec-cli unbox private_token`. + Or, if you don't want to do that, here's more detail on doing it all yourself: :::danger TODO TODO ::: -## Creating a new contract package -See [here](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-contracts#creating-a-new-contract-package) +## Example Noir Contract + +In keeping with the origins of blockchain, here's an example of a simple token contract. But here, the balances are private. + +#include_code easy_private_token_storage /yarn-project/noir-contracts/src/contracts/easy_private_token_contract/src/storage.nr rust + +#include_code easy_private_token_contract /yarn-project/noir-contracts/src/contracts/easy_private_token_contract/src/main.nr rust + +:::info Disclaimer +Please note that any example contract set out herein is provided solely for informational purposes only and does not constitute any inducement to use or deploy. Any implementation of any such contract with an interface or any other infrastructure should be used in accordance with applicable laws and regulations. +::: diff --git a/docs/docs/dev_docs/contracts/resources/common_patterns/access_control.md b/docs/docs/dev_docs/contracts/resources/common_patterns/access_control.md index e69de29bb2d..bc46d2532c8 100644 --- a/docs/docs/dev_docs/contracts/resources/common_patterns/access_control.md +++ b/docs/docs/dev_docs/contracts/resources/common_patterns/access_control.md @@ -0,0 +1,5 @@ +# Access Control + +## msg_sender + +## slow updates tree (TBC!!!) \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/state_variables.md b/docs/docs/dev_docs/contracts/state_variables.md new file mode 100644 index 00000000000..bf7f46723ed --- /dev/null +++ b/docs/docs/dev_docs/contracts/state_variables.md @@ -0,0 +1,35 @@ +# State Variables + +## `PublicState` + +Public state is persistent state which is _publicly visible_, by anyone in the world. + +For developers coming from other blockchain ecosystems (such as Ethereum) this will be a familiar concept, because there, _all_ state is _publicly visible_. + +Aztec public state follows an account-based model. That is, each state occupies a leaf in an account-based merkle tree; the _public state tree_ (LINK). See here (LINK) for more of the technical details. + +The `PublicState` struct, provides a wrapper around conventional Noir types `T`, allowing such types to be written-to and read-from the public state tree. + +#include_code PublicState /yarn-project/noir-contracts/src/contracts/public_token_contract/src/storage.nr rust + +:::danger TODO +Examples which: +- initialise a `PublicState` by itself (without being wrapped in a `Map`) +- initialise a `PublicState` where `T` is a custom struct. +::: + + +## `Map` + + +## Private State + +### UTXO trees + +### Notes + +### Custom Notes + +### `UTXO` + +### `UTXOSet` \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/storage.md b/docs/docs/dev_docs/contracts/storage.md index e69de29bb2d..71a407f228c 100644 --- a/docs/docs/dev_docs/contracts/storage.md +++ b/docs/docs/dev_docs/contracts/storage.md @@ -0,0 +1,13 @@ +# Storage + +> A common convention in Noir Contracts is to declare the state variables for your Noir Contract in a `storage.nr` file inside your project (see [directory structure](./layout.md#directory-structure)). This is just a convention, though: your contract would still work if you declare storage in the `main.nr` file. + +State variables must be declared inside a struct. (This enables us to declare types composed of nested generics in Noir - see [types](./types.md)). + +By way of example, we could define a private state variable `balances`, mapping user addresses to their token balances: + +#include_code storage-declaration /yarn-project/noir-contracts/src/contracts/private_token_contract/src/storage.nr rust + +#include_code storage-import /yarn-project/noir-contracts/src/contracts/private_token_contract/src/main.nr rust + +State variables come in two flavours: **public** state and **private** state. . \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/syntax.md b/docs/docs/dev_docs/contracts/syntax.md new file mode 100644 index 00000000000..288a46cb380 --- /dev/null +++ b/docs/docs/dev_docs/contracts/syntax.md @@ -0,0 +1,23 @@ +# Noir Contract Syntax + +[Vanilla Noir](https://noir-lang.org/) is a language which is agnostic to proof systems and use cases. Rather than baking Aztec-specific keywords and smart contract types directly into Noir (which would break this agnosticism), we have developed a library -- written in Vanilla Noir -- whose types and methods provide rich smart contract semantics. + +## Aztec stdlib + +On top of ['Vanialla Noir's' stdlib](https://noir-lang.org/standard_library/array_methods), we provide an [Aztec stdlib](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-libs) for writing Noir Contracts. The Aztec stdlib contains abstractions which remove the need to understand the low-level Aztec protocol. Notably, it provides: +- Public and private [state variable types](./types.md) +- Ready-made notes. +- Functions for [emitting](./events.md) encrypted and unencrypted logs +- [Oracle functions](./functions.md#oracle-calls) for accessing: + - private state + - secrets +- Functions for communicating with Ethereum L1 + + +To import the Aztec stdlib into your Noir Contract project, simply include it as a dependency: + +:::danger TODO +https://github.com/AztecProtocol/aztec-packages/issues/1335 +::: + +#include_code importing-aztec /yarn-project/noir-contracts/src/contracts/private_token_contract/Nargo.toml toml \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/types.md b/docs/docs/dev_docs/contracts/types.md index e69de29bb2d..de66faed98b 100644 --- a/docs/docs/dev_docs/contracts/types.md +++ b/docs/docs/dev_docs/contracts/types.md @@ -0,0 +1,2 @@ +See Noir docs for Noir types. +See [state_variables](./state_variables.md) for Noir Contract state variable types. \ No newline at end of file diff --git a/docs/docs/dev_docs/contracts/visibility.md b/docs/docs/dev_docs/contracts/visibility.md index e69de29bb2d..deb31e42106 100644 --- a/docs/docs/dev_docs/contracts/visibility.md +++ b/docs/docs/dev_docs/contracts/visibility.md @@ -0,0 +1,3 @@ +- internal +- external +- ? \ No newline at end of file diff --git a/docs/docs/embedding_github_code.md b/docs/docs/embedding_github_code.md index 9cf3ee5605c..ee8e1e6524b 100644 --- a/docs/docs/embedding_github_code.md +++ b/docs/docs/embedding_github_code.md @@ -6,7 +6,12 @@ title: Embedding Github Code Here's an example of some code: - + + + + + + # Fetched from github, when loading the page: @@ -15,7 +20,7 @@ Here's an example of embedding code from a file of a branch of a github repo: import GithubCode from '../src/components/GithubCode'; - + diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index ce388df8c2b..986e3b525d7 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -99,7 +99,7 @@ const config = { docs: { sidebar: { hideable: true, - autoCollapseCategories: true, + autoCollapseCategories: false, }, }, navbar: { @@ -165,7 +165,21 @@ const config = { prism: { theme: lightCodeTheme, darkTheme: darkCodeTheme, - additionalLanguages: ["rust", "solidity", "cpp"], + // https://prismjs.com/#supported-languages + // Commented-out languages exists in `node_modules/prismjs/components/` so I'm not sure why they don't work. + additionalLanguages: [ + "rust", + "solidity", + "cpp", + "javascript", + // "typescript", + "json", + // "bash", + // "solidity", + "toml", + "markdown", + "docker", + ], magicComments: [ // Remember to extend the default highlight class name as well! { diff --git a/docs/sidebars.js b/docs/sidebars.js index 0f5eefd7a19..31fd9d0c396 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -205,15 +205,17 @@ const sidebars = { id: "dev_docs/contracts/main", }, items: [ - "dev_docs/contracts/concepts", + "dev_docs/contracts/syntax", + "dev_docs/contracts/contract", "dev_docs/contracts/layout", + "dev_docs/contracts/types", + "dev_docs/contracts/storage", + "dev_docs/contracts/state_variables", + "dev_docs/contracts/functions", "dev_docs/contracts/control_structure", + "dev_docs/contracts/visibility", "dev_docs/contracts/globals", "dev_docs/contracts/events", - "dev_docs/contracts/storage", - "dev_docs/contracts/types", - "dev_docs/contracts/visibility", - "dev_docs/contracts/functions", "dev_docs/contracts/constrain", "dev_docs/contracts/compiling", "dev_docs/contracts/deploying", diff --git a/docs/src/preprocess/index.js b/docs/src/preprocess/index.js index 3a6413e2625..c7ce25e643d 100644 --- a/docs/src/preprocess/index.js +++ b/docs/src/preprocess/index.js @@ -1,24 +1,137 @@ +const { match } = require("assert"); const fs = require("fs"); const path = require("path"); const getLineNumberFromIndex = (fileContent, index) => { - return fileContent.substr(0, index).split("\n").length; + return fileContent.substring(0, index).split("\n").length; }; +/** + * Search for lines of the form + */ +function processHighlighting(codeSnippet, identifier) { + const lines = codeSnippet.split("\n"); + /** + * For an identifier = bar: + * + * Matches of the form: `highlight-next-line:foo:bar:baz` will be replaced with "highlight-next-line". + * Matches of the form: `highlight-next-line:foo:baz` will be replaced with "". + */ + const regex1 = /highlight-next-line:([a-zA-Z0-9-._:]+)/; + const replacement1 = "highlight-next-line"; + const regex2 = /highlight-start:([a-zA-Z0-9-._:]+)/; + const replacement2 = "highlight-start"; + const regex3 = /highlight-end:([a-zA-Z0-9-._:]+)/; + const replacement3 = "highlight-end"; + const regex4 = /this-will-error:([a-zA-Z0-9-._:]+)/; + const replacement4 = "this-will-error"; + + let result = ""; + let mutated = false; + + const processLine = (line, regex, replacement) => { + const match = line.match(regex); + if (match) { + mutated = true; + + const identifiers = match[1].split(":"); + if (identifiers.includes(identifier)) { + line = line.replace(match[0], replacement); + } else { + // Remove matched text completely + line = line.replace(match[0], ""); + } + } else { + // No match: it's an ordinary line of code. + } + return line.trim() == "//" || line.trim() == "#" ? "" : line; + }; + + for (let line of lines) { + mutated = false; + line = processLine(line, regex1, replacement1); + line = processLine(line, regex2, replacement2); + line = processLine(line, regex3, replacement3); + line = processLine(line, regex4, replacement4); + result += line === "" && mutated ? "" : line + "\n"; + } + + return result.trim(); +} + function extractCodeSnippet(filePath, identifier) { - const fileContent = fs.readFileSync(filePath, "utf-8"); + let fileContent = fs.readFileSync(filePath, "utf-8"); + let lineRemovalCount = 0; + let linesToRemove = []; + + // const startCommonRegexStr = "docs:start:([a-zA-Z0-9-:]+)"; + // const startRegexStr = `\/\/\s+${startCommonRegexStr}|#s+${startCommonRegexStr}`; // Allow for languages with `//` and `#` comment symbols. + // const startRegex = new RegExp(startRegexStr, "g"); + + // const endCommonRegexStr = "docs:end:([a-zA-Z0-9-:]+)"; + // const endRegexStr = `\/\/\s+${endCommonRegexStr}|#s+${endCommonRegexStr}`; // Allow for languages with `//` and `#` comment symbols. + // const endRegex = new RegExp(endRegexStr, "g"); + + const startRegex = /(?:\/\/|#)\s+docs:start:([a-zA-Z0-9-._:]+)/g; // `g` will iterate through the regex.exec loop + const endRegex = /(?:\/\/|#)\s+docs:end:([a-zA-Z0-9-._:]+)/g; + + // const startRegex = /\/\/\s+docs:start:([a-zA-Z0-9-:]+)/g; // `g` will iterate through the regex.exec loop + // const endRegex = /\/\/\s+docs:end:([a-zA-Z0-9-:]+)/g; + + const lookForMatch = (regex) => { + let match; + let matchFound = false; + let matchedLineNum = null; + let actualMatch = null; + let lines = fileContent.split("\n"); + while ((match = regex.exec(fileContent))) { + if (match !== null) { + const identifiers = match[1].split(":"); + let tempMatch = identifiers.includes(identifier) ? match : null; + + if (tempMatch === null) { + // If it's not a match, we'll make a note that we should remove the matched text, because it's from some other identifier and should appear in the snippet for this identifier. + for (let i = 0; i < lines.length; i++) { + let line = lines[i]; + if (line.trim() == match[0].trim()) { + linesToRemove.push(i); + ++lineRemovalCount; + } + } + } else { + if (matchFound === true) { + throw new Error( + `Duplicate for regex ${regex} and identifier ${identifier}` + ); + } + matchFound = true; + matchedLineNum = getLineNumberFromIndex(fileContent, tempMatch.index); + actualMatch = tempMatch; + } + } + } + + return [actualMatch, matchedLineNum]; + }; - const startTag = `// docs:start:${identifier}`; - const endTag = `// docs:end:${identifier}`; - const startIndex = fileContent.indexOf(startTag); - const endIndex = fileContent.indexOf(endTag); + let [startMatch, lineNum1] = lookForMatch(startRegex); + let [endMatch, lineNum2] = lookForMatch(endRegex); + + if (startMatch !== null) { + const startIdentifiers = startMatch[1].split(":"); + startMatch = startIdentifiers.includes(identifier) ? startMatch : null; + } + if (endMatch !== null) { + const endIdentifiers = endMatch[1].split(":"); + endMatch = endIdentifiers.includes(identifier) ? endMatch : null; + } - if (startIndex === -1 || endIndex === -1) { - if (startIndex === -1 && endIndex === -1) { + if (startMatch === null || endMatch === null) { + if (startMatch === null && endMatch === null) { throw new Error( `Identifier "${identifier}" not found in file "${filePath}"` ); - } else if (startIndex === -1) { + } else if (startMatch === null) { throw new Error( `Start line "docs:start:${identifier}" not found in file "${filePath}"` ); @@ -29,14 +142,30 @@ function extractCodeSnippet(filePath, identifier) { } } - const slicedContent = fileContent - .slice(startIndex + startTag.length, endIndex) - .trim(); + let startIndex = startMatch.index; + let endIndex = endMatch.index; + + let lines = fileContent.split("\n"); + + lines = lines.filter((l, i) => { + return !linesToRemove.includes(i); + }); + + lines = lines.filter((l, i) => { + return i + 1 > lineNum1 && i + 1 < lineNum2 - lineRemovalCount; + }); + + fileContent = lines.join("\n"); + + let codeSnippet = lines.join("\n"); const startLine = getLineNumberFromIndex(fileContent, startIndex) + 1; - const endLine = getLineNumberFromIndex(fileContent, endIndex) - 1; + const endLine = + getLineNumberFromIndex(fileContent, endIndex) - 1 - lineRemovalCount; + + codeSnippet = processHighlighting(codeSnippet, identifier); - return [slicedContent, startLine, endLine]; + return [codeSnippet, startLine, endLine]; } async function processMarkdownFilesInDir(rootDir, docsDir, regex) { @@ -80,7 +209,7 @@ async function processMarkdownFilesInDir(rootDir, docsDir, regex) { codeFilePath )}#L${startLine}-L${endLine}`; - const replacement = `\`\`\`${language} title=${identifier} showLineNumbers \n${codeSnippet}\n\`\`\`\n> [Link to source code.](${url})\n`; + const replacement = `\`\`\`${language} title="${identifier}" showLineNumbers \n${codeSnippet}\n\`\`\`\n> [Source code: ${url}](${url})\n`; // Replace the include tag with the code snippet updatedContent = updatedContent.replace(fullMatch, replacement); @@ -158,7 +287,7 @@ async function writeProcessedFiles(docsDir, destDir, cachedDestDir, content) { const cachedFileContent = fs.readFileSync(cachedDestFilePath, "utf-8"); if (existingFileContent !== cachedFileContent) { throw new Error( - `It looks like you might have accidentally edited files in the 'processed-docs/' dir instead of the 'docs/' dir (because there's a discrepancy between 'preprocessed-docs' and 'preprocessed-docs-cache', but they should always be the same unless they're tampered-with).\n\nWe don't want you to accidentally overwrite your work.\n\nCopy your work to the 'docs/' dir, and revert your 'processed-docs/' changes.\n\nI.e. copy from here: ${destFilePath}\n\nto here: ${content.filepath}\n\nIf this error's safety assumption is wrong, and you'd like to proceed with building, please delete the cached file ${cachedDestFilePath} and rerun the build.\n\n` + `It looks like you might have accidentally edited files in the 'processed-docs/' dir instead of the 'docs/' dir (because there's a discrepancy between 'preprocessed-docs' and 'preprocessed-docs-cache', but they should always be the same unless they're tampered-with).\n\nWe don't want you to accidentally overwrite your work.\n\nCopy your work to the 'docs/' dir, and revert your 'processed-docs/' changes.\n\nI.e. copy from here: ${destFilePath}\n\nto here: ${content.filepath}\n\nIf this error's safety assumption is wrong, and you'd like to proceed with building, please delete the cached file ${cachedDestFilePath} and rerun the build.\n\nAnd if you've not made any changes at all to the docs and you've just pulled master and are wondering what is going on, you might want to run \`yarn clear\` from this docs dir.` ); } } diff --git a/yarn-project/acir-simulator/src/client/private_execution.test.ts b/yarn-project/acir-simulator/src/client/private_execution.test.ts index d4b778b3093..0940860c36d 100644 --- a/yarn-project/acir-simulator/src/client/private_execution.test.ts +++ b/yarn-project/acir-simulator/src/client/private_execution.test.ts @@ -35,8 +35,9 @@ import { NonNativeTokenContractAbi, ParentContractAbi, PendingCommitmentsContractAbi, + PrivateTokenAirdropContractAbi, + PrivateTokenContractAbi, TestContractAbi, - ZkTokenContractAbi, } from '@aztec/noir-contracts/artifacts'; import { PackedArguments, TxExecutionRequest } from '@aztec/types'; @@ -159,7 +160,7 @@ describe('Private Execution test suite', () => { }); }); - describe('zk token contract', () => { + describe('private token airdrop contract', () => { const contractAddress = defaultContractAddress; const recipientPk = PrivateKey.fromString('0c9ed344548e8f9ba8aa3c9f8651eaa2853130f6c1e9c050ccf198f7ea18a7ec'); const mockFirstNullifier = new Fr(1111); @@ -213,7 +214,9 @@ describe('Private Execution test suite', () => { oracle.getFunctionABI.mockImplementation((_, selector) => Promise.resolve( - ZkTokenContractAbi.functions.find(f => selector.equals(generateFunctionSelector(f.name, f.parameters)))!, + PrivateTokenAirdropContractAbi.functions.find(f => + selector.equals(generateFunctionSelector(f.name, f.parameters)), + )!, ), ); }); @@ -252,7 +255,7 @@ describe('Private Execution test suite', () => { }); it('should a constructor with arguments that inserts notes', async () => { - const abi = ZkTokenContractAbi.functions.find(f => f.name === 'constructor')!; + const abi = PrivateTokenAirdropContractAbi.functions.find(f => f.name === 'constructor')!; const result = await runSimulator({ args: [140, owner], abi }); @@ -270,7 +273,7 @@ describe('Private Execution test suite', () => { }); it('should run the mint function', async () => { - const abi = ZkTokenContractAbi.functions.find(f => f.name === 'mint')!; + const abi = PrivateTokenAirdropContractAbi.functions.find(f => f.name === 'mint')!; const result = await runSimulator({ args: [140, owner], abi }); @@ -289,7 +292,7 @@ describe('Private Execution test suite', () => { it('should run the transfer function', async () => { const amountToTransfer = 100n; - const abi = ZkTokenContractAbi.functions.find(f => f.name === 'transfer')!; + const abi = PrivateTokenAirdropContractAbi.functions.find(f => f.name === 'transfer')!; const storageSlot = computeSlotForMapping(new Fr(1n), owner.toField(), circuitsWasm); const recipientStorageSlot = computeSlotForMapping(new Fr(1n), recipient.toField(), circuitsWasm); @@ -334,7 +337,7 @@ describe('Private Execution test suite', () => { it('should be able to transfer with dummy notes', async () => { const amountToTransfer = 100n; const balance = 160n; - const abi = ZkTokenContractAbi.functions.find(f => f.name === 'transfer')!; + const abi = PrivateTokenAirdropContractAbi.functions.find(f => f.name === 'transfer')!; const storageSlot = computeSlotForMapping(new Fr(1n), owner.toField(), circuitsWasm); @@ -361,7 +364,7 @@ describe('Private Execution test suite', () => { it('Should be able to claim a note by providing the correct secret', async () => { const amount = 100n; const secret = Fr.random(); - const abi = ZkTokenContractAbi.functions.find(f => f.name === 'claim')!; + const abi = PrivateTokenAirdropContractAbi.functions.find(f => f.name === 'claim')!; const storageSlot = new Fr(2n); // choose nonzero nonce otherwise reads will be interpreted as transient (inner note hash instead of unique+siloed) const nonce = new Fr(1n); @@ -396,6 +399,206 @@ describe('Private Execution test suite', () => { }); }); + describe('private token contract', () => { + const contractAddress = defaultContractAddress; + const recipientPk = PrivateKey.fromString('0c9ed344548e8f9ba8aa3c9f8651eaa2853130f6c1e9c050ccf198f7ea18a7ec'); + const mockFirstNullifier = new Fr(1111); + let owner: AztecAddress; + let recipient: AztecAddress; + let currentNoteIndex = 0n; + + const buildNote = (amount: bigint, owner: AztecAddress, storageSlot = Fr.random()) => { + // WARNING: this is not actually how nonces are computed! + // For the purpose of this test we use a mocked firstNullifier and and a random number + // to compute the nonce. Proper nonces are only enforced later by the kernel/later circuits + // which are not relevant to this test. In practice, the kernel first squashes all transient + // noteHashes with their matching nullifiers. It then reorders the remaining "persistable" + // noteHashes. A TX's real first nullifier (generated by the initial kernel) and a noteHash's + // array index at the output of the final kernel/ordering circuit are used to derive nonce via: + // `hash(firstNullifier, noteHashIndex)` + const noteHashIndex = Math.floor(Math.random()); // mock index in TX's final newNoteHashes array + const nonce = computeCommitmentNonce(circuitsWasm, mockFirstNullifier, noteHashIndex); + const preimage = [new Fr(amount), owner.toField(), Fr.random()]; + return { + contractAddress, + storageSlot, + nonce, + preimage, + siloedNullifier: new Fr(0), + index: currentNoteIndex++, + }; + }; + + beforeEach(async () => { + const { + address: ownerAddress, + partialAddress: ownerPartialAddress, + publicKey: ownerPubKey, + } = await makeAddressWithPreimagesFromPrivateKey(ownerPk); + + const { + address: recipientAddress, + partialAddress: recipientPartialAddress, + publicKey: recipientPubKey, + } = await makeAddressWithPreimagesFromPrivateKey(recipientPk); + + owner = ownerAddress; + recipient = recipientAddress; + + oracle.getPublicKey.mockImplementation((address: AztecAddress) => { + if (address.equals(owner)) return Promise.resolve([ownerPubKey, ownerPartialAddress]); + if (address.equals(recipient)) return Promise.resolve([recipientPubKey, recipientPartialAddress]); + throw new Error(`Unknown address ${address}`); + }); + + oracle.getFunctionABI.mockImplementation((_, selector) => + Promise.resolve( + PrivateTokenContractAbi.functions.find(f => selector.equals(generateFunctionSelector(f.name, f.parameters)))!, + ), + ); + }); + + it('should have an abi for computing note hash and nullifier', async () => { + const storageSlot = Fr.random(); + const note = buildNote(60n, owner, storageSlot); + + // Should be the same as how we compute the values for the ValueNote in the noir library. + const valueNoteHash = pedersenPlookupCommitInputs( + circuitsWasm, + note.preimage.map(f => f.toBuffer()), + ); + const innerNoteHash = Fr.fromBuffer( + pedersenPlookupCommitInputs(circuitsWasm, [storageSlot.toBuffer(), valueNoteHash]), + ); + const siloedNoteHash = siloCommitment(circuitsWasm, contractAddress, innerNoteHash); + const uniqueSiloedNoteHash = computeUniqueCommitment(circuitsWasm, note.nonce, siloedNoteHash); + const innerNullifier = Fr.fromBuffer( + pedersenPlookupCommitInputs(circuitsWasm, [uniqueSiloedNoteHash.toBuffer(), ownerPk.value]), + ); + + const result = await acirSimulator.computeNoteHashAndNullifier( + contractAddress, + note.nonce, + storageSlot, + note.preimage, + ); + + expect(result).toEqual({ + innerNoteHash, + siloedNoteHash, + uniqueSiloedNoteHash, + innerNullifier, + }); + }); + + it('should a constructor with arguments that inserts notes', async () => { + const abi = PrivateTokenContractAbi.functions.find(f => f.name === 'constructor')!; + + const result = await runSimulator({ args: [140, owner], abi }); + + expect(result.preimages.newNotes).toHaveLength(1); + const newNote = result.preimages.newNotes[0]; + expect(newNote.storageSlot).toEqual(computeSlotForMapping(new Fr(1n), owner.toField(), circuitsWasm)); + + const newCommitments = result.callStackItem.publicInputs.newCommitments.filter(field => !field.equals(Fr.ZERO)); + expect(newCommitments).toHaveLength(1); + + const [commitment] = newCommitments; + expect(commitment).toEqual( + await acirSimulator.computeInnerNoteHash(contractAddress, newNote.storageSlot, newNote.preimage), + ); + }); + + it('should run the mint function', async () => { + const abi = PrivateTokenContractAbi.functions.find(f => f.name === 'mint')!; + + const result = await runSimulator({ args: [140, owner], abi }); + + expect(result.preimages.newNotes).toHaveLength(1); + const newNote = result.preimages.newNotes[0]; + expect(newNote.storageSlot).toEqual(computeSlotForMapping(new Fr(1n), owner.toField(), circuitsWasm)); + + const newCommitments = result.callStackItem.publicInputs.newCommitments.filter(field => !field.equals(Fr.ZERO)); + expect(newCommitments).toHaveLength(1); + + const [commitment] = newCommitments; + expect(commitment).toEqual( + await acirSimulator.computeInnerNoteHash(contractAddress, newNote.storageSlot, newNote.preimage), + ); + }); + + it('should run the transfer function', async () => { + const amountToTransfer = 100n; + const abi = PrivateTokenContractAbi.functions.find(f => f.name === 'transfer')!; + + const storageSlot = computeSlotForMapping(new Fr(1n), owner.toField(), circuitsWasm); + const recipientStorageSlot = computeSlotForMapping(new Fr(1n), recipient.toField(), circuitsWasm); + + const notes = [buildNote(60n, owner, storageSlot), buildNote(80n, owner, storageSlot)]; + oracle.getNotes.mockResolvedValue(notes); + + const consumedNotes = await asyncMap(notes, ({ nonce, preimage }) => + acirSimulator.computeNoteHashAndNullifier(contractAddress, nonce, storageSlot, preimage), + ); + await insertLeaves(consumedNotes.map(n => n.siloedNoteHash)); + + const args = [amountToTransfer, owner, recipient]; + const result = await runSimulator({ args, abi }); + + // The two notes were nullified + const newNullifiers = result.callStackItem.publicInputs.newNullifiers.filter(field => !field.equals(Fr.ZERO)); + expect(newNullifiers).toEqual(consumedNotes.map(n => n.innerNullifier)); + + expect(result.preimages.newNotes).toHaveLength(2); + const [changeNote, recipientNote] = result.preimages.newNotes; + expect(recipientNote.storageSlot).toEqual(recipientStorageSlot); + + const newCommitments = result.callStackItem.publicInputs.newCommitments.filter(field => !field.equals(Fr.ZERO)); + expect(newCommitments).toHaveLength(2); + + const [changeNoteCommitment, recipientNoteCommitment] = newCommitments; + expect(recipientNoteCommitment).toEqual( + await acirSimulator.computeInnerNoteHash(contractAddress, recipientStorageSlot, recipientNote.preimage), + ); + expect(changeNoteCommitment).toEqual( + await acirSimulator.computeInnerNoteHash(contractAddress, storageSlot, changeNote.preimage), + ); + + expect(recipientNote.preimage[0]).toEqual(new Fr(amountToTransfer)); + expect(changeNote.preimage[0]).toEqual(new Fr(40n)); + + const readRequests = result.callStackItem.publicInputs.readRequests.filter(field => !field.equals(Fr.ZERO)); + expect(readRequests).toEqual(consumedNotes.map(n => n.uniqueSiloedNoteHash)); + }); + + it('should be able to transfer with dummy notes', async () => { + const amountToTransfer = 100n; + const balance = 160n; + const abi = PrivateTokenContractAbi.functions.find(f => f.name === 'transfer')!; + + const storageSlot = computeSlotForMapping(new Fr(1n), owner.toField(), circuitsWasm); + + const notes = [buildNote(balance, owner, storageSlot)]; + oracle.getNotes.mockResolvedValue(notes); + + const consumedNotes = await asyncMap(notes, ({ nonce, preimage }) => + acirSimulator.computeNoteHashAndNullifier(contractAddress, nonce, storageSlot, preimage), + ); + await insertLeaves(consumedNotes.map(n => n.siloedNoteHash)); + + const args = [amountToTransfer, owner, recipient]; + const result = await runSimulator({ args, abi }); + + const newNullifiers = result.callStackItem.publicInputs.newNullifiers.filter(field => !field.equals(Fr.ZERO)); + expect(newNullifiers).toEqual(consumedNotes.map(n => n.innerNullifier)); + + expect(result.preimages.newNotes).toHaveLength(2); + const [changeNote, recipientNote] = result.preimages.newNotes; + expect(recipientNote.preimage[0]).toEqual(new Fr(amountToTransfer)); + expect(changeNote.preimage[0]).toEqual(new Fr(balance - amountToTransfer)); + }); + }); + describe('nested calls', () => { const privateIncrement = txContextFields.chainId.value + txContextFields.version.value; diff --git a/yarn-project/acir-simulator/src/client/unconstrained_execution.test.ts b/yarn-project/acir-simulator/src/client/unconstrained_execution.test.ts index 6366924223d..7d3a49b40ce 100644 --- a/yarn-project/acir-simulator/src/client/unconstrained_execution.test.ts +++ b/yarn-project/acir-simulator/src/client/unconstrained_execution.test.ts @@ -5,7 +5,7 @@ import { encodeArguments } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; -import { ZkTokenContractAbi } from '@aztec/noir-contracts/artifacts'; +import { PrivateTokenContractAbi } from '@aztec/noir-contracts/artifacts'; import { FunctionCall } from '@aztec/types'; import { mock } from 'jest-mock-extended'; @@ -27,7 +27,7 @@ describe('Unconstrained Execution test suite', () => { acirSimulator = new AcirSimulator(oracle); }); - describe('zk token contract', () => { + describe('private token contract', () => { const ownerPk = PrivateKey.fromString('5e30a2f886b4b6a11aea03bf4910fbd5b24e61aa27ea4d05c393b3ab592a8d33'); let owner: AztecAddress; @@ -56,7 +56,7 @@ describe('Unconstrained Execution test suite', () => { it('should run the getBalance function', async () => { const contractAddress = AztecAddress.random(); - const abi = ZkTokenContractAbi.functions.find(f => f.name === 'getBalance')!; + const abi = PrivateTokenContractAbi.functions.find(f => f.name === 'getBalance')!; const preimages = [...Array(5).fill(buildNote(1n, owner)), ...Array(2).fill(buildNote(2n, owner))]; diff --git a/yarn-project/aztec-cli/README.md b/yarn-project/aztec-cli/README.md index 61c205508bf..7f7af031c01 100644 --- a/yarn-project/aztec-cli/README.md +++ b/yarn-project/aztec-cli/README.md @@ -145,7 +145,7 @@ aztec-cli deploy [options] Options: -- `-c, --contract-abi `: Path to the compiled Noir contract's ABI file in JSON format. You can also use one of Aztec's example contracts found in [@aztec/noir-contracts](https://www.npmjs.com/package/@aztec/noir-contracts), e.g. ZkTokenContractAbi. You can get a full ist of the available contracts with `aztec-cli example-contracts` +- `-c, --contract-abi `: Path to the compiled Noir contract's ABI file in JSON format. You can also use one of Aztec's example contracts found in [@aztec/noir-contracts](https://www.npmjs.com/package/@aztec/noir-contracts), e.g. PrivateTokenContractAbi. You can get a full ist of the available contracts with `aztec-cli example-contracts` - `-a, --args ` (optional): Contract constructor arguments Default: []. - `-u, --rpc-url `: URL of the Aztec RPC. Default: `http://localhost:8080`. - `-k, --public-key `: Public key of the deployer. If not provided, it will check the RPC for existing ones. @@ -161,7 +161,7 @@ aztec-cli deploy -c path/to/contract.abi.json -a ...args With an Aztec example contract: ```shell -aztec-cli deploy -c ZkTokenContractAbi -a 333 0x134567890abcdef +aztec-cli deploy -c PrivateTokenContractAbi -a 333 0x134567890abcdef ``` ### check-deploy @@ -321,7 +321,7 @@ aztec-cli call-fn [functionArgs.. Options: - `'-a, --args [functionArgs...]` (optional): Function arguments. Default: []. -- `-c, --contract-abi `: The compiled contract's ABI in JSON format. You can also use one of Aztec's example contracts found in (@aztec/noir-contracts)[https://www.npmjs.com/package/@aztec/noir-contracts], e.g. ZkTokenContractAbi. +- `-c, --contract-abi `: The compiled contract's ABI in JSON format. You can also use one of Aztec's example contracts found in (@aztec/noir-contracts)[https://www.npmjs.com/package/@aztec/noir-contracts], e.g. PrivateTokenContractAbi. - `-ca, --contract-address
`: Address of the contract. - `-k, --private-key `: The sender's private key. - `-u, --rpcUrl `: URL of the Aztec RPC. Default: `http://localhost:8080`. @@ -349,7 +349,7 @@ aztec-cli call [functionArgs...] Options: - `'-a, --args [functionArgs...]` (optional): Function arguments. Default: []. -- `-c, --contract-abi `: The compiled contract's ABI in JSON format. You can also use one of Aztec's example contracts found in (@aztec/noir-contracts)[https://www.npmjs.com/package/@aztec/noir-contracts], e.g. ZkTokenContractAbi. +- `-c, --contract-abi `: The compiled contract's ABI in JSON format. You can also use one of Aztec's example contracts found in (@aztec/noir-contracts)[https://www.npmjs.com/package/@aztec/noir-contracts], e.g. PrivateTokenContractAbi. - `-ca, --contract-address
`: Address of the contract. - `-f, --from `: Public key of the transaction viewer. If empty, it will try to find an account in the RPC. - `-u, --rpcUrl `: URL of the Aztec RPC. Default: `http://localhost:8080`. diff --git a/yarn-project/aztec-sandbox/README.md b/yarn-project/aztec-sandbox/README.md index 37bf454065a..ed50c63fee6 100644 --- a/yarn-project/aztec-sandbox/README.md +++ b/yarn-project/aztec-sandbox/README.md @@ -42,7 +42,7 @@ Before running locally you'll need to: From the `aztec-sandbox` directory, you can run the two existing examples: -- Deployment, mint and transfer on an Aztec ZK Token +- Deployment, mint and transfer on an Aztec Private Token - `yarn run:example:token` - An L1 / L2 uniswap token trade. - `yarn run:example:uniswap` diff --git a/yarn-project/aztec-sandbox/package.json b/yarn-project/aztec-sandbox/package.json index ff5eac786b2..1639c088c87 100644 --- a/yarn-project/aztec-sandbox/package.json +++ b/yarn-project/aztec-sandbox/package.json @@ -20,7 +20,7 @@ "prepare:check": "node ../yarn-project-base/scripts/update_build_manifest.mjs package.json --check", "build:dev": "tsc -b --watch", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --passWithNoTests", - "run:example:token": "DEBUG='aztec:*' node ./dest/examples/zk_token_contract.js", + "run:example:token": "DEBUG='aztec:*' node ./dest/examples/private_token_contract.js", "run:example:uniswap": "DEBUG='aztec:*' node ./dest/examples/uniswap_trade_on_l1_from_l2.js" }, "inherits": [ diff --git a/yarn-project/aztec-sandbox/src/examples/zk_token_contract.ts b/yarn-project/aztec-sandbox/src/examples/private_token_contract.ts similarity index 86% rename from yarn-project/aztec-sandbox/src/examples/zk_token_contract.ts rename to yarn-project/aztec-sandbox/src/examples/private_token_contract.ts index a6183793455..fb8f39b1b1f 100644 --- a/yarn-project/aztec-sandbox/src/examples/zk_token_contract.ts +++ b/yarn-project/aztec-sandbox/src/examples/private_token_contract.ts @@ -1,7 +1,7 @@ import { AztecAddress, Contract, Fr, PrivateKey, Wallet, createAccounts, createAztecRpcClient } from '@aztec/aztec.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { SchnorrSingleKeyAccountContractAbi } from '@aztec/noir-contracts/artifacts'; -import { ZkTokenContract } from '@aztec/noir-contracts/types'; +import { PrivateTokenContract } from '@aztec/noir-contracts/types'; const logger = createDebugLogger('aztec:http-rpc-client'); @@ -16,23 +16,23 @@ const INITIAL_BALANCE = 333n; const SECONDARY_AMOUNT = 33n; /** - * Deploys the ZK Token contract. + * Deploys the Private Token contract. * @param owner - The address that the initial balance will belong to. - * @returns An Aztec Contract object with the zk token's ABI. + * @returns An Aztec Contract object with the private token's ABI. */ async function deployZKContract(owner: AztecAddress) { logger('Deploying L2 contract...'); - const tx = ZkTokenContract.deploy(aztecRpcClient, INITIAL_BALANCE, owner).send(); + const tx = PrivateTokenContract.deploy(aztecRpcClient, INITIAL_BALANCE, owner).send(); const receipt = await tx.getReceipt(); - const contract = await ZkTokenContract.create(receipt.contractAddress!, wallet); + const contract = await PrivateTokenContract.create(receipt.contractAddress!, wallet); await tx.isMined(); logger('L2 contract deployed'); return contract; } /** - * Gets a user's balance from a ZK Token contract. - * @param contract - The ZK Token contract. + * Gets a user's balance from a Private Token contract. + * @param contract - The Private Token contract. * @param ownerAddress - Balance owner's Aztec Address. * @returns The owner's current balance of the token. */ diff --git a/yarn-project/aztec.js/src/abis/ecdsa_account_contract.json b/yarn-project/aztec.js/src/abis/ecdsa_account_contract.json index a1ec84c1883..0009266f685 100644 --- a/yarn-project/aztec.js/src/abis/ecdsa_account_contract.json +++ b/yarn-project/aztec.js/src/abis/ecdsa_account_contract.json @@ -84,7 +84,7 @@ } ], "returnTypes": [], - "bytecode": "H4sIAAAAAAAA/+1dZ3QcVxV+kmy5Ow5xt2wV9/6eiiW5yr13COmJZa8cgxuO7MQhkN5774XQe+gdQui9lxNCCCGEEEIIIfCTw1z7jv10WWl3dr/ZnXuy75x37l7N6u73fW/Km5k7d9aXGfNfc7QFH0150Hvx59DvLfxK4Q8Nel/PHyb84cIfIfyRwh8l/NHCHyP8KuGPFf444VcLv0b4tcKvE/544U8Q/kThTxL+ZOFPEf5U4U8T/nThzxD+TOHPEv5s4VvhO+HXC7+BfVovTmL9qNF6MIzHewSP6ygevzE8TmN5PKr5/2pZ3/Gs40TWazLrMpX5T2eeM5nPbMbtGF+Dh69R4G0S/hzhNwu/Rfitwp8r/HnCny/8BcJfKPxFwm8T/mLhLxH+UuEvE/5y4a8Q/krhrxL+auGvEf5a4a8T/nrhbxD+RuFvEv5m4W8R/lZzfH2kdbDGHG20HjTxeDfzuLby+M3jcVrA47GIdV/M+i5lHZezXitZl9XMfy3zXM98NjLuzYxvK+OrNF23D9rXDmM7nO0ItiPZjmI7mu0YtlVsx7Idx7aabQ3bWrZ1bMezncB2IttJbCezncJ2KttpbKezncF2JttZbGeztWwd23q2Dd7/vzHob0qjTSN/p4ntHLbNbFvYtrKdy3Ye2/lsF7BdyHYR2za2i9kuYbuU7TK2y9muYLuS7Sq2q9muYbuW7Tq269luYLuR7Sa2m9luYbvV0+bkoL/ZdG1lbNvYNtg5jY2p5vqUa3DbbH1re0uTbWxqn9PiWlxTS9OO+paGhlRLY0tza3trs211jQ0p19HU2tBhj7ZTvFg2zxYnzlOV4DxNCc7TleA8QwnOM5XgPEsJzrOV4DxHCc5tSnC2K8G5XQnOHUpwpoA4w7nkEI5Hc0yaU53M9hS2p7I9je3pbM9geybbs9iezfYcttvYtrPdznYH25Q5PpfrCPpO07WhNTwXp6ELNQwxnstc6G+7gv4WwaVCcKEYNo82VHLJI9owoMZPmni2pzT62XxYD0+HM8doI4D6/a6w+tlcWY/sDmcO0UYB9Xuq8PrZXFiP7glnxGhjgPr9vjj62aisqzLhjBBtLFC/p4unn43Celw2OLOMVg3U7w/F1c9my7omW5xZRKsF6vdM8fWz2bCui4IzQ7TxQP3+mAz9bCbWE6Li7CHaRKB+zyZHP9sT60m54Owm2mSgfn9Kln62O9ZTcsWZJtpUoH7PJU8/m471tHxwimjTgfr9OZn6Wcl6Rr44vWgzgfo9n1z9rM96FgInR5sN1O8vydbPHmONwhlEc0D9Xki+ftRcPTDWk0D9/qpEP+B1IvcUUL8XlegHvM7hngbq9zcl+gHP090zQP1eUqIf8DzTPQvU7+9K9AOeJ7nngPq9rEQ/4DzfPQ/U7x9K9APOU90LQP1eUaIfcJ7lXgTq908l+gHnCe4loH6vKtEPeJxzLwP1+5cS/YD7afcKUL/XlOgH3M+4V4H6/VuJfsDtxL0G1O8/BdIvX5xvBeoHXGdcofSzeeZfNRpc/lUTcFyHlhV0+82Z9RyDy79qBuo3rKzg+7+cWLcYXP5VK1C/4YXXz+bCeq7B5V/NA+o3ojj62ais5xtc/tUCoH4ji6efjcJ6ockCZ5bRFgH1G1Vc/Wy2rNtMljiziLYYqN/o4utns2G9xETAmSHaUqB+Y5Khn83EepmJiLOHaMuB+lUlRz/bE+sVJgec3URbCdRvbLL0s92xXmVyxJkm2mqgfuOSp59Nx3qNyQOniLYWqF91MvWzkvU6kydOL9p6oH41ydXP+qw3GABOjrYRqF9tsvWzIetNBoQziLYZqF9d8vWj5rYAY/nXnPLVb7wS/YDXidxwoH4TlOgHvM7hRgL1m6hEP+B5uhsN1G+SEv2A55muCqjfZCX6Ac+T3DigflOU6Aec57saoH5TlegHnKe6OqB+05ToB5xnuQlA/aYr0Q84T3CTgPrNUKIf8DjnpgD1m6lEP+B+2k0D6jdLiX7A/YybAdRvthL9gNuJmwXUzxZIv3xx7gaOBXCdcUj9whpZvTke5Zz59W13m641XcvN8drqe4K+13Rt6Hpg+4BjEHIt53j7mMsej9P+oL+N16UK031rA2LqLWJX//9vJLIOGf8pcfW9vD8nqm6WWJSYelRpFieizlM3Xyl6/aQevlbUukQZvlq0ej82cytKHR2bXSt4fRqbfSto3RcbrRWsnoqN3gpSp8Tm1mKv/2Fzb7HW1bD5NWS9imPnFXI+a/NrriEGjOj5YlzPTfCfEvc8gvfnROX5i0WJyZ9PszgReendfKXo+d49fK2oedQZvlq0/GSbuRUl79dm1wqeT2uzbwXNU7XRWsHyP230VpC8Sptbiz1f0ebeYs0DtPk1ZH5dbPPFrQowlseAMQ6c+4E4yzycB7zPA9n2M0ffOUqt3PtbheDWz1setkrvcxsGb1MlXk9L1637ejyM4DuYl5/I/t59nbs6Di89kNrWmdqxYV9nyhcxvAhekSZQmfd3/2J5L+/HK8VyX9hwWR9zXIRjrc1A1HAV6YIb/Fp8wMSzFp+XRlh/zazwxERzMuJ3pI6DTYwDF9cgnRdD3E6Du7UWF+9O/BjFelhAalqonQDykFvmYQw38oNBPxT08z0Og9gW6JBl4zpkVXo8wuYfsmh5L+zvNviHfuPpbdLoZrzfp8NnOKXYmercdLB9967ta1OH041ZRZq4/tRDHmH9cQyXxXqEDO+/+ysZ3Xc/xPZ8ticE/YKgHxY40PkdwI3IXQDEdSEOV8F2SEjMPt63e59Ls5I8Y17IgqLjXmSSPSsh3hfhxyjWWQlSU1p5/SN0XJjjuhAAHjenUQM0zoNKcB4y2ANLKdmulGyXTSsl20WLVkq2ixatLvtYpWQ7W0q2ixqtlGwXLVop2S5atFKy3bG4pWS7DK2UbGcjtVKyXbRopWS7aNFKyXbRopWS7aJFKyXbRYtWSraL1jhMKdkuz+bfRS7nz+8I+jvN8VbFlu4W9+HPfo5VeF/Bz8VKd6f59ZAMN8DjYQTfMBluCPupPbs6l+/dfuDw/s7UjnX7dvo3Evum4Z7upie1Xt7n3ml0o7hy3GhZfyz/+n6Cd/jbfmvzPvf3sAzAYjmy7Q30fivENcCz4XJf64FYHEcSHgYI/qE/ML7fPcJ/UAb+g9LgGFRA/n42kdxu/P1AuCzWzBQ/JrqCxcUGf1CJA+clSnBeqgTnZUpwXq4E5xVKcF6pBOdVSnBerQTnNUpwXqsE53VKcF6vBOcNSnDeiMHZ0VjfGCvOm5ToebMSnLcowXmrEpy3KcF5uxKcdyjBeacSnHcpwXm3Epz3KMF5rxKc9ynBeb8SnA8owfmgEpwPKcH5sBKcj8SEs1zgtPm1IxfVUZzfpYRzOZDzo0o4VwA5v1sJ515Azu9Rwrk3kPN7lXCuBHJ+nxLOHUDO71fC+WIg5w8o4XwJkPMHlXC+FMj5Q0o4Xwbk/GElnC8Hcv6IEs5XADl/VAnnK4GcP6aE81VAzh9Xwnk/kPNjSjhfDeT8CSWcrwFy/qQSztcCOX9KCeddQM6fVsL5OiDnzyjhfD2Q82eVcL4ByPlzSjjfCOT8eSWcbwJy/oISzjcDOX9RCedbgJy/pITzrUDOX1bC+TYg568o4Xw7kPNXlXC+A8j5a0o43wnk/LgSzncBOX9dCee7gZyfUML5HiDnbyjhfC+Q8zeVcL4PyPlbSjjfD+T8bSWcHwBy/o4Szg8COX9XCeeHgJy/p4Tzw0DO31fC+REg5x8o4dwHyPmHSjj3BXL+kRLO/YCcf6yEc38g558o4TwAyPmnSjgPBHL+mRLOg4Ccf66E82Ag518o4XwCkPMvlXAeAuT8KyWcTwRy/rUSzm8Acv6NEs4nATn/NgbOW9mGBQzpmRl6hiR8zR+dL9D8meaTNL8KC7/R8Yj2z7S/ou2X1mcaX+JLL3ChF6/QC1PoRSf0ghJ6sQi9EIRe5EEFEenFGfTCCyoGXhP02qDXBZ1exEAvUKAXH9ALC+hFA/SCACrsTwX5qZA+FcCnwvVUcJ4KxRMZKkBGBdWpYDkVBKdC3lSAmwpnU8FrKlRNBaapMDQVdKZCzFRAOSx8vDjoS4JOhX2pIC8V0qUCuFS4lgrOUqFYKvBKhVmpoCoVQqUCplR4dFPQqdDnFtazhTWlZ8MeDTo9O0TP0tCzJfSsBT17QLn4lJtOudqUu0y5vJTbSrmelPv4WNApN45yxSh3inKJKLeGck0o94JyEejePN2rpnu3dC+T7u3RvS669/N40OnewBNBp2vHdC2Vri3StTa69kTXYujaBJ2r07krncvRuQ3N9WnuS3NBmhvRXIGOnXQsoX0r7Wto26N18X/ogYnhJu4AAA==", + "bytecode": "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", "verificationKey": "0000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f" }, { @@ -152,7 +152,7 @@ } ], "returnTypes": [], - "bytecode": "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", + "bytecode": "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", "verificationKey": "0000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f" } ] diff --git a/yarn-project/aztec.js/src/abis/schnorr_multi_key_account_contract.json b/yarn-project/aztec.js/src/abis/schnorr_multi_key_account_contract.json index beb60713945..0d5b0d3fabd 100644 --- a/yarn-project/aztec.js/src/abis/schnorr_multi_key_account_contract.json +++ b/yarn-project/aztec.js/src/abis/schnorr_multi_key_account_contract.json @@ -140,7 +140,7 @@ } ], "returnTypes": [], - "bytecode": "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", + "bytecode": "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", "verificationKey": "0000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f" } ] diff --git a/yarn-project/aztec.js/src/abis/schnorr_single_key_account_contract.json b/yarn-project/aztec.js/src/abis/schnorr_single_key_account_contract.json index 7c5814b2032..9f2c9eb798f 100644 --- a/yarn-project/aztec.js/src/abis/schnorr_single_key_account_contract.json +++ b/yarn-project/aztec.js/src/abis/schnorr_single_key_account_contract.json @@ -95,7 +95,7 @@ } ], "returnTypes": [], - "bytecode": "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", + "bytecode": "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", "verificationKey": "0000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f" } ] diff --git a/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts b/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts index b219d65fb0a..44457dfa30e 100644 --- a/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts +++ b/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts @@ -4,7 +4,7 @@ import { AztecAddress, Wallet } from '@aztec/aztec.js'; import { DebugLogger } from '@aztec/foundation/log'; import { retryUntil } from '@aztec/foundation/retry'; import { toBigInt } from '@aztec/foundation/serialize'; -import { ChildContract, ZkTokenContract } from '@aztec/noir-contracts/types'; +import { ChildContract, PrivateTokenContract } from '@aztec/noir-contracts/types'; import { AztecRPC, TxStatus } from '@aztec/types'; import { @@ -70,15 +70,15 @@ describe('e2e_2_rpc_servers', () => { await awaitUserSynchronised(wallet, owner); // Then check the balance - const contractWithWallet = await ZkTokenContract.create(tokenAddress, wallet); + const contractWithWallet = await PrivateTokenContract.create(tokenAddress, wallet); const [balance] = await contractWithWallet.methods.getBalance(owner).view({ from: owner }); logger(`Account ${owner} balance: ${balance}`); expect(balance).toBe(expectedBalance); }; - const deployZkTokenContract = async (initialBalance: bigint, owner: AztecAddress) => { - logger(`Deploying ZkToken contract...`); - const tx = ZkTokenContract.deploy(aztecRpcServerA, initialBalance, owner).send(); + const deployPrivateTokenContract = async (initialBalance: bigint, owner: AztecAddress) => { + logger(`Deploying PrivateToken contract...`); + const tx = PrivateTokenContract.deploy(aztecRpcServerA, initialBalance, owner).send(); const receipt = await tx.getReceipt(); await tx.isMined({ interval: 0.1 }); const minedReceipt = await tx.getReceipt(); @@ -93,7 +93,7 @@ describe('e2e_2_rpc_servers', () => { const transferAmount1 = 654n; const transferAmount2 = 323n; - const tokenAddress = await deployZkTokenContract(initialBalance, userA); + const tokenAddress = await deployPrivateTokenContract(initialBalance, userA); // Add account B pub key and partial address to wallet A const [accountBPubKey, accountBPartialAddress] = await aztecRpcServerB.getPublicKeyAndPartialAddress(userB); @@ -102,10 +102,10 @@ describe('e2e_2_rpc_servers', () => { const [accountAPubKey, accountAPartialAddress] = await aztecRpcServerA.getPublicKeyAndPartialAddress(userA); await aztecRpcServerB.addPublicKeyAndPartialAddress(userA, accountAPubKey, accountAPartialAddress); - // Add zkToken to RPC server B + // Add privateToken to RPC server B await aztecRpcServerB.addContracts([ { - abi: ZkTokenContract.abi, + abi: PrivateTokenContract.abi, address: tokenAddress, portalContract: EthAddress.ZERO, }, @@ -118,7 +118,7 @@ describe('e2e_2_rpc_servers', () => { await expectUnencryptedLogsFromLastBlockToBe(aztecNode, ['Balance set in constructor']); // Transfer funds from A to B via RPC server A - const contractWithWalletA = await ZkTokenContract.create(tokenAddress, walletA); + const contractWithWalletA = await PrivateTokenContract.create(tokenAddress, walletA); const txAToB = contractWithWalletA.methods.transfer(transferAmount1, userA, userB).send({ origin: userA }); await txAToB.isMined({ interval: 0.1 }); @@ -133,7 +133,7 @@ describe('e2e_2_rpc_servers', () => { await expectUnencryptedLogsFromLastBlockToBe(aztecNode, ['Coins transferred']); // Transfer funds from B to A via RPC server B - const contractWithWalletB = await ZkTokenContract.create(tokenAddress, walletB); + const contractWithWalletB = await PrivateTokenContract.create(tokenAddress, walletB); const txBToA = contractWithWalletB.methods.transfer(transferAmount2, userB, userA).send({ origin: userB }); await txBToA.isMined({ interval: 0.1 }); diff --git a/yarn-project/end-to-end/src/e2e_aztec_js_browser.test.ts b/yarn-project/end-to-end/src/e2e_aztec_js_browser.test.ts index 0af9376be2c..bbd44ab2621 100644 --- a/yarn-project/end-to-end/src/e2e_aztec_js_browser.test.ts +++ b/yarn-project/end-to-end/src/e2e_aztec_js_browser.test.ts @@ -1,7 +1,7 @@ import * as AztecJs from '@aztec/aztec.js'; import { AztecAddress, PrivateKey } from '@aztec/circuits.js'; import { DebugLogger, createDebugLogger } from '@aztec/foundation/log'; -import { SchnorrSingleKeyAccountContractAbi, ZkTokenContractAbi } from '@aztec/noir-contracts/artifacts'; +import { PrivateTokenContractAbi, SchnorrSingleKeyAccountContractAbi } from '@aztec/noir-contracts/artifacts'; import { Server } from 'http'; import Koa from 'koa'; @@ -108,14 +108,14 @@ conditionalDescribe()('e2e_aztec.js_browser', () => { expect(result).toEqual(account.toString()); }); - it('Deploys ZK Token contract', async () => { + it('Deploys Private Token contract', async () => { const txHash = await page.evaluate( - async (rpcUrl, initialBalance, ZkTokenContractAbi) => { + async (rpcUrl, initialBalance, PrivateTokenContractAbi) => { const { DeployMethod, createAztecRpcClient, mustSucceedFetch } = window.AztecJs; const client = createAztecRpcClient(rpcUrl!, mustSucceedFetch); const owner = (await client.getAccounts())[0]; const publicKey = await client.getPublicKey(owner); - const tx = new DeployMethod(publicKey, client, ZkTokenContractAbi, [33n, owner]).send(); + const tx = new DeployMethod(publicKey, client, PrivateTokenContractAbi, [33n, owner]).send(); await tx.isMined(); // eslint-disable-next-line no-console console.log('Contract Deployed'); @@ -124,7 +124,7 @@ conditionalDescribe()('e2e_aztec.js_browser', () => { }, SANDBOX_URL, initialBalance, - ZkTokenContractAbi, + PrivateTokenContractAbi, ); const txResult = await testClient.getTxReceipt(AztecJs.TxHash.fromString(txHash)); @@ -134,7 +134,7 @@ conditionalDescribe()('e2e_aztec.js_browser', () => { it("Gets the owner's balance", async () => { const result = await page.evaluate( - async (rpcUrl, privateKey, SchnorrSingleKeyAccountContractAbi, contractAddress, ZkTokenContractAbi) => { + async (rpcUrl, privateKey, SchnorrSingleKeyAccountContractAbi, contractAddress, PrivateTokenContractAbi) => { const { Contract, AztecAddress, Fr, PrivateKey, createAztecRpcClient, getAccountWallet, mustSucceedFetch } = window.AztecJs; const client = createAztecRpcClient(rpcUrl!, mustSucceedFetch); @@ -145,7 +145,11 @@ conditionalDescribe()('e2e_aztec.js_browser', () => { PrivateKey.fromString(privateKey!), Fr.ZERO, ); - const contract = await Contract.create(AztecAddress.fromString(contractAddress), ZkTokenContractAbi, wallet); + const contract = await Contract.create( + AztecAddress.fromString(contractAddress), + PrivateTokenContractAbi, + wallet, + ); const [balance] = await contract.methods.getBalance(owner).view({ from: owner }); return balance; }, @@ -153,7 +157,7 @@ conditionalDescribe()('e2e_aztec.js_browser', () => { privKey.toString(), SchnorrSingleKeyAccountContractAbi, contractAddress.toString(), - ZkTokenContractAbi, + PrivateTokenContractAbi, ); logger('Owner balance:', result); expect(result).toEqual(initialBalance); @@ -166,7 +170,7 @@ conditionalDescribe()('e2e_aztec.js_browser', () => { privateKey, contractAddress, transferAmount, - ZkTokenContractAbi, + PrivateTokenContractAbi, SchnorrSingleKeyAccountContractAbi, ) => { const { AztecAddress, Contract, Fr, PrivateKey, createAztecRpcClient, getAccountWallet, mustSucceedFetch } = @@ -182,7 +186,11 @@ conditionalDescribe()('e2e_aztec.js_browser', () => { PrivateKey.fromString(privateKey!), Fr.ZERO, ); - const contract = await Contract.create(AztecAddress.fromString(contractAddress), ZkTokenContractAbi, wallet); + const contract = await Contract.create( + AztecAddress.fromString(contractAddress), + PrivateTokenContractAbi, + wallet, + ); const tx = contract.methods.transfer(transferAmount, owner, receiver).send({ origin: owner }); await tx.isMined(); // eslint-disable-next-line no-console @@ -194,7 +202,7 @@ conditionalDescribe()('e2e_aztec.js_browser', () => { privKey.toString(), contractAddress.toString(), transferAmount, - ZkTokenContractAbi, + PrivateTokenContractAbi, SchnorrSingleKeyAccountContractAbi, ); expect(result).toEqual(transferAmount); diff --git a/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts b/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts index 24f64f5f3ef..6a80c21dd1a 100644 --- a/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts @@ -5,8 +5,8 @@ import { Fr, PrivateKey, getContractDeploymentInfo } from '@aztec/circuits.js'; import { generateFunctionSelector } from '@aztec/foundation/abi'; import { toBufferBE } from '@aztec/foundation/bigint-buffer'; import { DebugLogger } from '@aztec/foundation/log'; -import { EscrowContractAbi, ZkTokenContractAbi } from '@aztec/noir-contracts/artifacts'; -import { EscrowContract, ZkTokenContract } from '@aztec/noir-contracts/types'; +import { EscrowContractAbi, PrivateTokenContractAbi } from '@aztec/noir-contracts/artifacts'; +import { EscrowContract, PrivateTokenContract } from '@aztec/noir-contracts/types'; import { AztecRPC, PublicKey } from '@aztec/types'; import { setup } from './fixtures/utils.js'; @@ -18,7 +18,7 @@ describe('e2e_escrow_contract', () => { let accounts: AztecAddress[]; let logger: DebugLogger; - let zkTokenContract: ZkTokenContract; + let privateTokenContract: PrivateTokenContract; let escrowContract: EscrowContract; let owner: AztecAddress; let recipient: AztecAddress; @@ -28,7 +28,7 @@ describe('e2e_escrow_contract', () => { beforeAll(() => { // Validate transfer selector. If this fails, then make sure to change it in the escrow contract. - const transferAbi = ZkTokenContractAbi.functions.find(f => f.name === 'transfer')!; + const transferAbi = PrivateTokenContractAbi.functions.find(f => f.name === 'transfer')!; const transferSelector = generateFunctionSelector(transferAbi.name, transferAbi.parameters); expect(transferSelector).toEqual(toBufferBE(0xdcd4c318n, 4)); }); @@ -51,9 +51,9 @@ describe('e2e_escrow_contract', () => { .deployed(); logger(`Escrow contract deployed at ${escrowContract.address}`); - // Deploy ZK token contract and mint funds for the escrow contract - zkTokenContract = await ZkTokenContract.deploy(wallet, 100n, escrowContract.address).send().deployed(); - logger(`Token contract deployed at ${zkTokenContract.address}`); + // Deploy Private Token contract and mint funds for the escrow contract + privateTokenContract = await PrivateTokenContract.deploy(wallet, 100n, escrowContract.address).send().deployed(); + logger(`Token contract deployed at ${privateTokenContract.address}`); }, 100_000); afterEach(async () => { @@ -62,7 +62,7 @@ describe('e2e_escrow_contract', () => { }, 30_000); const expectBalance = async (who: AztecAddress, expectedBalance: bigint) => { - const [balance] = await zkTokenContract.methods.getBalance(who).view({ from: who }); + const [balance] = await privateTokenContract.methods.getBalance(who).view({ from: who }); logger(`Account ${who} balance: ${balance}`); expect(balance).toBe(expectedBalance); }; @@ -73,7 +73,7 @@ describe('e2e_escrow_contract', () => { await expectBalance(escrowContract.address, 100n); logger(`Withdrawing funds from token contract to ${recipient}`); - await escrowContract.methods.withdraw(zkTokenContract.address, 30, recipient).send().wait(); + await escrowContract.methods.withdraw(privateTokenContract.address, 30, recipient).send().wait(); await expectBalance(owner, 0n); await expectBalance(recipient, 30n); @@ -82,18 +82,18 @@ describe('e2e_escrow_contract', () => { it('refuses to withdraw funds as a non-owner', async () => { await expect( - escrowContract.methods.withdraw(zkTokenContract.address, 30, recipient).simulate({ origin: recipient }), + escrowContract.methods.withdraw(privateTokenContract.address, 30, recipient).simulate({ origin: recipient }), ).rejects.toThrowError(); }, 60_000); it('moves funds using multiple keys on the same tx (#1010)', async () => { logger(`Minting funds in token contract to ${owner}`); - await zkTokenContract.methods.mint(50, owner).send().wait(); + await privateTokenContract.methods.mint(50, owner).send().wait(); await expectBalance(owner, 50n); const actions = [ - zkTokenContract.methods.transfer(10, owner, recipient).request(), - escrowContract.methods.withdraw(zkTokenContract.address, 20, recipient).request(), + privateTokenContract.methods.transfer(10, owner, recipient).request(), + escrowContract.methods.withdraw(privateTokenContract.address, 20, recipient).request(), ]; await new BatchCall(wallet, actions).send().wait(); diff --git a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts index 40ffa2b5657..9aa69678bcf 100644 --- a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts +++ b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts @@ -3,7 +3,7 @@ import { AztecRPCServer } from '@aztec/aztec-rpc'; import { AztecAddress, Wallet, generatePublicKey, getSchnorrAccount } from '@aztec/aztec.js'; import { PrivateKey } from '@aztec/circuits.js'; import { DebugLogger } from '@aztec/foundation/log'; -import { ZkTokenContract } from '@aztec/noir-contracts/types'; +import { PrivateTokenContract } from '@aztec/noir-contracts/types'; import { AztecRPC, TxStatus } from '@aztec/types'; import { @@ -19,7 +19,7 @@ describe('e2e_multiple_accounts_1_enc_key', () => { const accounts: AztecAddress[] = []; let logger: DebugLogger; - let zkTokenAddress: AztecAddress; + let privateTokenAddress: AztecAddress; const initialBalance = 987n; const numAccounts = 3; @@ -47,12 +47,12 @@ describe('e2e_multiple_accounts_1_enc_key', () => { expect(accountEncryptionPublicKey).toEqual(encryptionPublicKey); } - logger(`Deploying ZK Token...`); - zkTokenAddress = await ZkTokenContract.deploy(wallets[0], initialBalance, accounts[0]) + logger(`Deploying Private Token...`); + privateTokenAddress = await PrivateTokenContract.deploy(wallets[0], initialBalance, accounts[0]) .send() .deployed() .then(c => c.address); - logger(`ZK Token deployed at ${zkTokenAddress}`); + logger(`Private Token deployed at ${privateTokenAddress}`); }, 100_000); afterEach(async () => { @@ -67,7 +67,7 @@ describe('e2e_multiple_accounts_1_enc_key', () => { const owner = accounts[userIndex]; // Then check the balance - const contractWithWallet = await ZkTokenContract.create(zkTokenAddress, wallet); + const contractWithWallet = await PrivateTokenContract.create(privateTokenAddress, wallet); const [balance] = await contractWithWallet.methods.getBalance(owner).view({ from: owner }); logger(`Account ${owner} balance: ${balance}`); expect(balance).toBe(expectedBalance); @@ -84,7 +84,7 @@ describe('e2e_multiple_accounts_1_enc_key', () => { const sender = accounts[senderIndex]; const receiver = accounts[receiverIndex]; - const contractWithWallet = await ZkTokenContract.create(zkTokenAddress, wallets[senderIndex]); + const contractWithWallet = await PrivateTokenContract.create(privateTokenAddress, wallets[senderIndex]); const tx = contractWithWallet.methods.transfer(transferAmount, sender, receiver).send({ origin: sender }); await tx.isMined({ interval: 0.1 }); diff --git a/yarn-project/end-to-end/src/e2e_zk_token_contract.test.ts b/yarn-project/end-to-end/src/e2e_private_token_contract.test.ts similarity index 90% rename from yarn-project/end-to-end/src/e2e_zk_token_contract.test.ts rename to yarn-project/end-to-end/src/e2e_private_token_contract.test.ts index 4b58299099b..f39d935f024 100644 --- a/yarn-project/end-to-end/src/e2e_zk_token_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_private_token_contract.test.ts @@ -2,7 +2,7 @@ import { AztecNodeService } from '@aztec/aztec-node'; import { AztecRPCServer } from '@aztec/aztec-rpc'; import { AztecAddress, Wallet } from '@aztec/aztec.js'; import { DebugLogger } from '@aztec/foundation/log'; -import { ZkTokenContract } from '@aztec/noir-contracts/types'; +import { PrivateTokenContract } from '@aztec/noir-contracts/types'; import { AztecRPC, TxStatus } from '@aztec/types'; import { @@ -11,14 +11,14 @@ import { setup, } from './fixtures/utils.js'; -describe('e2e_zk_token_contract', () => { +describe('e2e_private_token_contract', () => { let aztecNode: AztecNodeService | undefined; let aztecRpcServer: AztecRPC; let wallet: Wallet; let accounts: AztecAddress[]; let logger: DebugLogger; - let contract: ZkTokenContract; + let contract: PrivateTokenContract; beforeEach(async () => { ({ aztecNode, aztecRpcServer, accounts, wallet, logger } = await setup(2)); @@ -39,7 +39,7 @@ describe('e2e_zk_token_contract', () => { const deployContract = async (initialBalance: bigint, owner: AztecAddress) => { logger(`Deploying L2 contract...`); - contract = await ZkTokenContract.deploy(wallet, initialBalance, owner).send().deployed(); + contract = await PrivateTokenContract.deploy(wallet, initialBalance, owner).send().deployed(); logger(`L2 contract deployed at ${contract.address}`); }; @@ -47,7 +47,7 @@ describe('e2e_zk_token_contract', () => { * Milestone 1.3. * https://hackmd.io/AG5rb9DyTRu3y7mBptWauA */ - it('1.3 should deploy zk token contract with initial token minted to the account', async () => { + it('1.3 should deploy private token contract with initial token minted to the account', async () => { const initialBalance = 987n; await deployContract(initialBalance, accounts[0]); await expectBalance(accounts[0], initialBalance); diff --git a/yarn-project/noir-compiler/src/fixtures/test_contract/Nargo.toml b/yarn-project/noir-compiler/src/fixtures/test_contract/Nargo.toml index 0cb398613b8..efbb4441408 100644 --- a/yarn-project/noir-compiler/src/fixtures/test_contract/Nargo.toml +++ b/yarn-project/noir-compiler/src/fixtures/test_contract/Nargo.toml @@ -1,4 +1,5 @@ [package] +name = "" authors = [""] compiler_version = "0.1" diff --git a/yarn-project/noir-compiler/src/fixtures/test_lib/Nargo.toml b/yarn-project/noir-compiler/src/fixtures/test_lib/Nargo.toml index e0b467ce5da..72ac7a481cb 100644 --- a/yarn-project/noir-compiler/src/fixtures/test_lib/Nargo.toml +++ b/yarn-project/noir-compiler/src/fixtures/test_lib/Nargo.toml @@ -1,4 +1,5 @@ [package] +name = "" authors = [""] compiler_version = "0.1" diff --git a/yarn-project/noir-contracts/README.md b/yarn-project/noir-contracts/README.md index 3549d2cb0e1..cb4b8768602 100644 --- a/yarn-project/noir-contracts/README.md +++ b/yarn-project/noir-contracts/README.md @@ -76,13 +76,13 @@ Please note that any example contract set out herein is provided solely for info Alternatively you can run `yarn noir:build CONTRACT1 CONTRACT2...` to build a subset of contracts: ``` - yarn noir:build zk_token public_token + yarn noir:build private_token public_token ``` To view compilation output, including errors, run with the `VERBOSE=1` flag: ``` - VERBOSE=1 yarn noir:build zk_token public_token + VERBOSE=1 yarn noir:build private_token public_token ``` ## Creating a new contract package diff --git a/yarn-project/noir-contracts/scripts/compile.sh b/yarn-project/noir-contracts/scripts/compile.sh index 4e0770431a2..6ad7bd25ed4 100755 --- a/yarn-project/noir-contracts/scripts/compile.sh +++ b/yarn-project/noir-contracts/scripts/compile.sh @@ -37,19 +37,10 @@ build() { cd src/contracts/$CONTRACT_FOLDER rm -f target/* - # If VERBOSE is not set, compile with 'nargo' and redirect standard error (stderr) to /dev/null and standard output (stdout) to /dev/null. # If the compilation fails, rerun the compilation with 'nargo' and show the compiler output. nargo compile --contracts; } -process() { - CONTRACT_NAME=$1 - - cd $ROOT - echo "Copying output for $CONTRACT_NAME" - NODE_OPTIONS=--no-warnings yarn ts-node --esm src/scripts/copy_output.ts $CONTRACT_NAME -} - echo "Using $(nargo --version)" # Build contracts diff --git a/yarn-project/noir-contracts/src/contracts/easy_zk_token_contract/Nargo.toml b/yarn-project/noir-contracts/src/contracts/easy_private_token_contract/Nargo.toml similarity index 87% rename from yarn-project/noir-contracts/src/contracts/easy_zk_token_contract/Nargo.toml rename to yarn-project/noir-contracts/src/contracts/easy_private_token_contract/Nargo.toml index 13c7460240b..78d480cc66b 100644 --- a/yarn-project/noir-contracts/src/contracts/easy_zk_token_contract/Nargo.toml +++ b/yarn-project/noir-contracts/src/contracts/easy_private_token_contract/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "easy_zk_token_contract" +name = "easy_private_token_contract" authors = [""] compiler_version = "0.1" type = "bin" diff --git a/yarn-project/noir-contracts/src/contracts/easy_zk_token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/easy_private_token_contract/src/main.nr similarity index 93% rename from yarn-project/noir-contracts/src/contracts/easy_zk_token_contract/src/main.nr rename to yarn-project/noir-contracts/src/contracts/easy_private_token_contract/src/main.nr index a404def60da..a0cdab38ad8 100644 --- a/yarn-project/noir-contracts/src/contracts/easy_zk_token_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/easy_private_token_contract/src/main.nr @@ -1,7 +1,7 @@ +// docs:start:easy_private_token_contract mod storage; -contract EasyZkToken { - // Libs +contract EasyPrivateToken { use dep::value_note::{ balance_utils, value_note::{ @@ -23,12 +23,13 @@ contract EasyZkToken { use crate::storage::Storage; - // Constructs the contract and sets `initial_supply` which is fully owned by `owner`. + /** + * Initialise the contract's initial state variables. + */ fn constructor( - //*********************************/ - // Should eventually be hidden: + /*********************************/ inputs: PrivateContextInputs, - //*********************************/ + /*********************************/ initial_supply: u120, owner: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { @@ -108,3 +109,4 @@ contract EasyZkToken { note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, preimage) } } +// docs:end:easy_private_token_contract diff --git a/yarn-project/noir-contracts/src/contracts/easy_zk_token_contract/src/storage.nr b/yarn-project/noir-contracts/src/contracts/easy_private_token_contract/src/storage.nr similarity index 60% rename from yarn-project/noir-contracts/src/contracts/easy_zk_token_contract/src/storage.nr rename to yarn-project/noir-contracts/src/contracts/easy_private_token_contract/src/storage.nr index 94a80fcb945..43f6b24fc24 100644 --- a/yarn-project/noir-contracts/src/contracts/easy_zk_token_contract/src/storage.nr +++ b/yarn-project/noir-contracts/src/contracts/easy_private_token_contract/src/storage.nr @@ -1,5 +1,5 @@ +// docs:start:easy_private_token_storage use dep::aztec::state_vars::map::Map; - use dep::easy_private_state::easy_private_state::EasyPrivateUint; struct Storage { @@ -9,7 +9,8 @@ struct Storage { impl Storage { fn init() -> Self { Storage { - balances: Map::new(1, |s| EasyPrivateUint::new(s)), + balances: Map::new(1, |slot| EasyPrivateUint::new(slot)), } } -} \ No newline at end of file +} +// docs:end:easy_private_token_storage diff --git a/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/Nargo.toml b/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/Nargo.toml new file mode 100644 index 00000000000..f833b9612f9 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "example_public_state_increment_contract" +authors = [""] +compiler_version = "0.1" +type = "bin" + +[dependencies] +aztec = { path = "../../../../noir-libs/noir-aztec" } \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/src/main.nr b/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/src/main.nr new file mode 100644 index 00000000000..4f3119f716b --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/src/main.nr @@ -0,0 +1,48 @@ +mod storage; + +contract ExamplePublicStateIncrement { + use dep::aztec::abi; + use dep::aztec::abi::PrivateContextInputs; + use dep::aztec::abi::PublicContextInputs; + use dep::aztec::context::Context; + use dep::aztec::oracle::logs::emit_unencrypted_log; + use dep::aztec::types::point::Point; + use crate::storage::Storage; + use dep::aztec::state_vars::{ + type_serialisation::u32_serialisation::{ + U32SerialisationMethods, + U32_SERIALISED_LEN, + }, + }; + + // call initialise_a(); + fn constructor( + inputs: PrivateContextInputs, + ) -> distinct pub abi::PrivateCircuitPublicInputs { + let mut context = Context::new(inputs, 0); + + let initialise_a_function_selector: Field = 1234; + let _return_values = context.call_public_function_no_args(context.this_address(), initialise_a_function_selector); + + context.finish() + } + + // a = 100; + open internal fn initialise_a( + _inputs: PublicContextInputs, + ) { + let storage = Storage::init(); + storage.a.write(100); + } + + // a += b; + open fn increment_a( + _inputs: PublicContextInputs, + b: Field, + ) { + let storage = Storage::init(); + let mut a = storage.a.read(); + a += b; + storage.a.write(a); + } +} diff --git a/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/src/storage.nr b/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/src/storage.nr new file mode 100644 index 00000000000..70c3495d60e --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/src/storage.nr @@ -0,0 +1,25 @@ +// docs:start:PublicState +use dep::aztec::state_vars::{ + // highlight-start:PublicState + public_state::PublicState, + type_serialisation::field_serialisation::{ + FieldSerialisationMethods, + FIELD_SERIALISED_LEN, + }, + // highlight-end:PublicState +}; + +struct Storage { + // highlight-next-line:PublicState + a: PublicState, +} + +impl Storage { + fn init() -> Self { + Storage { + // highlight-next-line:PublicState + a: PublicState::new(1, FieldSerialisationMethods), + } + } +} +// docs:end:PublicState \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/non_native_token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/non_native_token_contract/src/main.nr index b13639921fd..b47f6895823 100644 --- a/yarn-project/noir-contracts/src/contracts/non_native_token_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/non_native_token_contract/src/main.nr @@ -201,7 +201,7 @@ contract NonNativeToken { // Transfers `amount` of tokens from `sender`'s private balance to a `recipient`. - // Note: Copied from ZkToken + // Note: Copied from PrivateToken fn transfer( //*********************************/ // Should eventually be hidden: diff --git a/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr index 49577f87b8e..b78fd50d568 100644 --- a/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr @@ -24,10 +24,10 @@ contract Parent { ])); // Call the target private function - let callStackItem = context.call_private_function(targetContract, targetSelector, [0]); + let return_values = context.call_private_function(targetContract, targetSelector, [0]); // Copy the return value from the call to this function's return values - let result = callStackItem.public_inputs.return_values[0]; + let result = return_values[0]; context.return_values.push(result); // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. @@ -78,9 +78,9 @@ contract Parent { ])); // Enqueue the first public call - let callStackItem1 = context.call_public_function(targetContract, targetSelector, [targetValue]); + let return_values1 = context.call_public_function(targetContract, targetSelector, [targetValue]); // Enqueue the second public call - let _callStackItem2 = context.call_public_function(targetContract, targetSelector, [callStackItem1.public_inputs.return_values[0]]); + let _return_values2 = context.call_public_function(targetContract, targetSelector, [return_values1[0]]); // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. context.finish() @@ -101,7 +101,7 @@ contract Parent { let pubEntryPointSelector = 3221316504; let thisAddress = inputs.call_context.storage_contract_address; - let _callStackItem = context.call_public_function(thisAddress, pubEntryPointSelector, [targetContract, targetSelector, targetValue]); + let _return_values = context.call_public_function(thisAddress, pubEntryPointSelector, [targetContract, targetSelector, targetValue]); // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. context.finish() @@ -123,9 +123,9 @@ contract Parent { let pubEntryPointSelector = 3221316504; let thisAddress = inputs.call_context.storage_contract_address; - let _callStackItem1 = context.call_public_function(thisAddress, pubEntryPointSelector, [targetContract, targetSelector, targetValue]); + let _return_values1 = context.call_public_function(thisAddress, pubEntryPointSelector, [targetContract, targetSelector, targetValue]); - let _callStackItem2 = context.call_public_function(thisAddress, pubEntryPointSelector, [targetContract, targetSelector, targetValue + 1]); + let _return_values2 = context.call_public_function(thisAddress, pubEntryPointSelector, [targetContract, targetSelector, targetValue + 1]); // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. context.finish() diff --git a/yarn-project/noir-contracts/src/contracts/zk_token_contract/Nargo.toml b/yarn-project/noir-contracts/src/contracts/private_token_airdrop_contract/Nargo.toml similarity index 82% rename from yarn-project/noir-contracts/src/contracts/zk_token_contract/Nargo.toml rename to yarn-project/noir-contracts/src/contracts/private_token_airdrop_contract/Nargo.toml index 11a0f8df61c..9dbab5c7d3c 100644 --- a/yarn-project/noir-contracts/src/contracts/zk_token_contract/Nargo.toml +++ b/yarn-project/noir-contracts/src/contracts/private_token_airdrop_contract/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "zk_token_contract" +name = "private_token_airdrop_contract" authors = [""] compiler_version = "0.1" type = "bin" diff --git a/yarn-project/noir-contracts/src/contracts/zk_token_contract/src/claim_note.nr b/yarn-project/noir-contracts/src/contracts/private_token_airdrop_contract/src/claim_note.nr similarity index 100% rename from yarn-project/noir-contracts/src/contracts/zk_token_contract/src/claim_note.nr rename to yarn-project/noir-contracts/src/contracts/private_token_airdrop_contract/src/claim_note.nr diff --git a/yarn-project/noir-contracts/src/contracts/zk_token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/private_token_airdrop_contract/src/main.nr similarity index 99% rename from yarn-project/noir-contracts/src/contracts/zk_token_contract/src/main.nr rename to yarn-project/noir-contracts/src/contracts/private_token_airdrop_contract/src/main.nr index 0d706de004e..e5b1331ebdb 100644 --- a/yarn-project/noir-contracts/src/contracts/zk_token_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/private_token_airdrop_contract/src/main.nr @@ -1,7 +1,7 @@ mod claim_note; mod storage; -contract ZkToken { +contract PrivateTokenAirdrop { // Libs use dep::value_note::{ balance_utils, diff --git a/yarn-project/noir-contracts/src/contracts/zk_token_contract/src/storage.nr b/yarn-project/noir-contracts/src/contracts/private_token_airdrop_contract/src/storage.nr similarity index 100% rename from yarn-project/noir-contracts/src/contracts/zk_token_contract/src/storage.nr rename to yarn-project/noir-contracts/src/contracts/private_token_airdrop_contract/src/storage.nr diff --git a/yarn-project/noir-contracts/src/contracts/private_token_contract/Nargo.toml b/yarn-project/noir-contracts/src/contracts/private_token_contract/Nargo.toml new file mode 100644 index 00000000000..f787ae48c25 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/private_token_contract/Nargo.toml @@ -0,0 +1,12 @@ +# docs:start:importing-aztec +[package] +name = "private_token_contract" +authors = [""] +compiler_version = "0.1" +type = "bin" + +[dependencies] +# highlight-next-line:importing-aztec +aztec = { path = "../../../../noir-libs/noir-aztec" } +value_note = { path = "../../../../noir-libs/value-note"} +# docs:end:importing-aztec \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/private_token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/private_token_contract/src/main.nr new file mode 100644 index 00000000000..b96fcdc38ac --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/private_token_contract/src/main.nr @@ -0,0 +1,115 @@ +mod storage; + +contract PrivateToken { + // Libs + use dep::value_note::{ + balance_utils, + utils::{send_note, spend_notes}, + value_note::{VALUE_NOTE_LEN, ValueNoteMethods}, + }; + + use dep::aztec::abi; + use dep::aztec::abi::PrivateContextInputs; + use dep::aztec::context::Context; + use dep::aztec::note::{ + note_header::NoteHeader, + utils as note_utils, + }; + use dep::aztec::log::emit_unencrypted_log; + + // docs:start:storage-import + use crate::storage::Storage; + // docs:end:storage-import + + // Constructs the contract and sets `initial_supply` which is fully owned by `owner`. + fn constructor( + //*********************************/ + // Should eventually be hidden: + inputs: PrivateContextInputs, + //*********************************/ + initial_supply: Field, + owner: Field + ) -> distinct pub abi::PrivateCircuitPublicInputs { + let storage = Storage::init(); + let mut context = Context::new(inputs, abi::hash_args([initial_supply, owner])); + + // Insert new note to a set of user notes and emit the newly created encrypted note preimage via oracle call. + let owner_balance = storage.balances.at(owner); + if (initial_supply != 0) { + send_note(&mut context, owner_balance, initial_supply, owner); + emit_unencrypted_log(&mut context, "Balance set in constructor"); + } + + // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. + context.finish() + } + + // Mints `amount` of tokens to `owner`. + fn mint( + //*********************************/ + // Should eventually be hidden: + inputs: PrivateContextInputs, + //*********************************/ + amount: Field, + owner: Field + ) -> distinct pub abi::PrivateCircuitPublicInputs { + let storage = Storage::init(); + let mut context = Context::new(inputs, abi::hash_args([amount, owner])); + + // Insert new note to a set of user notes and emit the newly created encrypted note preimage via oracle call. + let owner_balance = storage.balances.at(owner); + send_note(&mut context, owner_balance, amount, owner); + emit_unencrypted_log(&mut context, "Coins minted"); + + // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel.. + context.finish() + } + + // Transfers `amount` of tokens from `sender` to a `recipient`. + fn transfer( + //*********************************/ + // Should eventually be hidden: + inputs: PrivateContextInputs, + //*********************************/ + amount: Field, + sender: Field, + recipient: Field, + ) -> distinct pub abi::PrivateCircuitPublicInputs { + let storage = Storage::init(); + let mut context = Context::new(inputs, abi::hash_args([amount, sender, recipient])); + + // Pick from the set of sender's notes to spend amount. + let sender_balance = storage.balances.at(sender); + spend_notes(&mut context, sender_balance, amount, sender); + + // Creates new note for the recipient. + let recipient_balance = storage.balances.at(recipient); + send_note(&mut context, recipient_balance, amount, recipient); + + emit_unencrypted_log(&mut context, "Coins transferred"); + + // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel.. + context.finish() + } + + // Helper function to get the balance of a user ("unconstrained" is a Noir alternative of Solidity's "view" function). + unconstrained fn getBalance( + owner: Field, + ) -> Field { + let storage = Storage::init(); + + // Get the set of notes owned by the user. + let owner_balance = storage.balances.at(owner); + + // Return the sum of all notes in the set. + balance_utils::get_balance(owner_balance.storage_slot) + } + + // Computes note hash and nullifier. + // Note 1: Needs to be defined by every contract producing logs. + // Note 2: Having it in all the contracts gives us the ability to compute the note hash and nullifier differently for different kind of notes. + unconstrained fn compute_note_hash_and_nullifier(contract_address: Field, nonce: Field, storage_slot: Field, preimage: [Field; VALUE_NOTE_LEN]) -> [Field; 4] { + let note_header = NoteHeader { contract_address, nonce, storage_slot }; + note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, preimage) + } +} diff --git a/yarn-project/noir-contracts/src/contracts/private_token_contract/src/storage.nr b/yarn-project/noir-contracts/src/contracts/private_token_contract/src/storage.nr new file mode 100644 index 00000000000..52fcd691490 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/private_token_contract/src/storage.nr @@ -0,0 +1,26 @@ +use dep::aztec::state_vars::{ + map::Map, + set::Set +}; +use dep::value_note::value_note::{ + ValueNote, + ValueNoteMethods, + VALUE_NOTE_LEN, +}; + +// docs:start:storage-declaration +// highlight-next-line:storage-declaration +struct Storage { + // maps an aztec address to its balance + balances: Map>, +} + +// highlight-next-line:storage-declaration +impl Storage { + fn init() -> Self { + Storage { + balances: Map::new(1, |slot| Set::new(slot, ValueNoteMethods)), + } + } +} +// docs:end:storage-declaration diff --git a/yarn-project/noir-contracts/src/contracts/public_token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/public_token_contract/src/main.nr index 827681f98d6..043562e7171 100644 --- a/yarn-project/noir-contracts/src/contracts/public_token_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/public_token_contract/src/main.nr @@ -6,7 +6,6 @@ contract PublicToken { use dep::aztec::abi::PublicContextInputs; use dep::aztec::context::Context; use dep::aztec::oracle::logs::emit_unencrypted_log; - use dep::aztec::types::point::Point; use crate::storage::Storage; // Constructs the contract. diff --git a/yarn-project/noir-contracts/src/contracts/public_token_contract/src/storage.nr b/yarn-project/noir-contracts/src/contracts/public_token_contract/src/storage.nr index 79135907caa..f5c2a4f61ce 100644 --- a/yarn-project/noir-contracts/src/contracts/public_token_contract/src/storage.nr +++ b/yarn-project/noir-contracts/src/contracts/public_token_contract/src/storage.nr @@ -1,17 +1,25 @@ -use dep::aztec::state_vars::map::Map; -use dep::aztec::state_vars::public_state::PublicState; -use dep::aztec::state_vars::type_serialisation::field_serialisation::FieldSerialisationMethods; -use dep::aztec::state_vars::type_serialisation::field_serialisation::FIELD_SERIALISED_LEN; +// docs:start:PublicState +use dep::aztec::state_vars::{ + map::Map, + // highlight-start:PublicState + public_state::PublicState, + type_serialisation::field_serialisation::{ + FieldSerialisationMethods, + FIELD_SERIALISED_LEN, + }, + // highlight-end:PublicState +}; struct Storage { + // highlight-next-line:PublicState balances: Map>, } - impl Storage { fn init() -> Self { Storage { balances: Map::new(1, |slot| PublicState::new(slot, FieldSerialisationMethods)), } } -} \ No newline at end of file +} +// docs:end:PublicState \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/main.nr index 7d63646ce21..bdb6b086a9d 100644 --- a/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/main.nr @@ -63,14 +63,14 @@ contract Uniswap { // inputAsset.withdraw(inputAmount, sender, recipient=l1UniswapPortal, callerOnL1=l1UniswapPortal) // only uniswap portal can call this (done to safeguard ordering of message consumption) // ref: https://docs.aztec.network/aztec/how-it-works/l1-l2-messaging#designated-caller - let callStackItem = context.call_private_function(inputAsset, withdrawFnSelector, [ + let return_values = context.call_private_function(inputAsset, withdrawFnSelector, [ inputAmount, sender, l1UniswapPortal, l1UniswapPortal, ]); - let result = callStackItem.public_inputs.return_values[0]; + let result = return_values[0]; context.return_values.push(result); // Send the swap message to L1 portal diff --git a/yarn-project/noir-contracts/src/scripts/compile.sh b/yarn-project/noir-contracts/src/scripts/compile.sh index 7c91f92d3bd..99500bb4de9 100755 --- a/yarn-project/noir-contracts/src/scripts/compile.sh +++ b/yarn-project/noir-contracts/src/scripts/compile.sh @@ -2,60 +2,15 @@ # Example: -# If you've compiled Noir from source: -# ./compile.sh --nargo-path=path/to/nargo --verbose zk_token ecdsa_account -# yarn noir:build --nargo-path=path/to/nargo zk_token ecdsa_account - -# If nargo is installed properly in your PATH: -# yarn noir:build zk_token ecdsa_account +# ./compile.sh private_token ecdsa_account +# or +# yarn noir:build private_token ecdsa_account # Enable strict mode: # Exit on error (set -e), treat unset variables as an error (set -u), # and propagate the exit status of the first failing command in a pipeline (set -o pipefail). set -euo pipefail; -ROOT=$(pwd) -NARGO_COMMAND="nargo" # Default nargo command - -# Function to display script usage -usage() { - echo "Usage: $0 [--nargo-path=] [--verbose] CONTRACT_NAME [CONTRACT_NAME...]" - echo "Arguments:" - echo " --nargo-path= Specify the path to the 'nargo' executable (optional)." - echo " --verbose Enable verbose compilation output (optional)." - echo " CONTRACT_NAME Name of the contract(s) to compile and process (omitting the '_contract' suffix)." - exit 1 -} - -# Parse command-line arguments -for arg in "$@"; do - case $arg in - --nargo-path=*) # Optional. - NARGO_COMMAND="${arg#*=}" # Extract the value after '--nargo-path=' - NARGO_COMMAND=$(eval echo "$NARGO_COMMAND") # Expand tilde (~) in the path to be the home directory (for example) - shift # Move to the next command-line argument - ;; - --verbose) # Optional. - # Set the VERBOSE environment variable to enable verbose mode - export VERBOSE=1 - shift # Move to the next command-line argument - ;; - *) - # If an unrecognized argument is provided, we assume it is a CONTRACT_NAME - # and break out of the loop to start processing the contracts. - break - ;; - esac -done - -# Check if at least one CONTRACT_NAME is provided, if not, display usage information. -if [ $# -eq 0 ]; then - usage - exit 0 -fi - -echo "Using $($NARGO_COMMAND --version)" - # Run build scripts ./scripts/compile.sh "$@" ./scripts/types.sh "$@" \ No newline at end of file diff --git a/yarn-project/noir-libs/noir-aztec/src/abi.nr b/yarn-project/noir-libs/noir-aztec/src/abi.nr index c5c7ca7c75f..65c96c3df59 100644 --- a/yarn-project/noir-libs/noir-aztec/src/abi.nr +++ b/yarn-project/noir-libs/noir-aztec/src/abi.nr @@ -32,6 +32,55 @@ use crate::oracle::debug_log; use crate::types::vec::BoundedVec; use crate::types::point::Point; +struct PrivateGlobalVariables { + chain_id: Field, + version: Field, +} + +impl PrivateGlobalVariables { + fn serialize(self) -> [Field; 2] { + [self.chain_id, self.version] + } +} + +struct PublicGlobalVariables { + chain_id: Field, + version: Field, + block_number: Field, + timestamp: Field, +} + +impl PublicGlobalVariables { + fn serialize(self) -> [Field; 4] { + [self.chain_id, self.version, self.block_number, self.timestamp] + } +} + +struct ContractDeploymentData { + deployer_public_key: Point, + constructor_vk_hash : Field, + function_tree_root : Field, + contract_address_salt : Field, + portal_contract_address : Field, +} + +impl ContractDeploymentData { + fn serialize(self) -> [Field; CONTRACT_DEPLOYMENT_DATA_LENGTH] { + [ + self.deployer_public_key.x, + self.deployer_public_key.y, + self.constructor_vk_hash, + self.function_tree_root, + self.contract_address_salt, + self.portal_contract_address, + ] + } + + fn hash(self) -> Field { + dep::std::hash::pedersen_with_separator(self.serialize(), GENERATOR_INDEX__CONTRACT_DEPLOYMENT_DATA)[0] + } +} + // PrivateContextInputs are expected to be provided to each private function struct PrivateContextInputs { call_context : CallContext, @@ -102,55 +151,6 @@ fn empty_commitment_trees_roots() -> CommitmentTreesRoots { CommitmentTreesRoots{ private_data_tree_root: 0, nullifier_tree_root: 0, contract_tree_root: 0, l1_to_l2_messages_tree_root: 0, blocks_tree_root: 0 } } -struct ContractDeploymentData { - deployer_public_key: Point, - constructor_vk_hash : Field, - function_tree_root : Field, - contract_address_salt : Field, - portal_contract_address : Field, -} - -impl ContractDeploymentData { - fn serialize(self) -> [Field; CONTRACT_DEPLOYMENT_DATA_LENGTH] { - [ - self.deployer_public_key.x, - self.deployer_public_key.y, - self.constructor_vk_hash, - self.function_tree_root, - self.contract_address_salt, - self.portal_contract_address, - ] - } - - fn hash(self) -> Field { - dep::std::hash::pedersen_with_separator(self.serialize(), GENERATOR_INDEX__CONTRACT_DEPLOYMENT_DATA)[0] - } -} - -struct PrivateGlobalVariables { - chain_id: Field, - version: Field, -} - -impl PrivateGlobalVariables { - fn serialize(self) -> [Field; 2] { - [self.chain_id, self.version] - } -} - -struct PublicGlobalVariables { - chain_id: Field, - version: Field, - block_number: Field, - timestamp: Field, -} - -impl PublicGlobalVariables { - fn serialize(self) -> [Field; 4] { - [self.chain_id, self.version, self.block_number, self.timestamp] - } -} - struct FunctionData { function_selector: Field, is_internal: bool, diff --git a/yarn-project/noir-libs/noir-aztec/src/context.nr b/yarn-project/noir-libs/noir-aztec/src/context.nr index 0b1c41ad28b..3ef7b4ce02f 100644 --- a/yarn-project/noir-libs/noir-aztec/src/context.nr +++ b/yarn-project/noir-libs/noir-aztec/src/context.nr @@ -96,6 +96,26 @@ impl Context { } } + fn msg_sender(self) -> Field { + self.inputs.call_context.msg_sender + } + + fn this_address(self) -> Field { + self.inputs.call_context.storage_contract_address + } + + fn this_portal_address(self) -> Field { + self.inputs.call_context.portal_contract_address + } + + fn chain_id(self) -> Field { + self.inputs.private_global_variables.chain_id + } + + fn version(self) -> Field { + self.inputs.private_global_variables.version + } + fn finish(self) -> abi::PrivateCircuitPublicInputs { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) let encrypted_logs_hash = [0; NUM_FIELDS_PER_SHA256]; @@ -165,18 +185,26 @@ impl Context { contract_address: Field, function_selector: Field, args: [Field; ARGS_COUNT] - ) -> PrivateCallStackItem { + ) -> [Field; RETURN_VALUES_LENGTH] { let args_hash = hash_args(args); assert(args_hash == arguments::pack_arguments(args)); self.call_private_function_with_packed_args(contract_address, function_selector, args_hash) } + fn call_private_function_no_args( + &mut self, + contract_address: Field, + function_selector: Field, + ) -> [Field; RETURN_VALUES_LENGTH] { + self.call_private_function_with_packed_args(contract_address, function_selector, 0) + } + fn call_private_function_with_packed_args( &mut self, contract_address: Field, function_selector: Field, args_hash: Field - ) -> PrivateCallStackItem { + ) -> [Field; RETURN_VALUES_LENGTH] { let fields = call_private_function_internal( contract_address, function_selector, @@ -253,7 +281,7 @@ impl Context { self.private_call_stack.push(item.hash()); - item + item.public_inputs.return_values } fn call_public_function( @@ -261,18 +289,26 @@ impl Context { contract_address: Field, function_selector: Field, args: [Field; ARGS_COUNT] - ) -> PublicCallStackItem { + ) -> [Field; RETURN_VALUES_LENGTH] { let args_hash = hash_args(args); assert(args_hash == arguments::pack_arguments(args)); self.call_public_function_with_packed_args(contract_address, function_selector, args_hash) } + fn call_public_function_no_args( + &mut self, + contract_address: Field, + function_selector: Field, + ) -> [Field; RETURN_VALUES_LENGTH] { + self.call_public_function_with_packed_args(contract_address, function_selector, 0) + } + fn call_public_function_with_packed_args( &mut self, contract_address: Field, function_selector: Field, args_hash: Field - ) -> PublicCallStackItem { + ) -> [Field; RETURN_VALUES_LENGTH] { let fields = enqueue_public_function_call_internal( contract_address, function_selector, @@ -330,6 +366,6 @@ impl Context { self.public_call_stack.push(item.hash()); - item + item.public_inputs.return_values } } diff --git a/yarn-project/noir-libs/noir-aztec/src/oracle/arguments.nr b/yarn-project/noir-libs/noir-aztec/src/oracle/arguments.nr index 544bea7b773..b8ab424835c 100644 --- a/yarn-project/noir-libs/noir-aztec/src/oracle/arguments.nr +++ b/yarn-project/noir-libs/noir-aztec/src/oracle/arguments.nr @@ -1,6 +1,7 @@ #[oracle(packArguments)] fn pack_arguments_oracle(_args: [Field; N]) -> Field {} +// TODO: explain what this does. unconstrained fn pack_arguments(args: [Field; N]) -> Field { pack_arguments_oracle(args) } diff --git a/yarn-project/noir-libs/noir-aztec/src/state_vars/public_state.nr b/yarn-project/noir-libs/noir-aztec/src/state_vars/public_state.nr index 018cdb19933..b4cae24ecfa 100644 --- a/yarn-project/noir-libs/noir-aztec/src/state_vars/public_state.nr +++ b/yarn-project/noir-libs/noir-aztec/src/state_vars/public_state.nr @@ -2,13 +2,13 @@ use crate::oracle::storage::storage_read; use crate::oracle::storage::storage_write; use crate::state_vars::type_serialisation::TypeSerialisationInterface; -struct PublicState { +struct PublicState { storage_slot: Field, - serialisation_methods: TypeSerialisationInterface, + serialisation_methods: TypeSerialisationInterface, } -impl PublicState { - fn new(storage_slot: Field, serialisation_methods: TypeSerialisationInterface) -> Self { +impl PublicState { + fn new(storage_slot: Field, serialisation_methods: TypeSerialisationInterface) -> Self { PublicState { storage_slot, serialisation_methods } } diff --git a/yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation.nr b/yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation.nr index f288e4a87e5..d76e52102a5 100644 --- a/yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation.nr +++ b/yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation.nr @@ -1,4 +1,5 @@ mod field_serialisation; +mod u32_serialisation; /** * Before Noir supports traits, a way of specifying the serialisation and deserialisation methods for a type. diff --git a/yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation/u32_serialisation.nr b/yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation/u32_serialisation.nr new file mode 100644 index 00000000000..21178a167f2 --- /dev/null +++ b/yarn-project/noir-libs/noir-aztec/src/state_vars/type_serialisation/u32_serialisation.nr @@ -0,0 +1,16 @@ +use crate::state_vars::type_serialisation::TypeSerialisationInterface; + +global U32_SERIALISED_LEN: Field = 1; + +fn deserialiseU32(fields: [Field; U32_SERIALISED_LEN]) -> u32 { + fields[0] as u32 +} + +fn serialiseU32(value: u32) -> [Field; U32_SERIALISED_LEN] { + [value as Field] +} + +global U32SerialisationMethods = TypeSerialisationInterface { + deserialise: deserialiseU32, + serialise: serialiseU32, +}; \ No newline at end of file diff --git a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts index bf06fc09ccf..0e5cee3f6f4 100644 --- a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts +++ b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts @@ -401,8 +401,8 @@ describe('sequencer/solo_block_builder', () => { expect(l2Block.number).toEqual(blockNumber); }, 20_000); - // This test specifically tests nullifier values which previously caused e2e_zk_token test to fail - it('e2e_zk_token edge case regression test on nullifier values', async () => { + // This test specifically tests nullifier values which previously caused e2e_private_token test to fail + it('e2e_private_token edge case regression test on nullifier values', async () => { const simulator = await WasmRollupCircuitSimulator.new(); const prover = new EmptyRollupProver(); builder = new SoloBlockBuilder(builderDb, vks, simulator, prover);