From 82f5f03acdaee8e23b149369cb9e6f89f257b757 Mon Sep 17 00:00:00 2001 From: Maddiaa <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 31 Jan 2024 01:16:27 +0000 Subject: [PATCH 01/20] fix: bb build (#4317) fix dirty merge after https://github.com/AztecProtocol/aztec-packages/pull/3718 --- barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 9fe3ff7cd4c..db98486ddbb 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -192,7 +192,7 @@ class GoblinMockCircuits { verifier1.verify_proof(function_accum.proof); // Execute recursive aggregation of previous kernel proof if one exists - if (!prev_kernel_accum.proof.proof_data.empty()) { + if (!prev_kernel_accum.proof.empty()) { RecursiveVerifier verifier2{ &builder, prev_kernel_accum.verification_key }; verifier2.verify_proof(prev_kernel_accum.proof); } From cdf1baf017c4833bc621ba4dd3681dd1a745e259 Mon Sep 17 00:00:00 2001 From: Maddiaa <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 31 Jan 2024 01:39:09 +0000 Subject: [PATCH 02/20] feat(avm): keep history of reads and writes in journal (#4315) fixes: https://github.com/AztecProtocol/aztec-packages/issues/3999 --- .../src/avm/journal/journal.test.ts | 38 +++++- .../acir-simulator/src/avm/journal/journal.ts | 123 +++++++++++++++--- .../src/avm/opcodes/external_calls.test.ts | 6 +- 3 files changed, 137 insertions(+), 30 deletions(-) diff --git a/yarn-project/acir-simulator/src/avm/journal/journal.test.ts b/yarn-project/acir-simulator/src/avm/journal/journal.test.ts index 58b0b3345b9..1588712e1c7 100644 --- a/yarn-project/acir-simulator/src/avm/journal/journal.test.ts +++ b/yarn-project/acir-simulator/src/avm/journal/journal.test.ts @@ -29,7 +29,7 @@ describe('journal', () => { journal.writeStorage(contractAddress, key, value); const journalUpdates: JournalData = journal.flush(); - expect(journalUpdates.storageWrites.get(contractAddress.toBigInt())?.get(key.toBigInt())).toEqual(value); + expect(journalUpdates.currentStorageValue.get(contractAddress.toBigInt())?.get(key.toBigInt())).toEqual(value); }); it('When reading from storage, should check the parent first', async () => { @@ -61,7 +61,7 @@ describe('journal', () => { expect(cachedResult).toEqual(cachedValue); }); - it('When reading from storage, should check the cache first', async () => { + it('When reading from storage, should check the cache first, and be appended to read/write journal', async () => { // Store a different value in storage vs the cache, and make sure the cache is returned const contractAddress = new Fr(1); const key = new Fr(2); @@ -80,6 +80,16 @@ describe('journal', () => { // Get the storage value const cachedResult = await journal.readStorage(contractAddress, key); expect(cachedResult).toEqual(cachedValue); + + // We expect the journal to store the access in [storedVal, cachedVal] - [time0, time1] + const { storageReads, storageWrites }: JournalData = journal.flush(); + const contractReads = storageReads.get(contractAddress.toBigInt()); + const keyReads = contractReads?.get(key.toBigInt()); + expect(keyReads).toEqual([storedValue, cachedValue]); + + const contractWrites = storageWrites.get(contractAddress.toBigInt()); + const keyWrites = contractWrites?.get(key.toBigInt()); + expect(keyWrites).toEqual([cachedValue]); }); }); @@ -127,17 +137,19 @@ describe('journal', () => { const logsT1 = [new Fr(3), new Fr(4)]; journal.writeStorage(contractAddress, key, value); + await journal.readStorage(contractAddress, key); journal.writeNoteHash(commitment); journal.writeLog(logs); journal.writeL1Message(logs); journal.writeNullifier(commitment); const journal1 = new AvmJournal(journal.hostStorage, journal); - journal.writeStorage(contractAddress, key, valueT1); - journal.writeNoteHash(commitmentT1); - journal.writeLog(logsT1); - journal.writeL1Message(logsT1); - journal.writeNullifier(commitmentT1); + journal1.writeStorage(contractAddress, key, valueT1); + await journal1.readStorage(contractAddress, key); + journal1.writeNoteHash(commitmentT1); + journal1.writeLog(logsT1); + journal1.writeL1Message(logsT1); + journal1.writeNullifier(commitmentT1); journal1.mergeWithParent(); @@ -147,6 +159,18 @@ describe('journal', () => { // Check that the UTXOs are merged const journalUpdates: JournalData = journal.flush(); + + // Check storage reads order is preserved upon merge + // We first read value from t0, then value from t1 + const contractReads = journalUpdates.storageReads.get(contractAddress.toBigInt()); + const slotReads = contractReads?.get(key.toBigInt()); + expect(slotReads).toEqual([value, valueT1]); + + // We first write value from t0, then value from t1 + const contractWrites = journalUpdates.storageReads.get(contractAddress.toBigInt()); + const slotWrites = contractWrites?.get(key.toBigInt()); + expect(slotWrites).toEqual([value, valueT1]); + expect(journalUpdates.newNoteHashes).toEqual([commitment, commitmentT1]); expect(journalUpdates.newLogs).toEqual([logs, logsT1]); expect(journalUpdates.newL1Messages).toEqual([logs, logsT1]); diff --git a/yarn-project/acir-simulator/src/avm/journal/journal.ts b/yarn-project/acir-simulator/src/avm/journal/journal.ts index 6168ce2cdf2..699d6b93f00 100644 --- a/yarn-project/acir-simulator/src/avm/journal/journal.ts +++ b/yarn-project/acir-simulator/src/avm/journal/journal.ts @@ -11,8 +11,14 @@ export type JournalData = { newNullifiers: Fr[]; newL1Messages: Fr[][]; newLogs: Fr[][]; + /** contract address -\> key -\> value */ - storageWrites: Map>; + currentStorageValue: Map>; + + /** contract address -\> key -\> value[] (stored in order of access) */ + storageWrites: Map>; + /** contract address -\> key -\> value[] (stored in order of access) */ + storageReads: Map>; }; /** @@ -28,9 +34,9 @@ export class AvmJournal { public readonly hostStorage: HostStorage; // Reading state - must be tracked for vm execution - // contract address -> key -> value - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3999) - private storageReads: Map> = new Map(); + // contract address -> key -> value[] (array stored in order of reads) + private storageReads: Map> = new Map(); + private storageWrites: Map> = new Map(); // New written state private newNoteHashes: Fr[] = []; @@ -41,7 +47,7 @@ export class AvmJournal { private newLogs: Fr[][] = []; // contract address -> key -> value - private storageWrites: Map> = new Map(); + private currentStorageValue: Map> = new Map(); private parentJournal: AvmJournal | undefined; @@ -74,12 +80,15 @@ export class AvmJournal { * @param value - */ public writeStorage(contractAddress: Fr, key: Fr, value: Fr) { - let contractMap = this.storageWrites.get(contractAddress.toBigInt()); + let contractMap = this.currentStorageValue.get(contractAddress.toBigInt()); if (!contractMap) { contractMap = new Map(); - this.storageWrites.set(contractAddress.toBigInt(), contractMap); + this.currentStorageValue.set(contractAddress.toBigInt(), contractMap); } contractMap.set(key.toBigInt(), value); + + // We want to keep track of all performed writes in the journal + this.journalWrite(contractAddress, key, value); } /** @@ -90,17 +99,52 @@ export class AvmJournal { * @param key - * @returns current value */ - public readStorage(contractAddress: Fr, key: Fr): Promise { - const cachedValue = this.storageWrites.get(contractAddress.toBigInt())?.get(key.toBigInt()); - if (cachedValue) { - return Promise.resolve(cachedValue); + public async readStorage(contractAddress: Fr, key: Fr): Promise { + // - We first try this journal's storage cache ( if written to before in this call frame ) + // - Then we try the parent journal's storage cache ( if it exists ) ( written to earlier in this block ) + // - Finally we try the host storage ( a trip to the database ) + + // Do not early return as we want to keep track of reads in this.storageReads + let value = this.currentStorageValue.get(contractAddress.toBigInt())?.get(key.toBigInt()); + if (!value && this.parentJournal) { + value = await this.parentJournal?.readStorage(contractAddress, key); } - if (this.parentJournal) { - return this.parentJournal?.readStorage(contractAddress, key); + if (!value) { + value = await this.hostStorage.publicStateDb.storageRead(contractAddress, key); } - return this.hostStorage.publicStateDb.storageRead(contractAddress, key); + + this.journalRead(contractAddress, key, value); + return Promise.resolve(value); } + /** + * We want to keep track of all performed reads in the journal + * This information is hinted to the avm circuit + + * @param contractAddress - + * @param key - + * @param value - + */ + journalUpdate(map: Map>, contractAddress: Fr, key: Fr, value: Fr): void { + let contractMap = map.get(contractAddress.toBigInt()); + if (!contractMap) { + contractMap = new Map>(); + map.set(contractAddress.toBigInt(), contractMap); + } + + let accessArray = contractMap.get(key.toBigInt()); + if (!accessArray) { + accessArray = new Array(); + contractMap.set(key.toBigInt(), accessArray); + } + accessArray.push(value); + } + + // Create an instance of journalUpdate that appends to the read array + private journalRead = this.journalUpdate.bind(this, this.storageReads); + // Create an instance of journalUpdate that appends to the writes array + private journalWrite = this.journalUpdate.bind(this, this.storageWrites); + public writeNoteHash(noteHash: Fr) { this.newNoteHashes.push(noteHash); } @@ -131,9 +175,14 @@ export class AvmJournal { this.parentJournal.newNoteHashes = this.parentJournal.newNoteHashes.concat(this.newNoteHashes); this.parentJournal.newL1Messages = this.parentJournal.newL1Messages.concat(this.newL1Messages); this.parentJournal.newNullifiers = this.parentJournal.newNullifiers.concat(this.newNullifiers); + this.parentJournal.newLogs = this.parentJournal.newLogs.concat(this.newLogs); // Merge Public State - mergeContractMaps(this.parentJournal.storageWrites, this.storageWrites); + mergeCurrentValueMaps(this.parentJournal.currentStorageValue, this.currentStorageValue); + + // Merge storage read and write journals + mergeContractJournalMaps(this.parentJournal.storageReads, this.storageReads); + mergeContractJournalMaps(this.parentJournal.storageWrites, this.storageWrites); } /** @@ -147,13 +196,15 @@ export class AvmJournal { newNullifiers: this.newNullifiers, newL1Messages: this.newL1Messages, newLogs: this.newLogs, + currentStorageValue: this.currentStorageValue, + storageReads: this.storageReads, storageWrites: this.storageWrites, }; } } /** - * Merges two contract maps together + * Merges two contract current value together * Where childMap keys will take precedent over the hostMap * The assumption being that the child map is created at a later time * And thus contains more up to date information @@ -161,24 +212,56 @@ export class AvmJournal { * @param hostMap - The map to be merged into * @param childMap - The map to be merged from */ -function mergeContractMaps(hostMap: Map>, childMap: Map>) { +function mergeCurrentValueMaps(hostMap: Map>, childMap: Map>) { for (const [key, value] of childMap) { const map1Value = hostMap.get(key); if (!map1Value) { hostMap.set(key, value); } else { - mergeStorageMaps(map1Value, value); + mergeStorageCurrentValueMaps(map1Value, value); } } } /** - * * @param hostMap - The map to be merge into * @param childMap - The map to be merged from */ -function mergeStorageMaps(hostMap: Map, childMap: Map) { +function mergeStorageCurrentValueMaps(hostMap: Map, childMap: Map) { for (const [key, value] of childMap) { hostMap.set(key, value); } } + +/** + * Merges two contract journalling maps together + * For read maps, we just append the childMap arrays into the host map arrays, as the order is important + * + * @param hostMap - The map to be merged into + * @param childMap - The map to be merged from + */ +function mergeContractJournalMaps(hostMap: Map>, childMap: Map>) { + for (const [key, value] of childMap) { + const map1Value = hostMap.get(key); + if (!map1Value) { + hostMap.set(key, value); + } else { + mergeStorageJournalMaps(map1Value, value); + } + } +} + +/** + * @param hostMap - The map to be merge into + * @param childMap - The map to be merged from + */ +function mergeStorageJournalMaps(hostMap: Map, childMap: Map) { + for (const [key, value] of childMap) { + const readArr = hostMap.get(key); + if (!readArr) { + hostMap.set(key, value); + } else { + readArr?.concat(value); + } + } +} diff --git a/yarn-project/acir-simulator/src/avm/opcodes/external_calls.test.ts b/yarn-project/acir-simulator/src/avm/opcodes/external_calls.test.ts index 1d91c3bc405..50c29128ec5 100644 --- a/yarn-project/acir-simulator/src/avm/opcodes/external_calls.test.ts +++ b/yarn-project/acir-simulator/src/avm/opcodes/external_calls.test.ts @@ -78,10 +78,10 @@ describe('External Calls', () => { expect(retValue).toEqual([new Field(1n), new Field(2n)]); // Check that the storage call has been merged into the parent journal - const { storageWrites } = journal.flush(); - expect(storageWrites.size).toEqual(1); + const { currentStorageValue } = journal.flush(); + expect(currentStorageValue.size).toEqual(1); - const nestedContractWrites = storageWrites.get(addr.toBigInt()); + const nestedContractWrites = currentStorageValue.get(addr.toBigInt()); expect(nestedContractWrites).toBeDefined(); const slotNumber = 1n; From c767662e49fc0347e4f05e61d70755d39ff2019b Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 31 Jan 2024 02:10:10 +0000 Subject: [PATCH 03/20] git subrepo push --branch=master barretenberg subrepo: subdir: "barretenberg" merged: "095410c56" upstream: origin: "https://github.com/AztecProtocol/barretenberg" branch: "master" commit: "095410c56" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- barretenberg/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index 4cdc575e338..dee34a9f1dd 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = a69f05acbfee3094126a55463ebedeca984d0340 - parent = d7e2d9c80262dd4dff714caac575785b3bf14482 + commit = 095410c56b5a2275756f5a123685bce85d3ae779 + parent = cdf1baf017c4833bc621ba4dd3681dd1a745e259 method = merge cmdver = 0.4.6 From 808b4eb21b74df2b352b571f2f93e949036bd626 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 31 Jan 2024 02:10:36 +0000 Subject: [PATCH 04/20] chore: replace relative paths to noir-protocol-circuits --- yarn-project/aztec-nr/aztec/Nargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/aztec-nr/aztec/Nargo.toml b/yarn-project/aztec-nr/aztec/Nargo.toml index fb8ba9b6fd4..8337b780e8a 100644 --- a/yarn-project/aztec-nr/aztec/Nargo.toml +++ b/yarn-project/aztec-nr/aztec/Nargo.toml @@ -5,4 +5,4 @@ compiler_version = ">=0.18.0" type = "lib" [dependencies] -protocol_types = { path = "../../noir-protocol-circuits/src/crates/types" } +protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.21.0", directory="yarn-project/noir-protocol-circuits/src/crates/types" } From 3ca24e08051933084afb0e55d7815d07f69eb0ed Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 31 Jan 2024 02:10:36 +0000 Subject: [PATCH 05/20] git_subrepo.sh: Fix parent in .gitrepo file. [skip ci] --- yarn-project/aztec-nr/.gitrepo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/aztec-nr/.gitrepo b/yarn-project/aztec-nr/.gitrepo index 3d2dd32adf4..c2d459b11e7 100644 --- a/yarn-project/aztec-nr/.gitrepo +++ b/yarn-project/aztec-nr/.gitrepo @@ -9,4 +9,4 @@ commit = 3341a62bc598619709a97972112817766fd3157f method = merge cmdver = 0.4.6 - parent = 6bfa1c5027af83e8afae254eb430e98e425a7d9d + parent = 9a63da31e611af0938913251113a7579858e7671 From bbdad91f5d69a4012acc0e8d986edb01e192ec97 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 31 Jan 2024 02:10:41 +0000 Subject: [PATCH 06/20] git subrepo push --branch=master yarn-project/aztec-nr subrepo: subdir: "yarn-project/aztec-nr" merged: "11a6bb5e9" upstream: origin: "https://github.com/AztecProtocol/aztec-nr" branch: "master" commit: "11a6bb5e9" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- yarn-project/aztec-nr/.gitrepo | 4 ++-- yarn-project/aztec-nr/aztec/Nargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn-project/aztec-nr/.gitrepo b/yarn-project/aztec-nr/.gitrepo index c2d459b11e7..1f67b713a75 100644 --- a/yarn-project/aztec-nr/.gitrepo +++ b/yarn-project/aztec-nr/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/aztec-nr branch = master - commit = 3341a62bc598619709a97972112817766fd3157f + commit = 11a6bb5e9b35778ede20d479f38d38028032a2d0 method = merge cmdver = 0.4.6 - parent = 9a63da31e611af0938913251113a7579858e7671 + parent = 3b68852174cf2b6faa4772716dffe9f7941558f8 diff --git a/yarn-project/aztec-nr/aztec/Nargo.toml b/yarn-project/aztec-nr/aztec/Nargo.toml index 8337b780e8a..fb8ba9b6fd4 100644 --- a/yarn-project/aztec-nr/aztec/Nargo.toml +++ b/yarn-project/aztec-nr/aztec/Nargo.toml @@ -5,4 +5,4 @@ compiler_version = ">=0.18.0" type = "lib" [dependencies] -protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.21.0", directory="yarn-project/noir-protocol-circuits/src/crates/types" } +protocol_types = { path = "../../noir-protocol-circuits/src/crates/types" } From 6af548e369d5d20bcbd08d346f5c6f89b7363f39 Mon Sep 17 00:00:00 2001 From: Cat McGee Date: Wed, 31 Jan 2024 13:53:32 +0600 Subject: [PATCH 07/20] feat(docs): Docs deeper dive into unconstrained functions (#4233) Closes https://github.com/AztecProtocol/dev-rel/issues/140 This is the new text - https://github.com/AztecProtocol/aztec-packages/pull/4233/files#diff-5cb9aa6cb90dbac61cb1828879ea8a227933807363bcf53683e7c7a833e27e0bR75 --------- Co-authored-by: josh crites Co-authored-by: Josh Crites --- docs/docs/developers/contracts/compiling.md | 4 +- docs/docs/developers/contracts/layout.md | 2 +- .../resources/common_patterns/authwit.md | 2 +- .../developers/contracts/syntax/context.mdx | 2 +- .../developers/contracts/syntax/events.md | 4 +- .../developers/contracts/syntax/functions.md | 314 ------------------ .../syntax/functions/calling_functions.md | 132 ++++++++ .../contracts/syntax/functions/constructor.md | 15 + .../syntax/functions/inner_workings.md | 100 ++++++ .../contracts/syntax/functions/main.md | 20 ++ .../contracts/syntax/functions/oracles.md | 23 ++ .../functions/public_private_unconstrained.md | 35 ++ .../contracts/syntax/functions/visibility.md | 25 ++ docs/docs/developers/contracts/syntax/main.md | 2 +- .../contracts/syntax/storage/private_state.md | 4 +- .../aztecnr-getting-started.md | 2 +- docs/docs/developers/getting_started/main.md | 2 +- docs/docs/developers/limitations/main.md | 8 +- .../writing_private_voting_contract.md | 2 +- .../docs/learn/concepts/pxe/acir_simulator.md | 2 +- docs/docs/learn/concepts/pxe/main.md | 2 +- docs/sidebars.js | 51 +-- .../src/client/unconstrained_execution.ts | 2 + 23 files changed, 400 insertions(+), 355 deletions(-) delete mode 100644 docs/docs/developers/contracts/syntax/functions.md create mode 100644 docs/docs/developers/contracts/syntax/functions/calling_functions.md create mode 100644 docs/docs/developers/contracts/syntax/functions/constructor.md create mode 100644 docs/docs/developers/contracts/syntax/functions/inner_workings.md create mode 100644 docs/docs/developers/contracts/syntax/functions/main.md create mode 100644 docs/docs/developers/contracts/syntax/functions/oracles.md create mode 100644 docs/docs/developers/contracts/syntax/functions/public_private_unconstrained.md create mode 100644 docs/docs/developers/contracts/syntax/functions/visibility.md diff --git a/docs/docs/developers/contracts/compiling.md b/docs/docs/developers/contracts/compiling.md index 1351006ed65..58c805006ec 100644 --- a/docs/docs/developers/contracts/compiling.md +++ b/docs/docs/developers/contracts/compiling.md @@ -115,7 +115,7 @@ Read more about interacting with contracts using `aztec.js` [here](../getting_st ### Aztec.nr interfaces -An Aztec.nr contract can [call a function](./syntax/functions.md) in another contract via `context.call_private_function` or `context.call_public_function`. However, this requires manually assembling the function selector and manually serializing the arguments, which is not type-safe. +An Aztec.nr contract can [call a function](./syntax/functions/main.md) in another contract via `context.call_private_function` or `context.call_public_function`. However, this requires manually assembling the function selector and manually serializing the arguments, which is not type-safe. To make this easier, the compiler can generate contract interface structs that expose a convenience method for each function listed in a given contract artifact. These structs are intended to be used from another contract project that calls into the current one. For each contract, two interface structs are generated: one to be used from private functions with a `PrivateContext`, and one to be used from open functions with a `PublicContext`. @@ -209,7 +209,7 @@ impl TokenPublicContextInterface { } ``` -Read more about how to use the Aztec.nr interfaces [here](./syntax/functions.md#contract-interface). +Read more about how to use the Aztec.nr interfaces [here](./syntax/functions/main.md). :::info At the moment, the compiler generates these interfaces from already compiled ABIs, and not from source code. This means that you should not import a generated interface from within the same project as its source contract, or you risk circular references. diff --git a/docs/docs/developers/contracts/layout.md b/docs/docs/developers/contracts/layout.md index 084a3a9c1fc..48fbc9a7030 100644 --- a/docs/docs/developers/contracts/layout.md +++ b/docs/docs/developers/contracts/layout.md @@ -2,7 +2,7 @@ title: Structure --- -A contract is a collection of persistent [state variables](./syntax/storage/main.md), and [functions](./syntax/functions) which may manipulate these variables. Functions and state variables 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 to an external function of the other contract. For anything to happen on the Aztec network, an external function of a contract needs to be called. +A contract is a collection of persistent [state variables](./syntax/storage/main.md), and [functions](./syntax/functions/main.md) which may manipulate these variables. Functions and state variables 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 to an external function of the other contract. For anything to happen on the Aztec network, an external function of a contract needs to be called. # Contract diff --git a/docs/docs/developers/contracts/resources/common_patterns/authwit.md b/docs/docs/developers/contracts/resources/common_patterns/authwit.md index 5700644561b..0858b4cbebb 100644 --- a/docs/docs/developers/contracts/resources/common_patterns/authwit.md +++ b/docs/docs/developers/contracts/resources/common_patterns/authwit.md @@ -11,7 +11,7 @@ description: Developer Documentation to use Authentication Witness for authentic Authentication Witness is a scheme for authentication actions on Aztec, so users can allow third-parties (eg protocols or other users) to execute an action on their behalf. -How it works logically is explained in the [foundational concepts](./../../../../learn/concepts/accounts/authwit.md) but we will do a short recap here. +How it works logically is explained in the [concepts](./../../../../learn/concepts/accounts/authwit.md) but we will do a short recap here. An authentication witness is defined for a specific action, such as allowing a Defi protocol to transfer funds on behalf of the user. An action is here something that could be explained as `A is allowed to perform X operation on behalf of B` and we define it as a hash computed as such: diff --git a/docs/docs/developers/contracts/syntax/context.mdx b/docs/docs/developers/contracts/syntax/context.mdx index b6fca013991..5f6a028dfed 100644 --- a/docs/docs/developers/contracts/syntax/context.mdx +++ b/docs/docs/developers/contracts/syntax/context.mdx @@ -99,7 +99,7 @@ The `args_hash` is the result of pedersen hashing all of a function's inputs. ### Return Values -The return values are a set of values that are returned from an applications execution to be passed to other functions through the kernel. Developers do not need to worry about passing their function return values to the `context` directly as `Aztec.nr` takes care of it for you. See the documentation surrounding `Aztec.nr` [macro expansion](./functions.md#after-expansion) for more details. +The return values are a set of values that are returned from an applications execution to be passed to other functions through the kernel. Developers do not need to worry about passing their function return values to the `context` directly as `Aztec.nr` takes care of it for you. See the documentation surrounding `Aztec.nr` [macro expansion](./functions/inner_workings.md#after-expansion) for more details. return_values : BoundedVec, diff --git a/docs/docs/developers/contracts/syntax/events.md b/docs/docs/developers/contracts/syntax/events.md index 2ccc3c0be38..234e978544f 100644 --- a/docs/docs/developers/contracts/syntax/events.md +++ b/docs/docs/developers/contracts/syntax/events.md @@ -61,7 +61,7 @@ In the future we will allow emitting arbitrary information. (If you currently emit arbitrary information, PXE will fail to decrypt, process and store this data, so it will not be queryable). ::: -To emit encrypted logs first import the `emit_encrypted_log` utility function which wraps an [oracle](./functions.md#oracle-functions): +To emit encrypted logs first import the `emit_encrypted_log` utility function which wraps an [oracle](./functions/oracles.md): #include_code encrypted_import /yarn-project/aztec-nr/address-note/src/address_note.nr rust @@ -95,7 +95,7 @@ They can be emitted by both public and private functions. :::danger - Emitting unencrypted events from private function is a significant privacy leak and it should be considered by the developer whether it is acceptable. -- Unencrypted events are currently **NOT** linked to the contract emitting them, so it is practically a [`debug_log`](./functions.md#a-few-useful-inbuilt-oracles). +- Unencrypted events are currently **NOT** linked to the contract emitting them, so it is practically a [`debug_log`](./functions/oracles.md#a-few-useful-inbuilt-oracles). ::: To emit unencrypted logs first import the `emit_unencrypted_log` utility function inside your contract: diff --git a/docs/docs/developers/contracts/syntax/functions.md b/docs/docs/developers/contracts/syntax/functions.md deleted file mode 100644 index 763f6349cdb..00000000000 --- a/docs/docs/developers/contracts/syntax/functions.md +++ /dev/null @@ -1,314 +0,0 @@ ---- -title: Functions -description: This page covers functions, private and public functions composability, as well as their differences. ---- - -Functions serve as the building blocks of smart contracts. Functions can be either public, ie they can interact with other contracts and the blockchain, or private for internal contract use. Every smart contract also has a private `constructor` function which is called when the contract is deployed. There are also special oracle functions, which can get data from outside of the smart contract. In the context of Aztec, oracles are often used to get user-provided inputs. - -On this page, you’ll learn more about: - -- How function visibility works in Aztec -- A detailed understanding of public, private, and unconstrained functions, and how to write them -- How constructors work and remain private -- The process of calling functions from within the same smart contract and from different contracts, including calling private functions from private functions, public from public, and even private from public -- What oracles and how Aztec smart contracts might use them - -## Visibility - -In Aztec there are multiple different types of visibility that can be applied to functions. Namely we have `data visibility` and `function visibility`. - -### Data Visibility - -Data visibility is used to describe whether the data (or state) used in a function is generally accessible (public) or on a need to know basis (private). Functions with public data visibility are executed by the sequencer, and functions with private data visibility are executed by the user. For more information on why this is the case, see [communication](../../../learn/concepts/communication/public_private_calls/main.md). - -In the following sections, we are going to see how these two "types" co-exists and interact. - -### Function visibility - -This is the kind of visibility you are more used to seeing in Solidity and more traditional programming languages. It is used to describe whether a function is callable from other contracts, or only from within the same contract. - -By default, all functions are callable from other contracts, similarly to the Solidity `public` visibility. To make them only callable from the contract itself, you can mark them as `internal`. Contrary to solidity, we don't have the `external` nor `private` keywords. `external` since it is limited usage when we don't support inheritance, and `private` since we don't support inheritance and it would also be confusing with multiple types of `private`. - -A good place to use `internal` is when you want a private function to be able to alter public state. As mentioned above, private functions cannot do this directly. They are able to call public functions and by making these internal we can ensure that this state manipulating function is only callable from our private function. - -:::danger -Note that non-internal functions could be used directly as an entry-point, which currently means that the `msg_sender` would be `0`, so for now, using address `0` as a burn address is not recommended. -::: - -## Mutability - -Currently, any function is "mutable" in the sense that it might alter state. In the future, we will support static calls, similarly to EVM. A static call is essentially a call that does not alter state (it keeps state static). This is useful for when you want to call a function in a separate contract, but ensure that it cannot alter state, or call other functions that might alter state (such as re-entering). - -Similarly, a special case of a mutating call is the `delegatecall` where the function executed might not be in the same contract as the state being altered. It is at this moment, not certain if `delegatecall`s should become a fully fledged feature. - -:::danger No `staticcall` or `delegatecall` support -While `staticcall` and `delegatecall` both have flags in the call context, they are currently not supported and will not behave as one would expect if usage is attempted. -::: - -## `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 initialize contract state. -- In Aztec terminology, a constructor is always a '`private` function' (i.e. it cannot be a `public` 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. - -An example of a somewhat boring constructor is as follows: - -#include_code empty-constructor /yarn-project/noir-contracts/contracts/test_contract/src/main.nr rust - -Although you can have a constructor that does nothing, you might want to do something with it, such as setting the deployer as an owner. - -#include_code constructor /yarn-project/noir-contracts/contracts/escrow_contract/src/main.nr rust - -:::danger -It is not possible to call public functions from within a constructor. Beware that the compiler will not throw an error if you do, but the execution will fail! -::: - -## `Public` Functions - -A public function is executed by the sequencer and has access to a state model that is very similar to that of the EVM and Ethereum. Even though they work in an EVM-like model for public transactions, they are able to write data into private storage that can be consumed later by a private function. - -To create a public function you can annotate it with the `#[aztec(public)]` attribute. This will make the [public context](./context.mdx#public-context) available within your current function's execution scope. - -#include_code set_minter /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust - -## `Private` Functions - -As alluded to earlier, a private function operates on private information, and is executed by the user. To tell the compiler that this is the kind of function we are creating annotate it with the `#[aztec(private)]` attribute. This will make the [private context](./context.mdx#private-context-broken-down) available within your current function's execution scope. - -#include_code redeem_shield /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust - -## `unconstrained` functions - -Unconstrained functions are an underlying part of Noir - a deeper explanation can be found [here](https://noir-lang.org/docs/noir/syntax/unconstrained). But in short, they are functions which are not directly constrained and therefore should be seen as untrusted! That they are untrusted means that, for security, the developer must make sure to constrain them when used! - -Beyond using them inside your other functions, they are convenient for providing an interface that reads storage, applies logic and returns values to a UI or test. Below is a snippet from exposing the `balance_of_private` function from a token implementation, which allows a user to easily read their balance, similar to the `balanceOf` function in the ERC20 standard. - -#include_code balance_of_private /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust - -:::info -Note, that unconstrained functions can have access to both public and private data when executed on the user's device. This is possible since it is not actually part of the circuits that are executed in contract execution. -::: - -## Oracle functions - -An oracle is something that allows us to get data from the outside world into our contracts. The most widely-known types of oracles in blockchain systems are probably Chainlink price feeds, which allow us to get the price of an asset in USD taking non-blockchain data into account. - -While this is one type of oracle, the more general oracle, allows us to get "some" data into the contract. In the context of oracle functions or oracle calls in Aztec, it can essentially be seen as user-provided arguments, that can be embedded at any point in the circuit, and thus don't need to be an input parameter. - -**Why is this useful? Why don't just pass them as input parameters?** -In the world of EVM, you would just read the values directly from storage and call it a day. However, when we are working with circuits for private execution, this becomes more tricky as you cannot just read the storage directly from your state tree, only commitments sit in there 😱. The pre-images (content) of your notes need to be provided to the function to prove that you actually allowed to spend them. - -You could of course provide them to your function as inputs, but then functions that have different underlying notes would end up with different function signatures and thus selectors. This means that integrating with many different tokens (with different underlying notes) would become a pain for the developers, see some of the motivation behind [EIP-4626](https://eips.ethereum.org/EIPS/eip-4626) for similar case in EVM. - -If we are instead fetching the notes using an oracle call, we can keep the function signature independent of the underlying notes and thus make it much easier to integrate with! A similar idea, but applied to the authentication mechanism is used for the Authentication Witnesses that allow us to have a single function signature for any wallet implementation making integrations a breeze, see [AuthWit](../../wallets/main#authorizing-actions) for more information on this. - -Oracles introduce **non-determinism** into a circuit, and thus are `unconstrained`. It is important that any information that is injected into a circuit through an oracle is later constrained for correctness. Otherwise, the circuit will be **under-constrained** and potentially insecure! - -`Aztec.nr` has a module dedicated to its oracles. If you are interested, you can view them by following the link below: -#include_code oracles-module /yarn-project/aztec-nr/aztec/src/oracle.nr rust - -You can learn how to use oracles in your smart contracts [here](../syntax/oracles.md). - -## Calling functions from other functions - -### Private -> Private - -In Aztec Private to Private function calls are handled by the [private kernel circuit](../../../learn/concepts/circuits/kernels/private_kernel.md), and take place on the user's device. -Behind the scenes, the `Private Execution Environment (PXE)` (the beating heart of Aztec that runs in your wallet) will execute all of the functions in the desired order "simulating" them in sequence. For example, a very common use-case of Private to Private interaction is calling another private function from an `account contract` (Account contracts are a general concept, more information about them can be found [here](../../wallets/writing_an_account_contract.md)). - -Take, for example, the following call stack: - -``` -AccountContract::entrypoint - |-> Foo::example_call - | -> Bar::nested_call - |-> Baz::example_call -``` - -In the example above the Account Contract has been instructed to call two external functions. In the first function all, to `Foo::example_call` a further nested call is performed to `Bar::nested_call`. Finally the account contract makes one last call to `Baz::example_call`. - -Lets further illustrate what these examples could look like - - - -```rust -// Foo contains a singular function that returns the result of Bar::nested_call -contract Foo { - #[aztec(private)] - fn example_call(input: Field) -> pub Field { - Bar::at().nested_call(input) - } -} - -// Bar contains a singular function that returns a `input + 1` -contract Bar { - #[aztec(private)] - fn nested_call(input: Field) -> pub Field { - input + 1 - } -} - -// Baz contains a singular function that simply returns `10` -contract Baz { - #[aztec(private)] - fn example_call() -> pub Field { - 10 - } -} -``` - -When simulating the following call stack, we can expect execution flow to continue procedurally. The simulator will begin at the account contract's entry point, find a call to `Foo::example_call`, then begin to execute the code there. When the simulator executes the code in contract `Foo`, it will find the further nested call to contract `Bar::nested_call`. It will execute the code in `Bar`, bringing the return value back to contract `Foo`. -The same process will be followed for contract `Baz`. - -So far the provided example is identical to other executions. Ethereum execution occurs in a similar way, during execution the EVM will execute instructions until it reaches an external call, where it will hop into a new context and execute code there, returning back when it is complete, bringing with it return values from the foreign execution. - -Those of you who have written circuits before may see an issue here. The account contract, contract `Foo`, `Bar` and `Baz` are all distinct circuits, which do not know anything about each other. How is it possible to use a value from contract `Bar` in contract `Foo`? This value will not be constrained. - -This is where the `kernel` circuit comes in. Once the execution of all of our functions has completed, we can just prove the execution of each of them independently. It is the job of the `kernel` circuit to constrain that the input parameters in a cross function call are correct, as well as the return values. The kernel will constrain that the value returned from `Foo::example_call` is the same value that is returned from `Bar::nested_call`, it will also be able to constrain the value returned by `Bar::nested_call` is the inputs to `Foo::example_call` + 1. - -The orchestration of these calls has an added benefit. All of the nested calls are **recursively proven**. This means that the kernel circuit essentially gobbles up each of our function's execution proofs. Condensing the size of the final proof to just be one. - - - -With this intuition in place, lets see how we actually perform the call. To make things easier, we can make a small struct that wraps the calls to something as seen in the `token_interface`s burn function below. This struct is just providing us a clean way to call function, but we could also just call the function directly as it is done in this function. - -:::info -Note that the function selector is computed using one of the oracles from earlier, and that the first `Field` is wrapped in parenthesis. Structs are outlined in tuple-form for selector computation, so they are wrapped in parenthesis--`AztecAddress` becomes `(Field)`. -::: - -#include_code private_burn_interface /yarn-project/noir-contracts/contracts/token_bridge_contract/src/token_interface.nr rust - -Using this interface, we can then call it as seen below. All the way down at the bottom we can see that we are calling the `burn` function from the `token_interface` struct. - -The following snippet is from a token bridge that is burning the underlying token and creating a message for L1 to mint some assets to the `recipient` on Ethereum. - -#include_code exit_to_l1_private /yarn-project/noir-contracts/contracts/token_bridge_contract/src/main.nr rust - -### Public -> Public - -The public execution environment in Aztec takes place on the sequencer through a [Public VM](../../../learn/concepts/hybrid_state/public_vm.md). This execution model is conceptually much simpler than the private transaction model as code is executed and proven on the sequencer. - -Using the same example code and call stack from the section [above](#private----private-function-calls), we will walk through how it gets executed in public. - -The first key difference is that public functions are not compiled to circuits, rather they are compiled to `Aztec Bytecode` (might also be referred to as brillig). - -This bytecode is run by the sequencer in the `Aztec VM`, which is in turn proven by the [`Aztec VM circuit`](../../../learn/concepts/hybrid_state/public_vm.md). -The mental model for public execution carries many of the same idea as are carried by Ethereum. Programs are compiled into a series of opcodes (known as bytecode). This bytecode is then executed. The extra step for the Aztec VM is that each opcode is then proven for correctness. - -Calling a public function from another public function is quite similar to what we saw for private to private, with the keyword private swapped for public. - -#include_code public_burn_interface /yarn-project/noir-contracts/contracts/token_bridge_contract/src/token_interface.nr rust -#include_code exit_to_l1_public /yarn-project/noir-contracts/contracts/token_bridge_contract/src/main.nr rust - -### Private -> Public - -As discussed above, private function execution and calls take place on the user's device, while public function execution and calls take place on a sequencer, in two different places at two different times, it is natural to question how we can achieve composability between the two. The solution is asynchronicity. Further reading can be found in the foundational concepts [here](../../../learn/concepts/communication/public_private_calls/main.md)). - -Private function execution takes place on the users device, where it keeps track of any public function calls that have been made. Whenever private execution completes, and a kernel proof is produced, the transaction sent to the network will include all of the public calls that were dispatched. -When the sequencer receives the messages, it will take over and execute the public parts of the transaction. - -As a consequence a private function _CANNOT_ accept a return value from a public function. It can only dispatch it. - -The code required to dispatch a public function call from a private function is actually quite similar to private to private calls. As an example, we will look at the token contract, where users can unshield assets from private to public domain, essentially a transfer from a private account to a public one (often used for depositing privately into DeFi etc). - -#include_code unshield /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust -#include_code increase_public_balance /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust - -As we can see above, the private to public transaction flow looks very similar to the others in snippets, with the practicality being a bit different behind the scenes. - - - -### Public -> Private - -Wait, I thought you said we could not do this? Well, you are right, we cannot do this directly. However, we can do this indirectly if we are a little cheeky. - -While we cannot directly call a private function, we can indirectly call it by adding a commitment to the note hash tree. This commitment can then be consumed by a private function later, to "finish" the execution. So while it is not practically a call, we can ensure that it could only happen as an effect of a public function call, which is still pretty useful. - -In the snippet below, we insert a custom note, the transparent note, into the commitments tree from public such that it can later be consumed in private. - -#include_code shield /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust - -If you recall the `redeem_shield` from back in the [private function section](#private-functions), you might remember it removing a `TransparentNote` from `pending_shields`. This is the note that we just inserted from public! - -#include_code redeem_shield /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust - -When the note is removed, it emits a nullifier so that it cannot be used again. This nullifier is then added to the note hash tree, and can be used to prove that the note was removed from the pending shields. Interestingly, we can generate the nullifier such that no-one who saw the public execution will know that it have been consumed. When sending messages between L1 and L2 in [portals](../portals/main.md) we are going to see this pattern again. - -:::danger -Something to be mindful of when inserting from public. Everyone can see the insertion and what happens in public, so if you are including a secret directly anyone would be able to see it. This is why the hash of the secret is used in the snippet above (`secret_hash`). -::: - ---- - -## Deep dive - -Below, we go more into depth of what is happening under the hood when you create a function in Aztec.nr and what the attributes are really doing. - -### Function type attributes explained. - -Aztec.nr uses an attribute system to annotate a function's type. Annotating a function with the `#[aztec(private)]` attribute tells the framework that this will be a private function that will be executed on a users device. Thus the compiler will create a circuit to define this function. - -However; `#aztec(private)` is just syntactic sugar. At compile time, the framework inserts code that allows the function to interact with the [kernel](../../../learn/concepts/circuits/kernels/private_kernel.md). - -To help illustrate how this interacts with the internals of Aztec and its kernel circuits, we can take an example private function, and explore what it looks like after Aztec.nr's macro expansion. - -#### Before expansion - -#include_code simple_macro_example /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust - -#### After expansion - -#include_code simple_macro_example_expanded /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust - -#### The expansion broken down? - -Viewing the expanded noir contract uncovers a lot about how noir contracts interact with the [kernel](../../../learn/concepts/circuits/kernels/private_kernel.md). To aid with developing intuition, we will break down each inserted line. - -**Receiving context from the kernel.** -#include_code context-example-inputs /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust - -Private function calls are able to interact with each other through orchestration from within the [kernel circuit](../../../learn/concepts/circuits/kernels/private_kernel.md). The kernel circuit forwards information to each app circuit. This information then becomes part of the private context. -For example, within each circuit we can access some global variables. To access them we can call `context.chain_id()`. The value of this chain ID comes from the values passed into the circuit from the kernel. - -The kernel can then check that all of the values passed to each circuit in a function call are the same. - -**Returning the context to the kernel.** -#include_code context-example-return /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust - -Just as the kernel passes information into the app circuits, the application must return information about the executed app back to the kernel. This is done through a rigid structure we call the `PrivateCircuitPublicInputs`. - -> _Why is it called the `PrivateCircuitPublicInputs`_ -> It is commonly asked why the return values of a function in a circuit are labeled as the `Public Inputs`. Common intuition from other programming paradigms suggests that the return values and public inputs should be distinct. -> However; In the eyes of the circuit, anything that is publicly viewable (or checkable) is a public input. Hence in this case, the return values are also public inputs. - -This structure contains a host of information about the executed program. It will contain any newly created nullifiers, any messages to be sent to l2 and most importantly it will contain the actual return values of the function! - -**Hashing the function inputs.** -#include_code context-example-hasher /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust - -_What is the hasher and why is it needed?_ - -Inside the kernel circuits, the inputs to functions are reduced to a single value; the inputs hash. This prevents the need for multiple different kernel circuits; each supporting differing numbers of inputs. The hasher abstraction that allows us to create an array of all of the inputs that can be reduced to a single value. - -**Creating the function's context.** -#include_code context-example-context /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust - -Each Aztec function has access to a [context](./context.mdx) object. This object although ergonomically a global variable, is local. It is initialized from the inputs provided by the kernel, and a hash of the function's inputs. - -#include_code context-example-context-return /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust - -As previously mentioned we use the kernel to pass information between circuits. This means that the return values of functions must also be passed to the kernel (where they can be later passed on to another function). -We achieve this by pushing return values to the execution context, which we then pass to the kernel. - -**Making the contract's storage available** -#include_code storage-example-context /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust - -When a [`Storage` struct](./storage/main.md) is declared within a contract, the `storage` keyword is made available. As shown in the macro expansion above, this calls the init function on the storage struct with the current function's context. - -Any state variables declared in the `Storage` struct can now be accessed as normal struct members. - -**Returning the function context to the kernel.** -#include_code context-example-finish /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust - -This function takes the application context, and converts it into the `PrivateCircuitPublicInputs` structure. This structure is then passed to the kernel circuit. diff --git a/docs/docs/developers/contracts/syntax/functions/calling_functions.md b/docs/docs/developers/contracts/syntax/functions/calling_functions.md new file mode 100644 index 00000000000..4b24e32a9c2 --- /dev/null +++ b/docs/docs/developers/contracts/syntax/functions/calling_functions.md @@ -0,0 +1,132 @@ +--- +title: Calling Functions from Other Functions +--- + +This page talks about how functions call other functions. For a more hands-on guide into calling functions from other functions, follow the [token tutorial](../../../tutorials/writing_token_contract.md). + +### Private -> Private + +In Aztec Private to Private function calls are handled by the [private kernel circuit](../../../../learn/concepts/circuits/kernels/private_kernel.md), and take place on the user's device. +Behind the scenes, the `Private Execution Environment (PXE)` (the beating heart of Aztec that runs in your wallet) will execute all of the functions in the desired order "simulating" them in sequence. For example, a very common use-case of private-to-private interaction is calling a private function on another contract from an `account contract` (Account contracts are a general concept, more information about them can be found [here](../../../wallets/writing_an_account_contract.md)). + +Take, for example, the following call stack: + +``` +AccountContract::entrypoint + |-> Foo::example_call + | -> Bar::nested_call + |-> Baz::example_call +``` + +In the example above the Account Contract has been instructed to call two external functions. In the first function all, to `Foo::example_call` a further nested call is performed to `Bar::nested_call`. Finally the Account Contract makes one last call to `Baz::example_call`. + +Lets further illustrate what these examples could look like + + + +```rust +// Foo contains a singular function that returns the result of Bar::nested_call +contract Foo { + #[aztec(private)] + fn example_call(input: Field) -> pub Field { + Bar::at().nested_call(input) + } +} + +// Bar contains a singular function that returns a `input + 1` +contract Bar { + #[aztec(private)] + fn nested_call(input: Field) -> pub Field { + input + 1 + } +} + +// Baz contains a singular function that simply returns `10` +contract Baz { + #[aztec(private)] + fn example_call() -> pub Field { + 10 + } +} +``` + +When simulating the following call stack, we can expect execution flow to continue procedurally. The simulator will begin at the account contract's entry point, find a call to `Foo::example_call`, then begin to execute the code there. When the simulator executes the code in contract `Foo`, it will find the further nested call to contract `Bar::nested_call`. It will execute the code in `Bar`, bringing the return value back to contract `Foo`. +The same process will be followed for contract `Baz`. + +So far the provided example is identical to other executions. Ethereum execution occurs in a similar way, during execution the EVM will execute instructions until it reaches an external call, where it will hop into a new context and execute code there, returning back when it is complete, bringing with it return values from the foreign execution. + +Aztec differs from Ethereum in that these function calls are really executing zk programs (or circuits). The account contract, contract `Foo`, `Bar` and `Baz` are all distinct circuits, which are not directly aware of one another in the way that Ethereum contracts are. How is it possible to use a value from contract `Bar` in contract `Foo`? `Foo` cannot guarantee claims about the execution of `Bar`. + +This is where the `kernel` circuit comes in. Once the execution of all of the contract functions has completed, it can prove the execution of each of them independently. It is the job of the `kernel` circuit to constrain that the input parameters in a cross function call are correct, as well as the return values. The kernel will constrain that the value returned from `Foo::example_call` is the same value that is returned from `Bar::nested_call`, it will also be able to guarantee the value returned by `Bar::nested_call` is the inputs to `Foo::example_call` + 1. + +The orchestration of these calls has an added benefit. All of the nested calls are **recursively proven**. This means that the kernel circuit essentially aggregates each of our function's execution proofs, resulting in one proof that proves all function execution. + + + +With this intuition in place, lets see how we actually perform the call. To make things easier, we can make a small struct that wraps the calls to something as seen in the token interface `burn` function below. This struct is providing us a clean way to call function, but we could also just call the function directly as it is done in this function. + +:::info +Note that the function selector is computed using Oracles, and that the first `Field` is wrapped in parenthesis. Structs are outlined in tuple-form for selector computation, so they are wrapped in parenthesis--e.g. `AztecAddress` becomes `(Field)`. +::: + +#include_code private_burn_interface /yarn-project/noir-contracts/contracts/token_bridge_contract/src/token_interface.nr rust + +Using this interface, we can then call it as seen below. All the way down at the bottom we can see that we are calling the `burn` function from the `token_interface` struct. + +The following snippet is from a token bridge that is burning the underlying token and creating a message for L1 to mint some assets to the `recipient` on Ethereum. + +#include_code exit_to_l1_private /yarn-project/noir-contracts/contracts/token_bridge_contract/src/main.nr rust + +### Public -> Public + +The public execution environment in Aztec takes place on the sequencer through a [Public VM](../../../../learn/concepts/hybrid_state/public_vm.md). This execution model is conceptually much simpler than the private transaction model as code is executed and proven on the sequencer. + +Using the same example code and call stack from the section [above](#private---private-function-calls), we will walk through how it gets executed in public. + +The first key difference is that public functions are not compiled to circuits, rather they are compiled to `Aztec Bytecode`. + +This bytecode is run by the sequencer in the `Aztec VM`, which is in turn proven by the [`Aztec VM circuit`](../../../../learn/concepts/hybrid_state/public_vm.md). +The mental model for public execution carries many of the same idea as are carried by Ethereum. Programs are compiled into a series of opcodes (known as bytecode). This bytecode is then executed. The extra step for the Aztec VM is that each opcode is then proven for correctness. + +Calling a public function from another public function is quite similar to what we saw for private to private, with the keyword private swapped for public. + +#include_code public_burn_interface /yarn-project/noir-contracts/contracts/token_bridge_contract/src/token_interface.nr rust +#include_code exit_to_l1_public /yarn-project/noir-contracts/contracts/token_bridge_contract/src/main.nr rust + +### Private -> Public + +As discussed above, private function execution and calls take place on the user's device, while public function execution and calls take place on a sequencer, in two different places at two different times. We can achieve composability between the two contexts via asynchronicity. Further reading can be found in the concepts [here](../../../../learn/concepts/communication/public_private_calls/main.md). + +Private function execution takes place on the users device, where it keeps track of any public function calls that have been made. Whenever private execution completes, and a kernel proof is produced, the transaction sent to the network will include all of the public calls that were dispatched. +When the sequencer receives the messages, it will execute the public parts of the transaction. + +As a consequence a private function _CANNOT_ accept a return value from a public function. It can only dispatch it. + +The code required to dispatch a public function call from a private function is similar to private-to-private calls. As an example, we will look at the token contract, where users can unshield assets from private to public domain. This is essentially a transfer from a private account to a public one (often used for depositing privately into DeFi etc). + +#include_code unshield /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust +#include_code increase_public_balance /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust + +As we can see above, in the code the private to public transaction flow looks very similar to the others in snippets, with the transaction data flow being a bit different behind the scenes. + + + +### Public -> Private + + +While we cannot directly call a private function from a public function, we can indirectly call it by adding a commitment to the note hash tree. This commitment can then be consumed by a private function later, to "finish" the execution. So while it is not practically a call, we can ensure that it could only happen as an effect of a public function call, which is still useful. + +In the snippet below, we insert a custom note, the transparent note, into the commitments tree from public such that it can later be consumed in private. + +#include_code shield /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust + +If you recall the `redeem_shield` from back in the [private function section](./public_private_unconstrained.md#private-functions), you might remember it removing a `TransparentNote` from `pending_shields`. This is the note that we just inserted from public! + +#include_code redeem_shield /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust + +When the note is removed, it emits a nullifier so that it cannot be used again. This nullifier is then added to the nullifier tree, and can be used to prove that the note was removed from the pending shields. Interestingly, we can generate the nullifier such that no-one who saw the public execution will know that it have been consumed. When sending messages between L1 and L2 in [portals](./../../../../learn/concepts/communication/cross_chain_calls.md) we are going to see this pattern again. + +:::danger +Something to be mindful of when inserting from public. Everyone can see the insertion and what happens in public, so if you are including a secret directly anyone would be able to see it. This is why the hash of the secret is used in the snippet above (`secret_hash`). +::: + diff --git a/docs/docs/developers/contracts/syntax/functions/constructor.md b/docs/docs/developers/contracts/syntax/functions/constructor.md new file mode 100644 index 00000000000..d0a9c7d0c3b --- /dev/null +++ b/docs/docs/developers/contracts/syntax/functions/constructor.md @@ -0,0 +1,15 @@ +--- +title: Constructor +--- +This page talks about declaring constructors in functions. + +For a more hands-on guide into declaring a constructor, follow the [private voting tutorial](../../../tutorials/writing_private_voting_contract.md). + +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 initialize contract state. +- In Aztec terminology, a constructor is always a '`private` function' (i.e. it cannot be a `public` function). +- A constructor behaves almost identically to any other function. It is 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. + +Although you can have a constructor that does nothing, you might want to do something with it, such as setting the deployer as an owner. + +#include_code constructor /yarn-project/noir-contracts/contracts/escrow_contract/src/main.nr rust diff --git a/docs/docs/developers/contracts/syntax/functions/inner_workings.md b/docs/docs/developers/contracts/syntax/functions/inner_workings.md new file mode 100644 index 00000000000..3b1a093e00a --- /dev/null +++ b/docs/docs/developers/contracts/syntax/functions/inner_workings.md @@ -0,0 +1,100 @@ +--- +title: Inner Workings of Functions +--- + +Below, we go more into depth of what is happening under the hood when you create a function in an Aztec contract and what the attributes are really doing. + +To get a more practical understanding about functions, read [the rest of this section](./main.md). + +## Private functions + +Aztec.nr uses an attribute system to annotate a function's type. Annotating a function with the `#[aztec(private)]` attribute tells the framework that this is a private function that will be executed on a users device. The compiler will create a circuit to define this function. + +`#aztec(private)` is just syntactic sugar. At compile time, the Aztec.nr framework inserts code that allows the function to interact with the [kernel](../../../../learn/concepts/circuits/kernels/private_kernel.md). + +To help illustrate how this interacts with the internals of Aztec and its kernel circuits, we can take an example private function, and explore what it looks like after Aztec.nr's macro expansion. + +#### Before expansion + +#include_code simple_macro_example /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust + +#### After expansion + +#include_code simple_macro_example_expanded /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust + +#### The expansion broken down? + +Viewing the expanded Aztec contract uncovers a lot about how Aztec contracts interact with the [kernel](../../../../learn/concepts/circuits/kernels/private_kernel.md). To aid with developing intuition, we will break down each inserted line. + +**Receiving context from the kernel.** +#include_code context-example-inputs /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust + +Private function calls are able to interact with each other through orchestration from within the [kernel circuit](../../../../learn/concepts/circuits/kernels/private_kernel.md). The kernel circuit forwards information to each contract function (recall each contract function is a circuit). This information then becomes part of the private context. +For example, within each private function we can access some global variables. To access them we can call on the `context`, e.g. `context.chain_id()`. The value of the chain ID comes from the values passed into the circuit from the kernel. + +The kernel checks that all of the values passed to each circuit in a function call are the same. + +**Returning the context to the kernel.** +#include_code context-example-return /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust + +The contract function must return information about the execution back to the kernel. This is done through a rigid structure we call the `PrivateCircuitPublicInputs`. + +> _Why is it called the `PrivateCircuitPublicInputs`?_ +> When verifying zk programs, return values are not computed at verification runtime, rather expected return values are provided as inputs and checked for correctness. Hence, the return values are considered public inputs. + +This structure contains a host of information about the executed program. It will contain any newly created nullifiers, any messages to be sent to l2 and most importantly it will contain the return values of the function. + +**Hashing the function inputs.** +#include_code context-example-hasher /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust + +_What is the hasher and why is it needed?_ + +Inside the kernel circuits, the inputs to functions are reduced to a single value; the inputs hash. This prevents the need for multiple different kernel circuits; each supporting differing numbers of inputs. The hasher abstraction that allows us to create an array of all of the inputs that can be reduced to a single value. + +**Creating the function's context.** +#include_code context-example-context /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust + +Each Aztec function has access to a [context](../context.mdx) object. This object, although labelled a global variable, is created locally on a users' device. It is initialized from the inputs provided by the kernel, and a hash of the function's inputs. + +#include_code context-example-context-return /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust + +We use the kernel to pass information between circuits. This means that the return values of functions must also be passed to the kernel (where they can be later passed on to another function). +We achieve this by pushing return values to the execution context, which we then pass to the kernel. + +**Making the contract's storage available** +#include_code storage-example-context /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust + +When a [`Storage` struct](../storage/main.md) is declared within a contract, the `storage` keyword is made available. As shown in the macro expansion above, this calls the init function on the storage struct with the current function's context. + +Any state variables declared in the `Storage` struct can now be accessed as normal struct members. + +**Returning the function context to the kernel.** +#include_code context-example-finish /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust + +This function takes the application context, and converts it into the `PrivateCircuitPublicInputs` structure. This structure is then passed to the kernel circuit. + +## Unconstrained functions + +Defining a function as `unconstrained` tells Aztec to simulate it completely client-side in the [ACIR simulator](../../../../learn/concepts/pxe/acir_simulator.md) without generating proofs. They are useful for extracting information from a user through an [oracle](./oracles.md). + +When an unconstrained function is called, it prompts the ACIR simulator to + +1. generate the execution environment +2. execute the function within this environment + +To generate the environment, the simulator gets the blockheader from the [PXE database](../../../../learn/concepts/pxe/main.md#database) and passes it along with the contract address to `ViewDataOracle`. This creates a context that simulates the state of the blockchain at a specific block, allowing the unconstrained function to access and interact with blockchain data as it would appear in that block, but without affecting the actual blockchain state. + +Once the execution environment is created, `execute_unconstrained_function` is invoked: + +#include_code execute_unconstrained_function yarn-project/acir-simulator/src/client/unconstrained_execution.ts typescript + +This: + +1. Prepares the ACIR for execution +2. Converts `args` into a format suitable for the ACVM (Abstract Circuit Virtual Machine), creating an initial witness (witness = set of inputs required to compute the function). `args` might be an oracle to request a user's balance +3. Executes the function in the ACVM, which involves running the ACIR with the initial witness and the context. If requesting a user's balance, this would query the balance from the PXE database +4. Extracts the return values from the `partialWitness` and decodes them based on the artifact to get the final function output. The [artifact](../../artifacts.md) is the compiled output of the contract, and has information like the function signature, parameter types, and return types + + + + diff --git a/docs/docs/developers/contracts/syntax/functions/main.md b/docs/docs/developers/contracts/syntax/functions/main.md new file mode 100644 index 00000000000..17de123e35b --- /dev/null +++ b/docs/docs/developers/contracts/syntax/functions/main.md @@ -0,0 +1,20 @@ +--- +title: Functions +--- + +Functions serve as the building blocks of smart contracts. Functions can be either **public**, ie they are publicly available for anyone to see and can directly interact with public state, or **private**, meaning they are executed completely client-side in the [PXE](../../../../learn/concepts/pxe/main.md). Read more about how private functions work [here](./inner_workings.md#private-functions). + +For a more practical guide of using multiple types of functions, follow the [token tutorial](../../../tutorials/writing_token_contract.md). + +Every smart contract has a private `constructor` function which is called when the contract is deployed. There are also special oracle functions, which can get data from outside of the smart contract. In the context of Aztec, oracles are often used to get user-provided inputs. + +Currently, any function is "mutable" in the sense that it might alter state. In the future, we will support static calls, similarly to EVM. A static call is essentially a call that does not alter state (it keeps state static). + +Explore this section to learn: + +- [How function visibility works in Aztec](./visibility.md) +- [Public, private, and unconstrained functions](./public_private_unconstrained.md), and how to write them +- How [constructors](./constructor.md) work and remain private +- [Calling functions from within the same smart contract and from different contracts](./calling_functions.md), including calling private functions from private functions, public from public, and even private from public +- [Oracles](./oracles) and how Aztec smart contracts might use them +- [How functions work under the hood](./inner_workings.md) \ No newline at end of file diff --git a/docs/docs/developers/contracts/syntax/functions/oracles.md b/docs/docs/developers/contracts/syntax/functions/oracles.md new file mode 100644 index 00000000000..28a57bed1d6 --- /dev/null +++ b/docs/docs/developers/contracts/syntax/functions/oracles.md @@ -0,0 +1,23 @@ +--- +title: Oracle Functions +--- + +This page goes over what oracles are in Aztec and how they work. + +Looking for a hands-on guide? You can learn how to use oracles in a smart contract [here](../oracles.md). + +An oracle is something that allows us to get data from the outside world into our contracts. The most widely-known types of oracles in blockchain systems are probably Chainlink price feeds, which allow us to get the price of an asset in USD taking non-blockchain data into account. + +While this is one type of oracle, the more general oracle, allows us to get any data into the contract. In the context of oracle functions or oracle calls in Aztec, it can essentially be seen as user-provided arguments, that can be fetched at any point in the circuit, and don't need to be an input parameter. + +**Why is this useful? Why don't just pass them as input parameters?** +In the world of EVM, you would just read the values directly from storage and call it a day. However, when we are working with circuits for private execution, this becomes more tricky as you cannot just read the storage directly from your state tree, because there are only commitments (e.g. hashes) there. The pre-images (content) of your commitments need to be provided to the function to prove that you actually allowed to modify them. + + +If we fetch the notes using an oracle call, we can keep the function signature independent of the underlying data and make it easier to use. A similar idea, applied to the authentication mechanism is used for the Authentication Witnesses that allow us to have a single function signature for any wallet implementation, see [AuthWit](../../../wallets/main#authorizing-actions) for more information on this. + +Oracles introduce **non-determinism** into a circuit, and thus are `unconstrained`. It is important that any information that is injected into a circuit through an oracle is later constrained for correctness. Otherwise, the circuit will be **under-constrained** and potentially insecure! + +`Aztec.nr` has a module dedicated to its oracles. If you are interested, you can view them by following the link below: +#include_code oracles-module /yarn-project/aztec-nr/aztec/src/oracle.nr rust + diff --git a/docs/docs/developers/contracts/syntax/functions/public_private_unconstrained.md b/docs/docs/developers/contracts/syntax/functions/public_private_unconstrained.md new file mode 100644 index 00000000000..678fc7ad9d3 --- /dev/null +++ b/docs/docs/developers/contracts/syntax/functions/public_private_unconstrained.md @@ -0,0 +1,35 @@ +--- +title: Public, Private, and Unconstrained Functions +--- + +This page explains the three types of functions that exist on Aztec - public, private, and unconstrained. For a deeper dive into how these functions work under the hood, check out the [Inner Workings](./inner_workings.md) page. + +## `Public` Functions + +A public function is executed by the sequencer and has access to a state model that is very similar to that of the EVM and Ethereum. Even though they work in an EVM-like model for public transactions, they are able to write data into private storage that can be consumed later by a private function. + +:::note +All data inserted into private storage from a public function will be publicly viewable (not private). +::: + +To create a public function you can annotate it with the `#[aztec(public)]` attribute. This will make the [public context](../context.mdx) available within the function's execution scope. + +#include_code set_minter /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust + +## `Private` Functions + +A private function operates on private information, and is executed by the user. Annotate the function with the `#[aztec(private)]` attribute to tell the compiler it's a private function. This will make the [private context](../context.mdx#private-context-broken-down) available within the function's execution scope. + +#include_code redeem_shield /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust + +## `unconstrained` functions + +Unconstrained functions are an underlying part of Noir - a deeper explanation can be found [here](https://noir-lang.org/docs/noir/syntax/unconstrained). In short, they are functions which are not directly constrained and therefore should be seen as un-trusted. That they are un-trusted means that the developer must make sure to constrain their return values when used. Note: Calling an unconstrained function from a private function means that you are injecting unconstrained values. + +Beyond using them inside your other functions, they are convenient for providing an interface that reads storage, applies logic and returns values to a UI or test. Below is a snippet from exposing the `balance_of_private` function from a token implementation, which allows a user to easily read their balance, similar to the `balanceOf` function in the ERC20 standard. + +#include_code balance_of_private /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust + +:::info +Note, that unconstrained functions can have access to both public and private data when executed on the user's device. This is possible since it is not actually part of the circuits that are executed in contract execution. +::: \ No newline at end of file diff --git a/docs/docs/developers/contracts/syntax/functions/visibility.md b/docs/docs/developers/contracts/syntax/functions/visibility.md new file mode 100644 index 00000000000..61756bff01e --- /dev/null +++ b/docs/docs/developers/contracts/syntax/functions/visibility.md @@ -0,0 +1,25 @@ +--- +title: Visibility +--- + +In Aztec there are multiple different types of visibility that can be applied to functions. Namely we have `data visibility` and `function visibility`. This page explains these types of visibility. + +For a practical guide of using multiple types of data and function visibility,follow the [token tutorial](../../../tutorials/writing_token_contract.md). + +### Data Visibility + +Data visibility is used to describe whether the data (or state) used in a function is generally accessible (public) or on a need to know basis (private). + +### Function visibility + +This is the kind of visibility you are more used to seeing in Solidity and more traditional programming languages. It is used to describe whether a function is callable from other contracts, or only from within the same contract. + +By default, all functions are callable from other contracts, similarly to the Solidity `public` visibility. To make them only callable from the contract itself, you can mark them as `internal`. Contrary to solidity, we don't have the `external` nor `private` keywords. `external` since it is limited usage when we don't support inheritance, and `private` since we don't support inheritance and it would also be confusing with multiple types of `private`. + +A good place to use `internal` is when you want a private function to be able to alter public state. As mentioned above, private functions cannot do this directly. They are able to call public functions and by making these internal we can ensure that this state manipulating function is only callable from our private function. + +:::danger +Note that non-internal functions could be used directly as an entry-point, which currently means that the `msg_sender` would be `0`, so for now, using address `0` as a burn address is not recommended. You can learn more about this in the [Accounts concept page](../../../../learn/concepts/accounts/main.md#entrypoint-restrictions). +::: + +To understand how visibility works under the hood, check out the [Inner Workings page](./inner_workings.md). \ No newline at end of file diff --git a/docs/docs/developers/contracts/syntax/main.md b/docs/docs/developers/contracts/syntax/main.md index 7157b46764c..73a6c7ffddc 100644 --- a/docs/docs/developers/contracts/syntax/main.md +++ b/docs/docs/developers/contracts/syntax/main.md @@ -12,7 +12,7 @@ Aztec.nr contains abstractions which remove the need to understand the low-level - Public and private [state variable types](./storage/main.md) - Some pre-designed notes - Functions for [emitting](./events.md) encrypted and unencrypted logs -- [Oracle functions](./functions.md#oracle-functions) for accessing: +- [Oracle functions](./functions/oracles.md) for accessing: - private state - secrets - Functions for communicating with [Ethereum L1](../portals/main.md) diff --git a/docs/docs/developers/contracts/syntax/storage/private_state.md b/docs/docs/developers/contracts/syntax/storage/private_state.md index f4e3836d030..35429d74020 100644 --- a/docs/docs/developers/contracts/syntax/storage/private_state.md +++ b/docs/docs/developers/contracts/syntax/storage/private_state.md @@ -184,7 +184,7 @@ Set is used for managing a collection of notes. All notes in a Set are of the sa You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/aztec-nr/aztec/src/state_vars/set.nr). -And can be added to the `Storage` struct as follows. Here adding a set for a custom note, the TransparentNote (useful for [public -> private communication](../functions.md#public---private)). +And can be added to the `Storage` struct as follows. Here adding a set for a custom note, the TransparentNote (useful for [public -> private communication](../functions/calling_functions.md#public---private)). #include_code storage_pending_shields /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust @@ -248,7 +248,7 @@ This function requires a `NoteViewerOptions`. The `NoteViewerOptions` is essenti ### NoteGetterOptions -`NoteGetterOptions` encapsulates a set of configurable options for filtering and retrieving a selection of notes from a [data oracle](../functions.md#oracle-functions). Developers can design instances of `NoteGetterOptions`, to determine how notes should be filtered and returned to the functions of their smart contracts. +`NoteGetterOptions` encapsulates a set of configurable options for filtering and retrieving a selection of notes from a [data oracle](../functions/oracles.md). Developers can design instances of `NoteGetterOptions`, to determine how notes should be filtered and returned to the functions of their smart contracts. You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/aztec-nr/aztec/src/note/note_getter_options.nr). diff --git a/docs/docs/developers/getting_started/aztecnr-getting-started.md b/docs/docs/developers/getting_started/aztecnr-getting-started.md index 599c50d84e0..32be3a1e2fa 100644 --- a/docs/docs/developers/getting_started/aztecnr-getting-started.md +++ b/docs/docs/developers/getting_started/aztecnr-getting-started.md @@ -114,7 +114,7 @@ Let’s create a `constructor` method to run on deployment that assigns an initi This function accesses the counts from storage. Then it assigns the passed initial counter to the `owner`'s counter privately using `at().add()`. -We have annotated this and other functions with `#[aztec(private)]` which are ABI macros so the compiler understands it will handle private inputs. Learn more about functions and annotations [here](../contracts/syntax/functions.md). +We have annotated this and other functions with `#[aztec(private)]` which are ABI macros so the compiler understands it will handle private inputs. Learn more about functions and annotations [here](../contracts/syntax/functions/main.md). ## Incrementing our counter diff --git a/docs/docs/developers/getting_started/main.md b/docs/docs/developers/getting_started/main.md index 0ee5ab59990..0e6fa1844ed 100644 --- a/docs/docs/developers/getting_started/main.md +++ b/docs/docs/developers/getting_started/main.md @@ -12,7 +12,7 @@ If this is your first time using Aztec, and you want to get started by learning ## Learn -If you want to read more about the high level concepts of Aztec before writing some code, head to the [Foundational Concepts section](../../learn/about_aztec/technical_overview.md). +If you want to read more about the high level concepts of Aztec before writing some code, head to the [Concepts section](../../learn/about_aztec/technical_overview.md). ## In this section diff --git a/docs/docs/developers/limitations/main.md b/docs/docs/developers/limitations/main.md index bc719c9307a..4101aeeb6d9 100644 --- a/docs/docs/developers/limitations/main.md +++ b/docs/docs/developers/limitations/main.md @@ -29,13 +29,13 @@ Help shape and define: - It is a testing environment, it is insecure, unaudited and does not generate any proofs, its only for testing purposes; - Constructors can not call nor alter public state - - The constructor is executed exclusively in private domain, WITHOUT the ability to call public functions or alter public state. This means to set initial storage values, you need to follow a pattern similar to [proxies in Ethereum](https://blog.openzeppelin.com/proxy-patterns), where you `initialize` the contract with values after it have been deployed, see [constructor](../contracts/syntax/functions.md#constructor). -- No static nor delegate calls (see [mutability](../contracts/syntax/functions.md#mutability)). + - The constructor is executed exclusively in private domain, WITHOUT the ability to call public functions or alter public state. This means to set initial storage values, you need to follow a pattern similar to [proxies in Ethereum](https://blog.openzeppelin.com/proxy-patterns), where you `initialize` the contract with values after it have been deployed, see [constructor](../contracts/syntax/functions/constructor.md). +- No static nor delegate calls (see [mutability](../contracts/syntax/functions/main.md)). - These values are unused in the call-context. - Beware that what you think of as a `view` could alter state ATM! Notably the account could alter state or re-enter whenever the account contract's `is_valid` function is called. - `msg_sender` is currently leaking when doing private -> public calls - The `msg_sender` will always be set, if you call a public function from the private world, the `msg_sender` will be set to the private caller's address. See [function context](../contracts/syntax/context.mdx). -- The initial `msg_sender` is 0, which can be problematic for some contracts, see [function visibility](../contracts/syntax/functions.md#function-visibility). +- The initial `msg_sender` is 0, which can be problematic for some contracts, see [function visibility](../contracts/syntax/functions/visibility.md). - Unencrypted logs don't link to the contract that emitted it, so essentially just a `debug_log`` that you can match values against. - A note that is created and nullified in the same transaction will still emit an encrypted log. - A limited amount of new commitments, nullifiers and calls that are supported by a transaction, see [circuit limitations](#circuit-limitations). @@ -193,7 +193,7 @@ Here are the current constants: #### What are the consequences? -When you write an [Aztec.nr](../contracts/main.md) [function](../contracts/syntax/functions.md), there will be upper bounds on the following: +When you write an [Aztec.nr](../contracts/main.md) [function](../contracts/syntax/functions/main.md), there will be upper bounds on the following: - The number of public state reads and writes; - The number of note reads and nullifications; diff --git a/docs/docs/developers/tutorials/writing_private_voting_contract.md b/docs/docs/developers/tutorials/writing_private_voting_contract.md index 82f46f860de..e24eecfa367 100644 --- a/docs/docs/developers/tutorials/writing_private_voting_contract.md +++ b/docs/docs/developers/tutorials/writing_private_voting_contract.md @@ -143,7 +143,7 @@ Create a private function called `cast_vote`: In this function, we do not create a nullifier with the address directly. This would leak privacy as it would be easy to reverse-engineer. We must add some randomness or some form of secret, like [nullifier secrets](../../learn/concepts/accounts/keys.md#nullifier-secrets). -To do this, we make an [oracle call](../contracts/syntax/functions.md#oracle-functions) to fetch the caller's secret key, hash it to create a nullifier, and push the nullifier to Aztec. The `secret.high` and `secret.low` values here refer to how we divide a large [Grumpkin scalar](https://github.com/AztecProtocol/aztec-packages/blob/7fb35874eae3f2cad5cb922282a619206573592c/noir/noir_stdlib/src/grumpkin_scalar.nr) value into its higher and lower parts. This allows for faster cryptographic computations so our hash can still be secure but is calculated faster. +To do this, we make an [oracle call](../contracts/syntax/functions/oracles.md) to fetch the caller's secret key, hash it to create a nullifier, and push the nullifier to Aztec. The `secret.high` and `secret.low` values here refer to how we divide a large [Grumpkin scalar](https://github.com/AztecProtocol/aztec-packages/blob/7fb35874eae3f2cad5cb922282a619206573592c/noir/noir_stdlib/src/grumpkin_scalar.nr) value into its higher and lower parts. This allows for faster cryptographic computations so our hash can still be secure but is calculated faster. After pushing the nullifier, we update the `tally` to reflect this vote. As we know from before, a private function cannot update public state directly, so we are calling a public function. diff --git a/docs/docs/learn/concepts/pxe/acir_simulator.md b/docs/docs/learn/concepts/pxe/acir_simulator.md index 1df355c9bb7..0b794773205 100644 --- a/docs/docs/learn/concepts/pxe/acir_simulator.md +++ b/docs/docs/learn/concepts/pxe/acir_simulator.md @@ -14,7 +14,7 @@ It simulates three types of functions: Private functions are simulated and proved client-side, and verified client-side in the private kernel circuit. -They are run with the assistance of a DB oracle that provides any private data requested by the function. You can read more about oracle functions in the smart contract section [here](../../../developers/contracts/syntax/functions.md#oracle-functions). +They are run with the assistance of a DB oracle that provides any private data requested by the function. You can read more about oracle functions in the smart contract section [here](../../../developers/contracts/syntax/functions/oracles.md). Private functions can call other private functions and can request to call a public function. The public function execution will be performed by the sequencer asynchronously, so private functions don't have direct access to the return values of public functions. diff --git a/docs/docs/learn/concepts/pxe/main.md b/docs/docs/learn/concepts/pxe/main.md index e8182ab218b..028aaf12081 100644 --- a/docs/docs/learn/concepts/pxe/main.md +++ b/docs/docs/learn/concepts/pxe/main.md @@ -62,7 +62,7 @@ The keystore is a secure storage for private and public keys. ## Oracles -Oracles are pieces of data that are injected into a smart contract function from the client side. You can read more about why and how they work in the [functions section](../../../developers/contracts/syntax/functions.md#oracle-functions). +Oracles are pieces of data that are injected into a smart contract function from the client side. You can read more about why and how they work in the [functions section](../../../developers/contracts/syntax/functions/oracles.md). ## For developers To learn how to develop on top of the PXE, refer to these guides: diff --git a/docs/sidebars.js b/docs/sidebars.js index 28f41753eaf..88dc7f7bd73 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -32,7 +32,7 @@ const sidebars = { "learn/about_aztec/what_is_aztec", "learn/about_aztec/vision", "learn/about_aztec/technical_overview", - + { type: "html", value: '', @@ -55,9 +55,7 @@ const sidebars = { type: "doc", id: "learn/concepts/hybrid_state/main", }, - items: [ - "learn/concepts/hybrid_state/public_vm", - ], + items: ["learn/concepts/hybrid_state/public_vm"], }, { label: "Storage", @@ -70,9 +68,7 @@ const sidebars = { type: "doc", id: "learn/concepts/storage/trees/main", }, - items: [ - "learn/concepts/storage/trees/indexed_merkle_tree", - ], + items: ["learn/concepts/storage/trees/indexed_merkle_tree"], }, "learn/concepts/storage/storage_slots", ], @@ -97,9 +93,7 @@ const sidebars = { type: "doc", id: "learn/concepts/smart_contracts/main", }, - items: [ - "learn/concepts/smart_contracts/contract_creation", - ], + items: ["learn/concepts/smart_contracts/contract_creation"], }, { label: "Communication", @@ -126,9 +120,7 @@ const sidebars = { type: "doc", id: "learn/concepts/pxe/main", }, - items: [ - "learn/concepts/pxe/acir_simulator", - ], + items: ["learn/concepts/pxe/acir_simulator"], }, { label: "Circuits", @@ -267,7 +259,7 @@ const sidebars = { items: [ "developers/cli/cli-commands", "developers/cli/sandbox-reference", - "developers/cli/run_more_than_one_pxe_sandbox" + "developers/cli/run_more_than_one_pxe_sandbox", ], }, { @@ -297,13 +289,28 @@ const sidebars = { id: "developers/contracts/syntax/storage/main", }, items: [ - "developers/contracts/syntax/storage/private_state", - "developers/contracts/syntax/storage/public_state", - "developers/contracts/syntax/storage/storage_slots", - ], + "developers/contracts/syntax/storage/private_state", + "developers/contracts/syntax/storage/public_state", + "developers/contracts/syntax/storage/storage_slots", + ], }, "developers/contracts/syntax/events", - "developers/contracts/syntax/functions", + { + label: "Functions", + type: "category", + link: { + type: "doc", + id: "developers/contracts/syntax/functions/main", + }, + items: [ + "developers/contracts/syntax/functions/public_private_unconstrained", + "developers/contracts/syntax/functions/visibility", + "developers/contracts/syntax/functions/constructor", + "developers/contracts/syntax/functions/calling_functions", + "developers/contracts/syntax/functions/oracles", + "developers/contracts/syntax/functions/inner_workings", + ], + }, "developers/contracts/syntax/oracles", { label: "Proving Historical Blockchain Data", @@ -311,10 +318,10 @@ const sidebars = { items: [ "developers/contracts/syntax/historical_access/how_to_prove_history", "developers/contracts/syntax/historical_access/history_lib_reference", - ], + ], }, "developers/contracts/syntax/slow_updates_tree", - + "developers/contracts/syntax/context", "developers/contracts/syntax/globals", ], @@ -491,4 +498,4 @@ const sidebars = { ], }; -module.exports = sidebars; \ No newline at end of file +module.exports = sidebars; diff --git a/yarn-project/acir-simulator/src/client/unconstrained_execution.ts b/yarn-project/acir-simulator/src/client/unconstrained_execution.ts index 26fa87f0846..62f934d41eb 100644 --- a/yarn-project/acir-simulator/src/client/unconstrained_execution.ts +++ b/yarn-project/acir-simulator/src/client/unconstrained_execution.ts @@ -10,6 +10,7 @@ import { ExecutionError } from '../common/errors.js'; import { AcirSimulator } from '../index.js'; import { ViewDataOracle } from './view_data_oracle.js'; +// docs:start:execute_unconstrained_function /** * Execute an unconstrained function and return the decoded values. */ @@ -45,3 +46,4 @@ export async function executeUnconstrainedFunction( return decodeReturnValues(artifact, extractReturnWitness(acir, partialWitness)); } +// docs:end:execute_unconstrained_function From 7cdc18692313017a70b9c8d761b7540eb96a9369 Mon Sep 17 00:00:00 2001 From: Lasse Herskind <16536249+LHerskind@users.noreply.github.com> Date: Wed, 31 Jan 2024 11:05:58 +0000 Subject: [PATCH 08/20] feat: Adding slitherin detectors (#4246) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding slitherin 🐍 detectors --- l1-contracts/Dockerfile | 2 +- l1-contracts/README.md | 4 +- l1-contracts/slither_output.md | 196 +++++++++++++++++++++++++++------ 3 files changed, 168 insertions(+), 34 deletions(-) diff --git a/l1-contracts/Dockerfile b/l1-contracts/Dockerfile index f6ccb1dc6b8..f5e51731f9f 100644 --- a/l1-contracts/Dockerfile +++ b/l1-contracts/Dockerfile @@ -1,6 +1,6 @@ # Building requires foundry. FROM ghcr.io/foundry-rs/foundry:nightly-4a643801d0b3855934cdec778e33e79c79971783 -RUN apk update && apk add git jq bash nodejs npm yarn python3 py3-pip && pip3 install slither-analyzer +RUN apk update && apk add git jq bash nodejs npm yarn python3 py3-pip && pip3 install slither-analyzer slitherin WORKDIR /usr/src/l1-contracts COPY . . RUN git init diff --git a/l1-contracts/README.md b/l1-contracts/README.md index e3b27c55388..258fb4cdedd 100644 --- a/l1-contracts/README.md +++ b/l1-contracts/README.md @@ -76,7 +76,7 @@ yarn lint --- -# Slither +# Slither & Slitherin We use slither as an automatic way to find blunders and common vulnerabilities in our contracts. It is not part of the docker image due to its slowness, but it can be run using the following command to generate a markdown file with the results: ```bash @@ -85,6 +85,6 @@ yarn slither When this command is run in CI, it will fail if the markdown file generated in docker don't match the one in the repository. -We assume that you already have slither installed. You can install it with `pip3 install slither-analyzer`. It is kept out of the bootstrap script as it is not a requirement for people who just want to run tests or are uninterested in the contracts. +We assume that you already have slither installed. You can install it with `pip3 install slither-analyzer slitherin`. It is kept out of the bootstrap script as it is not a requirement for people who just want to run tests or are uninterested in the contracts. > We are not running the `naming-convention` detector because we have our own rules for naming which is enforced by the linter. \ No newline at end of file diff --git a/l1-contracts/slither_output.md b/l1-contracts/slither_output.md index 7b45948006d..db4b5b391fd 100644 --- a/l1-contracts/slither_output.md +++ b/l1-contracts/slither_output.md @@ -1,19 +1,32 @@ Summary + - [pess-unprotected-setter](#pess-unprotected-setter) (1 results) (High) - [uninitialized-local](#uninitialized-local) (1 results) (Medium) - [unused-return](#unused-return) (1 results) (Medium) + - [pess-dubious-typecast](#pess-dubious-typecast) (8 results) (Medium) - [reentrancy-events](#reentrancy-events) (1 results) (Low) - [timestamp](#timestamp) (4 results) (Low) + - [pess-public-vs-external](#pess-public-vs-external) (4 results) (Low) - [assembly](#assembly) (5 results) (Informational) - [dead-code](#dead-code) (13 results) (Informational) - [solc-version](#solc-version) (1 results) (Informational) - [low-level-calls](#low-level-calls) (1 results) (Informational) - [similar-names](#similar-names) (1 results) (Informational) - [unused-state](#unused-state) (2 results) (Informational) + - [pess-magic-number](#pess-magic-number) (1 results) (Informational) - [constable-states](#constable-states) (1 results) (Optimization) +## pess-unprotected-setter +Impact: High +Confidence: Medium + - [ ] ID-0 +Function [Rollup.process(bytes,bytes32,bytes32,bytes,bytes)](src/core/Rollup.sol#L54-L94) is a non-protected setter archive is written + +src/core/Rollup.sol#L54-L94 + + ## uninitialized-local Impact: Medium Confidence: Medium - - [ ] ID-0 + - [ ] ID-1 [HeaderLib.decode(bytes).header](src/core/libraries/HeaderLib.sol#L133) is a local variable never initialized src/core/libraries/HeaderLib.sol#L133 @@ -22,16 +35,92 @@ src/core/libraries/HeaderLib.sol#L133 ## unused-return Impact: Medium Confidence: Medium - - [ ] ID-1 + - [ ] ID-2 [Rollup.process(bytes,bytes32,bytes32,bytes,bytes)](src/core/Rollup.sol#L54-L94) ignores return value by [(inHash,l1ToL2Msgs,l2ToL1Msgs) = MessagesDecoder.decode(_body)](src/core/Rollup.sol#L71-L72) src/core/Rollup.sol#L54-L94 +## pess-dubious-typecast +Impact: Medium +Confidence: High + - [ ] ID-3 +Dubious typecast in [TxsDecoder.read4(bytes,uint256)](src/core/libraries/decoders/TxsDecoder.sol#L298-L300): + bytes => bytes4 casting occurs in [uint256(uint32(bytes4(slice(_data,_offset,4))))](src/core/libraries/decoders/TxsDecoder.sol#L299) + +src/core/libraries/decoders/TxsDecoder.sol#L298-L300 + + + - [ ] ID-4 +Dubious typecast in [Decoder.read4(bytes,uint256)](src/core/libraries/decoders/Decoder.sol#L415-L417): + bytes => bytes4 casting occurs in [uint256(uint32(bytes4(slice(_data,_offset,4))))](src/core/libraries/decoders/Decoder.sol#L416) + +src/core/libraries/decoders/Decoder.sol#L415-L417 + + + - [ ] ID-5 +Dubious typecast in [Outbox.sendL1Messages(bytes32[])](src/core/messagebridge/Outbox.sol#L38-L46): + uint256 => uint32 casting occurs in [version = uint32(REGISTRY.getVersionFor(msg.sender))](src/core/messagebridge/Outbox.sol#L40) + +src/core/messagebridge/Outbox.sol#L38-L46 + + + - [ ] ID-6 +Dubious typecast in [Inbox.sendL2Message(DataStructures.L2Actor,uint32,bytes32,bytes32)](src/core/messagebridge/Inbox.sol#L45-L91): + uint256 => uint64 casting occurs in [fee = uint64(msg.value)](src/core/messagebridge/Inbox.sol#L64) + uint256 => uint32 casting occurs in [entries.insert(key,fee,uint32(_recipient.version),_deadline,_errIncompatibleEntryArguments)](src/core/messagebridge/Inbox.sol#L76) + +src/core/messagebridge/Inbox.sol#L45-L91 + + + - [ ] ID-7 +Dubious typecast in [HeaderLib.decode(bytes)](src/core/libraries/HeaderLib.sol#L128-L167): + bytes => bytes32 casting occurs in [header.lastArchive = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L136-L138) + bytes => bytes4 casting occurs in [header.lastArchive = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L136-L138) + bytes => bytes32 casting occurs in [header.bodyHash = bytes32(_header)](src/core/libraries/HeaderLib.sol#L141) + bytes => bytes32 casting occurs in [header.stateReference.l1ToL2MessageTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L144-L146) + bytes => bytes4 casting occurs in [header.stateReference.l1ToL2MessageTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L144-L146) + bytes => bytes32 casting occurs in [header.stateReference.partialStateReference.noteHashTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L147-L149) + bytes => bytes4 casting occurs in [header.stateReference.partialStateReference.noteHashTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L147-L149) + bytes => bytes32 casting occurs in [header.stateReference.partialStateReference.nullifierTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L150-L152) + bytes => bytes4 casting occurs in [header.stateReference.partialStateReference.nullifierTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L150-L152) + bytes => bytes32 casting occurs in [header.stateReference.partialStateReference.contractTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L153-L155) + bytes => bytes4 casting occurs in [header.stateReference.partialStateReference.contractTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L153-L155) + bytes => bytes32 casting occurs in [header.stateReference.partialStateReference.publicDataTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L156-L158) + bytes => bytes4 casting occurs in [header.stateReference.partialStateReference.publicDataTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L156-L158) + bytes => bytes32 casting occurs in [header.globalVariables.chainId = uint256(bytes32(_header))](src/core/libraries/HeaderLib.sol#L161) + bytes => bytes32 casting occurs in [header.globalVariables.version = uint256(bytes32(_header))](src/core/libraries/HeaderLib.sol#L162) + bytes => bytes32 casting occurs in [header.globalVariables.blockNumber = uint256(bytes32(_header))](src/core/libraries/HeaderLib.sol#L163) + bytes => bytes32 casting occurs in [header.globalVariables.timestamp = uint256(bytes32(_header))](src/core/libraries/HeaderLib.sol#L164) + +src/core/libraries/HeaderLib.sol#L128-L167 + + + - [ ] ID-8 +Dubious typecast in [MessagesDecoder.read4(bytes,uint256)](src/core/libraries/decoders/MessagesDecoder.sol#L110-L112): + bytes => bytes4 casting occurs in [uint256(uint32(bytes4(_data)))](src/core/libraries/decoders/MessagesDecoder.sol#L111) + +src/core/libraries/decoders/MessagesDecoder.sol#L110-L112 + + + - [ ] ID-9 +Dubious typecast in [Inbox.batchConsume(bytes32[],address)](src/core/messagebridge/Inbox.sol#L122-L143): + uint256 => uint32 casting occurs in [expectedVersion = uint32(REGISTRY.getVersionFor(msg.sender))](src/core/messagebridge/Inbox.sol#L128) + +src/core/messagebridge/Inbox.sol#L122-L143 + + + - [ ] ID-10 +Dubious typecast in [Decoder.getL2BlockNumber(bytes)](src/core/libraries/decoders/Decoder.sol#L132-L134): + bytes => bytes32 casting occurs in [uint256(bytes32(_l2Block))](src/core/libraries/decoders/Decoder.sol#L133) + +src/core/libraries/decoders/Decoder.sol#L132-L134 + + ## reentrancy-events Impact: Low Confidence: Medium - - [ ] ID-2 + - [ ] ID-11 Reentrancy in [Rollup.process(bytes,bytes32,bytes32,bytes,bytes)](src/core/Rollup.sol#L54-L94): External calls: - [inbox.batchConsume(l1ToL2Msgs,msg.sender)](src/core/Rollup.sol#L88) @@ -45,7 +134,7 @@ src/core/Rollup.sol#L54-L94 ## timestamp Impact: Low Confidence: Medium - - [ ] ID-3 + - [ ] ID-12 [Inbox.batchConsume(bytes32[],address)](src/core/messagebridge/Inbox.sol#L122-L143) uses timestamp for comparisons Dangerous comparisons: - [block.timestamp > entry.deadline](src/core/messagebridge/Inbox.sol#L136) @@ -53,7 +142,7 @@ Confidence: Medium src/core/messagebridge/Inbox.sol#L122-L143 - - [ ] ID-4 + - [ ] ID-13 [Inbox.sendL2Message(DataStructures.L2Actor,uint32,bytes32,bytes32)](src/core/messagebridge/Inbox.sol#L45-L91) uses timestamp for comparisons Dangerous comparisons: - [_deadline <= block.timestamp](src/core/messagebridge/Inbox.sol#L54) @@ -61,7 +150,7 @@ src/core/messagebridge/Inbox.sol#L122-L143 src/core/messagebridge/Inbox.sol#L45-L91 - - [ ] ID-5 + - [ ] ID-14 [HeaderLib.validate(HeaderLib.Header,uint256,uint256,bytes32)](src/core/libraries/HeaderLib.sol#L91-L121) uses timestamp for comparisons Dangerous comparisons: - [_header.globalVariables.timestamp > block.timestamp](src/core/libraries/HeaderLib.sol#L105) @@ -69,7 +158,7 @@ src/core/messagebridge/Inbox.sol#L45-L91 src/core/libraries/HeaderLib.sol#L91-L121 - - [ ] ID-6 + - [ ] ID-15 [Inbox.cancelL2Message(DataStructures.L1ToL2Msg,address)](src/core/messagebridge/Inbox.sol#L102-L113) uses timestamp for comparisons Dangerous comparisons: - [block.timestamp <= _message.deadline](src/core/messagebridge/Inbox.sol#L108) @@ -77,24 +166,58 @@ src/core/libraries/HeaderLib.sol#L91-L121 src/core/messagebridge/Inbox.sol#L102-L113 +## pess-public-vs-external +Impact: Low +Confidence: Medium + - [ ] ID-16 +The following public functions could be turned into external in [Registry](src/core/messagebridge/Registry.sol#L22-L129) contract: + [Registry.constructor()](src/core/messagebridge/Registry.sol#L29-L33) + +src/core/messagebridge/Registry.sol#L22-L129 + + + - [ ] ID-17 +The following public functions could be turned into external in [Rollup](src/core/Rollup.sol#L27-L103) contract: + [Rollup.constructor(IRegistry,IAvailabilityOracle)](src/core/Rollup.sol#L39-L44) + +src/core/Rollup.sol#L27-L103 + + + - [ ] ID-18 +The following public functions could be turned into external in [Outbox](src/core/messagebridge/Outbox.sol#L21-L149) contract: + [Outbox.constructor(address)](src/core/messagebridge/Outbox.sol#L29-L31) + [Outbox.get(bytes32)](src/core/messagebridge/Outbox.sol#L78-L85) + [Outbox.contains(bytes32)](src/core/messagebridge/Outbox.sol#L92-L94) + +src/core/messagebridge/Outbox.sol#L21-L149 + + + - [ ] ID-19 +The following public functions could be turned into external in [Inbox](src/core/messagebridge/Inbox.sol#L21-L231) contract: + [Inbox.constructor(address)](src/core/messagebridge/Inbox.sol#L30-L32) + [Inbox.contains(bytes32)](src/core/messagebridge/Inbox.sol#L174-L176) + +src/core/messagebridge/Inbox.sol#L21-L231 + + ## assembly Impact: Informational Confidence: High - - [ ] ID-7 + - [ ] ID-20 [Decoder.computeRoot(bytes32[])](src/core/libraries/decoders/Decoder.sol#L373-L392) uses assembly - [INLINE ASM](src/core/libraries/decoders/Decoder.sol#L380-L382) src/core/libraries/decoders/Decoder.sol#L373-L392 - - [ ] ID-8 + - [ ] ID-21 [TxsDecoder.decode(bytes)](src/core/libraries/decoders/TxsDecoder.sol#L71-L184) uses assembly - [INLINE ASM](src/core/libraries/decoders/TxsDecoder.sol#L98-L104) src/core/libraries/decoders/TxsDecoder.sol#L71-L184 - - [ ] ID-9 + - [ ] ID-22 [Decoder.computeConsumables(bytes)](src/core/libraries/decoders/Decoder.sol#L164-L301) uses assembly - [INLINE ASM](src/core/libraries/decoders/Decoder.sol#L196-L202) - [INLINE ASM](src/core/libraries/decoders/Decoder.sol#L289-L295) @@ -102,14 +225,14 @@ src/core/libraries/decoders/TxsDecoder.sol#L71-L184 src/core/libraries/decoders/Decoder.sol#L164-L301 - - [ ] ID-10 + - [ ] ID-23 [TxsDecoder.computeRoot(bytes32[])](src/core/libraries/decoders/TxsDecoder.sol#L256-L275) uses assembly - [INLINE ASM](src/core/libraries/decoders/TxsDecoder.sol#L263-L265) src/core/libraries/decoders/TxsDecoder.sol#L256-L275 - - [ ] ID-11 + - [ ] ID-24 [MessagesDecoder.decode(bytes)](src/core/libraries/decoders/MessagesDecoder.sol#L52-L102) uses assembly - [INLINE ASM](src/core/libraries/decoders/MessagesDecoder.sol#L81-L83) - [INLINE ASM](src/core/libraries/decoders/MessagesDecoder.sol#L94-L96) @@ -120,79 +243,79 @@ src/core/libraries/decoders/MessagesDecoder.sol#L52-L102 ## dead-code Impact: Informational Confidence: Medium - - [ ] ID-12 + - [ ] ID-25 [Decoder.computeConsumables(bytes)](src/core/libraries/decoders/Decoder.sol#L164-L301) is never used and should be removed src/core/libraries/decoders/Decoder.sol#L164-L301 - - [ ] ID-13 + - [ ] ID-26 [Inbox._errIncompatibleEntryArguments(bytes32,uint64,uint64,uint32,uint32,uint32,uint32)](src/core/messagebridge/Inbox.sol#L212-L230) is never used and should be removed src/core/messagebridge/Inbox.sol#L212-L230 - - [ ] ID-14 + - [ ] ID-27 [Decoder.slice(bytes,uint256,uint256)](src/core/libraries/decoders/Decoder.sol#L401-L407) is never used and should be removed src/core/libraries/decoders/Decoder.sol#L401-L407 - - [ ] ID-15 + - [ ] ID-28 [Outbox._errNothingToConsume(bytes32)](src/core/messagebridge/Outbox.sol#L115-L117) is never used and should be removed src/core/messagebridge/Outbox.sol#L115-L117 - - [ ] ID-16 + - [ ] ID-29 [Decoder.computeRoot(bytes32[])](src/core/libraries/decoders/Decoder.sol#L373-L392) is never used and should be removed src/core/libraries/decoders/Decoder.sol#L373-L392 - - [ ] ID-17 + - [ ] ID-30 [Hash.sha256ToField(bytes32)](src/core/libraries/Hash.sol#L59-L61) is never used and should be removed src/core/libraries/Hash.sol#L59-L61 - - [ ] ID-18 + - [ ] ID-31 [Decoder.computeKernelLogsHash(uint256,bytes)](src/core/libraries/decoders/Decoder.sol#L335-L365) is never used and should be removed src/core/libraries/decoders/Decoder.sol#L335-L365 - - [ ] ID-19 + - [ ] ID-32 [Decoder.read4(bytes,uint256)](src/core/libraries/decoders/Decoder.sol#L415-L417) is never used and should be removed src/core/libraries/decoders/Decoder.sol#L415-L417 - - [ ] ID-20 + - [ ] ID-33 [Decoder.computeStateHash(uint256,uint256,bytes)](src/core/libraries/decoders/Decoder.sol#L146-L154) is never used and should be removed src/core/libraries/decoders/Decoder.sol#L146-L154 - - [ ] ID-21 + - [ ] ID-34 [Decoder.computePublicInputHash(bytes,bytes32,bytes32)](src/core/libraries/decoders/Decoder.sol#L118-L125) is never used and should be removed src/core/libraries/decoders/Decoder.sol#L118-L125 - - [ ] ID-22 + - [ ] ID-35 [Inbox._errNothingToConsume(bytes32)](src/core/messagebridge/Inbox.sol#L197-L199) is never used and should be removed src/core/messagebridge/Inbox.sol#L197-L199 - - [ ] ID-23 + - [ ] ID-36 [Decoder.getL2BlockNumber(bytes)](src/core/libraries/decoders/Decoder.sol#L132-L134) is never used and should be removed src/core/libraries/decoders/Decoder.sol#L132-L134 - - [ ] ID-24 + - [ ] ID-37 [Outbox._errIncompatibleEntryArguments(bytes32,uint64,uint64,uint32,uint32,uint32,uint32)](src/core/messagebridge/Outbox.sol#L130-L148) is never used and should be removed src/core/messagebridge/Outbox.sol#L130-L148 @@ -201,13 +324,13 @@ src/core/messagebridge/Outbox.sol#L130-L148 ## solc-version Impact: Informational Confidence: High - - [ ] ID-25 + - [ ] ID-38 solc-0.8.21 is not recommended for deployment ## low-level-calls Impact: Informational Confidence: High - - [ ] ID-26 + - [ ] ID-39 Low level call in [Inbox.withdrawFees()](src/core/messagebridge/Inbox.sol#L148-L153): - [(success) = msg.sender.call{value: balance}()](src/core/messagebridge/Inbox.sol#L151) @@ -217,7 +340,7 @@ src/core/messagebridge/Inbox.sol#L148-L153 ## similar-names Impact: Informational Confidence: Medium - - [ ] ID-27 + - [ ] ID-40 Variable [Rollup.AVAILABILITY_ORACLE](src/core/Rollup.sol#L30) is too similar to [Rollup.constructor(IRegistry,IAvailabilityOracle)._availabilityOracle](src/core/Rollup.sol#L39) src/core/Rollup.sol#L30 @@ -226,22 +349,33 @@ src/core/Rollup.sol#L30 ## unused-state Impact: Informational Confidence: High - - [ ] ID-28 + - [ ] ID-41 [Decoder.END_TREES_BLOCK_HEADER_OFFSET](src/core/libraries/decoders/Decoder.sol#L103-L104) is never used in [Decoder](src/core/libraries/decoders/Decoder.sol#L72-L418) src/core/libraries/decoders/Decoder.sol#L103-L104 - - [ ] ID-29 + - [ ] ID-42 [Decoder.BLOCK_HEADER_OFFSET](src/core/libraries/decoders/Decoder.sol#L107-L108) is never used in [Decoder](src/core/libraries/decoders/Decoder.sol#L72-L418) src/core/libraries/decoders/Decoder.sol#L107-L108 +## pess-magic-number +Impact: Informational +Confidence: High + - [ ] ID-43 +Magic number 376 is used multiple times in: + [_header.length != 376](src/core/libraries/HeaderLib.sol#L129) + [Errors.HeaderLib__InvalidHeaderSize(376,_header.length)](src/core/libraries/HeaderLib.sol#L130) + +src/core/libraries/HeaderLib.sol#L129 + + ## constable-states Impact: Optimization Confidence: High - - [ ] ID-30 + - [ ] ID-44 [Rollup.lastWarpedBlockTs](src/core/Rollup.sol#L37) should be constant src/core/Rollup.sol#L37 From 348d18aa3c864fc80fc791029b2d91ee9e7e33d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Rodr=C3=ADguez?= Date: Wed, 31 Jan 2024 13:44:41 +0100 Subject: [PATCH 09/20] chore: git subrepo commit (merge) noir (#4321) subrepo: subdir: "noir" merged: "ab74cff2b" upstream: origin: "https://github.com/noir-lang/noir" branch: "aztec-packages" commit: "2badd023e" git-subrepo: version: "0.4.6" origin: "https://github.com/ingydotnet/git-subrepo" commit: "110b9eb" Please read [contributing guidelines](CONTRIBUTING.md) and remove this line. --- noir/.github/workflows/release.yml | 2 +- noir/.gitrepo | 2 +- .../acvm/src/compiler/transformers/mod.rs | 57 +---- noir/acvm-repo/acvm_js/src/logging.rs | 25 ++- noir/aztec_macros/src/lib.rs | 10 +- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 4 +- .../docs/noir/concepts/data_types/fields.md | 17 ++ .../NoirJS/backend_barretenberg/.nojekyll | 1 - .../classes/BarretenbergBackend.md | 202 ------------------ .../NoirJS/backend_barretenberg/index.md | 46 ---- .../interfaces/Backend.md | 132 ------------ .../type-aliases/BackendOptions.md | 19 -- .../type-aliases/CompiledCircuit.md | 20 -- .../type-aliases/ProofData.md | 20 -- .../backend_barretenberg/typedoc-sidebar.cjs | 4 - .../docs/reference/NoirJS/noir_js/.nojekyll | 1 - .../reference/NoirJS/noir_js/classes/Noir.md | 132 ------------ .../reference/NoirJS/noir_js/functions/and.md | 22 -- .../NoirJS/noir_js/functions/blake2s256.md | 21 -- .../functions/ecdsa_secp256k1_verify.md | 28 --- .../functions/ecdsa_secp256r1_verify.md | 28 --- .../NoirJS/noir_js/functions/keccak256.md | 21 -- .../NoirJS/noir_js/functions/sha256.md | 21 -- .../reference/NoirJS/noir_js/functions/xor.md | 22 -- .../docs/reference/NoirJS/noir_js/index.md | 37 ---- .../noir_js/type-aliases/CompiledCircuit.md | 20 -- .../type-aliases/ForeignCallHandler.md | 24 --- .../noir_js/type-aliases/ForeignCallInput.md | 9 - .../noir_js/type-aliases/ForeignCallOutput.md | 9 - .../NoirJS/noir_js/type-aliases/InputMap.md | 13 -- .../NoirJS/noir_js/type-aliases/ProofData.md | 20 -- .../NoirJS/noir_js/type-aliases/WitnessMap.md | 9 - .../NoirJS/noir_js/typedoc-sidebar.cjs | 4 - noir/docs/docusaurus.config.ts | 4 +- noir/docs/package.json | 3 +- noir/noir_stdlib/src/bigint.nr | 13 +- noir/noir_stdlib/src/collections.nr | 1 + .../src/collections/bounded_vec.nr | 88 ++++++++ noir/noir_stdlib/src/lib.nr | 2 +- noir/noir_stdlib/src/prelude.nr | 1 + noir/noir_stdlib/src/scalar_mul.nr | 26 ++- .../execution_success/scalar_mul/src/main.nr | 14 +- .../noir_test_success/bounded_vec/Nargo.toml | 7 + .../noir_test_success/bounded_vec/Prover.toml | 0 .../noir_test_success/bounded_vec/src/main.nr | 105 +++++++++ noir/tooling/bb_abstraction_leaks/build.rs | 2 +- .../noir_js_backend_barretenberg/package.json | 2 +- noir/yarn.lock | 10 +- .../aztec-nr/authwit/src/entrypoint.nr | 3 +- yarn-project/aztec-nr/aztec/src/context.nr | 1 - yarn-project/aztec-nr/aztec/src/lib.nr | 1 - .../aztec-nr/aztec/src/note/note_getter.nr | 1 - .../aztec/src/note/note_getter_options.nr | 1 - .../aztec/src/note/note_viewer_options.nr | 1 - yarn-project/aztec-nr/aztec/src/types.nr | 1 - yarn-project/aztec-nr/aztec/src/types/vec.nr | 126 ----------- .../src/main.nr | 1 - .../contracts/test_contract/src/main.nr | 3 +- .../crates/private-kernel-lib/src/common.nr | 15 +- .../src/private_kernel_init.nr | 14 +- .../src/private_kernel_inner.nr | 19 +- .../src/private_kernel_ordering.nr | 2 - .../crates/public-kernel-lib/src/common.nr | 13 +- .../src/public_kernel_private_previous.nr | 3 +- .../src/public_kernel_public_previous.nr | 8 +- .../rollup-lib/src/base/base_rollup_inputs.nr | 1 - .../src/abis/combined_accumulated_data.nr | 3 +- .../src/abis/private_circuit_public_inputs.nr | 45 ++-- .../src/abis/public_circuit_public_inputs.nr | 31 ++- .../src/crates/types/src/hash.nr | 1 - .../src/crates/types/src/header.nr | 9 +- .../src/crates/types/src/state_reference.nr | 5 +- .../types/src/tests/fixtures/read_requests.nr | 1 - .../src/tests/private_call_data_builder.nr | 19 +- .../private_circuit_public_inputs_builder.nr | 1 - .../src/tests/public_call_data_builder.nr | 1 - .../public_circuit_public_inputs_builder.nr | 1 - .../src/crates/types/src/utils.nr | 1 - .../src/crates/types/src/utils/arrays.nr | 1 - .../src/crates/types/src/utils/bounded_vec.nr | 194 ----------------- yarn-project/yarn.lock | 2 +- 81 files changed, 383 insertions(+), 1426 deletions(-) delete mode 100644 noir/docs/docs/reference/NoirJS/backend_barretenberg/.nojekyll delete mode 100644 noir/docs/docs/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md delete mode 100644 noir/docs/docs/reference/NoirJS/backend_barretenberg/index.md delete mode 100644 noir/docs/docs/reference/NoirJS/backend_barretenberg/interfaces/Backend.md delete mode 100644 noir/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md delete mode 100644 noir/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md delete mode 100644 noir/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md delete mode 100644 noir/docs/docs/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/.nojekyll delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/classes/Noir.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/functions/and.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/functions/blake2s256.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/functions/keccak256.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/functions/sha256.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/functions/xor.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/index.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/type-aliases/InputMap.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ProofData.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/type-aliases/WitnessMap.md delete mode 100644 noir/docs/docs/reference/NoirJS/noir_js/typedoc-sidebar.cjs create mode 100644 noir/noir_stdlib/src/collections/bounded_vec.nr create mode 100644 noir/test_programs/noir_test_success/bounded_vec/Nargo.toml create mode 100644 noir/test_programs/noir_test_success/bounded_vec/Prover.toml create mode 100644 noir/test_programs/noir_test_success/bounded_vec/src/main.nr delete mode 100644 yarn-project/aztec-nr/aztec/src/types.nr delete mode 100644 yarn-project/aztec-nr/aztec/src/types/vec.nr delete mode 100644 yarn-project/noir-protocol-circuits/src/crates/types/src/utils/bounded_vec.nr diff --git a/noir/.github/workflows/release.yml b/noir/.github/workflows/release.yml index 7dfc844d18f..71a0ab6d894 100644 --- a/noir/.github/workflows/release.yml +++ b/noir/.github/workflows/release.yml @@ -87,7 +87,7 @@ jobs: - name: Cut a new version working-directory: ./docs - run: yarn docusaurus docs:version ${{ steps.noir-version.outputs.semver }} + run: yarn version ${{ steps.noir-version.outputs.semver }} - name: Configure git run: | diff --git a/noir/.gitrepo b/noir/.gitrepo index 940fb7a0483..aca0a674c07 100644 --- a/noir/.gitrepo +++ b/noir/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/noir-lang/noir branch = aztec-packages - commit = ea6aebcc4e190d9dbadaf1dd0f70950651eed615 + commit = 2badd023eab159b7892bd507897bedb360bebebe parent = 3b25737324e45bdfb49233f73065569301282cc0 method = merge cmdver = 0.4.6 diff --git a/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs b/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs index 970eb9390bb..e184401c5d4 100644 --- a/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -99,61 +99,8 @@ pub(super) fn transform_internal( } } Opcode::BlackBoxFuncCall(ref func) => { - match func { - acir::circuit::opcodes::BlackBoxFuncCall::AND { output, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::XOR { output, .. } => { - transformer.mark_solvable(*output); - } - acir::circuit::opcodes::BlackBoxFuncCall::RANGE { .. } - | acir::circuit::opcodes::BlackBoxFuncCall::RecursiveAggregation { .. } - | acir::circuit::opcodes::BlackBoxFuncCall::BigIntFromLeBytes { .. } - | acir::circuit::opcodes::BlackBoxFuncCall::BigIntAdd { .. } - | acir::circuit::opcodes::BlackBoxFuncCall::BigIntNeg { .. } - | acir::circuit::opcodes::BlackBoxFuncCall::BigIntMul { .. } - | acir::circuit::opcodes::BlackBoxFuncCall::BigIntDiv { .. } => (), - acir::circuit::opcodes::BlackBoxFuncCall::SHA256 { outputs, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::Keccak256 { outputs, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::Keccak256VariableLength { - outputs, - .. - } - | acir::circuit::opcodes::BlackBoxFuncCall::Keccakf1600 { outputs, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::Blake2s { outputs, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::Blake3 { outputs, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::BigIntToLeBytes { - outputs, .. - } - | acir::circuit::opcodes::BlackBoxFuncCall::Poseidon2Permutation { - outputs, - .. - } - | acir::circuit::opcodes::BlackBoxFuncCall::Sha256Compression { - outputs, .. - } => { - for witness in outputs { - transformer.mark_solvable(*witness); - } - } - acir::circuit::opcodes::BlackBoxFuncCall::FixedBaseScalarMul { - outputs, - .. - } - | acir::circuit::opcodes::BlackBoxFuncCall::EmbeddedCurveAdd { - outputs, .. - } - | acir::circuit::opcodes::BlackBoxFuncCall::PedersenCommitment { - outputs, - .. - } => { - transformer.mark_solvable(outputs.0); - transformer.mark_solvable(outputs.1); - } - acir::circuit::opcodes::BlackBoxFuncCall::EcdsaSecp256k1 { output, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::EcdsaSecp256r1 { output, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::SchnorrVerify { output, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::PedersenHash { output, .. } => { - transformer.mark_solvable(*output); - } + for witness in func.get_outputs_vec() { + transformer.mark_solvable(witness); } new_acir_opcode_positions.push(acir_opcode_positions[index]); diff --git a/noir/acvm-repo/acvm_js/src/logging.rs b/noir/acvm-repo/acvm_js/src/logging.rs index f5d71fae067..483c23ab624 100644 --- a/noir/acvm-repo/acvm_js/src/logging.rs +++ b/noir/acvm-repo/acvm_js/src/logging.rs @@ -1,3 +1,4 @@ +use js_sys::{Error, JsString}; use tracing_subscriber::prelude::*; use tracing_subscriber::EnvFilter; use tracing_web::MakeWebConsoleWriter; @@ -7,12 +8,15 @@ use wasm_bindgen::prelude::*; /// /// @param {LogLevel} level - The maximum level of logging to be emitted. #[wasm_bindgen(js_name = initLogLevel, skip_jsdoc)] -pub fn init_log_level(filter: String) { +pub fn init_log_level(filter: String) -> Result<(), JsLogInitError> { // Set the static variable from Rust use std::sync::Once; - let filter: EnvFilter = - filter.parse().expect("Could not parse log filter while initializing logger"); + let filter: EnvFilter = filter.parse().map_err(|err| { + JsLogInitError::constructor( + format!("Could not parse log filter while initializing logger: {err}").into(), + ) + })?; static SET_HOOK: Once = Once::new(); SET_HOOK.call_once(|| { @@ -23,4 +27,19 @@ pub fn init_log_level(filter: String) { tracing_subscriber::registry().with(fmt_layer.with_filter(filter)).init(); }); + + Ok(()) +} + +/// `LogInitError` is a raw js error. +/// It'd be ideal that `LogInitError` was a subclass of Error, but for that we'd need to use JS snippets or a js module. +/// Currently JS snippets don't work with a nodejs target. And a module would be too much for just a custom error type. +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(extends = Error, js_name = "LogInitError", typescript_type = "LogInitError")] + #[derive(Clone, Debug, PartialEq, Eq)] + pub type JsLogInitError; + + #[wasm_bindgen(constructor, js_class = "Error")] + fn constructor(message: JsString) -> JsLogInitError; } diff --git a/noir/aztec_macros/src/lib.rs b/noir/aztec_macros/src/lib.rs index e2c232e3233..b1d401b4e53 100644 --- a/noir/aztec_macros/src/lib.rs +++ b/noir/aztec_macros/src/lib.rs @@ -846,11 +846,11 @@ fn make_return_push(push_value: Expression) -> Statement { /// Make Return push array /// /// Translates to: -/// `context.return_values.push_array({push_value})` -fn make_return_push_array(push_value: Expression) -> Statement { +/// `context.return_values.extend_from_array({push_value})` +fn make_return_extend_from_array(push_value: Expression) -> Statement { make_statement(StatementKind::Semi(method_call( context_return_values(), - "push_array", + "extend_from_array", vec![push_value], ))) } @@ -859,14 +859,14 @@ fn make_return_push_array(push_value: Expression) -> Statement { /// /// Translates to: /// ```noir -/// `context.return_values.push_array({push_value}.serialize())` +/// `context.return_values.extend_from_array({push_value}.serialize())` fn make_struct_return_type(expression: Expression) -> Statement { let serialized_call = method_call( expression, // variable "serialize", // method name vec![], // args ); - make_return_push_array(serialized_call) + make_return_extend_from_array(serialized_call) } /// Make array return type diff --git a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 217ea3f7584..d56d0ade3c4 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -400,8 +400,8 @@ impl AcirContext { // Operands are booleans. // // a ^ b == a + b - 2*a*b - let sum = self.add_var(lhs, rhs)?; let prod = self.mul_var(lhs, rhs)?; + let sum = self.add_var(lhs, rhs)?; self.add_mul_var(sum, -FieldElement::from(2_i128), prod) } else { let inputs = vec![AcirValue::Var(lhs, typ.clone()), AcirValue::Var(rhs, typ)]; @@ -461,8 +461,8 @@ impl AcirContext { if bit_size == 1 { // Operands are booleans // a + b - ab - let sum = self.add_var(lhs, rhs)?; let mul = self.mul_var(lhs, rhs)?; + let sum = self.add_var(lhs, rhs)?; self.sub_var(sum, mul) } else { // Implement OR in terms of AND diff --git a/noir/docs/docs/noir/concepts/data_types/fields.md b/noir/docs/docs/noir/concepts/data_types/fields.md index a1c67945d66..7870c98c858 100644 --- a/noir/docs/docs/noir/concepts/data_types/fields.md +++ b/noir/docs/docs/noir/concepts/data_types/fields.md @@ -157,6 +157,23 @@ fn main() { } ``` +### assert_max_bit_size + +Adds a constraint to specify that the field can be represented with `bit_size` number of bits + +```rust +fn assert_max_bit_size(self, bit_size: u32) +``` + +example: + +```rust +fn main() { + let field = 2 + field.assert_max_bit_size(32); +} +``` + ### sgn0 Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. diff --git a/noir/docs/docs/reference/NoirJS/backend_barretenberg/.nojekyll b/noir/docs/docs/reference/NoirJS/backend_barretenberg/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/docs/docs/reference/NoirJS/backend_barretenberg/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/docs/docs/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/noir/docs/docs/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md deleted file mode 100644 index af4a7558cdf..00000000000 --- a/noir/docs/docs/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md +++ /dev/null @@ -1,202 +0,0 @@ -# BarretenbergBackend - -## Implements - -- [`Backend`](../interfaces/Backend.md) - -## Constructors - -### new BarretenbergBackend(acirCircuit, options) - -```ts -new BarretenbergBackend(acirCircuit, options): BarretenbergBackend -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - -#### Returns - -[`BarretenbergBackend`](BarretenbergBackend.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -Generate a final proof. This is the proof for the circuit which will verify -intermediate proofs and or can be seen as the proof created for regular circuits. - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateFinalProof`](../interfaces/Backend.md#generatefinalproof) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(witness): Promise -``` - -Generates an intermediate proof. This is the proof that can be verified -in another circuit. - -This is sometimes referred to as a recursive proof. -We avoid this terminology as the only property of this proof -that matters is the fact that it is easy to verify in another circuit. -We _could_ choose to verify this proof outside of a circuit just as easily. - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `witness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProof`](../interfaces/Backend.md#generateintermediateproof) - -#### Example - -```typescript -const intermediateProof = await backend.generateIntermediateProof(witness); -``` - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -Generates artifacts that will be passed to a circuit that will verify this proof. - -Instead of passing the proof and verification key as a byte array, we pass them -as fields which makes it cheaper to verify in a circuit. - -The proof that is passed here will have been created using the `generateIntermediateProof` -method. - -The number of public inputs denotes how many public inputs are in the inner proof. - -#### Parameters - -| Parameter | Type | Default value | -| :------ | :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | -| `numOfPublicInputs` | `number` | `0` | - -#### Returns - -`Promise`\<`object`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`generateIntermediateProofArtifacts`](../interfaces/Backend.md#generateintermediateproofartifacts) - -#### Example - -```typescript -const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyFinalProof`](../interfaces/Backend.md#verifyfinalproof) - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Implementation of - -[`Backend`](../interfaces/Backend.md).[`verifyIntermediateProof`](../interfaces/Backend.md#verifyintermediateproof) - -#### Example - -```typescript -const isValidIntermediate = await backend.verifyIntermediateProof(proof); -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/backend_barretenberg/index.md b/noir/docs/docs/reference/NoirJS/backend_barretenberg/index.md deleted file mode 100644 index e32501acb71..00000000000 --- a/noir/docs/docs/reference/NoirJS/backend_barretenberg/index.md +++ /dev/null @@ -1,46 +0,0 @@ -# backend_barretenberg - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | - -### Interfaces - -| Interface | Description | -| :------ | :------ | -| [Backend](interfaces/Backend.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [BackendOptions](type-aliases/BackendOptions.md) | - | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | - -## Functions - -### publicInputsToWitnessMap() - -```ts -publicInputsToWitnessMap(publicInputs, abi): WitnessMap -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `publicInputs` | `string`[] | -| `abi` | `Abi` | - -#### Returns - -`WitnessMap` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/backend_barretenberg/interfaces/Backend.md b/noir/docs/docs/reference/NoirJS/backend_barretenberg/interfaces/Backend.md deleted file mode 100644 index 3eb9645c8d2..00000000000 --- a/noir/docs/docs/reference/NoirJS/backend_barretenberg/interfaces/Backend.md +++ /dev/null @@ -1,132 +0,0 @@ -# Backend - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the backend - -*** - -### generateFinalProof() - -```ts -generateFinalProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a final proof (not meant to be verified in another circuit) - -*** - -### generateIntermediateProof() - -```ts -generateIntermediateProof(decompressedWitness): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `decompressedWitness` | `Uint8Array` | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates an intermediate proof (meant to be verified in another circuit) - -*** - -### generateIntermediateProofArtifacts() - -```ts -generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | -| `numOfPublicInputs` | `number` | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Retrieves the artifacts from a proof in the Field format - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies a final proof - -*** - -### verifyIntermediateProof() - -```ts -verifyIntermediateProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Verifies an intermediate proof - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/noir/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md deleted file mode 100644 index 266ade75d17..00000000000 --- a/noir/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md +++ /dev/null @@ -1,19 +0,0 @@ -# BackendOptions - -```ts -type BackendOptions: object; -``` - -## Description - -An options object, currently only used to specify the number of threads to use. - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `threads` | `number` | **Description**

Number of threads | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md b/noir/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md b/noir/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md deleted file mode 100644 index 05cebbc4e94..00000000000 --- a/noir/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `string`[] | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/noir/docs/docs/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs deleted file mode 100644 index 2aaa55bccf6..00000000000 --- a/noir/docs/docs/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/docs/docs/reference/NoirJS/noir_js/.nojekyll b/noir/docs/docs/reference/NoirJS/noir_js/.nojekyll deleted file mode 100644 index e2ac6616add..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/docs/docs/reference/NoirJS/noir_js/classes/Noir.md b/noir/docs/docs/reference/NoirJS/noir_js/classes/Noir.md deleted file mode 100644 index 34e20d99684..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/classes/Noir.md +++ /dev/null @@ -1,132 +0,0 @@ -# Noir - -## Constructors - -### new Noir(circuit, backend) - -```ts -new Noir(circuit, backend?): Noir -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | -| `backend`? | `Backend` | - -#### Returns - -[`Noir`](Noir.md) - -## Methods - -### destroy() - -```ts -destroy(): Promise -``` - -#### Returns - -`Promise`\<`void`\> - -#### Description - -Destroys the underlying backend instance. - -#### Example - -```typescript -await noir.destroy(); -``` - -*** - -### execute() - -```ts -execute(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<`object`\> - -#### Description - -Allows to execute a circuit to get its witness and return value. - -#### Example - -```typescript -async execute(inputs) -``` - -*** - -### generateFinalProof() - -```ts -generateFinalProof(inputs, foreignCallHandler?): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | -| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | - -#### Returns - -`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> - -#### Description - -Generates a witness and a proof given an object as input. - -#### Example - -```typescript -async generateFinalProof(input) -``` - -*** - -### verifyFinalProof() - -```ts -verifyFinalProof(proofData): Promise -``` - -#### Parameters - -| Parameter | Type | -| :------ | :------ | -| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | - -#### Returns - -`Promise`\<`boolean`\> - -#### Description - -Instantiates the verification key and verifies a proof. - -#### Example - -```typescript -async verifyFinalProof(proof) -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/functions/and.md b/noir/docs/docs/reference/NoirJS/noir_js/functions/and.md deleted file mode 100644 index c783283e396..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/functions/and.md +++ /dev/null @@ -1,22 +0,0 @@ -# and() - -```ts -and(lhs, rhs): string -``` - -Performs a bitwise AND operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/functions/blake2s256.md b/noir/docs/docs/reference/NoirJS/noir_js/functions/blake2s256.md deleted file mode 100644 index 7882d0da8d5..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/functions/blake2s256.md +++ /dev/null @@ -1,21 +0,0 @@ -# blake2s256() - -```ts -blake2s256(inputs): Uint8Array -``` - -Calculates the Blake2s256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md deleted file mode 100644 index 5e3cd53e9d3..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256k1\_verify() - -```ts -ecdsa_secp256k1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256k1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md deleted file mode 100644 index 0b20ff68957..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md +++ /dev/null @@ -1,28 +0,0 @@ -# ecdsa\_secp256r1\_verify() - -```ts -ecdsa_secp256r1_verify( - hashed_msg, - public_key_x_bytes, - public_key_y_bytes, - signature): boolean -``` - -Verifies a ECDSA signature over the secp256r1 curve. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `hashed_msg` | `Uint8Array` | | -| `public_key_x_bytes` | `Uint8Array` | | -| `public_key_y_bytes` | `Uint8Array` | | -| `signature` | `Uint8Array` | | - -## Returns - -`boolean` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/functions/keccak256.md b/noir/docs/docs/reference/NoirJS/noir_js/functions/keccak256.md deleted file mode 100644 index d10f155ce86..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/functions/keccak256.md +++ /dev/null @@ -1,21 +0,0 @@ -# keccak256() - -```ts -keccak256(inputs): Uint8Array -``` - -Calculates the Keccak256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/functions/sha256.md b/noir/docs/docs/reference/NoirJS/noir_js/functions/sha256.md deleted file mode 100644 index 6ba4ecac022..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/functions/sha256.md +++ /dev/null @@ -1,21 +0,0 @@ -# sha256() - -```ts -sha256(inputs): Uint8Array -``` - -Calculates the SHA256 hash of the input bytes - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `inputs` | `Uint8Array` | | - -## Returns - -`Uint8Array` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/functions/xor.md b/noir/docs/docs/reference/NoirJS/noir_js/functions/xor.md deleted file mode 100644 index 8d762b895d3..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/functions/xor.md +++ /dev/null @@ -1,22 +0,0 @@ -# xor() - -```ts -xor(lhs, rhs): string -``` - -Performs a bitwise XOR operation between `lhs` and `rhs` - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `lhs` | `string` | | -| `rhs` | `string` | | - -## Returns - -`string` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/index.md b/noir/docs/docs/reference/NoirJS/noir_js/index.md deleted file mode 100644 index d600e21b299..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/index.md +++ /dev/null @@ -1,37 +0,0 @@ -# noir_js - -## Exports - -### Classes - -| Class | Description | -| :------ | :------ | -| [Noir](classes/Noir.md) | - | - -### Type Aliases - -| Type alias | Description | -| :------ | :------ | -| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | -| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | -| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | -| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | -| [InputMap](type-aliases/InputMap.md) | - | -| [ProofData](type-aliases/ProofData.md) | - | -| [WitnessMap](type-aliases/WitnessMap.md) | - | - -### Functions - -| Function | Description | -| :------ | :------ | -| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | -| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | -| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Verifies a ECDSA signature over the secp256k1 curve. | -| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | -| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | -| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | -| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md b/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md deleted file mode 100644 index 34e0dd04205..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md +++ /dev/null @@ -1,20 +0,0 @@ -# CompiledCircuit - -```ts -type CompiledCircuit: object; -``` - -## Description - -The representation of a compiled circuit - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `abi` | `Abi` | **Description**

ABI representation of the circuit | -| `bytecode` | `string` | **Description**

The bytecode of the circuit | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md deleted file mode 100644 index 812b8b16481..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md +++ /dev/null @@ -1,24 +0,0 @@ -# ForeignCallHandler - -```ts -type ForeignCallHandler: (name, inputs) => Promise; -``` - -A callback which performs an foreign call and returns the response. - -## Parameters - -| Parameter | Type | Description | -| :------ | :------ | :------ | -| `name` | `string` | The identifier for the type of foreign call being performed. | -| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | - -## Returns - -`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> - -outputs - An array of hex encoded outputs containing the results of the foreign call. - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md deleted file mode 100644 index dd95809186a..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallInput - -```ts -type ForeignCallInput: string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md deleted file mode 100644 index b71fb78a946..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md +++ /dev/null @@ -1,9 +0,0 @@ -# ForeignCallOutput - -```ts -type ForeignCallOutput: string | string[]; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/InputMap.md b/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/InputMap.md deleted file mode 100644 index c714e999d93..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/InputMap.md +++ /dev/null @@ -1,13 +0,0 @@ -# InputMap - -```ts -type InputMap: object; -``` - -## Index signature - - \[`key`: `string`\]: `InputValue` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ProofData.md b/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ProofData.md deleted file mode 100644 index 05cebbc4e94..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/ProofData.md +++ /dev/null @@ -1,20 +0,0 @@ -# ProofData - -```ts -type ProofData: object; -``` - -## Description - -The representation of a proof - -## Type declaration - -| Member | Type | Description | -| :------ | :------ | :------ | -| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | -| `publicInputs` | `string`[] | **Description**

Public inputs of a proof | - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/WitnessMap.md deleted file mode 100644 index 258c46f9d0c..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/type-aliases/WitnessMap.md +++ /dev/null @@ -1,9 +0,0 @@ -# WitnessMap - -```ts -type WitnessMap: Map; -``` - -*** - -Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/docs/docs/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/noir/docs/docs/reference/NoirJS/noir_js/typedoc-sidebar.cjs deleted file mode 100644 index fe2629ddc9f..00000000000 --- a/noir/docs/docs/reference/NoirJS/noir_js/typedoc-sidebar.cjs +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/InputMap","label":"InputMap"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; -module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/docs/docusaurus.config.ts b/noir/docs/docusaurus.config.ts index 4e0d053f61e..d1d344ba635 100644 --- a/noir/docs/docusaurus.config.ts +++ b/noir/docs/docusaurus.config.ts @@ -155,7 +155,7 @@ export default { entryPoints: ['../tooling/noir_js/src/index.ts'], tsconfig: '../tooling/noir_js/tsconfig.json', entryPointStrategy: 'resolve', - out: 'docs/reference/NoirJS/noir_js', + out: 'processed-docs/reference/NoirJS/noir_js', plugin: ['typedoc-plugin-markdown'], name: 'noir_js', disableSources: true, @@ -186,7 +186,7 @@ export default { entryPoints: ['../tooling/noir_js_backend_barretenberg/src/index.ts'], tsconfig: '../tooling/noir_js_backend_barretenberg/tsconfig.json', entryPointStrategy: 'resolve', - out: 'docs/reference/NoirJS/backend_barretenberg', + out: 'processed-docs/reference/NoirJS/backend_barretenberg', plugin: ['typedoc-plugin-markdown'], name: 'backend_barretenberg', disableSources: true, diff --git a/noir/docs/package.json b/noir/docs/package.json index 6c706e4f514..71b624ff565 100644 --- a/noir/docs/package.json +++ b/noir/docs/package.json @@ -7,7 +7,8 @@ "start": "yarn preprocess && docusaurus start", "build": "yarn preprocess && yarn version::stables && docusaurus build", "version::stables": "ts-node ./scripts/setStable.ts", - "serve": "serve build" + "serve": "serve build", + "version": "yarn preprocess && docusaurus docs:version" }, "dependencies": { "@docusaurus/core": "^3.0.1", diff --git a/noir/noir_stdlib/src/bigint.nr b/noir/noir_stdlib/src/bigint.nr index f3ecfba8343..14790f69241 100644 --- a/noir/noir_stdlib/src/bigint.nr +++ b/noir/noir_stdlib/src/bigint.nr @@ -1,4 +1,3 @@ - use crate::ops::{Add, Sub, Mul, Div, Rem,}; struct BigInt { @@ -8,21 +7,21 @@ struct BigInt { impl BigInt { #[builtin(bigint_add)] - pub fn bigint_add(self, other: BigInt) -> BigInt { + pub fn bigint_add(_self: Self, _other: BigInt) -> BigInt { } #[builtin(bigint_neg)] - pub fn bigint_neg(self, other: BigInt) -> BigInt { + pub fn bigint_neg(_self: Self, _other: BigInt) -> BigInt { } #[builtin(bigint_mul)] - pub fn bigint_mul(self, other: BigInt) -> BigInt { + pub fn bigint_mul(_self: Self, _other: BigInt) -> BigInt { } #[builtin(bigint_div)] - pub fn bigint_div(self, other: BigInt) -> BigInt { + pub fn bigint_div(_self: Self, _other: BigInt) -> BigInt { } #[builtin(bigint_from_le_bytes)] - pub fn from_le_bytes(bytes: [u8], modulus: [u8]) -> BigInt {} + pub fn from_le_bytes(_bytes: [u8], _modulus: [u8]) -> BigInt {} #[builtin(bigint_to_le_bytes)] - pub fn to_le_bytes(self) -> [u8] {} + pub fn to_le_bytes(_self: Self) -> [u8] {} } impl Add for BigInt { diff --git a/noir/noir_stdlib/src/collections.nr b/noir/noir_stdlib/src/collections.nr index e06c662e658..177ca96816f 100644 --- a/noir/noir_stdlib/src/collections.nr +++ b/noir/noir_stdlib/src/collections.nr @@ -1 +1,2 @@ mod vec; +mod bounded_vec; diff --git a/noir/noir_stdlib/src/collections/bounded_vec.nr b/noir/noir_stdlib/src/collections/bounded_vec.nr new file mode 100644 index 00000000000..332fefa63f9 --- /dev/null +++ b/noir/noir_stdlib/src/collections/bounded_vec.nr @@ -0,0 +1,88 @@ +struct BoundedVec { + storage: [T; MaxLen], + // TODO: change this to return a u64 as Noir now + // uses u64 for indexing + len: Field, + empty_value: T, +} + +impl BoundedVec { + pub fn new(initial_value: T) -> Self { + BoundedVec { storage: [initial_value; MaxLen], len: 0, empty_value: initial_value } + } + + pub fn get(mut self: Self, index: Field) -> T { + assert(index as u64 < self.len as u64); + self.storage[index] + } + + pub fn get_unchecked(mut self: Self, index: Field) -> T { + self.storage[index] + } + + pub fn push(&mut self, elem: T) { + assert(self.len as u64 < MaxLen as u64, "push out of bounds"); + + self.storage[self.len] = elem; + self.len += 1; + } + + pub fn len(self) -> Field { + self.len + } + + pub fn max_len(_self: BoundedVec) -> Field { + MaxLen + } + + // This is a intermediate method, while we don't have an + // .extend method + pub fn storage(self) -> [T; MaxLen] { + self.storage + } + + pub fn extend_from_array(&mut self, array: [T; Len]) { + let new_len = self.len + array.len(); + assert(new_len as u64 <= MaxLen as u64, "extend_from_array out of bounds"); + for i in 0..array.len() { + self.storage[self.len + i] = array[i]; + } + self.len = new_len; + } + + pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) { + let append_len = vec.len(); + let new_len = self.len + append_len; + assert(new_len as u64 <= MaxLen as u64, "extend_from_bounded_vec out of bounds"); + + let mut exceeded_len = false; + for i in 0..Len { + exceeded_len |= i == append_len; + if !exceeded_len { + self.storage[self.len + (i as Field)] = vec.get_unchecked(i as Field); + } + } + self.len = new_len; + } + + pub fn pop(&mut self) -> T { + assert(self.len as u64 > 0); + self.len -= 1; + + let elem = self.storage[self.len]; + self.storage[self.len] = self.empty_value; + elem + } + + pub fn any(self, predicate: fn[Env](T) -> bool) -> bool { + let mut ret = false; + let mut exceeded_len = false; + for i in 0..MaxLen { + exceeded_len |= i == self.len; + if (!exceeded_len) { + ret |= predicate(self.storage[i]); + } + } + ret + } +} \ No newline at end of file diff --git a/noir/noir_stdlib/src/lib.nr b/noir/noir_stdlib/src/lib.nr index b7c7833277a..90aff3c312b 100644 --- a/noir/noir_stdlib/src/lib.nr +++ b/noir/noir_stdlib/src/lib.nr @@ -25,7 +25,7 @@ mod ops; mod default; mod prelude; mod uint128; -mod bigint; +// mod bigint; // Oracle calls are required to be wrapped in an unconstrained function // Thus, the only argument to the `println` oracle is expected to always be an ident diff --git a/noir/noir_stdlib/src/prelude.nr b/noir/noir_stdlib/src/prelude.nr index 26c6a805d54..3244329aa4b 100644 --- a/noir/noir_stdlib/src/prelude.nr +++ b/noir/noir_stdlib/src/prelude.nr @@ -1,4 +1,5 @@ use crate::collections::vec::Vec; +use crate::collections::bounded_vec::BoundedVec; use crate::option::Option; use crate::{print, println, assert_constant}; use crate::uint128::U128; diff --git a/noir/noir_stdlib/src/scalar_mul.nr b/noir/noir_stdlib/src/scalar_mul.nr index fef2398222f..0e84b4f66fc 100644 --- a/noir/noir_stdlib/src/scalar_mul.nr +++ b/noir/noir_stdlib/src/scalar_mul.nr @@ -1,8 +1,22 @@ +use crate::ops::Add; + struct EmbeddedCurvePoint { x: Field, y: Field, } +impl EmbeddedCurvePoint { + fn double(self) -> EmbeddedCurvePoint { + embedded_curve_add(self, self) + } +} + +impl Add for EmbeddedCurvePoint { + fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { + embedded_curve_add(self, other) + } +} + // Computes a fixed base scalar multiplication over the embedded curve. // For bn254, We have Grumpkin and Baby JubJub. // For bls12-381, we have JubJub and Bandersnatch. @@ -11,12 +25,12 @@ struct EmbeddedCurvePoint { // underlying proof system. #[foreign(fixed_base_scalar_mul)] // docs:start:fixed_base_embedded_curve -pub fn fixed_base_embedded_curve(_low: Field, _high: Field) -> [Field; 2] {} +pub fn fixed_base_embedded_curve( + _low: Field, + _high: Field +) -> [Field; 2] // docs:end:fixed_base_embedded_curve +{} #[foreign(embedded_curve_add)] -pub fn embedded_curve_add(_point1: EmbeddedCurvePoint, _point2: EmbeddedCurvePoint) -> EmbeddedCurvePoint {} - -pub fn embedded_curve_double(point: EmbeddedCurvePoint) -> EmbeddedCurvePoint { - embedded_curve_add(point, point) -} +fn embedded_curve_add(_point1: EmbeddedCurvePoint, _point2: EmbeddedCurvePoint) -> EmbeddedCurvePoint {} diff --git a/noir/test_programs/execution_success/scalar_mul/src/main.nr b/noir/test_programs/execution_success/scalar_mul/src/main.nr index a88754da5d3..e20f47907db 100644 --- a/noir/test_programs/execution_success/scalar_mul/src/main.nr +++ b/noir/test_programs/execution_success/scalar_mul/src/main.nr @@ -20,18 +20,12 @@ fn main( let res = std::scalar_mul::fixed_base_embedded_curve(priv_key, 0); assert(res[0] == pub_x); assert(res[1] == pub_y); - let pub_point= std::scalar_mul::EmbeddedCurvePoint { - x: pub_x, - y: pub_y - }; + let pub_point= std::scalar_mul::EmbeddedCurvePoint { x: pub_x, y: pub_y }; let g1_y = 17631683881184975370165255887551781615748388533673675138860; - let g1= std::scalar_mul::EmbeddedCurvePoint { - x: 1, - y: g1_y - }; + let g1= std::scalar_mul::EmbeddedCurvePoint { x: 1, y: g1_y }; - let res = std::scalar_mul::embedded_curve_double(pub_point); - let double = std::scalar_mul::embedded_curve_add(g1,g1 ); + let res = pub_point.double(); + let double = g1.add(g1); assert(double.x == res.x); } diff --git a/noir/test_programs/noir_test_success/bounded_vec/Nargo.toml b/noir/test_programs/noir_test_success/bounded_vec/Nargo.toml new file mode 100644 index 00000000000..0d58f5872ef --- /dev/null +++ b/noir/test_programs/noir_test_success/bounded_vec/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bounded_vec" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file diff --git a/noir/test_programs/noir_test_success/bounded_vec/Prover.toml b/noir/test_programs/noir_test_success/bounded_vec/Prover.toml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/noir/test_programs/noir_test_success/bounded_vec/src/main.nr b/noir/test_programs/noir_test_success/bounded_vec/src/main.nr new file mode 100644 index 00000000000..d51d2cc3685 --- /dev/null +++ b/noir/test_programs/noir_test_success/bounded_vec/src/main.nr @@ -0,0 +1,105 @@ +#[test] +fn test_vec_push_pop() { + let mut vec: BoundedVec = BoundedVec::new(0); + assert(vec.len == 0); + vec.push(2); + assert(vec.len == 1); + vec.push(4); + assert(vec.len == 2); + vec.push(6); + assert(vec.len == 3); + let x = vec.pop(); + assert(x == 6); + assert(vec.len == 2); + assert(vec.get(0) == 2); + assert(vec.get(1) == 4); +} + +#[test] +fn test_vec_extend_from_array() { + let mut vec: BoundedVec = BoundedVec::new(0); + vec.extend_from_array([2, 4]); + assert(vec.len == 2); + assert(vec.get(0) == 2); + assert(vec.get(1) == 4); +} + +#[test(should_fail_with="extend_from_array out of bounds")] +fn test_vec_extend_from_array_out_of_bound() { + let mut vec: BoundedVec = BoundedVec::new(0); + vec.extend_from_array([2, 4, 6]); +} + +#[test(should_fail_with="extend_from_array out of bounds")] +fn test_vec_extend_from_array_twice_out_of_bound() { + let mut vec: BoundedVec = BoundedVec::new(0); + vec.extend_from_array([2]); + assert(vec.len == 1); + vec.extend_from_array([4, 6]); +} + +#[test(should_fail)] +fn test_vec_get_out_of_bound() { + let mut vec: BoundedVec = BoundedVec::new(0); + vec.extend_from_array([2, 4]); + let _x = vec.get(2); +} + +#[test(should_fail)] +fn test_vec_get_not_declared() { + let mut vec: BoundedVec = BoundedVec::new(0); + vec.extend_from_array([2]); + let _x = vec.get(1); +} + +#[test(should_fail)] +fn test_vec_get_uninitialized() { + let mut vec: BoundedVec = BoundedVec::new(0); + let _x = vec.get(0); +} + +#[test(should_fail_with="push out of bounds")] +fn test_vec_push_out_of_bound() { + let mut vec: BoundedVec = BoundedVec::new(0); + vec.push(1); + vec.push(2); +} + +#[test(should_fail_with="extend_from_bounded_vec out of bounds")] +fn test_vec_extend_from_bounded_vec_out_of_bound() { + let mut vec: BoundedVec = BoundedVec::new(0); + + let mut another_vec: BoundedVec = BoundedVec::new(0); + another_vec.extend_from_array([1, 2, 3]); + + vec.extend_from_bounded_vec(another_vec); +} + +#[test(should_fail_with="extend_from_bounded_vec out of bounds")] +fn test_vec_extend_from_bounded_vec_twice_out_of_bound() { + let mut vec: BoundedVec = BoundedVec::new(0); + vec.extend_from_array([1, 2]); + + let mut another_vec: BoundedVec = BoundedVec::new(0); + another_vec.push(3); + + vec.extend_from_bounded_vec(another_vec); +} + +#[test] +fn test_vec_any() { + let mut vec: BoundedVec = BoundedVec::new(0); + vec.extend_from_array([2, 4, 6]); + assert(vec.any(|v| v == 2) == true); + assert(vec.any(|v| v == 4) == true); + assert(vec.any(|v| v == 6) == true); + assert(vec.any(|v| v == 3) == false); +} + +#[test] +fn test_vec_any_not_default() { + let default_value = 1; + let mut vec: BoundedVec = BoundedVec::new(default_value); + vec.extend_from_array([2, 4]); + assert(vec.any(|v| v == default_value) == false); +} \ No newline at end of file diff --git a/noir/tooling/bb_abstraction_leaks/build.rs b/noir/tooling/bb_abstraction_leaks/build.rs index 18413f87793..6197f52cb4b 100644 --- a/noir/tooling/bb_abstraction_leaks/build.rs +++ b/noir/tooling/bb_abstraction_leaks/build.rs @@ -10,7 +10,7 @@ use const_format::formatcp; const USERNAME: &str = "AztecProtocol"; const REPO: &str = "aztec-packages"; -const VERSION: &str = "0.19.0"; +const VERSION: &str = "0.21.0"; const TAG: &str = formatcp!("aztec-packages-v{}", VERSION); const API_URL: &str = diff --git a/noir/tooling/noir_js_backend_barretenberg/package.json b/noir/tooling/noir_js_backend_barretenberg/package.json index cd2a6354ac4..a0123883efd 100644 --- a/noir/tooling/noir_js_backend_barretenberg/package.json +++ b/noir/tooling/noir_js_backend_barretenberg/package.json @@ -42,7 +42,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "0.19.0", + "@aztec/bb.js": "0.21.0", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, diff --git a/noir/yarn.lock b/noir/yarn.lock index db3f493bc62..743068f1907 100644 --- a/noir/yarn.lock +++ b/noir/yarn.lock @@ -235,9 +235,9 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@npm:0.19.0": - version: 0.19.0 - resolution: "@aztec/bb.js@npm:0.19.0" +"@aztec/bb.js@npm:0.21.0": + version: 0.21.0 + resolution: "@aztec/bb.js@npm:0.21.0" dependencies: comlink: ^4.4.1 commander: ^10.0.1 @@ -245,7 +245,7 @@ __metadata: tslib: ^2.4.0 bin: bb.js: dest/node/main.js - checksum: c78c22c3b8c43e0010a43145f973489aa7da9fcf0b8527884107f1f34ac3ca5f5d4ab087d74ce50cb75d6dbaef88bfc693e23745282faa30b81dc78481c65874 + checksum: a0fb97476f52025f3c31b7a5e890966ac375ed47c5cfd3434f5c3e4265af3c7566a162f37d6c56f394f44bfe4ba67e5002b7c5998ecc4f6abe70e04f5b8abe34 languageName: node linkType: hard @@ -4435,7 +4435,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": 0.19.0 + "@aztec/bb.js": 0.21.0 "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3 diff --git a/yarn-project/aztec-nr/authwit/src/entrypoint.nr b/yarn-project/aztec-nr/authwit/src/entrypoint.nr index 05ca66240f0..98987d49e36 100644 --- a/yarn-project/aztec-nr/authwit/src/entrypoint.nr +++ b/yarn-project/aztec-nr/authwit/src/entrypoint.nr @@ -1,5 +1,4 @@ use dep::aztec::abi; -use dep::aztec::types::vec::BoundedVec; use dep::aztec::context::PrivateContext; use dep::aztec::protocol_types::{ abis::{ @@ -66,7 +65,7 @@ impl Serialize for EntrypointPayload { fn serialize(self) -> [Field; ENTRYPOINT_PAYLOAD_SIZE] { let mut fields: BoundedVec = BoundedVec::new(0); for call in self.function_calls { - fields.push_array(call.serialize()); + fields.extend_from_array(call.serialize()); } fields.push(self.nonce); fields.storage diff --git a/yarn-project/aztec-nr/aztec/src/context.nr b/yarn-project/aztec-nr/aztec/src/context.nr index f2ef5dfc511..2766304193e 100644 --- a/yarn-project/aztec-nr/aztec/src/context.nr +++ b/yarn-project/aztec-nr/aztec/src/context.nr @@ -14,7 +14,6 @@ use crate::{ header::get_header_at, nullifier_key::{get_nullifier_key_pair, NullifierKeyPair}, }, - types::vec::BoundedVec, utils::Reader, }; use dep::protocol_types::{ diff --git a/yarn-project/aztec-nr/aztec/src/lib.nr b/yarn-project/aztec-nr/aztec/src/lib.nr index 9bf7bf42c8f..7a8531601c4 100644 --- a/yarn-project/aztec-nr/aztec/src/lib.nr +++ b/yarn-project/aztec-nr/aztec/src/lib.nr @@ -8,6 +8,5 @@ mod messaging; mod note; mod oracle; mod state_vars; -mod types; mod utils; use dep::protocol_types; diff --git a/yarn-project/aztec-nr/aztec/src/note/note_getter.nr b/yarn-project/aztec-nr/aztec/src/note/note_getter.nr index a442aad9f83..2200ed3cb58 100644 --- a/yarn-project/aztec-nr/aztec/src/note/note_getter.nr +++ b/yarn-project/aztec-nr/aztec/src/note/note_getter.nr @@ -17,7 +17,6 @@ use crate::note::{ utils::compute_note_hash_for_read_or_nullify, }; use crate::oracle; -use crate::types::vec::BoundedVec; fn check_note_header( context: PrivateContext, diff --git a/yarn-project/aztec-nr/aztec/src/note/note_getter_options.nr b/yarn-project/aztec-nr/aztec/src/note/note_getter_options.nr index 611ac239a34..bec2aa7f001 100644 --- a/yarn-project/aztec-nr/aztec/src/note/note_getter_options.nr +++ b/yarn-project/aztec-nr/aztec/src/note/note_getter_options.nr @@ -1,5 +1,4 @@ use dep::std::option::Option; -use crate::types::vec::BoundedVec; use dep::protocol_types::{ constants::MAX_READ_REQUESTS_PER_CALL, traits::Deserialize, diff --git a/yarn-project/aztec-nr/aztec/src/note/note_viewer_options.nr b/yarn-project/aztec-nr/aztec/src/note/note_viewer_options.nr index 5677b33f429..a935f63f791 100644 --- a/yarn-project/aztec-nr/aztec/src/note/note_viewer_options.nr +++ b/yarn-project/aztec-nr/aztec/src/note/note_viewer_options.nr @@ -1,6 +1,5 @@ use dep::std::option::Option; use crate::note::note_getter_options::{Select, Sort, Comparator, NoteStatus}; -use crate::types::vec::BoundedVec; use dep::protocol_types::{ constants::MAX_NOTES_PER_PAGE, traits::Deserialize, diff --git a/yarn-project/aztec-nr/aztec/src/types.nr b/yarn-project/aztec-nr/aztec/src/types.nr deleted file mode 100644 index ae46c9e0c88..00000000000 --- a/yarn-project/aztec-nr/aztec/src/types.nr +++ /dev/null @@ -1 +0,0 @@ -mod vec; // This can/should be moved out into an official noir library diff --git a/yarn-project/aztec-nr/aztec/src/types/vec.nr b/yarn-project/aztec-nr/aztec/src/types/vec.nr deleted file mode 100644 index 135bbbd53c3..00000000000 --- a/yarn-project/aztec-nr/aztec/src/types/vec.nr +++ /dev/null @@ -1,126 +0,0 @@ -struct BoundedVec { - storage: [T; MaxLen], - len: Field, -} - -impl BoundedVec { - pub fn new(initial_value: T) -> Self { - BoundedVec { storage: [initial_value; MaxLen], len: 0 } - } - - pub fn get(mut self: Self, index: Field) -> T { - assert(index as u64 < self.len as u64); - self.storage[index] - } - - pub fn get_unchecked(mut self: Self, index: Field) -> T { - self.storage[index] - } - - pub fn push(&mut self, elem: T) { - assert(self.len as u64 < MaxLen as u64); - - self.storage[self.len] = elem; - self.len += 1; - } - - pub fn push_array(&mut self, array: [T; Len]) { - let newLen = self.len + array.len(); - assert(newLen as u64 <= MaxLen as u64); - for i in 0..array.len() { - self.storage[self.len + i] = array[i]; - } - self.len = newLen; - } - - pub fn pop(&mut self) -> T { - assert(self.len as u64 > 0); - - let elem = self.storage[self.len - 1]; - self.len -= 1; - elem - } - - pub fn any(self, predicate: fn[Env](T) -> bool) -> bool { - let mut ret = false; - let mut exceeded_len = false; - for i in 0..MaxLen { - exceeded_len |= i == self.len; - if (!exceeded_len) { - ret |= predicate(self.storage[i]); - } - } - ret - } -} - -#[test] -fn test_vec_push_pop() { - let mut vec: BoundedVec = BoundedVec::new(0); - assert(vec.len == 0); - vec.push(2); - assert(vec.len == 1); - vec.push(4); - assert(vec.len == 2); - vec.push(6); - assert(vec.len == 3); - let x = vec.pop(); - assert(x == 6); - assert(vec.len == 2); - assert(vec.get(0) == 2); - assert(vec.get(1) == 4); -} - -#[test] -fn test_vec_push_array() { - let mut vec: BoundedVec = BoundedVec::new(0); - vec.push_array([2, 4]); - assert(vec.len == 2); - assert(vec.get(0) == 2); - assert(vec.get(1) == 4); -} - -#[test(should_fail)] -fn test_vec_get_out_of_bound() { - let mut vec: BoundedVec = BoundedVec::new(0); - vec.push_array([2, 4]); - let _x = vec.get(2); -} - -#[test(should_fail)] -fn test_vec_get_not_declared() { - let mut vec: BoundedVec = BoundedVec::new(0); - vec.push_array([2]); - let _x = vec.get(1); -} - -#[test(should_fail)] -fn test_vec_get_uninitialized() { - let mut vec: BoundedVec = BoundedVec::new(0); - let _x = vec.get(0); -} - -#[test(should_fail)] -fn test_vec_push_overflow() { - let mut vec: BoundedVec = BoundedVec::new(0); - vec.push(1); - vec.push(2); -} - -#[test] -fn test_vec_any() { - let mut vec: BoundedVec = BoundedVec::new(0); - vec.push_array([2, 4, 6]); - assert(vec.any(|v| v == 2) == true); - assert(vec.any(|v| v == 4) == true); - assert(vec.any(|v| v == 6) == true); - assert(vec.any(|v| v == 3) == false); -} - -#[test] -fn test_vec_any_not_default() { - let default_value = 1; - let mut vec: BoundedVec = BoundedVec::new(default_value); - vec.push_array([2, 4]); - assert(vec.any(|v| v == default_value) == false); -} diff --git a/yarn-project/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr b/yarn-project/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr index faef2015a90..6226024e39f 100644 --- a/yarn-project/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr @@ -5,7 +5,6 @@ contract SchnorrHardcodedAccount { use dep::aztec::{ abi::{ PrivateCircuitPublicInputs, PrivateContextInputs, Hasher }, context::PrivateContext, - types::vec::BoundedVec, }; use dep::authwit:: { diff --git a/yarn-project/noir-contracts/contracts/test_contract/src/main.nr b/yarn-project/noir-contracts/contracts/test_contract/src/main.nr index 14d7a7f6ee6..791016b7a8d 100644 --- a/yarn-project/noir-contracts/contracts/test_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/test_contract/src/main.nr @@ -41,7 +41,6 @@ contract Test { }, state_vars::immutable_singleton::ImmutableSingleton, log::emit_unencrypted_log_from_private, - types::vec::BoundedVec, }; use dep::token_portal_content_hash_lib::{get_mint_private_content_hash, get_mint_public_content_hash}; use dep::field_note::field_note::FieldNote; @@ -193,7 +192,7 @@ contract Test { args.push(a_field); args.push(a_bool as Field); args.push(a_number as Field); - args.push_array(an_array); + args.extend_from_array(an_array); args.push(a_struct.amount); args.push(a_struct.secret_hash); args.push(a_deep_struct.a_field); diff --git a/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/common.nr b/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/common.nr index d6a12b2a411..9b875910712 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/common.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/common.nr @@ -42,7 +42,6 @@ use dep::types::{ array_to_bounded_vec, validate_array, }, - bounded_vec::BoundedVec, }, traits::{is_empty, is_empty_array}, }; @@ -50,7 +49,7 @@ use dep::types::{ pub fn validate_arrays(app_public_inputs: PrivateCircuitPublicInputs) { // Each of the following arrays is expected to be zero-padded. // In addition, some of the following arrays (new_commitments, etc...) are passed - // to push_array_to_array() routines which rely on the passed arrays to be well-formed. + // to extend_from_array_to_array() routines which rely on the passed arrays to be well-formed. validate_array(app_public_inputs.return_values); validate_array(app_public_inputs.read_requests); @@ -197,7 +196,7 @@ pub fn update_end_values(private_call: PrivateCallData, public_inputs: &mut Kern ) } } - public_inputs.end.read_requests.push_vec(siloed_read_requests); + public_inputs.end.read_requests.extend_from_bounded_vec(siloed_read_requests); // Nullifier key validation requests. for i in 0..MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL { @@ -228,7 +227,7 @@ pub fn update_end_values(private_call: PrivateCallData, public_inputs: &mut Kern ); } } - public_inputs.end.new_nullifiers.push_vec(siloed_new_nullifiers); + public_inputs.end.new_nullifiers.extend_from_bounded_vec(siloed_new_nullifiers); // commitments let mut siloed_new_commitments: BoundedVec = BoundedVec::new(SideEffect::empty()); @@ -240,7 +239,7 @@ pub fn update_end_values(private_call: PrivateCallData, public_inputs: &mut Kern ); } } - public_inputs.end.new_commitments.push_vec(siloed_new_commitments); + public_inputs.end.new_commitments.extend_from_bounded_vec(siloed_new_commitments); // Call stacks // Private call stack. @@ -250,7 +249,7 @@ pub fn update_end_values(private_call: PrivateCallData, public_inputs: &mut Kern private_call_public_inputs.private_call_stack_hashes, private_call ); - public_inputs.end.private_call_stack.push_vec(private_call_stack); + public_inputs.end.private_call_stack.extend_from_bounded_vec(private_call_stack); // Public call stack. let public_call_stack = array_to_bounded_vec(private_call.public_call_stack); validate_call_requests( @@ -258,7 +257,7 @@ pub fn update_end_values(private_call: PrivateCallData, public_inputs: &mut Kern private_call_public_inputs.public_call_stack_hashes, private_call ); - public_inputs.end.public_call_stack.push_vec(public_call_stack); + public_inputs.end.public_call_stack.extend_from_bounded_vec(public_call_stack); // new l2 to l1 messages let portal_contract_address = private_call.portal_contract_address; @@ -277,7 +276,7 @@ pub fn update_end_values(private_call: PrivateCallData, public_inputs: &mut Kern new_l2_to_l1_msgs_to_insert.push(new_l2_to_l1_msgs) } } - public_inputs.end.new_l2_to_l1_msgs.push_vec(new_l2_to_l1_msgs_to_insert); + public_inputs.end.new_l2_to_l1_msgs.extend_from_bounded_vec(new_l2_to_l1_msgs_to_insert); // logs hashes // See the following thread if not clear: diff --git a/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_init.nr b/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_init.nr index 79eb6909614..798bcf16f9c 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_init.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_init.nr @@ -264,7 +264,7 @@ mod tests { fn input_validation_malformed_arrays_return_values() { let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); - builder.private_call.public_inputs.return_values.push_array([0, 9123]); + builder.private_call.public_inputs.return_values.extend_from_array([0, 9123]); builder.failed(); } @@ -273,7 +273,7 @@ mod tests { fn input_validation_malformed_arrays_read_requests() { let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); - builder.private_call.public_inputs.read_requests.push_array( + builder.private_call.public_inputs.read_requests.extend_from_array( [ SideEffect { value: 0, counter: 0 }, SideEffect { value: 9123, counter: 1 } @@ -287,7 +287,7 @@ mod tests { fn input_validation_malformed_arrays_commitments() { let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); - builder.private_call.public_inputs.new_commitments.push_array( + builder.private_call.public_inputs.new_commitments.extend_from_array( [ SideEffect { value: 0, counter: 0 }, SideEffect { value: 9123, counter: 1 } @@ -301,7 +301,7 @@ mod tests { fn input_validation_malformed_arrays_nullifiers() { let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); - builder.private_call.public_inputs.new_nullifiers.push_array( + builder.private_call.public_inputs.new_nullifiers.extend_from_array( [ SideEffectLinkedToNoteHash { value: 0, note_hash: 0, counter: 0 }, SideEffectLinkedToNoteHash { value: 9123, note_hash: 0, counter: 1 } @@ -315,7 +315,7 @@ mod tests { fn input_validation_malformed_arrays_private_call_stack() { let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); - builder.private_call.public_inputs.private_call_stack_hashes.push_array([0, 9123]); + builder.private_call.public_inputs.private_call_stack_hashes.extend_from_array([0, 9123]); builder.failed(); } @@ -324,7 +324,7 @@ mod tests { fn input_validation_malformed_arrays_public_call_stack() { let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); - builder.private_call.public_inputs.public_call_stack_hashes.push_array([0, 9123]); + builder.private_call.public_inputs.public_call_stack_hashes.extend_from_array([0, 9123]); builder.failed(); } @@ -333,7 +333,7 @@ mod tests { fn input_validation_malformed_arrays_new_l2_to_l1_msgs() { let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); - builder.private_call.public_inputs.new_l2_to_l1_msgs.push_array([0, 9123]); + builder.private_call.public_inputs.new_l2_to_l1_msgs.extend_from_array([0, 9123]); builder.failed(); } diff --git a/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_inner.nr b/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_inner.nr index b6329348cb4..13144419983 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -97,7 +97,6 @@ mod tests { hash::compute_logs_hash, utils::{ arrays::array_length, - bounded_vec::BoundedVec, }, }; @@ -441,7 +440,7 @@ mod tests { fn input_validation_malformed_arrays_return_values() { let mut builder = PrivateKernelInnerInputsBuilder::new(); - builder.private_call.public_inputs.return_values.push_array([0, 553]); + builder.private_call.public_inputs.return_values.extend_from_array([0, 553]); builder.failed(); } @@ -450,7 +449,7 @@ mod tests { fn input_validation_malformed_arrays_read_requests() { let mut builder = PrivateKernelInnerInputsBuilder::new(); - builder.private_call.public_inputs.read_requests.push_array( + builder.private_call.public_inputs.read_requests.extend_from_array( [ SideEffect { value: 0, counter: 0 }, SideEffect { value: 9123, counter: 1 } @@ -464,7 +463,7 @@ mod tests { fn input_validation_malformed_arrays_commitments() { let mut builder = PrivateKernelInnerInputsBuilder::new(); - builder.private_call.public_inputs.new_commitments.push_array( + builder.private_call.public_inputs.new_commitments.extend_from_array( [ SideEffect { value: 0, counter: 0 }, SideEffect { value: 9123, counter: 1 } @@ -478,7 +477,7 @@ mod tests { fn input_validation_malformed_arrays_nullifiers() { let mut builder = PrivateKernelInnerInputsBuilder::new(); - builder.private_call.public_inputs.new_nullifiers.push_array( + builder.private_call.public_inputs.new_nullifiers.extend_from_array( [ SideEffectLinkedToNoteHash { value: 0, note_hash: 0, counter: 0 }, SideEffectLinkedToNoteHash { value: 12, note_hash: 0, counter: 1 } @@ -492,7 +491,7 @@ mod tests { fn input_validation_malformed_arrays_private_call_stack() { let mut builder = PrivateKernelInnerInputsBuilder::new(); - builder.private_call.public_inputs.private_call_stack_hashes.push_array([0, 888]); + builder.private_call.public_inputs.private_call_stack_hashes.extend_from_array([0, 888]); builder.failed(); } @@ -501,7 +500,7 @@ mod tests { fn input_validation_malformed_arrays_public_call_stack() { let mut builder = PrivateKernelInnerInputsBuilder::new(); - builder.private_call.public_inputs.public_call_stack_hashes.push_array([0, 888]); + builder.private_call.public_inputs.public_call_stack_hashes.extend_from_array([0, 888]); builder.failed(); } @@ -510,12 +509,12 @@ mod tests { fn input_validation_malformed_arrays_new_l2_to_l1_msgs() { let mut builder = PrivateKernelInnerInputsBuilder::new(); - builder.private_call.public_inputs.new_l2_to_l1_msgs.push_array([0, 888]); + builder.private_call.public_inputs.new_l2_to_l1_msgs.extend_from_array([0, 888]); builder.failed(); } - #[test(should_fail_with = "push_vec out of bounds")] + #[test(should_fail_with = "extend_from_bounded_vec out of bounds")] fn private_kernel_should_fail_if_aggregating_too_many_commitments() { let mut builder = PrivateKernelInnerInputsBuilder::new(); @@ -530,7 +529,7 @@ mod tests { counter: i as u32, }; } - builder.previous_kernel.end.new_commitments.push_array(full_new_commitments); + builder.previous_kernel.end.new_commitments.extend_from_array(full_new_commitments); builder.failed(); } diff --git a/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_ordering.nr b/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_ordering.nr index c937d43d832..6c6496b7ad5 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_ordering.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_ordering.nr @@ -28,7 +28,6 @@ use dep::types::{ }, utils::{ arrays::{array_length, array_eq}, - bounded_vec::BoundedVec, }, traits::{Empty, is_empty} }; @@ -236,7 +235,6 @@ mod tests { tests::previous_kernel_data_builder::PreviousKernelDataBuilder, utils::{ arrays::{array_eq, array_length}, - bounded_vec::BoundedVec, }, traits::{Empty, is_empty, is_empty_array} }; diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/common.nr b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/common.nr index f197513228f..87929586626 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/common.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/common.nr @@ -28,7 +28,6 @@ use dep::types::{ hash::{silo_commitment, silo_nullifier, compute_l2_to_l1_hash, accumulate_sha256}, utils::{ arrays::{array_length, array_to_bounded_vec}, - bounded_vec::BoundedVec, }, traits::is_empty_array }; @@ -138,7 +137,7 @@ pub fn update_public_end_values(public_call: PublicCallData, circuit_outputs: &m let public_call_requests = array_to_bounded_vec(public_call.public_call_stack); let hashes = public_call.call_stack_item.public_inputs.public_call_stack_hashes; validate_call_requests(public_call_requests, hashes, public_call); - circuit_outputs.end.public_call_stack.push_vec(public_call_requests); + circuit_outputs.end.public_call_stack.extend_from_bounded_vec(public_call_requests); propagate_new_nullifiers(public_call, circuit_outputs); propagate_new_commitments(public_call, circuit_outputs); @@ -171,7 +170,7 @@ fn propagate_valid_public_data_update_requests( public_data_update_requests.push(public_data_update_request); } } - circuit_outputs.end.public_data_update_requests.push_vec(public_data_update_requests); + circuit_outputs.end.public_data_update_requests.extend_from_bounded_vec(public_data_update_requests); } fn propagate_valid_public_data_reads(public_call: PublicCallData, circuit_outputs: &mut KernelCircuitPublicInputsBuilder) { @@ -190,7 +189,7 @@ fn propagate_valid_public_data_reads(public_call: PublicCallData, circuit_output public_data_reads.push(public_data_read); } } - circuit_outputs.end.public_data_reads.push_vec(public_data_reads); + circuit_outputs.end.public_data_reads.extend_from_bounded_vec(public_data_reads); } fn propagate_new_commitments(public_call: PublicCallData, circuit_outputs: &mut KernelCircuitPublicInputsBuilder) { @@ -207,7 +206,7 @@ fn propagate_new_commitments(public_call: PublicCallData, circuit_outputs: &mut siloed_new_commitments.push(SideEffect { value: siloed_new_commitment, counter: new_commitments[i].counter }); } } - circuit_outputs.end.new_commitments.push_vec(siloed_new_commitments); + circuit_outputs.end.new_commitments.extend_from_bounded_vec(siloed_new_commitments); } fn propagate_new_nullifiers(public_call: PublicCallData, circuit_outputs: &mut KernelCircuitPublicInputsBuilder) { @@ -230,7 +229,7 @@ fn propagate_new_nullifiers(public_call: PublicCallData, circuit_outputs: &mut K } } - circuit_outputs.end.new_nullifiers.push_vec(siloed_new_nullifiers); + circuit_outputs.end.new_nullifiers.extend_from_bounded_vec(siloed_new_nullifiers); } fn propagate_new_l2_to_l1_messages(public_call: PublicCallData, public_inputs: &mut KernelCircuitPublicInputsBuilder) { @@ -254,7 +253,7 @@ fn propagate_new_l2_to_l1_messages(public_call: PublicCallData, public_inputs: & new_l2_to_l1_msgs_to_insert.push(new_l2_to_l1_msgs) } } - public_inputs.end.new_l2_to_l1_msgs.push_vec(new_l2_to_l1_msgs_to_insert); + public_inputs.end.new_l2_to_l1_msgs.extend_from_bounded_vec(new_l2_to_l1_msgs_to_insert); } /** diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_private_previous.nr b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_private_previous.nr index 0cab8070c21..43171da38b3 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_private_previous.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_private_previous.nr @@ -85,7 +85,6 @@ mod tests { array_eq, array_length, }, - bounded_vec::BoundedVec, }, }; use dep::types::constants::{ @@ -406,7 +405,7 @@ mod tests { contract_class_id: 78 } ]; - builder.previous_kernel.end.new_contracts.push_array(new_contracts); + builder.previous_kernel.end.new_contracts.extend_from_array(new_contracts); builder.public_call.append_public_call_requests_for_regular_calls(2); let storage = builder.public_call.public_call_stack.storage; diff --git a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_public_previous.nr b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_public_previous.nr index 985690d46b9..5f28c5d8dd7 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_public_previous.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/public-kernel-lib/src/public_kernel_public_previous.nr @@ -180,7 +180,7 @@ mod tests { SideEffect { value: previous[1].value + 1, counter: 3 }, SideEffect { value: previous[1].value + 2, counter: 4 } ]; - builder.public_call.public_inputs.new_commitments.push_array(current); + builder.public_call.public_inputs.new_commitments.extend_from_array(current); let siloed = current.map(|c: SideEffect| silo_commitment(contract_address, c.value)); let new_commitments = [ previous[0], previous[1], SideEffect { value: siloed[0], counter: 3 }, SideEffect { value: siloed[1], counter: 4 } @@ -247,7 +247,7 @@ mod tests { SideEffectLinkedToNoteHash { value: silo_nullifier(contract_address, current.value), note_hash: current.note_hash, counter: current.counter } ); - builder.public_call.public_inputs.new_nullifiers.push_array(current); + builder.public_call.public_inputs.new_nullifiers.extend_from_array(current); // There are 3 nullifiers in the previous kernel. The first one is the tx nullifier. let new_nullifiers = [previous[0], previous[1], previous[2], siloed[0], siloed[1]]; @@ -265,10 +265,10 @@ mod tests { // Setup 1 new l2 to l1 message on the previous kernel. let previous = [12345]; - builder.previous_kernel.end.new_l2_to_l1_msgs.push_array(previous); + builder.previous_kernel.end.new_l2_to_l1_msgs.extend_from_array(previous); // Setup 1 new l2 to l1 message on the current public inputs. let current = [67890]; - builder.public_call.public_inputs.new_l2_to_l1_msgs.push_array(current); + builder.public_call.public_inputs.new_l2_to_l1_msgs.extend_from_array(current); let tx_context = builder.previous_kernel.tx_context; let version = tx_context.version; let chain_id = tx_context.chain_id; diff --git a/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/base/base_rollup_inputs.nr b/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/base/base_rollup_inputs.nr index c6ac3c04df3..d831a4647e6 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/base/base_rollup_inputs.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/base/base_rollup_inputs.nr @@ -597,7 +597,6 @@ mod tests { abis::side_effect::SideEffect, tests::previous_kernel_data_builder::PreviousKernelDataBuilder, address::{AztecAddress, EthAddress}, - utils::bounded_vec::BoundedVec, utils::uint256::U256, partial_state_reference::PartialStateReference, }; diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/combined_accumulated_data.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/combined_accumulated_data.nr index 7ada51b7a52..9e74c0ae103 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/combined_accumulated_data.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/combined_accumulated_data.nr @@ -8,8 +8,7 @@ use crate::{ public_data_update_request::PublicDataUpdateRequest, side_effect::{SideEffect, SideEffectLinkedToNoteHash}, }, - mocked::AggregationObject, - utils::bounded_vec::BoundedVec + mocked::AggregationObject }; use crate::constants::{ MAX_READ_REQUESTS_PER_TX, diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/private_circuit_public_inputs.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/private_circuit_public_inputs.nr index 466420cd416..0df8915d1a4 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/private_circuit_public_inputs.nr @@ -9,7 +9,6 @@ use crate::{ pedersen_hash, }, header::Header, - utils::bounded_vec::BoundedVec, }; use crate::constants::{ MAX_READ_REQUESTS_PER_CALL, @@ -69,26 +68,26 @@ impl Hash for PrivateCircuitPublicInputs { let mut fields: BoundedVec = BoundedVec::new(0); fields.push(self.call_context.hash()); fields.push(self.args_hash); - fields.push_array(self.return_values); + fields.extend_from_array(self.return_values); for i in 0..MAX_READ_REQUESTS_PER_CALL{ - fields.push_array(self.read_requests[i].serialize()); + fields.extend_from_array(self.read_requests[i].serialize()); } for i in 0..MAX_NEW_COMMITMENTS_PER_CALL{ - fields.push_array(self.new_commitments[i].serialize()); + fields.extend_from_array(self.new_commitments[i].serialize()); } for i in 0..MAX_NEW_NULLIFIERS_PER_CALL{ - fields.push_array(self.new_nullifiers[i].serialize()); + fields.extend_from_array(self.new_nullifiers[i].serialize()); } - fields.push_array(self.private_call_stack_hashes); - fields.push_array(self.public_call_stack_hashes); - fields.push_array(self.new_l2_to_l1_msgs); + fields.extend_from_array(self.private_call_stack_hashes); + fields.extend_from_array(self.public_call_stack_hashes); + fields.extend_from_array(self.new_l2_to_l1_msgs); fields.push(self.end_side_effect_counter as Field); - fields.push_array(self.encrypted_logs_hash); - fields.push_array(self.unencrypted_logs_hash); + fields.extend_from_array(self.encrypted_logs_hash); + fields.extend_from_array(self.unencrypted_logs_hash); fields.push(self.encrypted_log_preimages_length); fields.push(self.unencrypted_log_preimages_length); - fields.push_array(self.historical_header.serialize()); + fields.extend_from_array(self.historical_header.serialize()); fields.push(self.contract_deployment_data.hash()); fields.push(self.chain_id); fields.push(self.version); @@ -102,29 +101,29 @@ impl Hash for PrivateCircuitPublicInputs { impl Serialize for PrivateCircuitPublicInputs { fn serialize(self) -> [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH] { let mut fields: BoundedVec = BoundedVec::new(0); - fields.push_array(self.call_context.serialize()); + fields.extend_from_array(self.call_context.serialize()); fields.push(self.args_hash); - fields.push_array(self.return_values); + fields.extend_from_array(self.return_values); for i in 0..MAX_READ_REQUESTS_PER_CALL{ - fields.push_array(self.read_requests[i].serialize()); + fields.extend_from_array(self.read_requests[i].serialize()); } for i in 0..MAX_NEW_COMMITMENTS_PER_CALL{ - fields.push_array(self.new_commitments[i].serialize()); + fields.extend_from_array(self.new_commitments[i].serialize()); } for i in 0..MAX_NEW_NULLIFIERS_PER_CALL{ - fields.push_array(self.new_nullifiers[i].serialize()); + fields.extend_from_array(self.new_nullifiers[i].serialize()); } - fields.push_array(self.private_call_stack_hashes); - fields.push_array(self.public_call_stack_hashes); - fields.push_array(self.new_l2_to_l1_msgs); + fields.extend_from_array(self.private_call_stack_hashes); + fields.extend_from_array(self.public_call_stack_hashes); + fields.extend_from_array(self.new_l2_to_l1_msgs); fields.push(self.end_side_effect_counter as Field); - fields.push_array(self.encrypted_logs_hash); - fields.push_array(self.unencrypted_logs_hash); + fields.extend_from_array(self.encrypted_logs_hash); + fields.extend_from_array(self.unencrypted_logs_hash); fields.push(self.encrypted_log_preimages_length); fields.push(self.unencrypted_log_preimages_length); - fields.push_array(self.historical_header.serialize()); - fields.push_array(self.contract_deployment_data.serialize()); + fields.extend_from_array(self.historical_header.serialize()); + fields.extend_from_array(self.contract_deployment_data.serialize()); fields.push(self.chain_id); fields.push(self.version); diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_circuit_public_inputs.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_circuit_public_inputs.nr index 5da7a1de2ff..6c130e5e65d 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_circuit_public_inputs.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/public_circuit_public_inputs.nr @@ -22,7 +22,6 @@ use crate::{ storage_update_request::StorageUpdateRequest, }, header::Header, - utils::bounded_vec::BoundedVec, }; struct PublicCircuitPublicInputs{ @@ -59,14 +58,14 @@ impl PublicCircuitPublicInputs{ let mut inputs: BoundedVec = BoundedVec::new(0); inputs.push(self.call_context.hash()); inputs.push(self.args_hash); - inputs.push_array(self.return_values); + inputs.extend_from_array(self.return_values); for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL { inputs.push(self.contract_storage_update_requests[i].hash()); } for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL { inputs.push(self.contract_storage_reads[i].hash()); } - inputs.push_array(self.public_call_stack_hashes); + inputs.extend_from_array(self.public_call_stack_hashes); for i in 0..MAX_NEW_COMMITMENTS_PER_CALL{ inputs.push(self.new_commitments[i].hash()); @@ -74,10 +73,10 @@ impl PublicCircuitPublicInputs{ for i in 0..MAX_NEW_NULLIFIERS_PER_CALL{ inputs.push(self.new_nullifiers[i].hash()); } - inputs.push_array(self.new_l2_to_l1_msgs); - inputs.push_array(self.unencrypted_logs_hash); + inputs.extend_from_array(self.new_l2_to_l1_msgs); + inputs.extend_from_array(self.unencrypted_logs_hash); inputs.push(self.unencrypted_log_preimages_length); - inputs.push_array(self.historical_header.serialize()); + inputs.extend_from_array(self.historical_header.serialize()); inputs.push(self.prover_address.to_field()); assert_eq(inputs.len(), PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH, "Incorrect number of input fields when hashing PublicCircuitPublicInputs"); @@ -87,27 +86,27 @@ impl PublicCircuitPublicInputs{ pub fn serialize(self) -> [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH] { let mut fields: BoundedVec = BoundedVec::new(0); - fields.push_array(self.call_context.serialize()); + fields.extend_from_array(self.call_context.serialize()); fields.push(self.args_hash); - fields.push_array(self.return_values); + fields.extend_from_array(self.return_values); for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL { - fields.push_array(self.contract_storage_update_requests[i].serialize()); + fields.extend_from_array(self.contract_storage_update_requests[i].serialize()); } for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL { - fields.push_array(self.contract_storage_reads[i].serialize()); + fields.extend_from_array(self.contract_storage_reads[i].serialize()); } - fields.push_array(self.public_call_stack_hashes); + fields.extend_from_array(self.public_call_stack_hashes); for i in 0..MAX_NEW_COMMITMENTS_PER_CALL{ - fields.push_array(self.new_commitments[i].serialize()); + fields.extend_from_array(self.new_commitments[i].serialize()); } for i in 0..MAX_NEW_NULLIFIERS_PER_CALL{ - fields.push_array(self.new_nullifiers[i].serialize()); + fields.extend_from_array(self.new_nullifiers[i].serialize()); } - fields.push_array(self.new_l2_to_l1_msgs); - fields.push_array(self.unencrypted_logs_hash); + fields.extend_from_array(self.new_l2_to_l1_msgs); + fields.extend_from_array(self.unencrypted_logs_hash); fields.push(self.unencrypted_log_preimages_length); - fields.push_array(self.historical_header.serialize()); + fields.extend_from_array(self.historical_header.serialize()); fields.push(self.prover_address.to_field()); fields.storage } diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/hash.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/hash.nr index bafa08de6cc..ab6c9f260c1 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/hash.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/hash.nr @@ -6,7 +6,6 @@ use crate::abis::new_contract_data::NewContractData as ContractLeafPreimage; use crate::abis::function_data::FunctionData; use crate::abis::side_effect::{SideEffect}; use crate::utils::uint256::U256; -use crate::utils::bounded_vec::BoundedVec; use crate::constants::{ ARGS_HASH_CHUNK_COUNT, ARGS_HASH_CHUNK_LENGTH, diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/header.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/header.nr index b838c453480..9e081cab674 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/header.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/header.nr @@ -22,7 +22,6 @@ use crate::{ traits::Empty, utils::{ arr_copy_slice, - bounded_vec::BoundedVec, }, }; @@ -40,10 +39,10 @@ impl Header { pub fn serialize(self) -> [Field; HEADER_LENGTH] { let mut fields: BoundedVec = BoundedVec::new(0); - fields.push_array(self.last_archive.serialize()); - fields.push_array(self.body_hash); - fields.push_array(self.state.serialize()); - fields.push_array(self.global_variables.serialize()); + fields.extend_from_array(self.last_archive.serialize()); + fields.extend_from_array(self.body_hash); + fields.extend_from_array(self.state.serialize()); + fields.extend_from_array(self.global_variables.serialize()); fields.storage } diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/state_reference.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/state_reference.nr index ea16db7d032..bb3c517551e 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/state_reference.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/state_reference.nr @@ -10,7 +10,6 @@ use crate::{ traits::Empty, utils::{ arr_copy_slice, - bounded_vec::BoundedVec, }, }; @@ -30,8 +29,8 @@ impl StateReference { fn serialize(self) -> [Field; STATE_REFERENCE_LENGTH] { let mut fields: BoundedVec = BoundedVec::new(0); - fields.push_array(self.l1_to_l2_message_tree.serialize()); - fields.push_array(self.partial.serialize()); + fields.extend_from_array(self.l1_to_l2_message_tree.serialize()); + fields.extend_from_array(self.partial.serialize()); fields.storage } diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/fixtures/read_requests.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/fixtures/read_requests.nr index dacb83e2707..a77ddd9b45f 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/fixtures/read_requests.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/fixtures/read_requests.nr @@ -3,7 +3,6 @@ use crate::abis::{ side_effect::SideEffect, }; use crate::tests::fixtures; -use crate::utils::bounded_vec::BoundedVec; use crate::constants::{ MAX_READ_REQUESTS_PER_CALL, }; diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/private_call_data_builder.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/private_call_data_builder.nr index cdedfa676ad..f922026211f 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/private_call_data_builder.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/private_call_data_builder.nr @@ -21,9 +21,6 @@ use crate::{ transaction::{ request::TxRequest, }, - utils::{ - bounded_vec::BoundedVec, - }, }; use crate::constants::{ MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, @@ -114,14 +111,14 @@ impl PrivateCallDataBuilder { pub fn append_private_call_requests(&mut self, num_requests: Field, is_delegate_call: bool) { let (hashes, call_requests) = self.generate_call_requests(self.private_call_stack, num_requests, is_delegate_call); - self.public_inputs.private_call_stack_hashes.push_vec(hashes); - self.private_call_stack.push_vec(call_requests); + self.public_inputs.private_call_stack_hashes.extend_from_bounded_vec(hashes); + self.private_call_stack.extend_from_bounded_vec(call_requests); } pub fn append_public_call_requests(&mut self, num_requests: Field, is_delegate_call: bool) { let (hashes, call_requests) = self.generate_call_requests(self.public_call_stack, num_requests, is_delegate_call); - self.public_inputs.public_call_stack_hashes.push_vec(hashes); - self.public_call_stack.push_vec(call_requests); + self.public_inputs.public_call_stack_hashes.extend_from_bounded_vec(hashes); + self.public_call_stack.extend_from_bounded_vec(call_requests); } fn generate_call_requests( @@ -162,14 +159,14 @@ impl PrivateCallDataBuilder { pub fn append_read_requests(&mut self, num_read_requests: Field) { let (read_requests, read_request_membership_witnesses) = fixtures::read_requests::generate_read_requests(num_read_requests); - self.public_inputs.read_requests.push_vec(read_requests); - self.read_request_membership_witnesses.push_vec(read_request_membership_witnesses); + self.public_inputs.read_requests.extend_from_bounded_vec(read_requests); + self.read_request_membership_witnesses.extend_from_bounded_vec(read_request_membership_witnesses); } pub fn append_transient_read_requests(&mut self, num_read_requests: Field) { let (read_requests, read_request_membership_witnesses) = fixtures::read_requests::generate_transient_read_requests(num_read_requests); - self.public_inputs.read_requests.push_vec(read_requests); - self.read_request_membership_witnesses.push_vec(read_request_membership_witnesses); + self.public_inputs.read_requests.extend_from_bounded_vec(read_requests); + self.read_request_membership_witnesses.extend_from_bounded_vec(read_request_membership_witnesses); } pub fn set_encrypted_logs(&mut self, hash: [Field; NUM_FIELDS_PER_SHA256], preimages_length: Field) { diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/private_circuit_public_inputs_builder.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/private_circuit_public_inputs_builder.nr index 9ea565e9166..46196b43b4a 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/private_circuit_public_inputs_builder.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/private_circuit_public_inputs_builder.nr @@ -13,7 +13,6 @@ use crate::{ fixtures, testing_harness::build_contract_deployment_data, }, - utils::bounded_vec::BoundedVec, }; use crate::constants::{ MAX_READ_REQUESTS_PER_CALL, diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/public_call_data_builder.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/public_call_data_builder.nr index a9f85427c66..48dd0bb62e1 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/public_call_data_builder.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/public_call_data_builder.nr @@ -17,7 +17,6 @@ use crate::{ fixtures, public_circuit_public_inputs_builder::PublicCircuitPublicInputsBuilder, }, - utils::bounded_vec::BoundedVec, }; use crate::constants::{ MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/public_circuit_public_inputs_builder.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/public_circuit_public_inputs_builder.nr index e266a8e34ee..41f2102a051 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/public_circuit_public_inputs_builder.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/public_circuit_public_inputs_builder.nr @@ -11,7 +11,6 @@ use crate::{ }, header::Header, tests::fixtures, - utils::bounded_vec::BoundedVec, }; use crate::constants::{ MAX_NEW_COMMITMENTS_PER_CALL, diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/utils.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/utils.nr index 068a027f7a7..f4c2b212cc2 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/utils.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/utils.nr @@ -3,7 +3,6 @@ // Reducing the size of this package would be welcome. mod arrays; -mod bounded_vec; mod field; mod uint256; diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/utils/arrays.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/utils/arrays.nr index 239867b05e0..609071c4d84 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/utils/arrays.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/utils/arrays.nr @@ -1,6 +1,5 @@ use dep::std::array; use dep::std::cmp::Eq; -use crate::utils::bounded_vec::BoundedVec; use crate::traits::{Empty, is_empty}; pub fn array_to_bounded_vec(array: [T; N]) -> BoundedVec where T: Empty + Eq { diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/utils/bounded_vec.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/utils/bounded_vec.nr deleted file mode 100644 index e9aa91c26de..00000000000 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/utils/bounded_vec.nr +++ /dev/null @@ -1,194 +0,0 @@ -struct BoundedVec { - storage: [T; MaxLen], - // TODO: change this to return a u64 as Noir now - // uses u64 for indexing - len: Field, - empty_value: T, -} - -impl BoundedVec { - pub fn new(initial_value: T) -> Self { - BoundedVec { storage: [initial_value; MaxLen], len: 0, empty_value: initial_value } - } - - pub fn get(mut self: Self, index: Field) -> T { - assert(index as u64 < self.len as u64); - self.storage[index] - } - - pub fn get_unchecked(mut self: Self, index: Field) -> T { - self.storage[index] - } - - pub fn push(&mut self, elem: T) { - assert(self.len as u64 < MaxLen as u64, "push out of bounds"); - - self.storage[self.len] = elem; - self.len += 1; - } - - pub fn len(self) -> Field { - self.len - } - - pub fn max_len(_self: BoundedVec) -> Field { - MaxLen - } - - // This is a intermediate method, while we don't have an - // .extend method - pub fn storage(self) -> [T; MaxLen] { - self.storage - } - - pub fn push_array(&mut self, array: [T; Len]) { - let new_len = self.len + array.len(); - assert(new_len as u64 <= MaxLen as u64, "push_array out of bounds"); - for i in 0..array.len() { - self.storage[self.len + i] = array[i]; - } - self.len = new_len; - } - - pub fn push_vec(&mut self, vec: BoundedVec) { - let append_len = vec.len(); - let new_len = self.len + append_len; - assert(new_len as u64 <= MaxLen as u64, "push_vec out of bounds"); - - let mut exceeded_len = false; - for i in 0..Len { - exceeded_len |= i == append_len; - if !exceeded_len { - self.storage[self.len + (i as Field)] = vec.get_unchecked(i as Field); - } - } - self.len = new_len; - } - - pub fn pop(&mut self) -> T { - assert(self.len as u64 > 0); - self.len -= 1; - - let elem = self.storage[self.len]; - self.storage[self.len] = self.empty_value; - elem - } - - pub fn any(self, predicate: fn[Env](T) -> bool) -> bool { - let mut ret = false; - let mut exceeded_len = false; - for i in 0..MaxLen { - exceeded_len |= i == self.len; - if (!exceeded_len) { - ret |= predicate(self.storage[i]); - } - } - ret - } -} - -#[test] -fn test_vec_push_pop() { - let mut vec: BoundedVec = BoundedVec::new(0); - assert(vec.len == 0); - vec.push(2); - assert(vec.len == 1); - vec.push(4); - assert(vec.len == 2); - vec.push(6); - assert(vec.len == 3); - let x = vec.pop(); - assert(x == 6); - assert(vec.len == 2); - assert(vec.get(0) == 2); - assert(vec.get(1) == 4); -} - -#[test] -fn test_vec_push_array() { - let mut vec: BoundedVec = BoundedVec::new(0); - vec.push_array([2, 4]); - assert(vec.len == 2); - assert(vec.get(0) == 2); - assert(vec.get(1) == 4); -} - -#[test(should_fail_with="push_array out of bounds")] -fn test_vec_push_array_out_of_bound() { - let mut vec: BoundedVec = BoundedVec::new(0); - vec.push_array([2, 4, 6]); -} - -#[test(should_fail_with="push_array out of bounds")] -fn test_vec_push_array_twice_out_of_bound() { - let mut vec: BoundedVec = BoundedVec::new(0); - vec.push_array([2]); - assert(vec.len == 1); - vec.push_array([4, 6]); -} - -#[test(should_fail)] -fn test_vec_get_out_of_bound() { - let mut vec: BoundedVec = BoundedVec::new(0); - vec.push_array([2, 4]); - let _x = vec.get(2); -} - -#[test(should_fail)] -fn test_vec_get_not_declared() { - let mut vec: BoundedVec = BoundedVec::new(0); - vec.push_array([2]); - let _x = vec.get(1); -} - -#[test(should_fail)] -fn test_vec_get_uninitialized() { - let mut vec: BoundedVec = BoundedVec::new(0); - let _x = vec.get(0); -} - -#[test(should_fail_with="push out of bounds")] -fn test_vec_push_out_of_bound() { - let mut vec: BoundedVec = BoundedVec::new(0); - vec.push(1); - vec.push(2); -} - -#[test(should_fail_with="push_vec out of bounds")] -fn test_vec_push_vec_out_of_bound() { - let mut vec: BoundedVec = BoundedVec::new(0); - - let mut another_vec: BoundedVec = BoundedVec::new(0); - another_vec.push_array([1, 2, 3]); - - vec.push_vec(another_vec); -} - -#[test(should_fail_with="push_vec out of bounds")] -fn test_vec_push_vec_twice_out_of_bound() { - let mut vec: BoundedVec = BoundedVec::new(0); - vec.push_array([1, 2]); - - let mut another_vec: BoundedVec = BoundedVec::new(0); - another_vec.push(3); - - vec.push_vec(another_vec); -} - -#[test] -fn test_vec_any() { - let mut vec: BoundedVec = BoundedVec::new(0); - vec.push_array([2, 4, 6]); - assert(vec.any(|v| v == 2) == true); - assert(vec.any(|v| v == 4) == true); - assert(vec.any(|v| v == 6) == true); - assert(vec.any(|v| v == 3) == false); -} - -#[test] -fn test_vec_any_not_default() { - let default_value = 1; - let mut vec: BoundedVec = BoundedVec::new(default_value); - vec.push_array([2, 4]); - assert(vec.any(|v| v == default_value) == false); -} diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 06235a30e20..472b7df6b99 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -2761,7 +2761,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@portal:../noir/packages/backend_barretenberg::locator=%40aztec%2Faztec3-packages%40workspace%3A." dependencies: - "@aztec/bb.js": 0.19.0 + "@aztec/bb.js": 0.21.0 "@noir-lang/types": 0.23.0 fflate: ^0.8.0 languageName: node From 4ddf8f42d005d3a1b72fac6b9d40c475a3c4231d Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 31 Jan 2024 12:45:29 +0000 Subject: [PATCH 10/20] git_subrepo.sh: Fix parent in .gitrepo file. [skip ci] --- noir/.gitrepo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/.gitrepo b/noir/.gitrepo index aca0a674c07..3a7ff342ced 100644 --- a/noir/.gitrepo +++ b/noir/.gitrepo @@ -7,6 +7,6 @@ remote = https://github.com/noir-lang/noir branch = aztec-packages commit = 2badd023eab159b7892bd507897bedb360bebebe - parent = 3b25737324e45bdfb49233f73065569301282cc0 + parent = 7cdc18692313017a70b9c8d761b7540eb96a9369 method = merge cmdver = 0.4.6 From 7fa80db4b08a3db2e387739a1397f01df01cf175 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 31 Jan 2024 12:45:32 +0000 Subject: [PATCH 11/20] git subrepo push --branch=aztec-packages noir subrepo: subdir: "noir" merged: "ddd94a2f7" upstream: origin: "https://github.com/noir-lang/noir" branch: "aztec-packages" commit: "ddd94a2f7" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- noir/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noir/.gitrepo b/noir/.gitrepo index 3a7ff342ced..debb993e0bc 100644 --- a/noir/.gitrepo +++ b/noir/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/noir-lang/noir branch = aztec-packages - commit = 2badd023eab159b7892bd507897bedb360bebebe - parent = 7cdc18692313017a70b9c8d761b7540eb96a9369 + commit = ddd94a2f7f620da14e4222c2325119737b91908d + parent = 4ddf8f42d005d3a1b72fac6b9d40c475a3c4231d method = merge cmdver = 0.4.6 From d4125e12459a0375e9fa2cb8b83f700654219cea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Wed, 31 Jan 2024 14:20:31 +0100 Subject: [PATCH 12/20] refactor: updating block hash to be header.hash() (#4286) Fixes #3941 + renamed AppendOnlyTreeSnapshot.empty() as AppendOnlyTreeSnapshot.zero() to have it consistent with Noir **Note**: I did a large refactor of `MerkleTrees` class because with this change a lot of stuff there just didn't make sense anymore. Overall I think it's much cleaner now. --- .../periphery/ContractDeploymentEmitter.sol | 2 +- .../interfaces/IContractDeploymentEmitter.sol | 2 +- .../archiver/src/archiver/archiver.ts | 6 +- .../archiver/kv_archiver_store/block_store.ts | 8 +- .../aztec-node/src/aztec-node/server.ts | 13 +- .../aztec-nr/aztec/src/oracle/header.nr | 2 +- yarn-project/circuit-types/src/l2_block.ts | 65 +++--- yarn-project/circuit-types/src/l2_tx.ts | 8 +- .../src/abis/__snapshots__/abis.test.ts.snap | 86 ------- .../circuits.js/src/abis/abis.test.ts | 37 --- yarn-project/circuits.js/src/abis/abis.ts | 85 ------- .../structs/__snapshots__/header.test.ts.snap | 44 ++++ .../src/structs/complete_address.ts | 2 +- .../circuits.js/src/structs/header.test.ts | 7 + .../circuits.js/src/structs/header.ts | 16 +- .../src/structs/partial_state_reference.ts | 16 +- .../rollup/append_only_tree_snapshot.ts | 4 +- .../src/structs/state_reference.ts | 4 +- .../circuits.js/src/types/partial_address.ts | 2 +- .../src/integration_l1_publisher.test.ts | 5 +- yarn-project/foundation/src/abi/encoder.ts | 2 +- yarn-project/merkle-tree/src/index.ts | 2 +- .../inclusion_proofs_contract/src/main.nr | 4 +- .../rollup-lib/src/base/base_rollup_inputs.nr | 4 +- .../src/crates/rollup-lib/src/hash.nr | 13 -- .../src/crates/rollup-lib/src/lib.nr | 2 - .../src/crates/rollup-lib/src/root.nr | 22 +- .../crates/types/src/abis/global_variables.nr | 14 -- .../src/crates/types/src/constants.nr | 2 +- .../src/crates/types/src/header.nr | 24 +- .../pxe/src/pxe_service/pxe_service.ts | 2 +- .../block_builder/solo_block_builder.test.ts | 40 ++-- .../src/block_builder/solo_block_builder.ts | 77 ++----- .../sequencer-client/src/sequencer/index.ts | 1 - .../src/sequencer/public_processor.ts | 3 +- .../sequencer-client/src/sequencer/utils.ts | 12 - .../world-state-db/merkle_tree_operations.ts | 25 +-- .../merkle_tree_operations_facade.ts | 32 +-- .../merkle_tree_snapshot_operations_facade.ts | 12 +- .../src/world-state-db/merkle_trees.ts | 212 +++++++----------- 40 files changed, 281 insertions(+), 638 deletions(-) create mode 100644 yarn-project/circuits.js/src/structs/__snapshots__/header.test.ts.snap delete mode 100644 yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/hash.nr delete mode 100644 yarn-project/sequencer-client/src/sequencer/utils.ts diff --git a/l1-contracts/src/periphery/ContractDeploymentEmitter.sol b/l1-contracts/src/periphery/ContractDeploymentEmitter.sol index 15a72458d40..efa55fc0f35 100644 --- a/l1-contracts/src/periphery/ContractDeploymentEmitter.sol +++ b/l1-contracts/src/periphery/ContractDeploymentEmitter.sol @@ -23,7 +23,7 @@ contract ContractDeploymentEmitter is IContractDeploymentEmitter { * @param _saltedInitializationHash - Salted init hash * @param _publicKeyHash - Public key hash * @param _acir - The acir bytecode of the L2 contract - * @dev See the link bellow for more info on partial address and public key: + * @dev See the link below for more info on partial address and public key: * https://github.com/AztecProtocol/aztec-packages/blob/master/docs/docs/concepts/foundation/accounts/keys.md#addresses-partial-addresses-and-public-keys * TODO: replace the link above with the link to deployed docs */ diff --git a/l1-contracts/src/periphery/interfaces/IContractDeploymentEmitter.sol b/l1-contracts/src/periphery/interfaces/IContractDeploymentEmitter.sol index bd45c93cd68..9debce8240f 100644 --- a/l1-contracts/src/periphery/interfaces/IContractDeploymentEmitter.sol +++ b/l1-contracts/src/periphery/interfaces/IContractDeploymentEmitter.sol @@ -19,7 +19,7 @@ interface IContractDeploymentEmitter { * @param saltedInitializationHash - Salted init hash * @param publicKeyHash - Public key hash * @param acir - The acir bytecode of the L2 contract - * @dev See the link bellow for more info on partial address and public key: + * @dev See the link below for more info on partial address and public key: * https://github.com/AztecProtocol/aztec-packages/blob/master/docs/docs/concepts/foundation/accounts/keys.md#addresses-partial-addresses-and-public-keys * TODO: replace the link above with the link to deployed docs */ diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index e350e216823..4856a608bdf 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -297,11 +297,7 @@ export class Archiver implements ArchiveSource { retrievedBlocks.retrievedData.map(block => { // Ensure we pad the L1 to L2 message array to the full size before storing. block.newL1ToL2Messages = padArrayEnd(block.newL1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP); - return L2Block.fromFields( - omit(block, ['newEncryptedLogs', 'newUnencryptedLogs']), - block.getBlockHash(), - block.getL1BlockNumber(), - ); + return L2Block.fromFields(omit(block, ['newEncryptedLogs', 'newUnencryptedLogs']), block.getL1BlockNumber()); }), ); } diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts index db38f09866a..ef637162c4e 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts @@ -9,7 +9,6 @@ type BlockContext = { blockNumber: number; l1BlockNumber: bigint; block: Buffer; - blockHash: Buffer; }; /** @@ -46,7 +45,6 @@ export class BlockStore { blockNumber: block.number, block: block.toBuffer(), l1BlockNumber: block.getL1BlockNumber(), - blockHash: block.getBlockHash(), }); for (const [i, tx] of block.getTxs().entries()) { @@ -77,7 +75,7 @@ export class BlockStore { */ *getBlocks(start: number, limit: number): IterableIterator { for (const blockCtx of this.#blocks.values(this.#computeBlockRange(start, limit))) { - yield L2Block.fromBuffer(blockCtx.block, blockCtx.blockHash); + yield L2Block.fromBuffer(blockCtx.block); } } @@ -92,9 +90,7 @@ export class BlockStore { return undefined; } - const block = L2Block.fromBuffer(blockCtx.block, blockCtx.blockHash); - - return block; + return L2Block.fromBuffer(blockCtx.block); } /** diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index e770dbcf840..2ccd40baa00 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -26,7 +26,6 @@ import { ARCHIVE_HEIGHT, CONTRACT_TREE_HEIGHT, Fr, - GlobalVariables, Header, L1_TO_L2_MSG_TREE_HEIGHT, NOTE_HASH_TREE_HEIGHT, @@ -35,7 +34,7 @@ import { PUBLIC_DATA_TREE_HEIGHT, PublicDataTreeLeafPreimage, } from '@aztec/circuits.js'; -import { computeGlobalsHash, computePublicDataTreeLeafSlot } from '@aztec/circuits.js/abis'; +import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/abis'; import { L1ContractAddresses, createEthereumChain } from '@aztec/ethereum'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { createDebugLogger } from '@aztec/foundation/log'; @@ -45,7 +44,6 @@ import { GlobalVariableBuilder, PublicProcessorFactory, SequencerClient, - buildInitialHeader, getGlobalVariableBuilder, } from '@aztec/sequencer-client'; import { SiblingPath } from '@aztec/types/membership'; @@ -537,7 +535,7 @@ export class AztecNodeService implements AztecNode { // No block was not found so we build the initial header. const committedDb = await this.#getWorldState('latest'); - return await buildInitialHeader(committedDb); + return await committedDb.buildInitialHeader(); } /** @@ -549,16 +547,11 @@ export class AztecNodeService implements AztecNode { const blockNumber = (await this.blockSource.getBlockNumber()) + 1; const newGlobalVariables = await this.globalVariableBuilder.buildGlobalVariables(new Fr(blockNumber)); const prevHeader = (await this.blockSource.getBlock(-1))?.header; - const prevGlobalVariables = prevHeader?.globalVariables ?? GlobalVariables.empty(); // Instantiate merkle trees so uncommitted updates by this simulation are local to it. // TODO we should be able to remove this after https://github.com/AztecProtocol/aztec-packages/issues/1869 // So simulation of public functions doesn't affect the merkle trees. - const merkleTrees = new MerkleTrees(this.merkleTreesDb, this.log); - const globalVariablesHash = computeGlobalsHash(prevGlobalVariables); - await merkleTrees.init({ - globalVariablesHash, - }); + const merkleTrees = await MerkleTrees.new(this.merkleTreesDb, this.log); const publicProcessorFactory = new PublicProcessorFactory( merkleTrees.asLatest(), diff --git a/yarn-project/aztec-nr/aztec/src/oracle/header.nr b/yarn-project/aztec-nr/aztec/src/oracle/header.nr index 33718bf206b..bcb7027d2d6 100644 --- a/yarn-project/aztec-nr/aztec/src/oracle/header.nr +++ b/yarn-project/aztec-nr/aztec/src/oracle/header.nr @@ -40,7 +40,7 @@ pub fn get_header_at(block_number: u32, context: PrivateContext) -> Header { let header = get_header_at_internal(block_number); // 4) Compute the block hash from the block header - let block_hash = header.block_hash(); + let block_hash = header.hash(); // 5) Get the membership witness of the block in the archive let witness = get_archive_membership_witness(last_archive_block_number, block_hash); diff --git a/yarn-project/circuit-types/src/l2_block.ts b/yarn-project/circuit-types/src/l2_block.ts index 0f7dc8844e8..4210e720eaf 100644 --- a/yarn-project/circuit-types/src/l2_block.ts +++ b/yarn-project/circuit-types/src/l2_block.ts @@ -11,7 +11,7 @@ import { } from '@aztec/circuits.js'; import { makeAppendOnlyTreeSnapshot, makeHeader } from '@aztec/circuits.js/factories'; import { times } from '@aztec/foundation/collection'; -import { keccak, sha256 } from '@aztec/foundation/crypto'; +import { sha256 } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; @@ -91,7 +91,6 @@ export class L2Block { public newL1ToL2Messages: Fr[] = [], newEncryptedLogs?: L2BlockL2Logs, newUnencryptedLogs?: L2BlockL2Logs, - private blockHash?: Buffer, l1BlockNumber?: bigint, ) { if (newCommitments.length % MAX_NEW_COMMITMENTS_PER_TX !== 0) { @@ -173,7 +172,6 @@ export class L2Block { newEncryptedLogs, newUnencryptedLogs, }, - undefined, // just for testing purposes, each random L2 block got emitted in the equivalent L1 block BigInt(l2BlockNum), ); @@ -229,7 +227,6 @@ export class L2Block { */ newUnencryptedLogs?: L2BlockL2Logs; }, - blockHash?: Buffer, l1BlockNumber?: bigint, ) { return new this( @@ -244,7 +241,6 @@ export class L2Block { fields.newL1ToL2Messages, fields.newEncryptedLogs, fields.newUnencryptedLogs, - blockHash, l1BlockNumber, ); } @@ -329,10 +325,9 @@ export class L2Block { /** * Deserializes L2 block without logs from a buffer. * @param buf - A serialized L2 block. - * @param blockHash - The hash of the block. * @returns Deserialized L2 block. */ - static fromBuffer(buf: Buffer | BufferReader, blockHash?: Buffer) { + static fromBuffer(buf: Buffer | BufferReader) { const reader = BufferReader.asReader(buf); const header = reader.readObject(Header); const archive = reader.readObject(AppendOnlyTreeSnapshot); @@ -345,20 +340,17 @@ export class L2Block { // TODO(sean): could an optimization of this be that it is encoded such that zeros are assumed const newL1ToL2Messages = reader.readVector(Fr); - return L2Block.fromFields( - { - archive, - header, - newCommitments, - newNullifiers, - newPublicDataWrites, - newL2ToL1Msgs, - newContracts, - newContractData, - newL1ToL2Messages, - }, - blockHash, - ); + return L2Block.fromFields({ + archive, + header, + newCommitments, + newNullifiers, + newPublicDataWrites, + newL2ToL1Msgs, + newContracts, + newContractData, + newL1ToL2Messages, + }); } /** @@ -441,14 +433,11 @@ export class L2Block { } /** - * Returns the block's hash. + * Returns the block's hash (hash of block header). * @returns The block's hash. */ - public getBlockHash(): Buffer { - if (!this.blockHash) { - this.blockHash = keccak(this.toBufferWithLogs()); - } - return this.blockHash; + public hash(): Fr { + return this.header.hash(); } /** @@ -460,11 +449,11 @@ export class L2Block { const buf = serializeToBuffer( this.header.globalVariables, // TODO(#3868) - AppendOnlyTreeSnapshot.empty(), // this.startNoteHashTreeSnapshot, - AppendOnlyTreeSnapshot.empty(), // this.startNullifierTreeSnapshot, - AppendOnlyTreeSnapshot.empty(), // this.startContractTreeSnapshot, - AppendOnlyTreeSnapshot.empty(), // this.startPublicDataTreeSnapshot, - AppendOnlyTreeSnapshot.empty(), // this.startL1ToL2MessageTreeSnapshot, + AppendOnlyTreeSnapshot.zero(), // this.startNoteHashTreeSnapshot, + AppendOnlyTreeSnapshot.zero(), // this.startNullifierTreeSnapshot, + AppendOnlyTreeSnapshot.zero(), // this.startContractTreeSnapshot, + AppendOnlyTreeSnapshot.zero(), // this.startPublicDataTreeSnapshot, + AppendOnlyTreeSnapshot.zero(), // this.startL1ToL2MessageTreeSnapshot, this.header.lastArchive, this.header.state.partial.noteHashTree, this.header.state.partial.nullifierTree, @@ -487,11 +476,11 @@ export class L2Block { const inputValue = serializeToBuffer( new Fr(Number(this.header.globalVariables.blockNumber.toBigInt()) - 1), // TODO(#3868) - AppendOnlyTreeSnapshot.empty(), // this.startNoteHashTreeSnapshot, - AppendOnlyTreeSnapshot.empty(), // this.startNullifierTreeSnapshot, - AppendOnlyTreeSnapshot.empty(), // this.startContractTreeSnapshot, - AppendOnlyTreeSnapshot.empty(), // this.startPublicDataTreeSnapshot, - AppendOnlyTreeSnapshot.empty(), // this.startL1ToL2MessageTreeSnapshot, + AppendOnlyTreeSnapshot.zero(), // this.startNoteHashTreeSnapshot, + AppendOnlyTreeSnapshot.zero(), // this.startNullifierTreeSnapshot, + AppendOnlyTreeSnapshot.zero(), // this.startContractTreeSnapshot, + AppendOnlyTreeSnapshot.zero(), // this.startPublicDataTreeSnapshot, + AppendOnlyTreeSnapshot.zero(), // this.startL1ToL2MessageTreeSnapshot, this.header.lastArchive, ); return sha256(inputValue); @@ -639,7 +628,7 @@ export class L2Block { newL2ToL1Msgs, newContracts, newContractData, - this.getBlockHash(), + this.hash(), Number(this.header.globalVariables.blockNumber.toBigInt()), ); } diff --git a/yarn-project/circuit-types/src/l2_tx.ts b/yarn-project/circuit-types/src/l2_tx.ts index 65588476418..593f85d7b81 100644 --- a/yarn-project/circuit-types/src/l2_tx.ts +++ b/yarn-project/circuit-types/src/l2_tx.ts @@ -57,7 +57,7 @@ export class L2Tx { /** * The unique identifier of the block containing the transaction. */ - public blockHash: Buffer, + public blockHash: Fr, /** * The block number in which the transaction was included. */ @@ -80,7 +80,7 @@ export class L2Tx { reader.readVector(Fr), reader.readVector(Fr), reader.readVector(ContractData), - reader.readBytes(Fr.SIZE_IN_BYTES), + Fr.fromBuffer(reader), reader.readNumber(), ); } @@ -106,7 +106,7 @@ export class L2Tx { new Vector(this.newL2ToL1Msgs).toBuffer(), new Vector(this.newContracts).toBuffer(), new Vector(this.newContractData).toBuffer(), - this.blockHash, + this.blockHash.toBuffer(), numToUInt32BE(this.blockNumber), ]); } @@ -127,7 +127,7 @@ export class L2Tx { times(rand(0, MAX_NEW_L2_TO_L1_MSGS_PER_TX), Fr.random), times(rand(0, MAX_NEW_CONTRACTS_PER_TX), Fr.random), times(rand(0, MAX_NEW_CONTRACTS_PER_TX), ContractData.random), - Fr.random().toBuffer(), + Fr.random(), 123, ); } diff --git a/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap b/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap index 8491e4c1e37..a04642f359b 100644 --- a/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap +++ b/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap @@ -10,49 +10,6 @@ exports[`abis Computes an empty public inputs hash 1`] = `"0x2e2b79cee62cb99e91 exports[`abis Computes an empty sideeffect hash 1`] = `"0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed"`; -exports[`abis compute globals hash 1`] = ` -Fr { - "asBigInt": 19996198784166720428914107076917074510032365849254400404611644441094528984289n, - "asBuffer": { - "data": [ - 44, - 53, - 114, - 139, - 52, - 188, - 28, - 197, - 40, - 157, - 117, - 130, - 246, - 163, - 68, - 239, - 11, - 227, - 228, - 184, - 250, - 189, - 231, - 11, - 41, - 32, - 78, - 168, - 174, - 60, - 100, - 225, - ], - "type": "Buffer", - }, -} -`; - exports[`abis compute private call stack item hash 1`] = ` Fr { "asBigInt": 12187345511405217717040217531423286257305914329376428594135414078733109256018n, @@ -280,49 +237,6 @@ exports[`abis computes a function selector 1`] = ` } `; -exports[`abis computes block hash with globals 1`] = ` -Fr { - "asBigInt": 7177915431153102916601456081755280584460785548870192083974540199919775120827n, - "asBuffer": { - "data": [ - 15, - 222, - 142, - 96, - 169, - 217, - 84, - 90, - 55, - 110, - 52, - 172, - 167, - 236, - 97, - 56, - 185, - 98, - 133, - 50, - 113, - 88, - 184, - 54, - 59, - 75, - 252, - 181, - 66, - 59, - 253, - 187, - ], - "type": "Buffer", - }, -} -`; - exports[`abis computes commitment nonce 1`] = ` Fr { "asBigInt": 7653394882992289714855533169019502055399179742531912347686813547951736946253n, diff --git a/yarn-project/circuits.js/src/abis/abis.test.ts b/yarn-project/circuits.js/src/abis/abis.test.ts index 30ed11ab262..99b718e52a9 100644 --- a/yarn-project/circuits.js/src/abis/abis.test.ts +++ b/yarn-project/circuits.js/src/abis/abis.test.ts @@ -6,7 +6,6 @@ import { FunctionData, FunctionLeafPreimage, FunctionSelector, - GlobalVariables, NewContractData, PublicCallStackItem, PublicCircuitPublicInputs, @@ -22,14 +21,12 @@ import { makeVerificationKey, } from '../tests/factories.js'; import { - computeBlockHashWithGlobals, computeCommitmentNonce, computeCommitmentsHash, computeContractLeaf, computeFunctionLeaf, computeFunctionSelector, computeFunctionTreeRoot, - computeGlobalsHash, computeNullifierHash, computePrivateCallStackItemHash, computePublicCallStackItemHash, @@ -113,40 +110,6 @@ describe('abis', () => { expect(res).toMatchSnapshot(); }); - it('computes block hash with globals', () => { - const globals = GlobalVariables.from({ - chainId: new Fr(1n), - version: new Fr(2n), - blockNumber: new Fr(3n), - timestamp: new Fr(4n), - }); - const noteHashTreeRoot = new Fr(5n); - const nullifierTreeRoot = new Fr(6n); - const contractTreeRoot = new Fr(7n); - const l1ToL2DataTreeRoot = new Fr(8n); - const publicDataTreeRoot = new Fr(9n); - const res = computeBlockHashWithGlobals( - globals, - noteHashTreeRoot, - nullifierTreeRoot, - contractTreeRoot, - l1ToL2DataTreeRoot, - publicDataTreeRoot, - ); - expect(res).toMatchSnapshot(); - }); - - it('compute globals hash', () => { - const globals = GlobalVariables.from({ - chainId: new Fr(1n), - version: new Fr(2n), - blockNumber: new Fr(3n), - timestamp: new Fr(4n), - }); - const res = computeGlobalsHash(globals); - expect(res).toMatchSnapshot(); - }); - it('computes public data tree value', () => { const value = new Fr(3n); const res = computePublicDataTreeValue(value); diff --git a/yarn-project/circuits.js/src/abis/abis.ts b/yarn-project/circuits.js/src/abis/abis.ts index 1b479589ac4..c6650f41e42 100644 --- a/yarn-project/circuits.js/src/abis/abis.ts +++ b/yarn-project/circuits.js/src/abis/abis.ts @@ -21,7 +21,6 @@ import { ContractStorageUpdateRequest, FunctionData, FunctionLeafPreimage, - GlobalVariables, NewContractData, PrivateCallStackItem, PrivateCircuitPublicInputs, @@ -212,90 +211,6 @@ export function siloNullifier(contract: AztecAddress, innerNullifier: Fr): Fr { return Fr.fromBuffer(pedersenHash([contract.toBuffer(), innerNullifier.toBuffer()], GeneratorIndex.OUTER_NULLIFIER)); } -/** - * Computes the block hash given the blocks globals and roots. - * @param globals - The global variables to put into the block hash. - * @param noteHashTree - The root of the note hash tree. - * @param nullifierTreeRoot - The root of the nullifier tree. - * @param contractTreeRoot - The root of the contract tree. - * @param l1ToL2DataTreeRoot - The root of the l1 to l2 data tree. - * @param publicDataTreeRoot - The root of the public data tree. - * @returns The block hash. - */ -// TODO(#3941) -export function computeBlockHashWithGlobals( - globals: GlobalVariables, - noteHashTreeRoot: Fr, - nullifierTreeRoot: Fr, - contractTreeRoot: Fr, - l1ToL2DataTreeRoot: Fr, - publicDataTreeRoot: Fr, -): Fr { - return computeBlockHash( - computeGlobalsHash(globals), - noteHashTreeRoot, - nullifierTreeRoot, - contractTreeRoot, - l1ToL2DataTreeRoot, - publicDataTreeRoot, - ); -} - -/** - * Computes the block hash given the blocks globals and roots. - * @param globalsHash - The global variables hash to put into the block hash. - * @param noteHashTree - The root of the note hash tree. - * @param nullifierTreeRoot - The root of the nullifier tree. - * @param contractTreeRoot - The root of the contract tree. - * @param l1ToL2DataTreeRoot - The root of the l1 to l2 data tree. - * @param publicDataTreeRoot - The root of the public data tree. - * @returns The block hash. - */ -// TODO(#3941): nuke this and replace with `Header.hash()` -export function computeBlockHash( - globalsHash: Fr, - noteHashTreeRoot: Fr, - nullifierTreeRoot: Fr, - contractTreeRoot: Fr, - l1ToL2DataTreeRoot: Fr, - publicDataTreeRoot: Fr, -): Fr { - return Fr.fromBuffer( - pedersenHash( - [ - globalsHash.toBuffer(), - noteHashTreeRoot.toBuffer(), - nullifierTreeRoot.toBuffer(), - contractTreeRoot.toBuffer(), - l1ToL2DataTreeRoot.toBuffer(), - publicDataTreeRoot.toBuffer(), - ], - GeneratorIndex.BLOCK_HASH, - ), - ); -} - -/** - * Computes the globals hash given the globals. - * @param globals - The global variables to put into the block hash. - * @returns The globals hash. - * TODO: move this to GlobalVariables? - * TODO(#3941) Investigate whether to nuke this once #3941 is done. - */ -export function computeGlobalsHash(globals: GlobalVariables): Fr { - return Fr.fromBuffer( - pedersenHash( - [ - globals.chainId.toBuffer(), - globals.version.toBuffer(), - globals.blockNumber.toBuffer(), - globals.timestamp.toBuffer(), - ], - GeneratorIndex.GLOBAL_VARIABLES, - ), - ); -} - /** * Computes a public data tree value ready for insertion. * @param value - Raw public data tree value to hash into a tree-insertion-ready value. diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/header.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/header.test.ts.snap new file mode 100644 index 00000000000..8a15a59ee84 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/__snapshots__/header.test.ts.snap @@ -0,0 +1,44 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Header computes hash 1`] = ` +Fr { + "asBigInt": 17991638921121681345555824161757346486368776085978982802127357651656088857262n, + "asBuffer": { + "data": [ + 39, + 198, + 232, + 33, + 120, + 194, + 121, + 42, + 23, + 66, + 111, + 251, + 166, + 131, + 251, + 128, + 16, + 46, + 122, + 209, + 193, + 24, + 177, + 67, + 172, + 91, + 198, + 153, + 236, + 93, + 170, + 174, + ], + "type": "Buffer", + }, +} +`; diff --git a/yarn-project/circuits.js/src/structs/complete_address.ts b/yarn-project/circuits.js/src/structs/complete_address.ts index 7708ee17607..cf34dfa2426 100644 --- a/yarn-project/circuits.js/src/structs/complete_address.ts +++ b/yarn-project/circuits.js/src/structs/complete_address.ts @@ -16,7 +16,7 @@ import { * * @remarks We have introduced this type because it is common that these 3 values are used together. They are commonly * used together because it is the information needed to send user a note. - * @remarks See the link bellow for details about how address is computed: + * @remarks See the link below for details about how address is computed: * https://github.com/AztecProtocol/aztec-packages/blob/master/docs/docs/concepts/foundation/accounts/keys.md#addresses-partial-addresses-and-public-keys */ export class CompleteAddress { diff --git a/yarn-project/circuits.js/src/structs/header.test.ts b/yarn-project/circuits.js/src/structs/header.test.ts index 5581a1b482a..72d49ae9bf2 100644 --- a/yarn-project/circuits.js/src/structs/header.test.ts +++ b/yarn-project/circuits.js/src/structs/header.test.ts @@ -18,4 +18,11 @@ describe('Header', () => { const res = Header.fromFieldArray(fieldArray); expect(res).toEqual(expected); }); + + it('computes hash', () => { + const seed = 9870243; + const header = makeHeader(seed, undefined); + const hash = header.hash(); + expect(hash).toMatchSnapshot(); + }); }); diff --git a/yarn-project/circuits.js/src/structs/header.ts b/yarn-project/circuits.js/src/structs/header.ts index 9f78ac3a1a0..016f9e9f98e 100644 --- a/yarn-project/circuits.js/src/structs/header.ts +++ b/yarn-project/circuits.js/src/structs/header.ts @@ -1,7 +1,8 @@ +import { pedersenHash } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, from2Fields, serializeToBuffer, to2Fields } from '@aztec/foundation/serialize'; -import { HEADER_LENGTH } from '../constants.gen.js'; +import { GeneratorIndex, HEADER_LENGTH } from '../constants.gen.js'; import { GlobalVariables } from './global_variables.js'; import { PartialStateReference } from './partial_state_reference.js'; import { AppendOnlyTreeSnapshot } from './rollup/append_only_tree_snapshot.js'; @@ -79,7 +80,7 @@ export class Header { static empty(): Header { return new Header( - AppendOnlyTreeSnapshot.empty(), + AppendOnlyTreeSnapshot.zero(), Buffer.alloc(NUM_BYTES_PER_SHA256), StateReference.empty(), GlobalVariables.empty(), @@ -88,7 +89,7 @@ export class Header { isEmpty(): boolean { return ( - this.lastArchive.isEmpty() && + this.lastArchive.isZero() && this.bodyHash.equals(Buffer.alloc(NUM_BYTES_PER_SHA256)) && this.state.isEmpty() && this.globalVariables.isEmpty() @@ -107,4 +108,13 @@ export class Header { const buffer = Buffer.from(str.replace(/^0x/i, ''), 'hex'); return Header.fromBuffer(buffer); } + + hash(): Fr { + return Fr.fromBuffer( + pedersenHash( + this.toFieldArray().map(f => f.toBuffer()), + GeneratorIndex.BLOCK_HASH, + ), + ); + } } diff --git a/yarn-project/circuits.js/src/structs/partial_state_reference.ts b/yarn-project/circuits.js/src/structs/partial_state_reference.ts index ed2ce885792..7e375eeb12a 100644 --- a/yarn-project/circuits.js/src/structs/partial_state_reference.ts +++ b/yarn-project/circuits.js/src/structs/partial_state_reference.ts @@ -29,10 +29,10 @@ export class PartialStateReference { static empty(): PartialStateReference { return new PartialStateReference( - AppendOnlyTreeSnapshot.empty(), - AppendOnlyTreeSnapshot.empty(), - AppendOnlyTreeSnapshot.empty(), - AppendOnlyTreeSnapshot.empty(), + AppendOnlyTreeSnapshot.zero(), + AppendOnlyTreeSnapshot.zero(), + AppendOnlyTreeSnapshot.zero(), + AppendOnlyTreeSnapshot.zero(), ); } @@ -51,10 +51,10 @@ export class PartialStateReference { isEmpty(): boolean { return ( - this.noteHashTree.isEmpty() && - this.nullifierTree.isEmpty() && - this.contractTree.isEmpty() && - this.publicDataTree.isEmpty() + this.noteHashTree.isZero() && + this.nullifierTree.isZero() && + this.contractTree.isZero() && + this.publicDataTree.isZero() ); } } diff --git a/yarn-project/circuits.js/src/structs/rollup/append_only_tree_snapshot.ts b/yarn-project/circuits.js/src/structs/rollup/append_only_tree_snapshot.ts index 4d8914029c1..09216a8a0a1 100644 --- a/yarn-project/circuits.js/src/structs/rollup/append_only_tree_snapshot.ts +++ b/yarn-project/circuits.js/src/structs/rollup/append_only_tree_snapshot.ts @@ -47,11 +47,11 @@ export class AppendOnlyTreeSnapshot { return AppendOnlyTreeSnapshot.fromBuffer(Buffer.from(str, STRING_ENCODING)); } - static empty() { + static zero() { return new AppendOnlyTreeSnapshot(Fr.ZERO, 0); } - isEmpty(): boolean { + isZero(): boolean { return this.root.isZero() && this.nextAvailableLeafIndex === 0; } } diff --git a/yarn-project/circuits.js/src/structs/state_reference.ts b/yarn-project/circuits.js/src/structs/state_reference.ts index 7079c4511f4..284d988e07f 100644 --- a/yarn-project/circuits.js/src/structs/state_reference.ts +++ b/yarn-project/circuits.js/src/structs/state_reference.ts @@ -30,10 +30,10 @@ export class StateReference { } static empty(): StateReference { - return new StateReference(AppendOnlyTreeSnapshot.empty(), PartialStateReference.empty()); + return new StateReference(AppendOnlyTreeSnapshot.zero(), PartialStateReference.empty()); } isEmpty(): boolean { - return this.l1ToL2MessageTree.isEmpty() && this.partial.isEmpty(); + return this.l1ToL2MessageTree.isZero() && this.partial.isEmpty(); } } diff --git a/yarn-project/circuits.js/src/types/partial_address.ts b/yarn-project/circuits.js/src/types/partial_address.ts index e99d3786536..21877f72e88 100644 --- a/yarn-project/circuits.js/src/types/partial_address.ts +++ b/yarn-project/circuits.js/src/types/partial_address.ts @@ -1,7 +1,7 @@ import { Fr } from '@aztec/foundation/fields'; /** - * A type which along with public key forms a preimage of a contract address. See the link bellow for more details + * A type which along with public key forms a preimage of a contract address. See the link below for more details * https://github.com/AztecProtocol/aztec-packages/blob/master/docs/docs/concepts/foundation/accounts/keys.md#addresses-partial-addresses-and-public-keys */ export type PartialAddress = Fr; diff --git a/yarn-project/end-to-end/src/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/integration_l1_publisher.test.ts index 4b6c4da2429..f147fccfd4b 100644 --- a/yarn-project/end-to-end/src/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/integration_l1_publisher.test.ts @@ -36,7 +36,6 @@ import { L1Publisher, RealRollupCircuitSimulator, SoloBlockBuilder, - buildInitialHeader, getL1Publisher, getVerificationKeys, makeEmptyProcessedTx as makeEmptyProcessedTxFromHistoricalTreeRoots, @@ -150,7 +149,7 @@ describe('L1Publisher integration', () => { l1BlockPublishRetryIntervalMS: 100, }); - prevHeader = await buildInitialHeader(builderDb); + prevHeader = await builderDb.buildInitialHeader(); }, 100_000); const makeEmptyProcessedTx = async () => { @@ -256,7 +255,7 @@ describe('L1Publisher integration', () => { l2ToL1Messages: block.newL2ToL1Msgs.map(m => `0x${m.toBuffer().toString('hex').padStart(64, '0')}`), }, block: { - // The json formatting in forge is a bit brittle, so we convert Fr to a number in the few values bellow. + // The json formatting in forge is a bit brittle, so we convert Fr to a number in the few values below. // This should not be a problem for testing as long as the values are not larger than u32. archive: `0x${block.archive.root.toBuffer().toString('hex').padStart(64, '0')}`, body: `0x${block.bodyToBuffer().toString('hex')}`, diff --git a/yarn-project/foundation/src/abi/encoder.ts b/yarn-project/foundation/src/abi/encoder.ts index cf25db56f54..ad515013769 100644 --- a/yarn-project/foundation/src/abi/encoder.ts +++ b/yarn-project/foundation/src/abi/encoder.ts @@ -92,7 +92,7 @@ class ArgumentEncoder { break; } for (const field of abiType.fields) { - // The ugly check bellow is here because of a `CompleteAddress`. Since it has `address` property but in ABI + // The ugly check below is here because of a `CompleteAddress`. Since it has `address` property but in ABI // it's called inner we set `field.name` here to `address` instead of using `field.name`. I know it's hacky // but using address.address in Noir looks stupid and renaming `address` param of `CompleteAddress` // to `inner` doesn't make sense. diff --git a/yarn-project/merkle-tree/src/index.ts b/yarn-project/merkle-tree/src/index.ts index 68826f44e42..45ae1771bbf 100644 --- a/yarn-project/merkle-tree/src/index.ts +++ b/yarn-project/merkle-tree/src/index.ts @@ -6,7 +6,7 @@ export * from './pedersen.js'; export * from './sparse_tree/sparse_tree.js'; export { StandardIndexedTree } from './standard_indexed_tree/standard_indexed_tree.js'; export * from './standard_tree/standard_tree.js'; -export { INITIAL_LEAF } from './tree_base.js'; +export { INITIAL_LEAF, getTreeMeta } from './tree_base.js'; export { newTree } from './new_tree.js'; export { loadTree } from './load_tree.js'; export * from './snapshots/snapshot_builder.js'; diff --git a/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr b/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr index 58cb7b377a7..12a3a797029 100644 --- a/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr @@ -97,7 +97,7 @@ contract InclusionProofs { fn test_note_inclusion_proof( owner: AztecAddress, block_number: u32, // The block at which we'll prove that the note exists - // Value bellow is only used when the note is not found --> used to test the note inclusion failure case (it + // Value below is only used when the note is not found --> used to test the note inclusion failure case (it // allows me to pass in random value of note nullifier - I cannot add and fetch a random note from PXE because // PXE performs note commitment inclusion check when you add a new note). spare_commitment: Field @@ -126,7 +126,7 @@ contract InclusionProofs { fn test_nullifier_non_inclusion_proof( owner: AztecAddress, block_number: u32, // The block at which we'll prove that the nullifier does not exists - // Value bellow is only used when the note is not found --> used to test the nullifier non-inclusion failure + // Value below is only used when the note is not found --> used to test the nullifier non-inclusion failure // case (it allows me to pass in random value of note nullifier - I cannot add and fetch a random note from PXE // because PXE performs note commitment inclusion check when you add a new note). spare_nullifier: Field diff --git a/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/base/base_rollup_inputs.nr b/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/base/base_rollup_inputs.nr index d831a4647e6..33612695bbb 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/base/base_rollup_inputs.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/base/base_rollup_inputs.nr @@ -339,7 +339,7 @@ impl BaseRollupInputs { // Rebuild the block hash let header = self.kernel_data.public_inputs.constants.historical_header; - let previous_block_hash = header.block_hash(); + let previous_block_hash = header.hash(); let previous_block_hash_witness = self.archive_root_membership_witness; @@ -737,7 +737,7 @@ mod tests { let _nullifier = builder.end.new_nullifiers.pop(); inputs.kernel_data = builder.is_public(); - inputs.pre_existing_blocks[0] = inputs.kernel_data.historical_header.block_hash(); + inputs.pre_existing_blocks[0] = inputs.kernel_data.historical_header.hash(); inputs } diff --git a/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/hash.nr b/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/hash.nr deleted file mode 100644 index 6f314de2f24..00000000000 --- a/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/hash.nr +++ /dev/null @@ -1,13 +0,0 @@ -use dep::types::{ - abis::global_variables::GlobalVariables, - constants::GENERATOR_INDEX__BLOCK_HASH, - state_reference::StateReference, -}; - -pub fn compute_block_hash_with_globals(globals: GlobalVariables, state: StateReference) -> Field { - let inputs = [ - globals.hash(), state.partial.note_hash_tree.root, state.partial.nullifier_tree.root, state.partial.contract_tree.root, state.l1_to_l2_message_tree.root, state.partial.public_data_tree.root - ]; - - dep::std::hash::pedersen_hash_with_separator(inputs, GENERATOR_INDEX__BLOCK_HASH) -} diff --git a/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/lib.nr b/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/lib.nr index 1d0df93cc9d..08534d6cb25 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/lib.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/lib.nr @@ -11,8 +11,6 @@ mod root; mod components; -mod hash; - mod merkle_tree; mod tests; diff --git a/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/root.nr b/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/root.nr index 1fca5912f62..cfd8ad62d4e 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/root.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/root.nr @@ -13,7 +13,7 @@ use dep::types::{ state_reference::StateReference, utils::uint256::U256, }; -use crate::{components, hash::compute_block_hash_with_globals}; +use crate::components; use crate::merkle_tree::{calculate_subtree, calculate_empty_tree_root}; impl RootRollupInputs { @@ -49,12 +49,15 @@ impl RootRollupInputs { partial: right.end, }; - // Build the block hash for this iteration from the tree roots and global variables - // Then insert the block into the archive tree - let block_hash = compute_block_hash_with_globals( - left.constants.global_variables, + let header = Header { + last_archive: left.constants.last_archive, + body_hash: components::compute_calldata_hash(self.previous_rollup_data), state, - ); + global_variables : left.constants.global_variables + }; + + // Build the block hash for this by hashing the header and then insert the new leaf to archive tree. + let block_hash = header.hash(); // Update the archive let archive = components::insert_subtree_to_snapshot_tree( @@ -65,13 +68,6 @@ impl RootRollupInputs { 0 ); - let header = Header { - last_archive: left.constants.last_archive, - body_hash: components::compute_calldata_hash(self.previous_rollup_data), - state, - global_variables : left.constants.global_variables - }; - RootRollupPublicInputs{ aggregation_object, archive, diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/global_variables.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/global_variables.nr index 23a43a02703..d5f2857151b 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/global_variables.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/global_variables.nr @@ -45,20 +45,6 @@ impl Eq for GlobalVariables { } } -// TODO(#3941) This is only used in Header.block_hash() --> Nuke it once that func is updated -impl Hash for GlobalVariables { - fn hash(self) -> Field { - dep::std::hash::pedersen_hash_with_separator([ - self.chain_id, - self.version, - self.block_number, - self.timestamp - ], - GENERATOR_INDEX__GLOBAL_VARIABLES, - ) - } -} - impl Empty for GlobalVariables { fn empty() -> Self { Self { diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/constants.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/constants.nr index 8a65c1d284c..baeddd68ea5 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/constants.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/constants.nr @@ -85,7 +85,7 @@ global ARGS_HASH_CHUNK_COUNT: u32 = 16; // NOIR CONSTANTS - constants used only in yarn-packages/noir-contracts // Some are defined here because Noir doesn't yet support globals referencing other globals yet. -// Move these constants to a noir file once the issue bellow is resolved: +// Move these constants to a noir file once the issue below is resolved: // https://github.com/noir-lang/noir/issues/1734 global L1_TO_L2_MESSAGE_LENGTH: Field = 8; global L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH: Field = 25; diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/header.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/header.nr index 9e081cab674..30e01dce3b1 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/header.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/header.nr @@ -19,7 +19,10 @@ use crate::{ StateReference, STATE_REFERENCE_LENGTH, }, - traits::Empty, + traits::{ + Empty, + Hash, + }, utils::{ arr_copy_slice, }, @@ -68,19 +71,6 @@ impl Header { global_variables: GlobalVariables::deserialize(global_variables_fields), } } - - // TODO(#3941) Rename this as hash() and make it hash the whole header - pub fn block_hash(self) -> Field { - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3595) - pedersen_hash([ - self.global_variables.hash(), - self.state.partial.note_hash_tree.root, - self.state.partial.nullifier_tree.root, - self.state.partial.contract_tree.root, - self.state.l1_to_l2_message_tree.root, - self.state.partial.public_data_tree.root, - ], GENERATOR_INDEX__BLOCK_HASH) - } } impl Empty for Header { @@ -93,3 +83,9 @@ impl Empty for Header { } } } + +impl Hash for Header { + fn hash(self) -> Field { + pedersen_hash(self.serialize(), GENERATOR_INDEX__BLOCK_HASH) + } +} diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index faab1796d97..7cdcccef715 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -445,7 +445,7 @@ export class PXEService implements PXE { txHash, TxStatus.MINED, '', - settledTx.blockHash, + settledTx.blockHash.toBuffer(), settledTx.blockNumber, deployedContractAddress, ); 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 3a005017e91..470ce36f9cc 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 @@ -15,6 +15,7 @@ import { BaseOrMergeRollupPublicInputs, Fr, GlobalVariables, + Header, KernelCircuitPublicInputs, MAX_NEW_COMMITMENTS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, @@ -33,7 +34,7 @@ import { SideEffectLinkedToNoteHash, StateReference, } from '@aztec/circuits.js'; -import { computeBlockHashWithGlobals, computeContractLeaf } from '@aztec/circuits.js/abis'; +import { computeContractLeaf } from '@aztec/circuits.js/abis'; import { fr, makeBaseOrMergeRollupPublicInputs, @@ -63,7 +64,6 @@ import { makeEmptyProcessedTx as makeEmptyProcessedTxFromHistoricalTreeRoots, makeProcessedTx, } from '../sequencer/processed_tx.js'; -import { buildInitialHeader } from '../sequencer/utils.js'; import { RollupSimulator } from '../simulator/index.js'; import { RealRollupCircuitSimulator } from '../simulator/rollup.js'; import { SoloBlockBuilder } from './solo_block_builder.js'; @@ -122,7 +122,7 @@ describe('sequencer/solo_block_builder', () => { }, 20_000); const makeEmptyProcessedTx = async () => { - const header = await buildInitialHeader(builderDb); + const header = await builderDb.buildInitialHeader(); return makeEmptyProcessedTxFromHistoricalTreeRoots(header, chainId, version); }; @@ -157,14 +157,7 @@ describe('sequencer/solo_block_builder', () => { }; const updateArchive = async () => { - const blockHash = computeBlockHashWithGlobals( - globalVariables, - rootRollupOutput.header.state.partial.noteHashTree.root, - rootRollupOutput.header.state.partial.nullifierTree.root, - rootRollupOutput.header.state.partial.contractTree.root, - rootRollupOutput.header.state.l1ToL2MessageTree.root, - rootRollupOutput.header.state.partial.publicDataTree.root, - ); + const blockHash = rootRollupOutput.header.hash(); await expectsDb.appendLeaves(MerkleTreeId.ARCHIVE, [blockHash.toBuffer()]); }; @@ -191,7 +184,7 @@ describe('sequencer/solo_block_builder', () => { const buildMockSimulatorInputs = async () => { const kernelOutput = makePrivateKernelPublicInputsFinal(); - kernelOutput.constants.historicalHeader = await buildInitialHeader(expectsDb); + kernelOutput.constants.historicalHeader = await expectsDb.buildInitialHeader(); const tx = await makeProcessedTx( new Tx( @@ -214,15 +207,8 @@ describe('sequencer/solo_block_builder', () => { await updateExpectedTreesFromTxs([txs[1]]); baseRollupOutputRight.end = await getPartialStateReference(); - // Update l1 to l2 data tree - // And update the root trees now to create proper output to the root rollup circuit + // Update l1 to l2 message tree await updateL1ToL2MessageTree(mockL1ToL2Messages); - rootRollupOutput.header.state = await getStateReference(); - - // Calculate block hash - rootRollupOutput.header.globalVariables = globalVariables; - await updateArchive(); - rootRollupOutput.archive = await getTreeSnapshot(MerkleTreeId.ARCHIVE); const newNullifiers = txs.flatMap(tx => tx.data.end.newNullifiers); const newCommitments = txs.flatMap(tx => tx.data.end.newCommitments); @@ -237,9 +223,11 @@ describe('sequencer/solo_block_builder', () => { const newEncryptedLogs = new L2BlockL2Logs(txs.map(tx => tx.encryptedLogs || new TxL2Logs([]))); const newUnencryptedLogs = new L2BlockL2Logs(txs.map(tx => tx.unencryptedLogs || new TxL2Logs([]))); + // We are constructing the block here just to get body hash/calldata hash so we can pass in an empty archive and header const l2Block = L2Block.fromFields({ - archive: rootRollupOutput.archive, - header: rootRollupOutput.header, + archive: AppendOnlyTreeSnapshot.zero(), + header: Header.empty(), + // Only the values below go to body hash/calldata hash newCommitments: newCommitments.map((sideEffect: SideEffect) => sideEffect.value), newNullifiers: newNullifiers.map((sideEffect: SideEffectLinkedToNoteHash) => sideEffect.value), newContracts, @@ -251,7 +239,13 @@ describe('sequencer/solo_block_builder', () => { newUnencryptedLogs, }); + // Now we update can make the final header, compute the block hash and update archive + rootRollupOutput.header.globalVariables = globalVariables; rootRollupOutput.header.bodyHash = l2Block.getCalldataHash(); + rootRollupOutput.header.state = await getStateReference(); + + await updateArchive(); + rootRollupOutput.archive = await getTreeSnapshot(MerkleTreeId.ARCHIVE); return txs; }; @@ -297,7 +291,7 @@ describe('sequencer/solo_block_builder', () => { const makeBloatedProcessedTx = async (seed = 0x1) => { const tx = mockTx(seed); const kernelOutput = KernelCircuitPublicInputs.empty(); - kernelOutput.constants.historicalHeader = await buildInitialHeader(builderDb); + kernelOutput.constants.historicalHeader = await builderDb.buildInitialHeader(); kernelOutput.end.publicDataUpdateRequests = makeTuple( MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, i => new PublicDataUpdateRequest(fr(i), fr(0), fr(i + 10)), diff --git a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts index 49318dcaa67..488b7191456 100644 --- a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts +++ b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts @@ -42,12 +42,7 @@ import { VK_TREE_HEIGHT, VerificationKey, } from '@aztec/circuits.js'; -import { - computeBlockHash, - computeBlockHashWithGlobals, - computeContractLeaf, - computeGlobalsHash, -} from '@aztec/circuits.js/abis'; +import { computeContractLeaf } from '@aztec/circuits.js/abis'; import { makeTuple } from '@aztec/foundation/array'; import { toBigIntBE } from '@aztec/foundation/bigint-buffer'; import { padArrayEnd } from '@aztec/foundation/collection'; @@ -158,19 +153,19 @@ export class SoloBlockBuilder implements BlockBuilder { protected validateTxs(txs: ProcessedTx[]) { for (const tx of txs) { const txHeader = tx.data.constants.historicalHeader; - if (txHeader.state.l1ToL2MessageTree.isEmpty()) { + if (txHeader.state.l1ToL2MessageTree.isZero()) { throw new Error(`Empty L1 to L2 messages tree in tx: ${toFriendlyJSON(tx)}`); } - if (txHeader.state.partial.noteHashTree.isEmpty()) { + if (txHeader.state.partial.noteHashTree.isZero()) { throw new Error(`Empty note hash tree in tx: ${toFriendlyJSON(tx)}`); } - if (txHeader.state.partial.nullifierTree.isEmpty()) { + if (txHeader.state.partial.nullifierTree.isZero()) { throw new Error(`Empty nullifier tree in tx: ${toFriendlyJSON(tx)}`); } - if (txHeader.state.partial.contractTree.isEmpty()) { + if (txHeader.state.partial.contractTree.isZero()) { throw new Error(`Empty contract tree in tx: ${toFriendlyJSON(tx)}`); } - if (txHeader.state.partial.publicDataTree.isEmpty()) { + if (txHeader.state.partial.publicDataTree.isZero()) { throw new Error(`Empty public data tree in tx: ${toFriendlyJSON(tx)}`); } } @@ -276,48 +271,15 @@ export class SoloBlockBuilder implements BlockBuilder { const rootProof = await this.prover.getRootRollupProof(rootInput, rootOutput); - // Update the root trees with the latest data and contract tree roots, - // and validate them against the output of the root circuit simulation + // Update the archive with the latest block header this.debug(`Updating and validating root trees`); - const globalVariablesHash = computeGlobalsHash(left[0].constants.globalVariables); - await this.db.updateLatestGlobalVariablesHash(globalVariablesHash); - await this.db.updateArchive(globalVariablesHash); + await this.db.updateArchive(rootOutput.header); await this.validateRootOutput(rootOutput); return [rootOutput, rootProof]; } - async updateArchive(globalVariables: GlobalVariables) { - // Calculate the block hash and add it to the historical block hashes tree - const blockHash = await this.calculateBlockHash(globalVariables); - await this.db.appendLeaves(MerkleTreeId.ARCHIVE, [blockHash.toBuffer()]); - } - - protected async calculateBlockHash(globals: GlobalVariables) { - const [noteHashTreeRoot, nullifierTreeRoot, contractTreeRoot, publicDataTreeRoot, l1ToL2MessageTreeRoot] = ( - await Promise.all( - [ - MerkleTreeId.NOTE_HASH_TREE, - MerkleTreeId.NULLIFIER_TREE, - MerkleTreeId.CONTRACT_TREE, - MerkleTreeId.PUBLIC_DATA_TREE, - MerkleTreeId.L1_TO_L2_MESSAGE_TREE, - ].map(tree => this.getTreeSnapshot(tree)), - ) - ).map(r => r.root); - - const blockHash = computeBlockHashWithGlobals( - globals, - noteHashTreeRoot, - nullifierTreeRoot, - contractTreeRoot, - l1ToL2MessageTreeRoot, - publicDataTreeRoot, - ); - return blockHash; - } - protected async validatePartialState(partialState: PartialStateReference) { await Promise.all([ this.validateSimulatedTree( @@ -491,20 +453,6 @@ export class SoloBlockBuilder implements BlockBuilder { return new MembershipWitness(height, index, assertLength(path.toFieldArray(), height)); } - protected getHistoricalTreesMembershipWitnessFor(tx: ProcessedTx) { - const header = tx.data.constants.historicalHeader; - // TODO(#3941) - const blockHash = computeBlockHash( - computeGlobalsHash(header.globalVariables), - header.state.partial.noteHashTree.root, - header.state.partial.nullifierTree.root, - header.state.partial.contractTree.root, - header.state.l1ToL2MessageTree.root, - header.state.partial.publicDataTree.root, - ); - return this.getMembershipWitnessFor(blockHash, MerkleTreeId.ARCHIVE, ARCHIVE_HEIGHT); - } - protected async getConstantRollupData(globalVariables: GlobalVariables): Promise { return ConstantRollupData.from({ baseRollupVkHash: DELETE_FR, @@ -734,6 +682,13 @@ export class SoloBlockBuilder implements BlockBuilder { publicDataSiblingPath, }); + const blockHash = tx.data.constants.historicalHeader.hash(); + const archiveRootMembershipWitness = await this.getMembershipWitnessFor( + blockHash, + MerkleTreeId.ARCHIVE, + ARCHIVE_HEIGHT, + ); + return BaseRollupInputs.from({ kernelData: this.getKernelDataFor(tx), start, @@ -746,7 +701,7 @@ export class SoloBlockBuilder implements BlockBuilder { publicDataReadsPreimages: txPublicDataReadsInfo.newPublicDataReadsPreimages, publicDataReadsMembershipWitnesses: txPublicDataReadsInfo.newPublicDataReadsWitnesses, - archiveRootMembershipWitness: await this.getHistoricalTreesMembershipWitnessFor(tx), + archiveRootMembershipWitness, constants, }); diff --git a/yarn-project/sequencer-client/src/sequencer/index.ts b/yarn-project/sequencer-client/src/sequencer/index.ts index 43a83d121a1..4e1a69cbc9b 100644 --- a/yarn-project/sequencer-client/src/sequencer/index.ts +++ b/yarn-project/sequencer-client/src/sequencer/index.ts @@ -1,3 +1,2 @@ export * from './sequencer.js'; export * from './config.js'; -export * from './utils.js'; diff --git a/yarn-project/sequencer-client/src/sequencer/public_processor.ts b/yarn-project/sequencer-client/src/sequencer/public_processor.ts index 51e1ad011d8..ebc2c87aa93 100644 --- a/yarn-project/sequencer-client/src/sequencer/public_processor.ts +++ b/yarn-project/sequencer-client/src/sequencer/public_processor.ts @@ -56,7 +56,6 @@ import { PublicKernelCircuitSimulator } from '../simulator/index.js'; import { ContractsDataSourcePublicDB, WorldStateDB, WorldStatePublicDB } from '../simulator/public_executor.js'; import { RealPublicKernelCircuitSimulator } from '../simulator/public_kernel.js'; import { FailedTx, ProcessedTx, makeEmptyProcessedTx, makeProcessedTx } from './processed_tx.js'; -import { buildInitialHeader } from './utils.js'; /** * Creates new instances of PublicProcessor given the provided merkle tree db and contract data source. @@ -79,7 +78,7 @@ export class PublicProcessorFactory { historicalHeader: Header | undefined, globalVariables: GlobalVariables, ): Promise { - historicalHeader = historicalHeader ?? (await buildInitialHeader(this.merkleTree)); + historicalHeader = historicalHeader ?? (await this.merkleTree.buildInitialHeader()); const publicContractsDB = new ContractsDataSourcePublicDB(this.contractDataSource); const worldStatePublicDB = new WorldStatePublicDB(this.merkleTree); diff --git a/yarn-project/sequencer-client/src/sequencer/utils.ts b/yarn-project/sequencer-client/src/sequencer/utils.ts deleted file mode 100644 index eebff558fea..00000000000 --- a/yarn-project/sequencer-client/src/sequencer/utils.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { AppendOnlyTreeSnapshot, GlobalVariables, Header } from '@aztec/circuits.js'; -import { MerkleTreeOperations } from '@aztec/world-state'; - -/** - * Builds the initial header by reading the roots from the database. - * - * TODO(#4148) Proper genesis state. If the state is empty, we allow anything for now. - */ -export async function buildInitialHeader(db: MerkleTreeOperations) { - const state = await db.getStateReference(); - return new Header(AppendOnlyTreeSnapshot.empty(), Buffer.alloc(32, 0), state, GlobalVariables.empty()); -} diff --git a/yarn-project/world-state/src/world-state-db/merkle_tree_operations.ts b/yarn-project/world-state/src/world-state-db/merkle_tree_operations.ts index 3d4d5db1509..8a59832253a 100644 --- a/yarn-project/world-state/src/world-state-db/merkle_tree_operations.ts +++ b/yarn-project/world-state/src/world-state-db/merkle_tree_operations.ts @@ -1,6 +1,5 @@ import { L2Block, MerkleTreeId } from '@aztec/circuit-types'; -import { NullifierLeafPreimage, StateReference } from '@aztec/circuits.js'; -import { Fr } from '@aztec/foundation/fields'; +import { Header, NullifierLeafPreimage, StateReference } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { IndexedTreeLeafPreimage } from '@aztec/foundation/trees'; import { BatchInsertionResult } from '@aztec/merkle-tree'; @@ -56,6 +55,11 @@ export interface MerkleTreeOperations { */ getStateReference(): Promise; + /** + * Builds the initial header. + */ + buildInitialHeader(): Promise
; + /** * Gets sibling path for a leaf. * @param treeId - The tree to be queried for a sibling path. @@ -115,22 +119,11 @@ export interface MerkleTreeOperations { getLeafValue(treeId: MerkleTreeId, index: bigint): Promise; /** - * Inserts the new block hash into the archive. + * Inserts the block hash into the archive. * This includes all of the current roots of all of the data trees and the current blocks global vars. - * @param globalVariablesHash - The global variables hash to insert into the block hash. - */ - updateArchive(globalVariablesHash: Fr): Promise; - - /** - * Updates the latest global variables hash - * @param globalVariablesHash - The latest global variables hash - */ - updateLatestGlobalVariablesHash(globalVariablesHash: Fr): Promise; - - /** - * Gets the global variables hash from the previous block + * @param header - The header to insert into the archive. */ - getLatestGlobalVariablesHash(): Promise; + updateArchive(header: Header): Promise; /** * Batch insert multiple leaves into the tree. diff --git a/yarn-project/world-state/src/world-state-db/merkle_tree_operations_facade.ts b/yarn-project/world-state/src/world-state-db/merkle_tree_operations_facade.ts index 2669172c813..f36513f6e78 100644 --- a/yarn-project/world-state/src/world-state-db/merkle_tree_operations_facade.ts +++ b/yarn-project/world-state/src/world-state-db/merkle_tree_operations_facade.ts @@ -1,6 +1,5 @@ import { L2Block, MerkleTreeId } from '@aztec/circuit-types'; -import { NullifierLeafPreimage, StateReference } from '@aztec/circuits.js'; -import { Fr } from '@aztec/foundation/fields'; +import { Header, NullifierLeafPreimage, StateReference } from '@aztec/circuits.js'; import { IndexedTreeLeafPreimage } from '@aztec/foundation/trees'; import { BatchInsertionResult } from '@aztec/merkle-tree'; import { SiblingPath } from '@aztec/types/membership'; @@ -32,6 +31,14 @@ export class MerkleTreeOperationsFacade implements MerkleTreeOperations { return this.trees.getStateReference(this.includeUncommitted); } + /** + * Builds the initial header. + * @returns The initial header. + */ + buildInitialHeader(): Promise
{ + return this.trees.buildInitialHeader(this.includeUncommitted); + } + /** * Appends a set of leaf values to the tree. * @param treeId - Id of the tree to append leaves to. @@ -128,25 +135,10 @@ export class MerkleTreeOperationsFacade implements MerkleTreeOperations { /** * Inserts the new block hash into the archive. * This includes all of the current roots of all of the data trees and the current blocks global vars. - * @param globalVariablesHash - The global variables hash to insert into the block hash. - */ - public updateArchive(globalVariablesHash: Fr): Promise { - return this.trees.updateArchive(globalVariablesHash, this.includeUncommitted); - } - - /** - * Updates the latest global variables hash - * @param globalVariablesHash - The latest global variables hash - */ - public updateLatestGlobalVariablesHash(globalVariablesHash: Fr): Promise { - return this.trees.updateLatestGlobalVariablesHash(globalVariablesHash, this.includeUncommitted); - } - - /** - * Gets the global variables hash from the previous block + * @param header - The header to insert into the archive. */ - public getLatestGlobalVariablesHash(): Promise { - return this.trees.getLatestGlobalVariablesHash(this.includeUncommitted); + public updateArchive(header: Header): Promise { + return this.trees.updateArchive(header, this.includeUncommitted); } /** diff --git a/yarn-project/world-state/src/world-state-db/merkle_tree_snapshot_operations_facade.ts b/yarn-project/world-state/src/world-state-db/merkle_tree_snapshot_operations_facade.ts index a0f94f8a14d..79e7a01d16f 100644 --- a/yarn-project/world-state/src/world-state-db/merkle_tree_snapshot_operations_facade.ts +++ b/yarn-project/world-state/src/world-state-db/merkle_tree_snapshot_operations_facade.ts @@ -1,5 +1,5 @@ import { MerkleTreeId } from '@aztec/circuit-types'; -import { AppendOnlyTreeSnapshot, Fr, PartialStateReference, StateReference } from '@aztec/circuits.js'; +import { AppendOnlyTreeSnapshot, Fr, Header, PartialStateReference, StateReference } from '@aztec/circuits.js'; import { IndexedTreeLeafPreimage } from '@aztec/foundation/trees'; import { BatchInsertionResult, IndexedTreeSnapshot, TreeSnapshot } from '@aztec/merkle-tree'; import { SiblingPath } from '@aztec/types/membership'; @@ -34,10 +34,6 @@ export class MerkleTreeSnapshotOperationsFacade implements MerkleTreeOperations return tree.findLeafIndex(value); } - getLatestGlobalVariablesHash(): Promise { - return Promise.reject(new Error('not implemented')); - } - async getLeafPreimage( treeId: MerkleTreeId.NULLIFIER_TREE, index: bigint, @@ -152,11 +148,11 @@ export class MerkleTreeSnapshotOperationsFacade implements MerkleTreeOperations return Promise.reject(new Error('Tree snapshot operations are read-only')); } - updateLatestGlobalVariablesHash(): Promise { + updateLeaf(): Promise { return Promise.reject(new Error('Tree snapshot operations are read-only')); } - updateLeaf(): Promise { - return Promise.reject(new Error('Tree snapshot operations are read-only')); + buildInitialHeader(): Promise
{ + throw new Error('Building initial header not supported on snapshot.'); } } diff --git a/yarn-project/world-state/src/world-state-db/merkle_trees.ts b/yarn-project/world-state/src/world-state-db/merkle_trees.ts index 21d4e453236..3a55636c273 100644 --- a/yarn-project/world-state/src/world-state-db/merkle_trees.ts +++ b/yarn-project/world-state/src/world-state-db/merkle_trees.ts @@ -5,6 +5,7 @@ import { CONTRACT_TREE_HEIGHT, Fr, GlobalVariables, + Header, L1_TO_L2_MSG_TREE_HEIGHT, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NOTE_HASH_TREE_HEIGHT, @@ -19,12 +20,10 @@ import { PublicDataTreeLeafPreimage, StateReference, } from '@aztec/circuits.js'; -import { computeBlockHash, computeGlobalsHash } from '@aztec/circuits.js/abis'; -import { Committable } from '@aztec/foundation/committable'; import { SerialQueue } from '@aztec/foundation/fifo'; -import { createDebugLogger } from '@aztec/foundation/log'; +import { DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { IndexedTreeLeafPreimage } from '@aztec/foundation/trees'; -import { AztecKVStore, AztecSingleton } from '@aztec/kv-store'; +import { AztecKVStore } from '@aztec/kv-store'; import { AppendOnlyTree, BatchInsertionResult, @@ -33,6 +32,7 @@ import { StandardIndexedTree, StandardTree, UpdateOnlyTree, + getTreeMeta, loadTree, newTree, } from '@aztec/merkle-tree'; @@ -43,18 +43,6 @@ import { INITIAL_NULLIFIER_TREE_SIZE, INITIAL_PUBLIC_DATA_TREE_SIZE, MerkleTreeD import { HandleL2BlockResult, IndexedTreeId, MerkleTreeOperations, TreeInfo } from './merkle_tree_operations.js'; import { MerkleTreeOperationsFacade } from './merkle_tree_operations_facade.js'; -/** - * Data necessary to reinitialize the merkle trees from Db. - */ -interface FromDbOptions { - /** - * The global variables hash from the last block. - */ - globalVariablesHash: Fr; -} - -const LAST_GLOBAL_VARS_HASH = 'lastGlobalVarsHash'; - /** * The nullifier tree is an indexed tree. */ @@ -78,22 +66,26 @@ class PublicDataTree extends StandardIndexedTree { */ export class MerkleTrees implements MerkleTreeDb { private trees: (AppendOnlyTree | UpdateOnlyTree)[] = []; - private latestGlobalVariablesHash: Committable; private jobQueue = new SerialQueue(); - #globalVariablesHash: AztecSingleton; + private constructor(private store: AztecKVStore, private log: DebugLogger) {} - constructor(private store: AztecKVStore, private log = createDebugLogger('aztec:merkle_trees')) { - this.latestGlobalVariablesHash = new Committable(Fr.ZERO); - this.#globalVariablesHash = store.openSingleton(LAST_GLOBAL_VARS_HASH); + /** + * Method to asynchronously create and initialize a MerkleTrees instance. + * @param store - The db instance to use for data persistance. + * @returns - A fully initialized MerkleTrees instance. + */ + public static async new(store: AztecKVStore, log = createDebugLogger('aztec:merkle_trees')) { + const merkleTrees = new MerkleTrees(store, log); + await merkleTrees.#init(); + return merkleTrees; } /** - * initializes the collection of Merkle Trees. - * @param fromDbOptions - Options to initialize the trees from the database. + * Initializes the collection of Merkle Trees. */ - public async init(fromDbOptions?: FromDbOptions) { - const fromDb = fromDbOptions !== undefined; + async #init() { + const fromDb = this.#isDbPopulated(); const initializeTree = fromDb ? loadTree : newTree; const hasher = new Pedersen(); @@ -145,30 +137,19 @@ export class MerkleTrees implements MerkleTreeDb { this.jobQueue.start(); - // The first leaf in the blocks tree contains the empty roots of the other trees and empty global variables. if (!fromDb) { - const initialGlobalVariablesHash = computeGlobalsHash(GlobalVariables.empty()); - await this._updateLatestGlobalVariablesHash(initialGlobalVariablesHash); - await this._updateArchive(initialGlobalVariablesHash, true); - await this._commit(); - } else { - await this._updateLatestGlobalVariablesHash(fromDbOptions.globalVariablesHash); - // make the restored global variables hash and tree roots current - await this._commit(); + // We are not initializing from db so we need to populate the first leaf of the archive tree which is a hash of + // the initial header. + const initialHeder = await this.buildInitialHeader(true); + await this.#updateArchive(initialHeder, true); } + + await this.#commit(); } - /** - * Method to asynchronously create and initialize a MerkleTrees instance. - * @param store - The db instance to use for data persistance. - * @returns - A fully initialized MerkleTrees instance. - */ - public static async new(store: AztecKVStore) { - const merkleTrees = new MerkleTrees(store); - const globalVariablesHash = store.openSingleton(LAST_GLOBAL_VARS_HASH); - const val = globalVariablesHash.get(); - await merkleTrees.init(val ? { globalVariablesHash: Fr.fromBuffer(val) } : undefined); - return merkleTrees; + public async buildInitialHeader(includeUncommitted: boolean): Promise
{ + const state = await this.getStateReference(includeUncommitted); + return new Header(AppendOnlyTreeSnapshot.zero(), Buffer.alloc(32, 0), state, GlobalVariables.empty()); } /** @@ -195,29 +176,12 @@ export class MerkleTrees implements MerkleTreeDb { } /** - * Inserts into the roots trees (CONTRACT_TREE_ROOTS_TREE, NOTE_HASH_TREE_ROOTS_TREE, L1_TO_L2_MESSAGE_TREE_ROOTS_TREE) - * the current roots of the corresponding trees (CONTRACT_TREE, NOTE_HASH_TREE, L1_TO_L2_MESSAGE_TREE). - * @param globalsHash - The current global variables hash. + * Updates the archive with the new block/header hash. + * @param header - The header whose hash to insert into the archive. * @param includeUncommitted - Indicates whether to include uncommitted data. */ - public async updateArchive(globalsHash: Fr, includeUncommitted: boolean) { - await this.synchronize(() => this._updateArchive(globalsHash, includeUncommitted)); - } - - /** - * Updates the latest global variables hash - * @param globalVariablesHash - The latest global variables hash - */ - public async updateLatestGlobalVariablesHash(globalVariablesHash: Fr) { - return await this.synchronize(() => this._updateLatestGlobalVariablesHash(globalVariablesHash)); - } - - /** - * Gets the global variables hash from the previous block - * @param includeUncommitted - Indicates whether to include uncommitted data. - */ - public async getLatestGlobalVariablesHash(includeUncommitted: boolean): Promise { - return await this.synchronize(() => this._getGlobalVariablesHash(includeUncommitted)); + public async updateArchive(header: Header, includeUncommitted: boolean) { + await this.synchronize(() => this.#updateArchive(header, includeUncommitted)); } /** @@ -227,7 +191,7 @@ export class MerkleTrees implements MerkleTreeDb { * @returns The tree info for the specified tree. */ public async getTreeInfo(treeId: MerkleTreeId, includeUncommitted: boolean): Promise { - return await this.synchronize(() => this._getTreeInfo(treeId, includeUncommitted)); + return await this.synchronize(() => this.#getTreeInfo(treeId, includeUncommitted)); } /** @@ -256,19 +220,6 @@ export class MerkleTrees implements MerkleTreeDb { return Promise.resolve(state); } - // TODO(#3941) - private async _getCurrentBlockHash(globalsHash: Fr, includeUncommitted: boolean): Promise { - const state = await this.getStateReference(includeUncommitted); - return computeBlockHash( - globalsHash, - state.partial.noteHashTree.root, - state.partial.nullifierTree.root, - state.partial.contractTree.root, - state.l1ToL2MessageTree.root, - state.partial.publicDataTree.root, - ); - } - /** * Gets the value at the given index. * @param treeId - The ID of the tree to get the leaf value from. @@ -296,7 +247,7 @@ export class MerkleTrees implements MerkleTreeDb { index: bigint, includeUncommitted: boolean, ): Promise> { - return await this.synchronize(() => this._getSiblingPath(treeId, index, includeUncommitted)); + return await this.synchronize(() => this.trees[treeId].getSiblingPath(index, includeUncommitted)); } /** @@ -306,7 +257,7 @@ export class MerkleTrees implements MerkleTreeDb { * @returns Empty promise. */ public async appendLeaves(treeId: MerkleTreeId, leaves: Buffer[]): Promise { - return await this.synchronize(() => this._appendLeaves(treeId, leaves)); + return await this.synchronize(() => this.#appendLeaves(treeId, leaves)); } /** @@ -314,7 +265,7 @@ export class MerkleTrees implements MerkleTreeDb { * @returns Empty promise. */ public async commit(): Promise { - return await this.synchronize(() => this._commit()); + return await this.synchronize(() => this.#commit()); } /** @@ -322,7 +273,7 @@ export class MerkleTrees implements MerkleTreeDb { * @returns Empty promise. */ public async rollback(): Promise { - return await this.synchronize(() => this._rollback()); + return await this.synchronize(() => this.#rollback()); } /** @@ -350,7 +301,7 @@ export class MerkleTrees implements MerkleTreeDb { | undefined > { return await this.synchronize(() => - Promise.resolve(this._getIndexedTree(treeId).findIndexOfPreviousKey(value, includeUncommitted)), + Promise.resolve(this.#getIndexedTree(treeId).findIndexOfPreviousKey(value, includeUncommitted)), ); } @@ -367,7 +318,7 @@ export class MerkleTrees implements MerkleTreeDb { includeUncommitted: boolean, ): Promise { return await this.synchronize(() => - Promise.resolve(this._getIndexedTree(treeId).getLatestLeafPreimageCopy(index, includeUncommitted)), + Promise.resolve(this.#getIndexedTree(treeId).getLatestLeafPreimageCopy(index, includeUncommitted)), ); } @@ -397,7 +348,7 @@ export class MerkleTrees implements MerkleTreeDb { * @returns Empty promise. */ public async updateLeaf(treeId: IndexedTreeId, leaf: Buffer, index: bigint): Promise { - return await this.synchronize(() => this._updateLeaf(treeId, leaf, index)); + return await this.synchronize(() => this.#updateLeaf(treeId, leaf, index)); } /** @@ -406,7 +357,7 @@ export class MerkleTrees implements MerkleTreeDb { * @returns Whether the block handled was produced by this same node. */ public async handleL2Block(block: L2Block): Promise { - return await this.synchronize(() => this._handleL2Block(block)); + return await this.synchronize(() => this.#handleL2Block(block)); } /** @@ -441,18 +392,17 @@ export class MerkleTrees implements MerkleTreeDb { return await this.jobQueue.put(fn); } - private _updateLatestGlobalVariablesHash(globalVariablesHash: Fr): Promise { - this.latestGlobalVariablesHash.set(globalVariablesHash); - return Promise.resolve(); - } + async #updateArchive(header: Header, includeUncommitted: boolean) { + const state = await this.getStateReference(includeUncommitted); - private _getGlobalVariablesHash(includeUncommitted: boolean): Promise { - return Promise.resolve(this.latestGlobalVariablesHash.get(includeUncommitted)); - } + // This method should be called only when the block builder already updated the state so we sanity check that it's + // the case here. + if (!state.toBuffer().equals(header.state.toBuffer())) { + throw new Error('State in header does not match current state'); + } - private async _updateArchive(globalsHash: Fr, includeUncommitted: boolean) { - const blockHash = await this._getCurrentBlockHash(globalsHash, includeUncommitted); - await this._appendLeaves(MerkleTreeId.ARCHIVE, [blockHash.toBuffer()]); + const blockHash = header.hash(); + await this.#appendLeaves(MerkleTreeId.ARCHIVE, [blockHash.toBuffer()]); } /** @@ -461,7 +411,7 @@ export class MerkleTrees implements MerkleTreeDb { * @param includeUncommitted - Indicates whether to include uncommitted data. * @returns The tree info for the specified tree. */ - private _getTreeInfo(treeId: MerkleTreeId, includeUncommitted: boolean): Promise { + #getTreeInfo(treeId: MerkleTreeId, includeUncommitted: boolean): Promise { const treeInfo = { treeId, root: this.trees[treeId].getRoot(includeUncommitted), @@ -476,32 +426,17 @@ export class MerkleTrees implements MerkleTreeDb { * @param treeId - Id of the tree to get an instance of. * @returns The indexed tree for the specified tree id. */ - private _getIndexedTree(treeId: IndexedTreeId): IndexedTree { + #getIndexedTree(treeId: IndexedTreeId): IndexedTree { return this.trees[treeId] as IndexedTree; } - /** - * Returns the sibling path for a leaf in a tree. - * @param treeId - Id of the tree to get the sibling path from. - * @param index - Index of the leaf to get the sibling path for. - * @param includeUncommitted - Indicates whether to include uncommitted updates in the sibling path. - * @returns Promise containing the sibling path for the leaf. - */ - private _getSiblingPath( - treeId: MerkleTreeId, - index: bigint, - includeUncommitted: boolean, - ): Promise> { - return Promise.resolve(this.trees[treeId].getSiblingPath(index, includeUncommitted)); - } - /** * Appends leaves to a tree. * @param treeId - Id of the tree to append leaves to. * @param leaves - Leaves to append. * @returns Empty promise. */ - private async _appendLeaves(treeId: MerkleTreeId, leaves: Buffer[]): Promise { + async #appendLeaves(treeId: MerkleTreeId, leaves: Buffer[]): Promise { const tree = this.trees[treeId]; if (!('appendLeaves' in tree)) { throw new Error('Tree does not support `appendLeaves` method'); @@ -509,7 +444,7 @@ export class MerkleTrees implements MerkleTreeDb { return await tree.appendLeaves(leaves); } - private async _updateLeaf(treeId: IndexedTreeId, leaf: Buffer, index: bigint): Promise { + async #updateLeaf(treeId: IndexedTreeId, leaf: Buffer, index: bigint): Promise { const tree = this.trees[treeId]; if (!('updateLeaf' in tree)) { throw new Error('Tree does not support `updateLeaf` method'); @@ -521,30 +456,27 @@ export class MerkleTrees implements MerkleTreeDb { * Commits all pending updates. * @returns Empty promise. */ - private async _commit(): Promise { + async #commit(): Promise { for (const tree of this.trees) { await tree.commit(); } - this.latestGlobalVariablesHash.commit(); - await this.#globalVariablesHash.set(this.latestGlobalVariablesHash.get().toBuffer()); } /** * Rolls back all pending updates. * @returns Empty promise. */ - private async _rollback(): Promise { + async #rollback(): Promise { for (const tree of this.trees) { await tree.rollback(); } - this.latestGlobalVariablesHash.rollback(); } public getSnapshot(blockNumber: number) { return Promise.all(this.trees.map(tree => tree.getSnapshot(blockNumber))); } - private async _snapshot(blockNumber: number): Promise { + async #snapshot(blockNumber: number): Promise { for (const tree of this.trees) { await tree.snapshot(blockNumber); } @@ -554,7 +486,7 @@ export class MerkleTrees implements MerkleTreeDb { * Handles a single L2 block (i.e. Inserts the new commitments into the merkle tree). * @param l2Block - The L2 block to handle. */ - private async _handleL2Block(l2Block: L2Block): Promise { + async #handleL2Block(l2Block: L2Block): Promise { const treeRootWithIdPairs = [ [l2Block.header.state.partial.contractTree.root, MerkleTreeId.CONTRACT_TREE], [l2Block.header.state.partial.nullifierTree.root, MerkleTreeId.NULLIFIER_TREE], @@ -570,10 +502,10 @@ export class MerkleTrees implements MerkleTreeDb { const ourBlock = treeRootWithIdPairs.every(([root, id]) => compareRoot(root, id)); if (ourBlock) { this.log(`Block ${l2Block.number} is ours, committing world state`); - await this._commit(); + await this.#commit(); } else { this.log(`Block ${l2Block.number} is not ours, rolling back world state and committing state from chain`); - await this._rollback(); + await this.#rollback(); // Sync the append only trees for (const [tree, leaves] of [ @@ -581,7 +513,7 @@ export class MerkleTrees implements MerkleTreeDb { [MerkleTreeId.NOTE_HASH_TREE, l2Block.newCommitments], [MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l2Block.newL1ToL2Messages], ] as const) { - await this._appendLeaves( + await this.#appendLeaves( tree, leaves.map(fr => fr.toBuffer()), ); @@ -605,20 +537,15 @@ export class MerkleTrees implements MerkleTreeDb { ); } - // Sync and add the block to the blocks tree - const globalVariablesHash = computeGlobalsHash(l2Block.header.globalVariables); - await this._updateLatestGlobalVariablesHash(globalVariablesHash); - this.log(`Synced global variables with hash ${globalVariablesHash}`); - - const blockHash = await this._getCurrentBlockHash(globalVariablesHash, true); - await this._appendLeaves(MerkleTreeId.ARCHIVE, [blockHash.toBuffer()]); + // The last thing remaining is to update the archive + await this.#updateArchive(l2Block.header, true); - await this._commit(); + await this.#commit(); } for (const [root, treeId] of treeRootWithIdPairs) { const treeName = MerkleTreeId[treeId]; - const info = await this._getTreeInfo(treeId, false); + const info = await this.#getTreeInfo(treeId, false); const syncedStr = '0x' + info.root.toString('hex'); const rootStr = root.toString(); // Sanity check that the rebuilt trees match the roots published by the L2 block @@ -630,8 +557,19 @@ export class MerkleTrees implements MerkleTreeDb { this.log(`Tree ${treeName} synched with size ${info.size} root ${rootStr}`); } } - await this._snapshot(l2Block.number); + await this.#snapshot(l2Block.number); return { isBlockOurs: ourBlock }; } + + #isDbPopulated(): boolean { + try { + getTreeMeta(this.store, MerkleTreeId[MerkleTreeId.NULLIFIER_TREE]); + // Tree meta was found --> db is populated + return true; + } catch (e) { + // Tree meta was not found --> db is not populated + return false; + } + } } From 84e1f7dd0e005351bb742b015270ab2fd575136d Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 31 Jan 2024 14:06:07 +0000 Subject: [PATCH 13/20] fix: aztec binary fixes (#4273) Small fixes following introduction of `aztec` binary. - Archiver http server wasn't starting - Ensure p2p bootstrap server logs to user - Remove unused env variable in terraform --- yarn-project/aztec/src/cli/cli.ts | 4 ++-- yarn-project/aztec/src/cli/cmds/start_p2p_bootstrap.ts | 3 +++ yarn-project/p2p-bootstrap/terraform/main.tf | 4 ---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/yarn-project/aztec/src/cli/cli.ts b/yarn-project/aztec/src/cli/cli.ts index da6b97a454b..b4620842cbd 100644 --- a/yarn-project/aztec/src/cli/cli.ts +++ b/yarn-project/aztec/src/cli/cli.ts @@ -51,10 +51,10 @@ export function getProgram(userLog: LogFn, debugLogger: DebugLogger): Command { services = await startPXE(options, signalHandlers, userLog); } else if (options.archiver) { const { startArchiver } = await import('./cmds/start_archiver.js'); - await startArchiver(options, signalHandlers); + services = await startArchiver(options, signalHandlers); } else if (options.p2pBootstrap) { const { startP2PBootstrap } = await import('./cmds/start_p2p_bootstrap.js'); - await startP2PBootstrap(options, signalHandlers, debugLogger); + await startP2PBootstrap(options, signalHandlers, userLog, debugLogger); } if (services.length) { const rpcServer = createNamespacedJsonRpcServer(services, debugLogger); diff --git a/yarn-project/aztec/src/cli/cmds/start_p2p_bootstrap.ts b/yarn-project/aztec/src/cli/cmds/start_p2p_bootstrap.ts index 3ed48cf12cf..2e49c478a40 100644 --- a/yarn-project/aztec/src/cli/cmds/start_p2p_bootstrap.ts +++ b/yarn-project/aztec/src/cli/cmds/start_p2p_bootstrap.ts @@ -1,11 +1,13 @@ import { DebugLogger } from '@aztec/aztec.js'; import { BootstrapNode, P2PConfig, getP2PConfigEnvVars } from '@aztec/p2p'; +import { LogFn } from '../../../../foundation/src/log/log_fn.js'; import { mergeEnvVarsAndCliOptions, parseModuleOptions } from '../util.js'; export const startP2PBootstrap = async ( options: any, signalHandlers: (() => Promise)[], + userLog: LogFn, debugLogger: DebugLogger, ) => { // Start a P2P bootstrap node. @@ -14,5 +16,6 @@ export const startP2PBootstrap = async ( const bootstrapNode = new BootstrapNode(debugLogger); const config = mergeEnvVarsAndCliOptions(envVars, cliOptions); await bootstrapNode.start(config); + userLog(`P2P bootstrap node started on ${config.tcpListenIp}:${config.tcpListenPort}`); signalHandlers.push(bootstrapNode.stop); }; diff --git a/yarn-project/p2p-bootstrap/terraform/main.tf b/yarn-project/p2p-bootstrap/terraform/main.tf index 376d59c134b..57070dcfa76 100644 --- a/yarn-project/p2p-bootstrap/terraform/main.tf +++ b/yarn-project/p2p-bootstrap/terraform/main.tf @@ -123,10 +123,6 @@ resource "aws_ecs_task_definition" "p2p-bootstrap" { "name": "NODE_ENV", "value": "production" }, - { - "name": "MODE", - "value": "p2p-bootstrap" - }, { "name": "P2P_TCP_LISTEN_PORT", "value": "${var.BOOTNODE_LISTEN_PORT + count.index}" From 1faead5bf5e07417e2d4452a2e3ff096a273a41a Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 31 Jan 2024 15:02:10 +0000 Subject: [PATCH 14/20] fix: relative LogFn import (#4328) fix relative import of `LogFn` that should come from `@aztec/foundation` --- yarn-project/aztec/src/cli/cmds/start_p2p_bootstrap.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/aztec/src/cli/cmds/start_p2p_bootstrap.ts b/yarn-project/aztec/src/cli/cmds/start_p2p_bootstrap.ts index 2e49c478a40..2fedcfd5645 100644 --- a/yarn-project/aztec/src/cli/cmds/start_p2p_bootstrap.ts +++ b/yarn-project/aztec/src/cli/cmds/start_p2p_bootstrap.ts @@ -1,7 +1,7 @@ import { DebugLogger } from '@aztec/aztec.js'; +import { LogFn } from '@aztec/foundation/log'; import { BootstrapNode, P2PConfig, getP2PConfigEnvVars } from '@aztec/p2p'; -import { LogFn } from '../../../../foundation/src/log/log_fn.js'; import { mergeEnvVarsAndCliOptions, parseModuleOptions } from '../util.js'; export const startP2PBootstrap = async ( From 5f9eee48579a507512612e283b4106ddf9d72555 Mon Sep 17 00:00:00 2001 From: Lasse Herskind <16536249+LHerskind@users.noreply.github.com> Date: Wed, 31 Jan 2024 15:32:15 +0000 Subject: [PATCH 15/20] feat: crude stable var implementation (#4289) Initial crude implementation for #4130. The way I am getting a hold of the public values through the oracle in here is an abomination. #4320 is created to fix this. --- .circleci/config.yml | 8 +-- .../src/client/client_execution_context.ts | 27 +++++++- .../src/history/public_value_inclusion.nr | 18 +++-- yarn-project/aztec-nr/aztec/src/state_vars.nr | 1 + .../src/state_vars/stable_public_state.nr | 69 +++++++++++++++++++ .../src/e2e_inclusion_proofs_contract.test.ts | 8 ++- ...ngleton.test.ts => e2e_state_vars.test.ts} | 20 +++++- .../docs_example_contract/src/main.nr | 34 ++++++--- .../inclusion_proofs_contract/src/main.nr | 16 +++++ 9 files changed, 180 insertions(+), 21 deletions(-) create mode 100644 yarn-project/aztec-nr/aztec/src/state_vars/stable_public_state.nr rename yarn-project/end-to-end/src/{e2e_singleton.test.ts => e2e_state_vars.test.ts} (89%) diff --git a/.circleci/config.yml b/.circleci/config.yml index cf0b8686481..0fae211493d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -610,7 +610,7 @@ jobs: name: "Test" command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=e2e_sandbox_example.test.ts - e2e-singleton: + e2e-state-vars: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -619,7 +619,7 @@ jobs: - *setup_env - run: name: "Test" - command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=e2e_singleton.test.ts + command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=e2e_state_vars.test.ts e2e-block-building: docker: @@ -1240,7 +1240,7 @@ workflows: # TODO(3458): Investigate intermittent failure # - e2e-slow-tree: *e2e_test - e2e-sandbox-example: *e2e_test - - e2e-singleton: *e2e_test + - e2e-state-vars: *e2e_test - e2e-block-building: *e2e_test - e2e-nested-contract: *e2e_test - e2e-non-contract-account: *e2e_test @@ -1278,7 +1278,7 @@ workflows: - e2e-token-contract - e2e-blacklist-token-contract - e2e-sandbox-example - - e2e-singleton + - e2e-state-vars - e2e-block-building - e2e-nested-contract - e2e-non-contract-account diff --git a/yarn-project/acir-simulator/src/client/client_execution_context.ts b/yarn-project/acir-simulator/src/client/client_execution_context.ts index 73f9d346792..f3d684f4ef0 100644 --- a/yarn-project/acir-simulator/src/client/client_execution_context.ts +++ b/yarn-project/acir-simulator/src/client/client_execution_context.ts @@ -10,7 +10,7 @@ import { SideEffect, TxContext, } from '@aztec/circuits.js'; -import { computeUniqueCommitment, siloCommitment } from '@aztec/circuits.js/abis'; +import { computePublicDataTreeLeafSlot, computeUniqueCommitment, siloCommitment } from '@aztec/circuits.js/abis'; import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { FunctionAbi, FunctionArtifact, countArgumentsSize } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; @@ -436,4 +436,29 @@ export class ClientExecutionContext extends ViewDataOracle { startSideEffectCounter, ); } + + /** + * Read the public storage data. + * @param startStorageSlot - The starting storage slot. + * @param numberOfElements - Number of elements to read from the starting storage slot. + */ + public async storageRead(startStorageSlot: Fr, numberOfElements: number): Promise { + // TODO(#4320): This is a hack to work around not having directly access to the public data tree but + // still having access to the witnesses + const bn = await this.db.getBlockNumber(); + + const values = []; + for (let i = 0n; i < numberOfElements; i++) { + const storageSlot = new Fr(startStorageSlot.value + i); + const leafSlot = computePublicDataTreeLeafSlot(this.contractAddress, storageSlot); + const witness = await this.db.getPublicDataTreeWitness(bn, leafSlot); + if (!witness) { + throw new Error(`No witness for slot ${storageSlot.toString()}`); + } + const value = witness.leafPreimage.value; + this.log(`Oracle storage read: slot=${storageSlot.toString()} value=${value}`); + values.push(value); + } + return values; + } } diff --git a/yarn-project/aztec-nr/aztec/src/history/public_value_inclusion.nr b/yarn-project/aztec-nr/aztec/src/history/public_value_inclusion.nr index 62c65bfd858..ad14fb77cb3 100644 --- a/yarn-project/aztec-nr/aztec/src/history/public_value_inclusion.nr +++ b/yarn-project/aztec-nr/aztec/src/history/public_value_inclusion.nr @@ -35,12 +35,20 @@ pub fn prove_public_value_inclusion( // 4) Check that the witness matches the corresponding public_value let preimage = witness.leaf_preimage; - if preimage.slot == public_value_leaf_slot { - assert_eq(preimage.value, value, "Public value does not match value in witness"); + + // Here we have two cases. Code based on same checks in `validate_public_data_reads` in `base_rollup_inputs` + // 1. The value is the same as the one in the witness + // 2. The value was never initialized and is zero + let is_less_than_slot = full_field_less_than(preimage.slot, public_value_leaf_slot); + let is_next_greater_than = full_field_less_than(public_value_leaf_slot, preimage.next_slot); + let is_max = ((preimage.next_index == 0) & (preimage.next_slot == 0)); + let is_in_range = is_less_than_slot & (is_next_greater_than | is_max); + + if is_in_range { + assert_eq(value, 0, "Non-existant public data leaf value is non-zero"); } else { - assert_eq(value, 0, "Got non-zero public value for non-existing slot"); - assert(full_field_less_than(preimage.slot, public_value_leaf_slot), "Invalid witness range"); - assert(full_field_less_than(public_value_leaf_slot, preimage.next_slot), "Invalid witness range"); + assert_eq(preimage.slot, public_value_leaf_slot, "Public data slot don't match witness"); + assert_eq(preimage.value, value, "Public value does not match the witness"); } // 5) Prove that the leaf we validated is in the public data tree diff --git a/yarn-project/aztec-nr/aztec/src/state_vars.nr b/yarn-project/aztec-nr/aztec/src/state_vars.nr index e1e813891ff..d8213bb1ef0 100644 --- a/yarn-project/aztec-nr/aztec/src/state_vars.nr +++ b/yarn-project/aztec-nr/aztec/src/state_vars.nr @@ -3,3 +3,4 @@ mod map; mod public_state; mod set; mod singleton; +mod stable_public_state; diff --git a/yarn-project/aztec-nr/aztec/src/state_vars/stable_public_state.nr b/yarn-project/aztec-nr/aztec/src/state_vars/stable_public_state.nr new file mode 100644 index 00000000000..013f059aef0 --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/state_vars/stable_public_state.nr @@ -0,0 +1,69 @@ +use crate::context::{Context}; +use crate::oracle::{ + storage::{storage_read, storage_write}, +}; +use crate::history::public_value_inclusion::prove_public_value_inclusion; +use dep::std::option::Option; +use dep::protocol_types::traits::{Deserialize, Serialize}; + +struct StablePublicState{ + context: Context, + storage_slot: Field, +} + +impl StablePublicState { + pub fn new( + // Note: Passing the contexts to new(...) just to have an interface compatible with a Map. + context: Context, + storage_slot: Field + ) -> Self { + assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); + Self { + context, + storage_slot, + } + } + + // Intended to be only called once. + pub fn initialize(self, value: T) where T: Serialize { + assert(self.context.private.is_none(), "Public state wrties only supported in public functions"); + // TODO: Must throw if the storage slot is not empty -> cannot allow overwriting + // This is currently impractical, as public functions are never marked `is_contract_deployment` + // in the `call_context`, only private functions will have this flag set. + let fields = T::serialize(value); + storage_write(self.storage_slot, fields); + } + + pub fn read_public(self) -> T where T: Deserialize { + assert(self.context.private.is_none(), "Public read only supported in public functions"); + let fields = storage_read(self.storage_slot); + T::deserialize(fields) + } + + pub fn read_private(self) -> T where T: Deserialize { + assert(self.context.public.is_none(), "Private read only supported in private functions"); + let private_context = self.context.private.unwrap(); + + // Read the value from storage (using the public tree) + let fields = storage_read(self.storage_slot); + + // TODO: The block_number here can be removed when using the current header in the membership proof. + let block_number = private_context.get_header().global_variables.block_number; + + // Loop over the fields and prove their inclusion in the public tree + for i in 0..fields.len() { + // TODO: Update membership proofs to use current header (Requires #4179) + // Currently executing unnecessary computation: + // - a membership proof of the header(block_number) in the history + // - a membership proof of the value in the public tree of the header + prove_public_value_inclusion( + fields[i], + self.storage_slot + i, + block_number as u32, + (*private_context), + ) + } + T::deserialize(fields) + } + +} diff --git a/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts b/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts index 287d3fc27f1..87821e95d11 100644 --- a/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts @@ -157,11 +157,15 @@ describe('e2e_inclusion_proofs_contract', () => { it('public value existence failure case', async () => { // Choose random block number between first block and current block number to test archival node const blockNumber = await getRandomBlockNumber(); - const randomPublicValue = Fr.random(); await expect( contract.methods.test_public_value_inclusion_proof(randomPublicValue, blockNumber).send().wait(), - ).rejects.toThrow(/Public value does not match value in witness/); + ).rejects.toThrow('Public value does not match the witness'); + }); + + it('proves existence of uninitialized public value', async () => { + const blockNumber = await getRandomBlockNumber(); + await contract.methods.test_public_unused_value_inclusion_proof(blockNumber).send().wait(); }); }); diff --git a/yarn-project/end-to-end/src/e2e_singleton.test.ts b/yarn-project/end-to-end/src/e2e_state_vars.test.ts similarity index 89% rename from yarn-project/end-to-end/src/e2e_singleton.test.ts rename to yarn-project/end-to-end/src/e2e_state_vars.test.ts index 6c1407ef053..0ad3a75a04e 100644 --- a/yarn-project/end-to-end/src/e2e_singleton.test.ts +++ b/yarn-project/end-to-end/src/e2e_state_vars.test.ts @@ -3,7 +3,7 @@ import { DocsExampleContract } from '@aztec/noir-contracts'; import { setup } from './fixtures/utils.js'; -describe('e2e_singleton', () => { +describe('e2e_state_vars', () => { let wallet: Wallet; let teardown: () => Promise; @@ -19,6 +19,24 @@ describe('e2e_singleton', () => { afterAll(() => teardown()); + describe('Stable Public State', () => { + it('private read of uninitialized stable', async () => { + const s = await contract.methods.get_stable().view(); + + const receipt2 = await contract.methods.match_stable(s.account, s.points).send().wait(); + expect(receipt2.status).toEqual(TxStatus.MINED); + }); + + it('private read of initialized stable', async () => { + const receipt = await contract.methods.initialize_stable(1).send().wait(); + expect(receipt.status).toEqual(TxStatus.MINED); + const s = await contract.methods.get_stable().view(); + + const receipt2 = await contract.methods.match_stable(s.account, s.points).send().wait(); + expect(receipt2.status).toEqual(TxStatus.MINED); + }, 200_000); + }); + describe('Singleton', () => { it('fail to read uninitialized singleton', async () => { expect(await contract.methods.is_legendary_initialized().view()).toEqual(false); diff --git a/yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr b/yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr index 9300ef77ecd..a87b7c960cc 100644 --- a/yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr @@ -18,9 +18,6 @@ contract DocsExample { address::AztecAddress, }; use dep::aztec::{ - oracle::{ - debug_log::debug_log_format, - }, note::{ note_header::NoteHeader, note_getter_options::{NoteGetterOptions, Comparator}, @@ -28,7 +25,7 @@ contract DocsExample { utils as note_utils, }, context::{PrivateContext, PublicContext, Context}, - state_vars::{map::Map, public_state::PublicState,singleton::Singleton, immutable_singleton::ImmutableSingleton, set::Set}, + state_vars::{map::Map, public_state::PublicState,singleton::Singleton, immutable_singleton::ImmutableSingleton, set::Set, stable_public_state::StablePublicState}, }; // how to import methods from other files/folders within your workspace use crate::options::create_account_card_getter_options; @@ -49,6 +46,7 @@ contract DocsExample { // docs:end:storage-map-singleton-declaration test: Set, imm_singleton: ImmutableSingleton, + stable_value: StablePublicState, } impl Storage { @@ -59,20 +57,21 @@ contract DocsExample { 1 ), // docs:start:start_vars_singleton - legendary_card: Singleton::new(context, 2), + legendary_card: Singleton::new(context, 3), // docs:end:start_vars_singleton // just used for docs example (not for game play): // docs:start:state_vars-MapSingleton profiles: Map::new( context, - 3, + 4, |context, slot| { Singleton::new(context, slot) }, ), // docs:end:state_vars-MapSingleton - test: Set::new(context, 4), - imm_singleton: ImmutableSingleton::new(context, 4), + test: Set::new(context, 5), + imm_singleton: ImmutableSingleton::new(context, 6), + stable_value: StablePublicState::new(context, 7), } } } @@ -80,6 +79,25 @@ contract DocsExample { #[aztec(private)] fn constructor() {} + #[aztec(public)] + fn initialize_stable(points: u8) { + let mut new_leader = Leader { account: context.msg_sender(), points }; + storage.stable_value.initialize(new_leader); + } + + #[aztec(private)] + fn match_stable(account: AztecAddress, points: u8) { + let expected = Leader { account, points }; + let read = storage.stable_value.read_private(); + + assert(read.account == expected.account, "Invalid account"); + assert(read.points == expected.points, "Invalid points"); + } + + unconstrained fn get_stable() -> pub Leader { + storage.stable_value.read_public() + } + #[aztec(private)] fn initialize_immutable_singleton(randomness: Field, points: u8) { let mut new_card = CardNote::new(points, randomness, context.msg_sender()); diff --git a/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr b/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr index 12a3a797029..37517063ad3 100644 --- a/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr @@ -51,6 +51,7 @@ contract InclusionProofs { struct Storage { private_values: Map>, public_value: PublicState, + public_unused_value: PublicState, } impl Storage { @@ -67,6 +68,10 @@ contract InclusionProofs { context, 2, // Storage slot ), + public_unused_value: PublicState::new( + context, + 3, // Storage slot + ), } } } @@ -192,6 +197,17 @@ contract InclusionProofs { // docs:end:prove_nullifier_inclusion } + #[aztec(private)] + fn test_public_unused_value_inclusion_proof(block_number: u32 // The block at which we'll prove that the public value exists + ) { + prove_public_value_inclusion( + 0, + storage.public_unused_value.storage_slot, + block_number, + context + ); + } + #[aztec(private)] fn test_public_value_inclusion_proof( public_value: Field, From cc17afe73da1f2cad18080797f30210908caa7f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 31 Jan 2024 12:34:27 -0300 Subject: [PATCH 16/20] docs: add simple api description for note_getter_options.status (#4329) This doesn't do much more than just mention the feature added in https://github.com/AztecProtocol/aztec-packages/pull/4238. It feels like an expansion of this would fit better elsewhere as its own suggested design pattern, since reading nullified state is niche and can be tricky to get right. --- .../contracts/syntax/storage/private_state.md | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/docs/docs/developers/contracts/syntax/storage/private_state.md b/docs/docs/developers/contracts/syntax/storage/private_state.md index 35429d74020..d636459720a 100644 --- a/docs/docs/developers/contracts/syntax/storage/private_state.md +++ b/docs/docs/developers/contracts/syntax/storage/private_state.md @@ -246,69 +246,77 @@ The key distinction is that this method is unconstrained. It does not perform a This function requires a `NoteViewerOptions`. The `NoteViewerOptions` is essentially similar to the [`NoteGetterOptions`](#notegetteroptions), except that it doesn't take a custom filter. -### NoteGetterOptions +## `NoteGetterOptions` `NoteGetterOptions` encapsulates a set of configurable options for filtering and retrieving a selection of notes from a [data oracle](../functions/oracles.md). Developers can design instances of `NoteGetterOptions`, to determine how notes should be filtered and returned to the functions of their smart contracts. You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/aztec-nr/aztec/src/note/note_getter_options.nr). -#### `selects: BoundedVec, N>` +### `selects: BoundedVec, N>` `selects` is a collection of filtering criteria, specified by `Select { field_index: u8, value: Field, comparator: u3 }` structs. It instructs the data oracle to find notes whose (`field_index`)th field matches the provided `value`, according to the `comparator`. -#### `sorts: BoundedVec, N>` +### `sorts: BoundedVec, N>` `sorts` is a set of sorting instructions defined by `Sort { field_index: u8, order: u2 }` structs. This directs the data oracle to sort the matching notes based on the value of the specified field index and in the indicated order. The value of order is **1** for _DESCENDING_ and **2** for _ASCENDING_. -#### `limit: u32` +### `limit: u32` When the `limit` is set to a non-zero value, the data oracle will return a maximum of `limit` notes. -#### `offset: u32` +### `offset: u32` This setting enables us to skip the first `offset` notes. It's particularly useful for pagination. -#### `filter: fn ([Option; MAX_READ_REQUESTS_PER_CALL], FILTER_ARGS) -> [Option; MAX_READ_REQUESTS_PER_CALL]` +### `filter: fn ([Option; MAX_READ_REQUESTS_PER_CALL], FILTER_ARGS) -> [Option; MAX_READ_REQUESTS_PER_CALL]` Developers have the option to provide a custom filter. This allows specific logic to be applied to notes that meet the criteria outlined above. The filter takes the notes returned from the oracle and `filter_args` as its parameters. It's important to note that the process of applying the custom filter to get the final notes is not constrained. It's crucial to verify the returned notes even if certain assumptions are made in the custom filter. -#### `filter_args: FILTER_ARGS` +### `filter_args: FILTER_ARGS` `filter_args` provides a means to furnish additional data or context to the custom filter. -#### Methods +### `status: u2` + +`status` allows the caller to retrieve notes that have been nullified, which can be useful to prove historical data. Note that when querying for both active and nullified notes the caller cannot know if each note retrieved has or has not been nullified. + +### Methods Several methods are available on `NoteGetterOptions` to construct the options in a more readable manner: -#### `fn new() -> NoteGetterOptions` +### `fn new() -> NoteGetterOptions` This function initializes a `NoteGetterOptions` that simply returns the maximum number of notes allowed in a call. -#### `fn with_filter(filter, filter_args) -> NoteGetterOptions` +### `fn with_filter(filter, filter_args) -> NoteGetterOptions` This function initializes a `NoteGetterOptions` with a [`filter`](#filter-fn-optionnote-max_read_requests_per_call-filter_args---optionnote-max_read_requests_per_call) and [`filter_args`](#filter_args-filter_args). -#### `.select` +### `.select` This method adds a [`Select`](#selects-boundedvecoptionselect-n) criterion to the options. -#### `.sort` +### `.sort` This method adds a [`Sort`](#sorts-boundedvecoptionsort-n) criterion to the options. -#### `.set_limit` +### `.set_limit` This method lets you set a limit for the maximum number of notes to be retrieved. -#### `.set_offset` +### `.set_offset` This method sets the offset value, which determines where to start retrieving notes. -#### Examples +### `.set_status` + +This method sets the status of notes to retrieve (active or nullified). -##### Example 1 +### Examples + +#### Example 1 The following code snippet creates an instance of `NoteGetterOptions`, which has been configured to find the cards that belong to `account_address`. The returned cards are sorted by their points in descending order, and the first `offset` cards with the highest points are skipped. @@ -342,7 +350,7 @@ The limit is `MAX_READ_REQUESTS_PER_CALL` by default. But we can set it to any v #include_code state_vars-NoteGetterOptionsPickOne /yarn-project/noir-contracts/contracts/docs_example_contract/src/options.nr rust -##### Example 2 +#### Example 2 An example of how we can use a Comparator to select notes when calling a Noir contract from aztec.js is below. @@ -351,4 +359,3 @@ An example of how we can use a Comparator to select notes when calling a Noir co In this example, we use the above typescript code to invoke a call to our Noir contract below. This Noir contract function takes an input to match with, and a comparator to use when fetching and selecting notes from storage. #include_code state_vars-NoteGetterOptionsComparatorExampleNoir /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust - From f85a87084e3fdba20b6f74d7e53b2e95925e8548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 31 Jan 2024 12:34:38 -0300 Subject: [PATCH 17/20] docs: minor quickstart fixes (#4330) These are just fixes of simple typos or removals of repeated sections (the private state intro, likely the result of merging two articles). I also added short notes on using non-default ports for the Sandbox quickstart which would've saved me quite a lot of head-scratching and debugging. Opening again since https://github.com/AztecProtocol/aztec-packages/pull/4065 cannot be merged as we don't run CI on forks. --- docs/docs/developers/getting_started/quickstart.md | 6 +++++- docs/docs/learn/concepts/hybrid_state/main.md | 14 +------------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/docs/docs/developers/getting_started/quickstart.md b/docs/docs/developers/getting_started/quickstart.md index 822cf85f5a7..a7f1f894916 100644 --- a/docs/docs/developers/getting_started/quickstart.md +++ b/docs/docs/developers/getting_started/quickstart.md @@ -53,7 +53,7 @@ Once these have been installed, to start the sandbox, run: aztec-sandbox ``` -This will attempt to run the Sandbox on ` localhost:8080`, so you will have to make sure nothing else is running on that port or change the port defined in `./.aztec/docker-compose.yml`. Running the command again will overwrite any changes made to the `docker-compose.yml`. +This will attempt to run the Sandbox on ` localhost:8080`, so you will have to make sure nothing else is running on that port or change the port defined in `./.aztec/docker-compose.yml`. Running the installation again will overwrite any changes made to the `docker-compose.yml`. This command will also install the CLI if a node package version of the CLI isn't found locally. @@ -71,6 +71,10 @@ Start by deploying a token contract. After it is deployed, we check that the dep #include_code deploy yarn-project/end-to-end/src/guides/up_quick_start.sh bash +:::note +If you're not using the default port for the Sandbox, make sure to pass the `--rpc-url` parameter, e.g.: `--rpc-url http://localhost:8000`. +::: + Note that the deployed contract address is exported, so we can use it as `$CONTRACT` later on. ## Call a contract with the CLI diff --git a/docs/docs/learn/concepts/hybrid_state/main.md b/docs/docs/learn/concepts/hybrid_state/main.md index ac2565ee39f..2c540f2a077 100644 --- a/docs/docs/learn/concepts/hybrid_state/main.md +++ b/docs/docs/learn/concepts/hybrid_state/main.md @@ -12,18 +12,6 @@ Internal to the Aztec network, public state is stored and updated by the sequenc ## Private State -Every smart contract needs a way to track information over time - that's what state is. In order to have both private and public transactions and storage in Aztec, we have to have public and private state. - -On this page, you’ll learn - -- Aztec's unique interpretation of private state -- Representation of private state in an append-only database -- Concept of 'deleting' private state variables using nullifiers -- How to modify private state -- How Aztec abstracts the UTXO model from developers - -## Private State on Aztec - Private state must be treated differently from public state and this must be expressed in the semantics of Aztec.nr. Private state is encrypted and therefore is "owned" by a user or a set of users (via shared secrets) that are able to decrypt the state. @@ -32,7 +20,7 @@ Private state is represented in an append-only database since updating a record The act of "deleting" a private state variable can be represented by adding an associated nullifier to a nullifier set. The nullifier is generated such that, without knowing the decryption key of the owner, an observer cannot link a state record with a nullifier. -Modification of state variables can be emulated by nullifying the a state record and creating a new record to represent the variable. Private state has an intrinsic UTXO structure and this must be represented in the language semantics of manipulating private state. +Modification of state variables can be emulated by nullifying the state record and creating a new record to represent the variable. Private state has an intrinsic UTXO structure and this must be represented in the language semantics of manipulating private state. ### Abstracting UTXO's from App's / Users From 8928fb1f46ce6403eb425548d254e8cfbb6ae6a9 Mon Sep 17 00:00:00 2001 From: Jean M <132435771+jeanmon@users.noreply.github.com> Date: Wed, 31 Jan 2024 17:27:51 +0100 Subject: [PATCH 18/20] docs(yp): AVM circuit - user memory section (#4323) Resolves #4043 --- yellow-paper/docs/public-vm/avm-circuit.md | 27 +++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/yellow-paper/docs/public-vm/avm-circuit.md b/yellow-paper/docs/public-vm/avm-circuit.md index c5e91882b67..65234632f13 100644 --- a/yellow-paper/docs/public-vm/avm-circuit.md +++ b/yellow-paper/docs/public-vm/avm-circuit.md @@ -108,7 +108,32 @@ The VM circuit's **Memory Controller** processes loads and stores between interm When decoded, instructions that operate on memory map to some Memory Controller sub-operations. A memory read maps to a `LOAD` sub-operation which loads a word from memory into an intermediate register. The memory offset for this sub-operation is generally specified by an instruction argument. Similarly, a memory write maps to a `STORE` sub-operation which stores a word from an intermediate register to memory. ### User Memory -**TODO** + +This table tracks all memory `Read` or `Write` operations. As introduced in the ["Memory State Model"](./state-model.md), a memory cell is indexed by a 32-bit unsigned integer (`u32`), i.e., the memory capacity is of $2^{32}$ words. Each word is associated with a tag defining its type (`uninitialized`, `u8`, `u16`, `u32`, `u64`, `u128`, `field`). At the beginning of a new call, each memory cell is of type `uninitialized` and has value 0. + +The main property enforcement of this table concerns read/write consistency of every memory cell. This must ensure: + +- Each initial read on a memory cell must have value 0 (`uninitialized` is compatible with any other type). +- Each read on a memory cell must have the same value and the same tag as those set by the last write on this memory cell. + +In addition, this table ensures that the instruction tag corresponding to a memory operation is the same as the memory cell tag. The instruction tag is passed to the memory controller and added to the pertaining row(s) of this table. Note that this is common for an instruction to generate several memory operations and thus several rows in this table. + +The user memory table essentially consists of the following colums: + +- `CALL_PTR`: call pointer uniquely identifying the contract call +- `CLK`: clock value of the memory operation +- `ADDR`: address (type `u32`) pertaining to the memory operation +- `VAL`: value which is read (resp. written) from (resp. to) the memory address +- `TAG`: tag associated to this memory address +- `IN_TAG`: tag of the pertaining instruction +- `RW`: boolean indicating whether memory operation is read or write +- `TAG_ERR`: boolean set to true if there is a mismatch between `TAG` and `IN_TAG` + +To facilitate consistency check, the rows are sorted by `CALL_PTR` then by `ADDR` and then by `CLK` in ascending (arrow of time) order. Any (non-initial) read operation row is constrained to have the same `VAL` and `TAG` than the previous row. A write operation does not need to be constrained. + +The tag consistency check can be performed within every row (order of rows does not matter). + +Note that `CLK` also plays the role of a foreign key to point to the corresponding sub-operation. This is crucial to enforce consistency of copied values between the sub-operations and memory table. ### Calldata **TODO** From c366c6e6d5c9f28a5dc92a303dcab4a23fb2d84e Mon Sep 17 00:00:00 2001 From: David Banks <47112877+dbanks12@users.noreply.github.com> Date: Wed, 31 Jan 2024 13:39:59 -0500 Subject: [PATCH 19/20] feat(avm-transpiler): Brillig to AVM transpiler (#4227) Resolves #4270 1. Transpiler module 2. Docker & CI for transpiler module 3. Auto-transpile contracts starting with `avm_test_*` 4. AVM test contract for transpilation & simulation 5. AVM Simulator test with transpiled contract 6. Small fix in TS TaggedMemory --------- Co-authored-by: Maddiaa <47148561+Maddiaa0@users.noreply.github.com> --- .circleci/config.yml | 15 + avm-transpiler/.gitignore | 2 + avm-transpiler/Cargo.lock | 2019 +++++++++++++++++ avm-transpiler/Cargo.toml | 21 + avm-transpiler/Dockerfile | 13 + avm-transpiler/Dockerfile.dockerignore | 7 + avm-transpiler/README.md | 15 + avm-transpiler/bootstrap.sh | 19 + avm-transpiler/scripts/bootstrap_native.sh | 20 + avm-transpiler/src/instructions.rs | 115 + avm-transpiler/src/main.rs | 46 + avm-transpiler/src/opcodes.rs | 168 ++ avm-transpiler/src/transpile.rs | 289 +++ avm-transpiler/src/transpile_contract.rs | 120 + avm-transpiler/src/utils.rs | 41 + bootstrap.sh | 1 + build_manifest.yml | 7 + .../src/avm/avm_memory_types.ts | 6 +- .../acir-simulator/src/avm/index.test.ts | 26 +- .../cli/src/cmds/example_contracts.ts | 2 +- yarn-project/noir-contracts/Nargo.toml | 7 +- .../contracts/avm_test_contract/Nargo.toml | 8 + .../contracts/avm_test_contract/src/main.nr | 26 + yarn-project/noir-contracts/package.json | 2 +- .../noir-contracts/package.local.json | 2 +- .../noir-contracts/scripts/transpile.sh | 8 + yarn-project/yarn-project-base/Dockerfile | 3 + 27 files changed, 2999 insertions(+), 9 deletions(-) create mode 100644 avm-transpiler/.gitignore create mode 100644 avm-transpiler/Cargo.lock create mode 100644 avm-transpiler/Cargo.toml create mode 100644 avm-transpiler/Dockerfile create mode 100644 avm-transpiler/Dockerfile.dockerignore create mode 100644 avm-transpiler/README.md create mode 100755 avm-transpiler/bootstrap.sh create mode 100755 avm-transpiler/scripts/bootstrap_native.sh create mode 100644 avm-transpiler/src/instructions.rs create mode 100644 avm-transpiler/src/main.rs create mode 100644 avm-transpiler/src/opcodes.rs create mode 100644 avm-transpiler/src/transpile.rs create mode 100644 avm-transpiler/src/transpile_contract.rs create mode 100644 avm-transpiler/src/utils.rs create mode 100644 yarn-project/noir-contracts/contracts/avm_test_contract/Nargo.toml create mode 100644 yarn-project/noir-contracts/contracts/avm_test_contract/src/main.nr create mode 100755 yarn-project/noir-contracts/scripts/transpile.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index 0fae211493d..b036b70684a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -125,6 +125,17 @@ jobs: name: "Build" command: cond_spot_run_build noir-compile-acir-tests 32 + avm-transpiler: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build avm-transpiler 32 + # Barretenberg barretenberg-wasm-linux-clang: docker: @@ -1137,6 +1148,9 @@ workflows: - noir-ecr-manifest <<: *defaults + # Transpiler + - avm-transpiler: *defaults + # Barretenberg - barretenberg-x86_64-linux-gcc: *defaults - barretenberg-x86_64-linux-clang: *defaults @@ -1185,6 +1199,7 @@ workflows: # Yarn Project - yarn-project-base: requires: + - avm-transpiler - l1-contracts - bb-js - noir-ecr-manifest diff --git a/avm-transpiler/.gitignore b/avm-transpiler/.gitignore new file mode 100644 index 00000000000..212de442f4e --- /dev/null +++ b/avm-transpiler/.gitignore @@ -0,0 +1,2 @@ +/target +.DS_Store \ No newline at end of file diff --git a/avm-transpiler/Cargo.lock b/avm-transpiler/Cargo.lock new file mode 100644 index 00000000000..ea35df3013e --- /dev/null +++ b/avm-transpiler/Cargo.lock @@ -0,0 +1,2019 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "acir" +version = "0.39.0" +dependencies = [ + "acir_field", + "base64 0.21.7", + "bincode", + "brillig", + "flate2", + "serde", + "thiserror", +] + +[[package]] +name = "acir_field" +version = "0.39.0" +dependencies = [ + "ark-bn254", + "ark-ff", + "cfg-if", + "hex", + "num-bigint", + "num-traits", + "serde", +] + +[[package]] +name = "acvm" +version = "0.39.0" +dependencies = [ + "acir", + "acvm_blackbox_solver", + "brillig_vm", + "indexmap 1.9.3", + "num-bigint", + "thiserror", + "tracing", +] + +[[package]] +name = "acvm_blackbox_solver" +version = "0.39.0" +dependencies = [ + "acir", + "blake2", + "blake3", + "k256", + "keccak", + "p256", + "sha2", + "sha3", + "thiserror", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "arena" +version = "0.23.0" +dependencies = [ + "generational-arena", +] + +[[package]] +name = "ark-bn254" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest", + "itertools", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "avm-transpiler" +version = "0.1.0" +dependencies = [ + "acvm", + "base64 0.21.7", + "env_logger", + "log", + "noirc_driver", + "regex", + "serde", + "serde_json", +] + +[[package]] +name = "aztec_macros" +version = "0.23.0" +dependencies = [ + "iter-extended", + "noirc_frontend", +] + +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + +[[package]] +name = "blake3" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "brillig" +version = "0.39.0" +dependencies = [ + "acir_field", + "serde", +] + +[[package]] +name = "brillig_vm" +version = "0.39.0" +dependencies = [ + "acir", + "acvm_blackbox_solver", + "num-bigint", + "num-traits", +] + +[[package]] +name = "build-data" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aed3884e2cab7c973c8fd2d150314b6a932df7fdc830edcaf1e8e7c4ae9db3c0" +dependencies = [ + "chrono", + "safe-lock", + "safe-regex", +] + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets", +] + +[[package]] +name = "chumsky" +version = "0.8.0" +source = "git+https://github.com/jfecher/chumsky?rev=ad9d312#ad9d312d9ffbc66c14514fa2b5752f4127b44f1e" +dependencies = [ + "hashbrown 0.11.2", +] + +[[package]] +name = "clap" +version = "4.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "codespan" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3362992a0d9f1dd7c3d0e89e0ab2bb540b7a95fea8cd798090e758fda2899b5e" +dependencies = [ + "codespan-reporting", + "serde", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.48", +] + +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "env_filter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e7cf40684ae96ade6232ed84582f40ce0a66efcd43a5117aef610534f8e0b8" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fm" +version = "0.23.0" +dependencies = [ + "codespan-reporting", + "serde", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generational-arena" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877e94aff08e743b651baaea359664321055749b398adff8740a7399af7796e7" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash 0.7.7", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.7", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "iana-time-zone" +version = "0.1.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "im" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" +dependencies = [ + "bitmaps", + "rand_core", + "rand_xoshiro", + "serde", + "sized-chunks", + "typenum", + "version_check", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", + "serde", +] + +[[package]] +name = "iter-extended" +version = "0.23.0" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "js-sys" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonrpc" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34efde8d2422fb79ed56db1d3aea8fa5b583351d15a26770cdee2f88813dd702" +dependencies = [ + "base64 0.13.1", + "minreq", + "serde", + "serde_json", +] + +[[package]] +name = "k256" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "sha2", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "libc" +version = "0.2.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "minreq" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3371dfc7b772c540da1380123674a8e20583aca99907087d990ca58cf44203" +dependencies = [ + "log", + "serde", + "serde_json", +] + +[[package]] +name = "noirc_abi" +version = "0.23.0" +dependencies = [ + "acvm", + "iter-extended", + "noirc_frontend", + "num-bigint", + "num-traits", + "serde", + "serde_json", + "thiserror", + "toml", +] + +[[package]] +name = "noirc_driver" +version = "0.23.0" +dependencies = [ + "acvm", + "aztec_macros", + "build-data", + "clap", + "fm", + "fxhash", + "iter-extended", + "noirc_abi", + "noirc_errors", + "noirc_evaluator", + "noirc_frontend", + "rust-embed", + "serde", + "tracing", +] + +[[package]] +name = "noirc_errors" +version = "0.23.0" +dependencies = [ + "acvm", + "base64 0.21.7", + "chumsky", + "codespan", + "codespan-reporting", + "flate2", + "fm", + "serde", + "serde_json", + "serde_with", + "tracing", +] + +[[package]] +name = "noirc_evaluator" +version = "0.23.0" +dependencies = [ + "acvm", + "fxhash", + "im", + "iter-extended", + "noirc_errors", + "noirc_frontend", + "num-bigint", + "serde", + "thiserror", + "tracing", +] + +[[package]] +name = "noirc_frontend" +version = "0.23.0" +dependencies = [ + "acvm", + "arena", + "chumsky", + "fm", + "iter-extended", + "noirc_errors", + "noirc_printable_type", + "regex", + "rustc-hash", + "serde", + "serde_json", + "small-ord-set", + "smol_str", + "thiserror", + "tracing", +] + +[[package]] +name = "noirc_printable_type" +version = "0.23.0" +dependencies = [ + "acvm", + "iter-extended", + "jsonrpc", + "regex", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "p256" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" +dependencies = [ + "ecdsa", + "elliptic-curve", + "sha2", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core", +] + +[[package]] +name = "regex" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint", + "hmac", + "zeroize", +] + +[[package]] +name = "rust-embed" +version = "6.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a36224c3276f8c4ebc8c20f158eca7ca4359c8db89991c4925132aaaf6702661" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "6.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49b94b81e5b2c284684141a2fb9e2a31be90638caf040bf9afbc5a0416afe1ac" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.48", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "7.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d38ff6bf570dc3bb7100fce9f7b60c33fa71d80e88da3f2580df4ff2bdded74" +dependencies = [ + "sha2", + "walkdir", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + +[[package]] +name = "safe-lock" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "077d73db7973cccf63eb4aff1e5a34dc2459baa867512088269ea5f2f4253c90" + +[[package]] +name = "safe-proc-macro2" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd85be67db87168aa3c13fd0da99f48f2ab005dccad5af5626138dc1df20eb6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "safe-quote" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e530f7831f3feafcd5f1aae406ac205dd998436b4007c8e80f03eca78a88f7" +dependencies = [ + "safe-proc-macro2", +] + +[[package]] +name = "safe-regex" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15289bf322e0673d52756a18194167f2378ec1a15fe884af6e2d2cb934822b0" +dependencies = [ + "safe-regex-macro", +] + +[[package]] +name = "safe-regex-compiler" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba76fae590a2aa665279deb1f57b5098cbace01a0c5e60e262fcf55f7c51542" +dependencies = [ + "safe-proc-macro2", + "safe-quote", +] + +[[package]] +name = "safe-regex-macro" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c2e96b5c03f158d1b16ba79af515137795f4ad4e8de3f790518aae91f1d127" +dependencies = [ + "safe-proc-macro2", + "safe-regex-compiler", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" + +[[package]] +name = "serde" +version = "1.0.195" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.195" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "serde_json" +version = "1.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_with" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5c9fdb6b00a489875b22efd4b78fe2b363b72265cc5f6eb2e2b9ee270e6140c" +dependencies = [ + "base64 0.21.7", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.1.0", + "serde", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff351eb4b33600a2e138dfa0b10b65a238ea8ff8fb2387c422c5022a3e8298" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + +[[package]] +name = "small-ord-set" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf7035a2b2268a5be8c1395738565b06beda836097e12021cdefc06b127a0e7e" +dependencies = [ + "smallvec", +] + +[[package]] +name = "smallvec" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" + +[[package]] +name = "smol_str" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad6c857cbab2627dcf01ec85a623ca4e7dcb5691cbaa3d7fb7653671f0d09c9" +dependencies = [ + "serde", +] + +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "time" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +dependencies = [ + "deranged", + "itoa", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +dependencies = [ + "time-core", +] + +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.1.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.48", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winnow" +version = "0.5.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" +dependencies = [ + "memchr", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] diff --git a/avm-transpiler/Cargo.toml b/avm-transpiler/Cargo.toml new file mode 100644 index 00000000000..9d4f0a001ea --- /dev/null +++ b/avm-transpiler/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "avm-transpiler" +version = "0.1.0" +authors = ["The Aztec Team "] +edition = "2021" +license = "MIT OR Apache-2.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +# local +acvm = { path = "../noir/acvm-repo/acvm" } +noirc_driver = { path = "../noir/compiler/noirc_driver" } + +# external +base64 = "0.21" +regex = "1.10" +env_logger = "0.11" +log = "0.4" +serde_json = "1.0" +serde = { version = "1.0.136", features = ["derive"]} \ No newline at end of file diff --git a/avm-transpiler/Dockerfile b/avm-transpiler/Dockerfile new file mode 100644 index 00000000000..1f55f8ba40d --- /dev/null +++ b/avm-transpiler/Dockerfile @@ -0,0 +1,13 @@ +FROM rust:bookworm + +WORKDIR /usr/src +COPY ./avm-transpiler ./avm-transpiler +COPY ./noir ./noir + +WORKDIR /usr/src/avm-transpiler +RUN apt-get update && apt-get install -y git +RUN ./scripts/bootstrap_native.sh + +FROM ubuntu:lunar +COPY --from=0 /usr/src/avm-transpiler/target/release/avm-transpiler /usr/src/avm-transpiler/target/release/avm-transpiler +ENTRYPOINT ["sh", "-c"] \ No newline at end of file diff --git a/avm-transpiler/Dockerfile.dockerignore b/avm-transpiler/Dockerfile.dockerignore new file mode 100644 index 00000000000..8edf9d12d62 --- /dev/null +++ b/avm-transpiler/Dockerfile.dockerignore @@ -0,0 +1,7 @@ +** + +!avm-transpiler/ +!noir/ +**/target/ +**/node_modules/ +**/packages/ \ No newline at end of file diff --git a/avm-transpiler/README.md b/avm-transpiler/README.md new file mode 100644 index 00000000000..2cd932c2451 --- /dev/null +++ b/avm-transpiler/README.md @@ -0,0 +1,15 @@ +# AVM Transpiler + +This component transpiles Aztec public contracts code from Noir's Brillig bytecode to AVM (Aztec Virtual Machine) bytecode. + +## Build + +``` +./boostrap.sh +``` + +## Run + +``` +cargo run +``` diff --git a/avm-transpiler/bootstrap.sh b/avm-transpiler/bootstrap.sh new file mode 100755 index 00000000000..916d8107876 --- /dev/null +++ b/avm-transpiler/bootstrap.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -eu + +cd $(dirname "$0") + +CMD=${1:-} + +if [ -n "$CMD" ]; then + if [ "$CMD" = "clean" ]; then + cargo clean + git clean -fdx + exit 0 + else + echo "Unknown command: $CMD" + exit 1 + fi +fi + +./scripts/bootstrap_native.sh \ No newline at end of file diff --git a/avm-transpiler/scripts/bootstrap_native.sh b/avm-transpiler/scripts/bootstrap_native.sh new file mode 100755 index 00000000000..3e0e2ed853a --- /dev/null +++ b/avm-transpiler/scripts/bootstrap_native.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -eu + +cd $(dirname "$0")/.. + +# If this project has been subrepod into another project, set build data manually. +export SOURCE_DATE_EPOCH=$(date +%s) +export GIT_DIRTY=false +if [ -f ".gitrepo" ]; then + export GIT_COMMIT=$(awk '/commit =/ {print $3}' .gitrepo) +else + export GIT_COMMIT=$(git rev-parse --verify HEAD) +fi + +# Build native. +if [ -n "${DEBUG:-}" ]; then + cargo build +else + cargo build --release +fi diff --git a/avm-transpiler/src/instructions.rs b/avm-transpiler/src/instructions.rs new file mode 100644 index 00000000000..efc195cc5b0 --- /dev/null +++ b/avm-transpiler/src/instructions.rs @@ -0,0 +1,115 @@ +use crate::opcodes::AvmOpcode; + +/// Common values of the indirect instruction flag +pub const ZEROTH_OPERAND_INDIRECT: u8 = 0b00000001; +pub const FIRST_OPERAND_INDIRECT: u8 = 0b00000010; +pub const ZEROTH_FIRST_OPERANDS_INDIRECT: u8 = 0b00000011; + +/// A simple representation of an AVM instruction for the purpose +/// of generating an AVM bytecode from Brillig. +/// Note: this does structure not impose rules like "ADD instruction must have 3 operands" +/// That job is left to the instruction decoder, not this thin transpiler. +pub struct AvmInstruction { + pub opcode: AvmOpcode, + + /// Any instructions with memory offset operands have the indirect flag + /// Each bit is a boolean: 0:direct, 1:indirect + /// The 0th bit corresponds to an instruction's 0th offset arg, 1st to 1st, etc... + pub indirect: Option, + + /// Some instructions have a destination or input tag + // TODO(4271): add in_tag alongside its support in TS + //pub in_tag: Option, + pub dst_tag: Option, + + /// Different instructions have different numbers of operands + pub operands: Vec, +} +impl AvmInstruction { + /// String representation for printing AVM programs + pub fn to_string(&self) -> String { + let mut out_str = format!("opcode {}", self.opcode.name()); + if let Some(indirect) = self.indirect { + out_str += format!(", indirect: {}", indirect).as_str(); + } + // TODO(4271): add in_tag alongside its support in TS + if let Some(dst_tag) = self.dst_tag { + out_str += format!(", dst_tag: {}", dst_tag as u8).as_str(); + } + if self.operands.len() > 0 { + out_str += ", operands: ["; + for operand in &self.operands { + out_str += format!("{}, ", operand.to_string()).as_str(); + } + out_str += "]"; + } + out_str + } + /// Bytes representation for generating AVM bytecode + pub fn to_bytes(&self) -> Vec { + let mut bytes = Vec::new(); + bytes.push(self.opcode as u8); + if let Some(indirect) = self.indirect { + bytes.push(indirect); + } + // TODO(4271): add in_tag alongside its support in TS + if let Some(dst_tag) = self.dst_tag { + // TODO(4271): make 8 bits when TS supports deserialization of 8 bit flags + //bytes.push(dst_tag as u8); + bytes.extend_from_slice(&(dst_tag as u32).to_be_bytes()); + } + for operand in &self.operands { + bytes.extend_from_slice(&operand.to_be_bytes()); + } + bytes + } +} +impl Default for AvmInstruction { + fn default() -> Self { + AvmInstruction { + opcode: AvmOpcode::ADD, + // TODO(4266): default to Some(0), since all instructions have indirect flag except jumps + indirect: None, + dst_tag: None, + operands: vec![], + } + } +} + +/// AVM instructions may include a type tag +#[derive(Copy, Clone)] +pub enum AvmTypeTag { + UNINITIALIZED, + UINT8, + UINT16, + UINT32, + UINT64, + UINT128, + FIELD, + INVALID, +} + +/// Operands are usually 32 bits (offsets or jump destinations) +/// Constants (as used by the SET instruction) can have size +/// different from 32 bits +pub enum AvmOperand { + U32 { value: u32 }, + // TODO(4267): Support operands of size other than 32 bits (for SET) + //U128 { value: u128 }, +} +impl AvmOperand { + pub fn to_string(&self) -> String { + match self { + AvmOperand::U32 { value } => format!(" U32:{}", value), + // TODO(4267): Support operands of size other than 32 bits (for SET) + //AvmOperand::U128 { value } => format!("U128:{}", value), + } + } + pub fn to_be_bytes(&self) -> Vec { + match self { + AvmOperand::U32 { value } => value.to_be_bytes().to_vec(), + // TODO(4267): Support operands of size other than 32 bits (for SET) + //AvmOperand::U128 { value } => value.to_be_bytes().to_vec(), + } + } +} diff --git a/avm-transpiler/src/main.rs b/avm-transpiler/src/main.rs new file mode 100644 index 00000000000..064bf343bbf --- /dev/null +++ b/avm-transpiler/src/main.rs @@ -0,0 +1,46 @@ +use log::warn; +use std::env; +use std::fs; +use std::path::Path; + +mod instructions; +mod opcodes; +mod transpile; +mod transpile_contract; +mod utils; + +use transpile_contract::{CompiledAcirContract, TranspiledContract}; + +fn main() { + env_logger::init(); + + let args: Vec = env::args().collect(); + let in_contract_artifact_path = &args[1]; + let out_transpiled_artifact_path = &args[2]; + + // Parse original (pre-transpile) contract + let contract_json = + fs::read_to_string(Path::new(in_contract_artifact_path)).expect("Unable to read file"); + let raw_json_obj: serde_json::Value = + serde_json::from_str(&contract_json).expect("Unable to parse json"); + + // Skip if contract has "transpiled: true" flag! + if let Some(transpiled) = raw_json_obj.get("transpiled") { + match transpiled { + serde_json::Value::Bool(true) => { + warn!("Contract already transpiled. Skipping."); + return; // nothing to transpile + } + _ => (), + } + } + // Parse json into contract object + let contract: CompiledAcirContract = + serde_json::from_str(&contract_json).expect("Unable to parse json"); + + // Transpile contract to AVM bytecode + let transpiled_contract = TranspiledContract::from(contract); + let transpiled_json = + serde_json::to_string(&transpiled_contract).expect("Unable to serialize json"); + fs::write(out_transpiled_artifact_path, transpiled_json).expect("Unable to write file"); +} diff --git a/avm-transpiler/src/opcodes.rs b/avm-transpiler/src/opcodes.rs new file mode 100644 index 00000000000..cc3c828d2ec --- /dev/null +++ b/avm-transpiler/src/opcodes.rs @@ -0,0 +1,168 @@ +/// All AVM opcodes +/// Keep updated with TS and yellow paper! +#[derive(Copy, Clone)] +pub enum AvmOpcode { + // Compute + // Compute - Arithmetic + ADD, + SUB, + MUL, + DIV, + // Compute - Comparators + EQ, + LT, + LTE, + // Compute - Bitwise + AND, + OR, + XOR, + NOT, + SHL, + SHR, + // Compute - Type Conversions + CAST, + + // Execution Environment + ADDRESS, + STORAGEADDRESS, + ORIGIN, + SENDER, + PORTAL, + FEEPERL1GAS, + FEEPERL2GAS, + FEEPERDAGAS, + CONTRACTCALLDEPTH, + // Execution Environment - Globals + CHAINID, + VERSION, + BLOCKNUMBER, + TIMESTAMP, + COINBASE, + BLOCKL1GASLIMIT, + BLOCKL2GASLIMIT, + BLOCKDAGASLIMIT, + // Execution Environment - Calldata + CALLDATACOPY, + + // Machine State + // Machine State - Gas + L1GASLEFT, + L2GASLEFT, + DAGASLEFT, + // Machine State - Internal Control Flow + JUMP, + JUMPI, + INTERNALCALL, + INTERNALRETURN, + // Machine State - Memory + SET, + MOV, + CMOV, + + // World State + BLOCKHEADERBYNUMBER, + SLOAD, // Public Storage + SSTORE, // Public Storage + READL1TOL2MSG, // Messages + SENDL2TOL1MSG, // Messages + EMITNOTEHASH, // Notes & Nullifiers + EMITNULLIFIER, // Notes & Nullifiers + + // Accrued Substate + EMITUNENCRYPTEDLOG, + + // Control Flow - Contract Calls + CALL, + STATICCALL, + RETURN, + REVERT, + + // Gadgets + KECCAK, + POSEIDON, +} + +impl AvmOpcode { + pub fn name(&self) -> &'static str { + match self { + // Compute + // Compute - Arithmetic + AvmOpcode::ADD => "ADD", + AvmOpcode::SUB => "SUB", + AvmOpcode::MUL => "MUL", + AvmOpcode::DIV => "DIV", + // Compute - Comparators + AvmOpcode::EQ => "EQ", + AvmOpcode::LT => "LT", + AvmOpcode::LTE => "LTE", + // Compute - Bitwise + AvmOpcode::AND => "AND", + AvmOpcode::OR => "OR", + AvmOpcode::XOR => "XOR", + AvmOpcode::NOT => "NOT", + AvmOpcode::SHL => "SHL", + AvmOpcode::SHR => "SHR", + // Compute - Type Conversions + AvmOpcode::CAST => "CAST", + + // Execution Environment + AvmOpcode::ADDRESS => "ADDRESS", + AvmOpcode::STORAGEADDRESS => "STORAGEADDRESS", + AvmOpcode::ORIGIN => "ORIGIN", + AvmOpcode::SENDER => "SENDER", + AvmOpcode::PORTAL => "PORTAL", + AvmOpcode::FEEPERL1GAS => "FEEPERL1GAS", + AvmOpcode::FEEPERL2GAS => "FEEPERL2GAS", + AvmOpcode::FEEPERDAGAS => "FEEPERDAGAS", + AvmOpcode::CONTRACTCALLDEPTH => "CONTRACTCALLDEPTH", + // Execution Environment - Globals + AvmOpcode::CHAINID => "CHAINID", + AvmOpcode::VERSION => "VERSION", + AvmOpcode::BLOCKNUMBER => "BLOCKNUMBER", + AvmOpcode::TIMESTAMP => "TIMESTAMP", + AvmOpcode::COINBASE => "COINBASE", + AvmOpcode::BLOCKL1GASLIMIT => "BLOCKL1GASLIMIT", + AvmOpcode::BLOCKL2GASLIMIT => "BLOCKL2GASLIMIT", + AvmOpcode::BLOCKDAGASLIMIT => "BLOCKDAGASLIMIT", + // Execution Environment - Calldata + AvmOpcode::CALLDATACOPY => "CALLDATACOPY", + + // Machine State + // Machine State - Gas + AvmOpcode::L1GASLEFT => "L1GASLEFT", + AvmOpcode::L2GASLEFT => "L2GASLEFT", + AvmOpcode::DAGASLEFT => "DAGASLEFT", + // Machine State - Internal Control Flow + AvmOpcode::JUMP => "JUMP", + AvmOpcode::JUMPI => "JUMPI", + AvmOpcode::INTERNALCALL => "INTERNALCALL", + AvmOpcode::INTERNALRETURN => "INTERNALRETURN", + // Machine State - Memory + AvmOpcode::SET => "SET", + AvmOpcode::MOV => "MOV", + AvmOpcode::CMOV => "CMOV", + + // World State + AvmOpcode::BLOCKHEADERBYNUMBER => "BLOCKHEADERBYNUMBER", + AvmOpcode::SLOAD => "SLOAD", // Public Storage + AvmOpcode::SSTORE => "SSTORE", // Public Storage + AvmOpcode::READL1TOL2MSG => "READL1TOL2MSG", // Messages + AvmOpcode::SENDL2TOL1MSG => "SENDL2TOL1MSG", // Messages + AvmOpcode::EMITNOTEHASH => "EMITNOTEHASH", // Notes & Nullifiers + AvmOpcode::EMITNULLIFIER => "EMITNULLIFIER", // Notes & Nullifiers + + // Accrued Substate + AvmOpcode::EMITUNENCRYPTEDLOG => "EMITUNENCRYPTEDLOG", + + // Control Flow - Contract Calls + AvmOpcode::CALL => "CALL", + AvmOpcode::STATICCALL => "STATICCALL", + AvmOpcode::RETURN => "RETURN", + AvmOpcode::REVERT => "REVERT", + + // Gadgets + AvmOpcode::KECCAK => "KECCAK", + AvmOpcode::POSEIDON => "POSEIDON", + } + } +} diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs new file mode 100644 index 00000000000..9785e41c7a1 --- /dev/null +++ b/avm-transpiler/src/transpile.rs @@ -0,0 +1,289 @@ +use acvm::acir::brillig::Opcode as BrilligOpcode; +use acvm::acir::circuit::brillig::Brillig; + +use acvm::brillig_vm::brillig::{BinaryFieldOp, BinaryIntOp}; + +use crate::instructions::{ + AvmInstruction, AvmOperand, AvmTypeTag, FIRST_OPERAND_INDIRECT, ZEROTH_OPERAND_INDIRECT, +}; +use crate::opcodes::AvmOpcode; +use crate::utils::{dbg_print_avm_program, dbg_print_brillig_program}; + +/// Transpile a Brillig program to AVM bytecode +pub fn brillig_to_avm(brillig: &Brillig) -> Vec { + dbg_print_brillig_program(&brillig); + + let mut avm_instrs: Vec = Vec::new(); + + // Map Brillig pcs to AVM pcs + // (some Brillig instructions map to >1 AVM instruction) + let brillig_pcs_to_avm_pcs = map_brillig_pcs_to_avm_pcs(avm_instrs.len(), brillig); + + // Transpile a Brillig instruction to one or more AVM instructions + for brillig_instr in &brillig.bytecode { + match brillig_instr { + BrilligOpcode::BinaryFieldOp { + destination, + op, + lhs, + rhs, + } => { + let avm_opcode = match op { + BinaryFieldOp::Add => AvmOpcode::ADD, + BinaryFieldOp::Sub => AvmOpcode::SUB, + BinaryFieldOp::Mul => AvmOpcode::MUL, + BinaryFieldOp::Div => AvmOpcode::DIV, + BinaryFieldOp::Equals => AvmOpcode::EQ, + }; + // TODO(4268): set in_tag to `field` + avm_instrs.push(AvmInstruction { + opcode: avm_opcode, + operands: vec![ + AvmOperand::U32 { + value: lhs.to_usize() as u32, + }, + AvmOperand::U32 { + value: rhs.to_usize() as u32, + }, + AvmOperand::U32 { + value: destination.to_usize() as u32, + }, + ], + ..Default::default() + }); + } + BrilligOpcode::BinaryIntOp { + destination, + op, + bit_size: _, // TODO(4268): support u8..u128 and use in_tag + lhs, + rhs, + } => { + let avm_opcode = match op { + BinaryIntOp::Add => AvmOpcode::ADD, + BinaryIntOp::Sub => AvmOpcode::SUB, + BinaryIntOp::Mul => AvmOpcode::MUL, + BinaryIntOp::UnsignedDiv => AvmOpcode::DIV, + BinaryIntOp::Equals => AvmOpcode::EQ, + BinaryIntOp::LessThan => AvmOpcode::LT, + BinaryIntOp::LessThanEquals => AvmOpcode::LTE, + BinaryIntOp::And => AvmOpcode::AND, + BinaryIntOp::Or => AvmOpcode::OR, + BinaryIntOp::Xor => AvmOpcode::XOR, + BinaryIntOp::Shl => AvmOpcode::SHL, + BinaryIntOp::Shr => AvmOpcode::SHR, + _ => panic!( + "Transpiler doesn't know how to process BinaryIntOp {:?}", + brillig_instr + ), + }; + // TODO(4268): support u8..u128 and use in_tag + avm_instrs.push(AvmInstruction { + opcode: avm_opcode, + operands: vec![ + AvmOperand::U32 { + value: lhs.to_usize() as u32, + }, + AvmOperand::U32 { + value: rhs.to_usize() as u32, + }, + AvmOperand::U32 { + value: destination.to_usize() as u32, + }, + ], + ..Default::default() + }); + } + BrilligOpcode::CalldataCopy { destination_address, size, offset } => { + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::CALLDATACOPY, + operands: vec![ + AvmOperand::U32 { + value: *offset as u32, // cdOffset (calldata offset) + }, AvmOperand::U32 { + value: *size as u32, + }, AvmOperand::U32 { + value: destination_address.to_usize() as u32, // dstOffset + }], + ..Default::default() + }); + } + BrilligOpcode::Jump { location } => { + let avm_loc = brillig_pcs_to_avm_pcs[*location]; + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::JUMP, + operands: vec![AvmOperand::U32 { + value: avm_loc as u32, + }], + ..Default::default() + }); + } + BrilligOpcode::JumpIf { + condition, + location, + } => { + let avm_loc = brillig_pcs_to_avm_pcs[*location]; + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::JUMPI, + operands: vec![ + AvmOperand::U32 { + value: avm_loc as u32, + }, + AvmOperand::U32 { + value: condition.to_usize() as u32, + }, + ], + ..Default::default() + }); + } + BrilligOpcode::Const { destination, value } => { + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::SET, + dst_tag: Some(AvmTypeTag::UINT32), + operands: vec![ + // TODO(4267): support u8..u128 and use dst_tag + AvmOperand::U32 { + value: value.to_usize() as u32, + }, + AvmOperand::U32 { + value: destination.to_usize() as u32, + }, + ], + ..Default::default() + }); + } + BrilligOpcode::Mov { + destination, + source, + } => { + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::MOV, + operands: vec![ + AvmOperand::U32 { + value: source.to_usize() as u32, + }, + AvmOperand::U32 { + value: destination.to_usize() as u32, + }, + ], + ..Default::default() + }); + } + BrilligOpcode::Load { + destination, + source_pointer, + } => { + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::MOV, + indirect: Some(ZEROTH_OPERAND_INDIRECT), // indirect srcOffset operand + operands: vec![ + AvmOperand::U32 { + value: source_pointer.to_usize() as u32, + }, + AvmOperand::U32 { + value: destination.to_usize() as u32, + }, + ], + ..Default::default() + }); + } + BrilligOpcode::Store { + destination_pointer, + source, + } => { + // INDIRECT dstOffset operand (bit 1 set high) + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::MOV, + indirect: Some(FIRST_OPERAND_INDIRECT), // indirect dstOffset operand + operands: vec![ + AvmOperand::U32 { + value: source.to_usize() as u32, + }, + AvmOperand::U32 { + value: destination_pointer.to_usize() as u32, + }, + ], + ..Default::default() + }); + } + BrilligOpcode::Call { location } => { + let avm_loc = brillig_pcs_to_avm_pcs[*location]; + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::INTERNALCALL, + operands: vec![AvmOperand::U32 { + value: avm_loc as u32, + }], + ..Default::default() + }); + } + BrilligOpcode::Return {} => avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::INTERNALRETURN, + ..Default::default() + }), + BrilligOpcode::Stop { return_data_offset, return_data_size } => { + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::RETURN, + operands: vec![ + AvmOperand::U32 { value: *return_data_offset as u32}, + AvmOperand::U32 { value: *return_data_size as u32}, + ], + ..Default::default() + }); + } + BrilligOpcode::Trap { /*return_data_offset, return_data_size*/ } => { + // TODO(https://github.com/noir-lang/noir/issues/3113): Trap should support return data + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::REVERT, + operands: vec![ + //AvmOperand::U32 { value: *return_data_offset as u32}, + //AvmOperand::U32 { value: *return_data_size as u32}, + AvmOperand::U32 { value: 0}, + AvmOperand::U32 { value: 0}, + ], + ..Default::default() + }); + } + _ => panic!( + "Transpiler doesn't know how to process {:?} brillig instruction", + brillig_instr + ), + } + } + + dbg_print_avm_program(&avm_instrs); + + // Constructing bytecode from instructions + let mut bytecode = Vec::new(); + for i in 0..avm_instrs.len() { + let instr_bytes = avm_instrs[i].to_bytes(); + bytecode.extend_from_slice(&instr_bytes); + } + bytecode +} + +/// Compute an array that maps each Brillig pc to an AVM pc. +/// This must be done before transpiling to properly transpile jump destinations. +/// This is necessary for two reasons: +/// 1. The transpiler injects `initial_offset` instructions at the beginning of the program. +/// 2. Some brillig instructions (_e.g._ Stop, or certain ForeignCalls) map to multiple AVM instructions +/// args: +/// initial_offset: how many AVM instructions were inserted at the start of the program +/// brillig: the Brillig program +/// returns: an array where each index is a Brillig pc, +/// and each value is the corresponding AVM pc. +fn map_brillig_pcs_to_avm_pcs(initial_offset: usize, brillig: &Brillig) -> Vec { + let mut pc_map = Vec::with_capacity(brillig.bytecode.len()); + pc_map.resize(brillig.bytecode.len(), 0); + pc_map[0] = initial_offset; + for i in 0..brillig.bytecode.len() - 1 { + let num_avm_instrs_for_this_brillig_instr = match &brillig.bytecode[i] { + BrilligOpcode::Load { .. } => 2, + BrilligOpcode::Store { .. } => 2, + _ => 1, + }; + // next Brillig pc will map to an AVM pc offset by the + // number of AVM instructions generated for this Brillig one + pc_map[i + 1] = pc_map[i] + num_avm_instrs_for_this_brillig_instr; + } + pc_map +} diff --git a/avm-transpiler/src/transpile_contract.rs b/avm-transpiler/src/transpile_contract.rs new file mode 100644 index 00000000000..2a8b762139f --- /dev/null +++ b/avm-transpiler/src/transpile_contract.rs @@ -0,0 +1,120 @@ +use log::info; +use regex::Regex; +use serde::{Deserialize, Serialize}; + +use acvm::acir::circuit::Circuit; +use noirc_driver::ContractFunctionType; + +use crate::transpile::brillig_to_avm; +use crate::utils::extract_brillig_from_acir; + +/// Representation of a contract with some transpiled functions +#[derive(Debug, Serialize, Deserialize)] +pub struct TranspiledContract { + pub transpiled: bool, + pub noir_version: String, + pub name: String, + // Functions can be ACIR or AVM + pub functions: Vec, + pub events: serde_json::Value, + pub file_map: serde_json::Value, + //pub warnings: serde_json::Value, +} + +/// A regular contract with ACIR+Brillig functions +/// but with fields irrelevant to transpilation +/// represented as catch-all serde Values +#[derive(Debug, Serialize, Deserialize)] +pub struct CompiledAcirContract { + pub noir_version: String, + pub name: String, + pub functions: Vec, + pub events: serde_json::Value, + pub file_map: serde_json::Value, + //pub warnings: serde_json::Value, +} + +/// Representation of a contract function +/// with AVM bytecode as a base64 string +#[derive(Debug, Serialize, Deserialize)] +pub struct AvmContractFunction { + pub name: String, + pub function_type: ContractFunctionType, + pub is_internal: bool, + pub abi: serde_json::Value, + pub bytecode: String, // base64 + pub debug_symbols: serde_json::Value, +} + +/// Representation of an ACIR contract function but with +/// catch-all serde Values for fields irrelevant to transpilation +#[derive(Debug, Serialize, Deserialize)] +pub struct AcirContractFunction { + pub name: String, + pub function_type: ContractFunctionType, + pub is_internal: bool, + pub abi: serde_json::Value, + #[serde( + serialize_with = "Circuit::serialize_circuit_base64", + deserialize_with = "Circuit::deserialize_circuit_base64" + )] + pub bytecode: Circuit, + pub debug_symbols: serde_json::Value, +} + +/// An enum that allows the TranspiledContract struct to contain +/// functions with either ACIR or AVM bytecode +#[derive(Debug, Serialize, Deserialize)] +#[serde(untagged)] // omit Acir/Avm tag for these objects in json +pub enum AvmOrAcirContractFunction { + Acir(AcirContractFunction), + Avm(AvmContractFunction), +} + +/// Transpilation is performed when a TranspiledContract +/// is constructed from a CompiledAcirContract +impl From for TranspiledContract { + fn from(contract: CompiledAcirContract) -> Self { + let mut functions = Vec::new(); + for function in contract.functions { + // TODO(4269): once functions are tagged for transpilation to AVM, check tag + let re = Regex::new(r"avm_.*$").unwrap(); + if function.function_type == ContractFunctionType::Unconstrained + && re.is_match(function.name.as_str()) + { + info!( + "Transpiling AVM function {} on contract {}", + function.name, contract.name + ); + // Extract Brillig Opcodes from acir + let acir_circuit = function.bytecode.clone(); + let brillig = extract_brillig_from_acir(&acir_circuit.opcodes); + + // Transpile to AVM + let avm_bytecode = brillig_to_avm(&brillig); + + // Push modified function entry to ABI + functions.push(AvmOrAcirContractFunction::Avm(AvmContractFunction { + name: function.name, + function_type: function.function_type, + is_internal: function.is_internal, + abi: function.abi, + bytecode: base64::encode(avm_bytecode), + debug_symbols: function.debug_symbols, + })); + } else { + // This function is not flagged for transpilation. Push original entry. + functions.push(AvmOrAcirContractFunction::Acir(function)); + } + } + TranspiledContract { + transpiled: true, + noir_version: contract.noir_version, + name: contract.name, + functions, // some acir, some transpiled avm functions + events: contract.events, + file_map: contract.file_map, + //warnings: contract.warnings, + } + } +} diff --git a/avm-transpiler/src/utils.rs b/avm-transpiler/src/utils.rs new file mode 100644 index 00000000000..2f31c900450 --- /dev/null +++ b/avm-transpiler/src/utils.rs @@ -0,0 +1,41 @@ +use log::debug; + +use acvm::acir::circuit::brillig::Brillig; +use acvm::acir::circuit::Opcode; + +use crate::instructions::AvmInstruction; + +/// Extract the Brillig program from its ACIR wrapper instruction. +/// An Noir unconstrained function compiles to one ACIR instruction +/// wrapping a Brillig program. This function just extracts that Brillig +/// assuming the 0th ACIR opcode is the wrapper. +pub fn extract_brillig_from_acir(opcodes: &Vec) -> &Brillig { + if opcodes.len() != 1 { + panic!("There should only be one brillig opcode"); + } + let opcode = &opcodes[0]; + let brillig = match opcode { + Opcode::Brillig(brillig) => brillig, + _ => panic!("Tried to extract a Brillig program from its ACIR wrapper opcode, but the opcode doesn't contain Brillig!"), + }; + brillig +} + +/// Print inputs, outputs, and instructions in a Brillig program +pub fn dbg_print_brillig_program(brillig: &Brillig) { + debug!("Printing Brillig program..."); + debug!("\tInputs: {:?}", brillig.inputs); + for i in 0..brillig.bytecode.len() { + let instr = &brillig.bytecode[i]; + debug!("\tPC:{0} {1:?}", i, instr); + } + debug!("\tOutputs: {:?}", brillig.outputs); +} + +/// Print each instruction in an AVM program +pub fn dbg_print_avm_program(avm_program: &Vec) { + debug!("Printing AVM program..."); + for i in 0..avm_program.len() { + debug!("\tPC:{0}: {1}", i, &avm_program[i].to_string()); + } +} diff --git a/bootstrap.sh b/bootstrap.sh index 8e8b31e9b0d..502bdc19956 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -54,6 +54,7 @@ PROJECTS=( barretenberg noir l1-contracts + avm-transpiler yarn-project ) diff --git a/build_manifest.yml b/build_manifest.yml index 861b632af04..00af54931b9 100644 --- a/build_manifest.yml +++ b/build_manifest.yml @@ -133,6 +133,7 @@ yarn-project-base: - noir - noir-packages - boxes-files + - avm-transpiler yarn-project: buildDir: yarn-project @@ -209,3 +210,9 @@ yellow-paper: buildDir: yellow-paper rebuildPatterns: - ^yellow-paper/ + +avm-transpiler: + buildDir: . + dockerfile: avm-transpiler/Dockerfile + rebuildPatterns: + - ^avm-transpiler/ \ No newline at end of file diff --git a/yarn-project/acir-simulator/src/avm/avm_memory_types.ts b/yarn-project/acir-simulator/src/avm/avm_memory_types.ts index 8963276813b..40c02b65463 100644 --- a/yarn-project/acir-simulator/src/avm/avm_memory_types.ts +++ b/yarn-project/acir-simulator/src/avm/avm_memory_types.ts @@ -220,11 +220,13 @@ export enum TypeTag { // TODO: Consider automatic conversion when getting undefined values. export class TaggedMemory { - static readonly MAX_MEMORY_SIZE = 1n << 32n; + // FIXME: memory should be 2^32, but TS doesn't allow for arrays that big. + static readonly MAX_MEMORY_SIZE = Number(1n << 31n); // 1n << 32n private _mem: MemoryValue[]; constructor() { - this._mem = []; + // Initialize memory size, but leave all entries undefined. + this._mem = new Array(TaggedMemory.MAX_MEMORY_SIZE); } public get(offset: number): MemoryValue { diff --git a/yarn-project/acir-simulator/src/avm/index.test.ts b/yarn-project/acir-simulator/src/avm/index.test.ts index 8fb3a49dab0..f085bc0bc00 100644 --- a/yarn-project/acir-simulator/src/avm/index.test.ts +++ b/yarn-project/acir-simulator/src/avm/index.test.ts @@ -1,4 +1,5 @@ import { Fr } from '@aztec/foundation/fields'; +import { AvmTestContractArtifact } from '@aztec/noir-contracts'; import { mock } from 'jest-mock-extended'; @@ -11,7 +12,7 @@ import { encodeToBytecode } from './opcodes/encode_to_bytecode.js'; import { Opcode } from './opcodes/opcodes.js'; describe('avm', () => { - it('Should execute bytecode', async () => { + it('Should execute bytecode that performs basic addition', async () => { const calldata: Fr[] = [new Fr(1), new Fr(2)]; const journal = mock(); @@ -38,4 +39,27 @@ describe('avm', () => { expect(returnData.length).toBe(1); expect(returnData).toEqual([new Fr(3)]); }); + + describe('testing transpiled Noir contracts', () => { + it('Should execute contract function that performs addition', async () => { + const calldata: Fr[] = [new Fr(1), new Fr(2)]; + const journal = mock(); + + // Get contract function artifact + const addArtifact = AvmTestContractArtifact.functions.find(f => f.name === 'avm_addArgsReturn')!; + + // Decode bytecode into instructions + const instructions = decodeBytecode(Buffer.from(addArtifact.bytecode, 'base64')); + + // Execute instructions + const context = new AvmMachineState(initExecutionEnvironment({ calldata })); + const avmReturnData = await executeAvm(context, journal, instructions); + + expect(avmReturnData.reverted).toBe(false); + + const returnData = avmReturnData.output; + expect(returnData.length).toBe(1); + expect(returnData).toEqual([new Fr(3)]); + }); + }); }); diff --git a/yarn-project/cli/src/cmds/example_contracts.ts b/yarn-project/cli/src/cmds/example_contracts.ts index 5b40c5c60c3..c7ee019eccc 100644 --- a/yarn-project/cli/src/cmds/example_contracts.ts +++ b/yarn-project/cli/src/cmds/example_contracts.ts @@ -4,6 +4,6 @@ import { getExampleContractArtifacts } from '../utils.js'; export async function exampleContracts(log: LogFn) { const abisList = await getExampleContractArtifacts(); - const names = Object.keys(abisList); + const names = Object.keys(abisList).filter(name => name !== 'AvmTestContractArtifact'); names.forEach(name => log(name)); } diff --git a/yarn-project/noir-contracts/Nargo.toml b/yarn-project/noir-contracts/Nargo.toml index 1b980b3dad3..4c919e77911 100644 --- a/yarn-project/noir-contracts/Nargo.toml +++ b/yarn-project/noir-contracts/Nargo.toml @@ -1,8 +1,9 @@ [workspace] members = [ - "contracts/benchmarking_contract", - "contracts/card_game_contract", - "contracts/child_contract", + "contracts/avm_test_contract", + "contracts/benchmarking_contract", + "contracts/card_game_contract", + "contracts/child_contract", "contracts/counter_contract", "contracts/docs_example_contract", "contracts/easy_private_token_contract", diff --git a/yarn-project/noir-contracts/contracts/avm_test_contract/Nargo.toml b/yarn-project/noir-contracts/contracts/avm_test_contract/Nargo.toml new file mode 100644 index 00000000000..f3d8583d433 --- /dev/null +++ b/yarn-project/noir-contracts/contracts/avm_test_contract/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "avm_test_contract" +authors = [""] +compiler_version = ">=0.18.0" +type = "contract" + +[dependencies] +aztec = { path = "../../../aztec-nr/aztec" } diff --git a/yarn-project/noir-contracts/contracts/avm_test_contract/src/main.nr b/yarn-project/noir-contracts/contracts/avm_test_contract/src/main.nr new file mode 100644 index 00000000000..00e35dfe6ba --- /dev/null +++ b/yarn-project/noir-contracts/contracts/avm_test_contract/src/main.nr @@ -0,0 +1,26 @@ +// + +contract AvmTest { + // Libs + use dep::aztec::protocol_types::{ + address::AztecAddress, + }; + + #[aztec(private)] + fn constructor() {} + + // Function name prefix "avm_" flags it for transpilation + unconstrained fn avm_addArgsReturn(argA: Field, argB: Field) -> pub Field { + argA + argB + } + + // Function required for all contracts + unconstrained fn compute_note_hash_and_nullifier( + _contract_address: AztecAddress, + _nonce: Field, + _storage_slot: Field, + _serialized_note: [Field; 1] + ) -> pub [Field; 4] { + [0, 0, 0, 0] + } +} diff --git a/yarn-project/noir-contracts/package.json b/yarn-project/noir-contracts/package.json index 6845b1f90ff..38bf26e463b 100644 --- a/yarn-project/noir-contracts/package.json +++ b/yarn-project/noir-contracts/package.json @@ -14,7 +14,7 @@ "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --passWithNoTests", - "build:contracts": "./scripts/compile.sh && ./scripts/generate-types.sh" + "build:contracts": "./scripts/compile.sh && ./scripts/transpile.sh && ./scripts/generate-types.sh" }, "inherits": [ "../package.common.json", diff --git a/yarn-project/noir-contracts/package.local.json b/yarn-project/noir-contracts/package.local.json index 6fb912b0da8..9ea766d3f11 100644 --- a/yarn-project/noir-contracts/package.local.json +++ b/yarn-project/noir-contracts/package.local.json @@ -1,7 +1,7 @@ { "scripts": { "build": "yarn clean && yarn build:contracts && tsc -b", - "build:contracts": "./scripts/compile.sh && ./scripts/generate-types.sh", + "build:contracts": "./scripts/compile.sh && ./scripts/transpile.sh && ./scripts/generate-types.sh", "clean": "rm -rf ./dest .tsbuildinfo ./src ./target" } } diff --git a/yarn-project/noir-contracts/scripts/transpile.sh b/yarn-project/noir-contracts/scripts/transpile.sh new file mode 100755 index 00000000000..c330ee0f654 --- /dev/null +++ b/yarn-project/noir-contracts/scripts/transpile.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail + +echo "Transpiling contracts..." +for contract_json in target/avm_test_*.json; do + echo Transpiling $contract_json... + ../../avm-transpiler/target/release/avm-transpiler $contract_json $contract_json +done \ No newline at end of file diff --git a/yarn-project/yarn-project-base/Dockerfile b/yarn-project/yarn-project-base/Dockerfile index b373d429178..fb2b49237e6 100644 --- a/yarn-project/yarn-project-base/Dockerfile +++ b/yarn-project/yarn-project-base/Dockerfile @@ -47,6 +47,7 @@ FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/bb.js as bb.js FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/noir as noir FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/noir-packages as noir-packages FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/boxes-files as boxes-files +FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/avm-transpiler as transpiler FROM node:18.19.0 RUN apt update && apt install -y jq curl perl && rm -rf /var/lib/apt/lists/* && apt-get clean @@ -61,6 +62,8 @@ COPY --from=noir /usr/src/noir/target/release/nargo /usr/src/noir/target/release COPY --from=noir-packages /usr/src/noir/packages /usr/src/noir/packages # Copy in boxes COPY --from=boxes-files /usr/src/boxes /usr/src/boxes +# Copy in transpiler +COPY --from=transpiler /usr/src/avm-transpiler/target/release/avm-transpiler /usr/src/avm-transpiler/target/release/avm-transpiler # We install a symlink to yarn-project's node_modules at a location that all portalled packages can find as they # walk up the tree as part of module resolution. The supposedly idiomatic way of supporting module resolution From aeb4cf0d9cec6127cac947c4f0de8e853b2f34e0 Mon Sep 17 00:00:00 2001 From: ludamad Date: Wed, 31 Jan 2024 14:37:41 -0500 Subject: [PATCH 20/20] fix: mac build (#4336) --- .../src/barretenberg/ecc/fields/field_conversion.hpp | 2 +- .../barretenberg/ecc/fields/field_conversion.test.cpp | 11 +---------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.hpp b/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.hpp index c2298236512..cf5b12d1def 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.hpp @@ -208,4 +208,4 @@ template std::vector inline convert_to_bn254_frs(co return fr_vec; } -} // namespace bb::field_conversion \ No newline at end of file +} // namespace bb::field_conversion diff --git a/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.test.cpp b/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.test.cpp index d54ca02ba4b..0a024f82545 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.test.cpp @@ -15,15 +15,6 @@ class FieldConversionTest : public ::testing::Test { } }; -/** - * @brief Field conversion test for size_t - */ -TEST_F(FieldConversionTest, FieldConversionSizeT) -{ - size_t x = 210849; - check_conversion(x); -} - /** * @brief Field conversion test for uint32_t */ @@ -140,4 +131,4 @@ TEST_F(FieldConversionTest, FieldConversionUnivariateGrumpkinFr) check_conversion(x1); } -} // namespace bb::field_conversion_tests \ No newline at end of file +} // namespace bb::field_conversion_tests