From ad3da14eb715c1ec4a1e3b5ffc3d792eb738e404 Mon Sep 17 00:00:00 2001 From: Gregorio Juliana Date: Wed, 10 Jul 2024 14:27:01 +0200 Subject: [PATCH 01/32] fix: updated docs (#7418) Slightly uglier docker command working around the way our `aztecprotocol/aztec` image is built --- docs/docs/guides/smart_contracts/testing_contracts/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/guides/smart_contracts/testing_contracts/index.md b/docs/docs/guides/smart_contracts/testing_contracts/index.md index 4dd515a9c065..1a4e5d5f0fc4 100644 --- a/docs/docs/guides/smart_contracts/testing_contracts/index.md +++ b/docs/docs/guides/smart_contracts/testing_contracts/index.md @@ -39,14 +39,14 @@ In order to use the TXE, it must be running on a known address. :::tip If you have [the sandbox](../../../getting_started.md) installed, you can quickly deploy a TXE by running: -`docker run --workdir /usr/src/yarn-project/txe/dest/bin --entrypoint node --name txe -p 8080:8080 aztecprotocol/aztec index.js` +`docker run --workdir /usr/src/yarn-project --entrypoint bash --name txe -p 8080:8080 --rm -it aztecprotocol/aztec -c "yarn workspaces focus @aztec/txe && cd txe && yarn build && yarn start"` This will be improved in the future with a dedicated command. ::: By default, TXE runs at `http://localhost:8080`. Using `aztec-nargo`, contract tests can be run with: -`aztec-nargo test --oracle-resolver http://host.docker.internal:8080` +`aztec-nargo test --use-legacy --silence-warnings --oracle-resolver http://host.docker.internal:8080` :::warning Since TXE tests are written in Noir and executed with `aztec-nargo`, they all run in parallel. This also means every test creates their own isolated environment, so state modifications are local to each one of them. From 60cead28dbdc397e80dfa14e180d01e53c202f15 Mon Sep 17 00:00:00 2001 From: josh crites Date: Wed, 10 Jul 2024 14:42:08 +0200 Subject: [PATCH 02/32] chore(docs): Cleanup voting tutorial and deployment guide (#7406) The voting tutorial code was recently updated, this PR updates the text. It also updates some of the deployment docs to reference source code instead of using hardcoded blocks. --- .../smart_contracts/how_to_deploy_contract.md | 59 +++++-------------- .../writing_contracts/storage/notes.md | 33 ++++++----- .../private_voting_contract.md | 30 +++++----- .../contract_tutorials/token_contract.md | 4 +- .../simple_dapp/2_contract_deployment.md | 7 +-- .../aztec.js/src/contract/deploy_method.ts | 3 +- .../src/composed/docs_examples.test.ts | 4 +- 7 files changed, 55 insertions(+), 85 deletions(-) diff --git a/docs/docs/guides/smart_contracts/how_to_deploy_contract.md b/docs/docs/guides/smart_contracts/how_to_deploy_contract.md index 96ac3ffd337f..710bd8cc40ad 100644 --- a/docs/docs/guides/smart_contracts/how_to_deploy_contract.md +++ b/docs/docs/guides/smart_contracts/how_to_deploy_contract.md @@ -26,72 +26,43 @@ aztec-nargo compile Generate the typescript class: ```bash -aztec-builder ./aztec-nargo/output/target/path -o src/artifacts +aztec-builder codegen ./aztec-nargo/output/target/path -o src/artifacts ``` This would create a typescript file like `Example.ts` in `./src/artifacts`. Read more on the [compiling page](how_to_compile_contract.md). -Now you can import it to easily deploy and interact with the contract. +You can use the `Contract` class to deploy a contract: -```ts -import { ExampleContract } from "./target/Example.js"; - -const tx = ExampleContract.deploy(pxe).send(); -await tx.wait({ interval: 0.5 }); -const receipt = await tx.getReceipt(); -const exampleContract = await ExampleContract.at( - receipt.contractAddress!, - myWallet -); -``` +#include_code dapp-deploy yarn-project/end-to-end/src/sample-dapp/deploy.mjs typescript + +Or you can use the generated contract class. See [below](#deploying-token-contract) for more details. ### Deploy Arguments There are several optional arguments that can be passed: The `deploy(...)` method is generated automatically with the typescript class representing your contract. -Its arguments are `PXE` client and contract constructor arguments. Additionally the `.send()` method can have a few optional arguments too, which are specified in an optional object: -- `contractAddressSalt?: Fr`: A salt which is one of the inputs when computing a contract address of the contract to be deployed. - By default is set to a random value. - Set it, if you need a deterministic contract address (same functionality as Ethereum's `CREATE2` opcode). - -```ts -const tx = ExampleContract.deploy(pxe).send({ - contractAddressSalt: new Fr(3n), -}); -``` +#include_code deploy_options yarn-project/aztec.js/src/contract/deploy_method.ts typescript ### Deploying token contract To give you a more complete example we will deploy a `Token` contract whose artifacts are included in the `@aztec/noir-contracts.js` package. -The contract has `admin` as a constructor argument. -We will deploy the contract and pass the `admin` address as an argument. - ```ts -const admin = AztecAddress.from( - "0x147392a39e593189902458f4303bc6e0a39128c5a1c1612f76527a162d36d529" -); -// TokenContract is the TS interface that is automatically generated when compiling the contract with the `-ts` flag. -const contract = await TokenContract.deploy(wallet, admin).send().deployed(); -logger(`Contract deployed at ${contract.address}`); -``` - -If everything went as expected you should see the following output (with a different address): +#include_code create_account_imports yarn-project/end-to-end/src/composed/docs_examples.test.ts raw +#include_code import_contract yarn-project/end-to-end/src/composed/docs_examples.test.ts raw +#include_code import_token_contract yarn-project/end-to-end/src/composed/docs_examples.test.ts raw -> Contract deployed at `0x151de6120ae6628129ee852c5fc7bcbc8531055f76d4347cdc86003bbea96906` +async function main(){ -If we pass the salt as an argument: + #include_code full_deploy yarn-project/end-to-end/src/composed/docs_examples.test.ts raw -```ts -const contract = await TokenContract.deploy(wallet, admin) - .send({ contractAddressSalt: Fr.fromString("0x123") }) - .deployed(); +} ``` -the resulting address will be deterministic. - -> **NOTE**: You can try running the deployment with the same salt the second time in which case the transaction will fail because the address has been already deployed to. +:::note +You can try running the deployment with the same salt the second time in which case the transaction will fail because the address has been already deployed to. +::: diff --git a/docs/docs/guides/smart_contracts/writing_contracts/storage/notes.md b/docs/docs/guides/smart_contracts/writing_contracts/storage/notes.md index b3dc19621d23..0a08f39705e1 100644 --- a/docs/docs/guides/smart_contracts/writing_contracts/storage/notes.md +++ b/docs/docs/guides/smart_contracts/writing_contracts/storage/notes.md @@ -41,34 +41,34 @@ The address of the contract is included in a Note's data to ensure that differen ### Note types -There is more than one Note type, such as the `Set` type is used for private variables. There are also `Singleton` and `ImmutableSingleton` types. +There is more than one Note type, such as the `PrivateSet` type is used for private variables. There are also `PrivateMutable` and `PrivateImmutable` types. Furthermore, notes can be completely custom types, storing any value or set of values that are desired by an application. ### Initialization Private state variables are stored locally when the contract is created. Depending on the application, values may be privately shared by the creator with others via encrypted logs onchain. -A hash of a note is stored in the append-only note hash tree so as to prove existence of the current state of the note in a privacy preserving way. +A hash of a note is stored in the append-only note hash tree on the network so as to prove existence of the current state of the note in a privacy preserving way. #### Note Hash Tree -By virtue of being append only, notes are not edited. If two transactions amend a private value, multiple notes will be inserted into the tree. The header will contain the same logical storage slot. +By virtue of being append only, notes are not edited. If two transactions amend a private value, multiple notes will be inserted into the tree (to the note hash tree and the [nullifier tree](../../../../protocol-specs/state/nullifier-tree.md)). The header will contain the same logical storage slot. ### Reading Notes :::info -- Only those with appropriate keys/information will be able to successfully read private values that they have permission to -- Notes can be read outside of a transaction or "off-chain" with no changes to data structures on-chain - ::: +Only those with appropriate keys/information will be able to successfully read private values that they have permission to. Notes can be read outside of a transaction or "off-chain" with no changes to data structures on-chain. -When a note is read in a transaction, a subsequent read from another transaction of the same note would reveal a link between the two. So to preserve privacy, notes that are read in a transaction are said to be "consumed" (defined below), and new note(s) are then created with a unique hash (includes transaction identifier). +::: + +When a note is read in a transaction, a subsequent read from another transaction of the same note would reveal a link between the two. So to preserve privacy, notes that are read in a transaction are said to be "consumed" (defined below), and new note(s) are then created with a unique hash. -With type `Set`, a private variable's value is interpreted as the sum of values of notes with the same logical storage slot. +With type `PrviateSet`, a private variable's value is interpreted as the sum of values of notes with the same logical storage slot. -Consuming, deleting, or otherwise "nullifying" a note is NOT done by deleting the Note hash, this would leak information, but rather by creating a nullifier deterministically linked to the value. This nullifier is inserted into another storage tree, aptly named the nullifier tree. +Consuming, deleting, or otherwise "nullifying" a note is NOT done by deleting the Note hash; this would leak information. Rather a nullifier is created deterministically linked to the value. This nullifier is inserted into another the nullifier storage tree. -When interpreting a value, the local private execution checks that its notes (of the corresponding storage slot/ID) have not been nullified. +When reading a value, the local private execution checks that its notes (of the corresponding storage slot/ID) have not been nullified. ### Updating @@ -76,7 +76,7 @@ When interpreting a value, the local private execution checks that its notes (of Only those with appropriate keys/information will be able to successfully nullify a value that they have permission to. ::: -To update a value, its previous note hash(es) are nullified. The new note value is updated in the PXE, and the updated note hash inserted into the note hash tree. +To update a value, its previous note hash(es) are nullified. The new note value is updated in the user's private execution environment (PXE), and the updated note hash inserted into the note hash tree. ## Supplementary components @@ -88,15 +88,16 @@ Some optional background resources on notes can be found here: Notes touch several core components of the protocol, but we will focus on a the essentials first. -#### Some code context +### Some code context The way Aztec benefits from the Noir language is via three important components: -- `Aztec-nr` - a Noir framework enabling contracts on Aztec, written in Noir. Includes useful Note implementations +- `Aztec.nr` - a Noir framework enabling contracts on Aztec, written in Noir. Includes useful Note implementations - `noir contracts` - example Aztec contracts - `noir-protocol-circuits` - a crate containing essential circuits for the protocol (public circuits and private wrappers) A lot of what we will look at will be in [aztec-nr/aztec/src/note](https://github.com/AztecProtocol/aztec-packages/tree/#include_aztec_version/noir-projects/aztec-nr/aztec/src/note), specifically the lifecycle and note interface. + Looking at the noir circuits in these components, you will see references to the distinction between public/private execution and state. ### Lifecycle functions @@ -129,12 +130,12 @@ For example in ValueNote, the `serialize_content` function simply returns: the v ### Value as a sum of Notes We recall that multiple notes are associated with a "slot" (or ID), and so the value of a numerical note (like ValueNote) is the sum of each note's value. -The helper function in [balance_utils](https://github.com/AztecProtocol/aztec-packages/blob/#include_/noir-projects/aztec-nr/value-note/src/balance_utils.nr) implements this logic taking a `Set` of `ValueNotes`. +The helper function in [balance_utils](https://github.com/AztecProtocol/aztec-packages/blob/#include_/noir-projects/aztec-nr/value-note/src/balance_utils.nr) implements this logic taking a `PrivateSet` of `ValueNotes`. A couple of things worth clarifying: -- A `Set` takes a Generic type, specified here as `ValueNote`, but can be any `Note` type (for all notes in the set) -- A `Set` of notes also specifies _the_ slot of all Notes that it holds +- A `PrivateSet` takes a Generic type, specified here as `ValueNote`, but can be any `Note` type (for all notes in the set) +- A `PrivateSet` of notes also specifies _the_ slot of all Notes that it holds ### Example - Notes in action diff --git a/docs/docs/tutorials/contract_tutorials/private_voting_contract.md b/docs/docs/tutorials/contract_tutorials/private_voting_contract.md index 16606e5c5082..667720f466ff 100644 --- a/docs/docs/tutorials/contract_tutorials/private_voting_contract.md +++ b/docs/docs/tutorials/contract_tutorials/private_voting_contract.md @@ -56,7 +56,7 @@ aztec = { git="https://github.com/AztecProtocol/aztec-packages", tag="#include_a Go to `main.nr` and delete the sample code. Replace it with this contract initialization: ```rust -contract Voting { +contract EasyPrivateVoting { } ``` @@ -69,11 +69,12 @@ Inside this, paste these imports: We are using various utils within the Aztec library: -- `Context` and `PrivateContext` - exposes things such as the contract address, msg_sender, etc +- `PrivateContext` - exposes things such as the contract address, msg_sender, etc - `AztecAddress` - A type for storing an address on Aztec - `FunctionSelector` - Used for computing a selector to call a function - `Map` - A data storage type for storing candidates with the number of votes they have - `PublicMutable` - A type of storage, which holds a mutable public value. We'll store votes as PublicMutables +- `SharedImmutable` - an immutable storage value that is accessible in private and public execution. ## Set up storage @@ -84,9 +85,10 @@ Define the storage struct like so: In this contract, we will store three vars: -1. admin, as an Aztec address held in public state -2. tally, as a map with key as the persona and value as the number (in Field) held in public state -3. vote_ended, as a boolean held in public state +1. `admin`, as an Aztec address held in public state +2. `tally`, as a map with key as the persona and value as the number (in Field) held in public state +3. `vote_ended`, as a boolean held in public state +4. `active_at_block` specifies which block people can start voting. This variable specifies the block at which people must use their nullifier secret key to vote. Because nullifier keys are rotatable, if this is not included the same account would be able to vote more than once. ## Constructor @@ -112,7 +114,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](../../aztec/concepts/accounts/keys.md#nullifier-secrets). -To do this, we make an [oracle call](../../aztec/concepts/smart_contracts/oracles/index.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. +To do this, we make an [oracle call](../../aztec/concepts/smart_contracts/oracles/index.md) to fetch the caller's secret key, hash it to create a nullifier, and push the nullifier to Aztec. 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. @@ -124,10 +126,10 @@ The first thing we do here is assert that the vote has not ended. `assert()` takes two arguments: the assertion, in this case that `storage.vote_ended` is not false, and the error thrown if the assertion fails. -The code after the assertion will only run if the assertion is true. In this snippet, we read the current vote tally at the voteId, add 1 to it, and write this new number to the voteId. The `Field` element allows us to use `+` to add to an integer. +The code after the assertion will only run if the assertion is true. In this snippet, we read the current vote tally at the `candidate`, add 1 to it, and write this new number to the `candidate`. The `Field` element allows us to use `+` to add to an integer. -:::danger -Note that due to [key rotation](../../aztec/concepts/accounts/keys.md#key-rotation), it would be possible for a user to rotate their nullifier secret key and be able to vote again. Refer to [common patterns](../../guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md) for more information +:::warning +Refer to [common patterns](../../guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md) for more information about key rotation and considerations. ::: ## Getting the number of votes @@ -140,13 +142,13 @@ We set it as `unconstrained` and do not annotate it because it is only reading f ## Allowing an admin to end a voting period -To ensure that only an admin can end a voting period, we can use another `assert()` statement. +To ensure that only an `admin` can end a voting period, we can use another `assert()` statement. Paste this function in your contract: #include_code end_vote noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr rust -Here, we are asserting that the `msg_sender()` is equal to the admin stored in public state. We have to create an `AztecAddress` type from the `msg_sender()` in order to do a direct comparison. +Here, we are asserting that the `msg_sender()` is equal to the `admin` stored in public state. ## Compiling and deploying @@ -158,13 +160,13 @@ aztec-nargo compile This will create a new directory called `target` and a JSON artifact inside it. -Once it is compiled you can [deploy](../../reference/sandbox_reference/index.md). +Use the `aztec-builder` to generate the Typescript artifact for the contract: ```bash -aztec-builder target -o src/artifacts +aztec-builder codegen target --outdir src/artifacts ``` -Once it is compiled you can [deploy](../../guides/smart_contracts/how_to_deploy_contract.md) it to the sandbox just like you did in the [counter contract tutorial](./counter_contract.md). +Once it is compiled you can [deploy](../../guides/smart_contracts/how_to_deploy_contract.md) it to the sandbox. ## Next steps diff --git a/docs/docs/tutorials/contract_tutorials/token_contract.md b/docs/docs/tutorials/contract_tutorials/token_contract.md index b51fe9daa7d5..ef83e6514e3e 100644 --- a/docs/docs/tutorials/contract_tutorials/token_contract.md +++ b/docs/docs/tutorials/contract_tutorials/token_contract.md @@ -487,9 +487,7 @@ aztec-builder target -o src/artifacts ### Testing -Review the end to end tests for reference: - -https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/end-to-end/src/e2e_token_contract/*.test.ts +Review [the end to end tests](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/end-to-end/src/e2e_token_contract/) for reference. ### Token Bridge Contract diff --git a/docs/docs/tutorials/simple_dapp/2_contract_deployment.md b/docs/docs/tutorials/simple_dapp/2_contract_deployment.md index 945d1fc74ebd..34d56026835f 100644 --- a/docs/docs/tutorials/simple_dapp/2_contract_deployment.md +++ b/docs/docs/tutorials/simple_dapp/2_contract_deployment.md @@ -69,12 +69,7 @@ We import the contract artifacts we have generated plus the dependencies we'll n Note that the token's `_initialize()` method expects an `owner` address to mint an initial set of tokens to. We are using the first account from the Sandbox for this. :::info -If you are using the generated typescript classes, you can drop the generic `ContractDeployer` in favor of using the `deploy` method of the generated class, which will automatically load the artifact for you and type-check the constructor arguments: - -```typescript -await Token.deploy(client).send().wait(); -``` - +If you are using the generated typescript classes, you can drop the generic `ContractDeployer` in favor of using the `deploy` method of the generated class, which will automatically load the artifact for you and type-check the constructor arguments. SEe the [How to deploy a contract](../../guides/smart_contracts/how_to_deploy_contract.md) page for more info. ::: Run the snippet above as `node src/deploy.mjs`, and you should see the following output, along with a new `addresses.json` file in your project root: diff --git a/yarn-project/aztec.js/src/contract/deploy_method.ts b/yarn-project/aztec.js/src/contract/deploy_method.ts index c572d526f446..4823ac28210b 100644 --- a/yarn-project/aztec.js/src/contract/deploy_method.ts +++ b/yarn-project/aztec.js/src/contract/deploy_method.ts @@ -23,6 +23,7 @@ import { DeploySentTx } from './deploy_sent_tx.js'; * Options for deploying a contract on the Aztec network. * Allows specifying a contract address salt, and additional send method options. */ +// docs:start:deploy_options export type DeployOptions = { /** An optional salt value used to deterministically calculate the contract address. */ contractAddressSalt?: Fr; @@ -35,7 +36,7 @@ export type DeployOptions = { /** Skip contract initialization. */ skipInitialization?: boolean; } & SendMethodOptions; - +// docs:end:deploy_options // TODO(@spalladino): Add unit tests for this class! /** diff --git a/yarn-project/end-to-end/src/composed/docs_examples.test.ts b/yarn-project/end-to-end/src/composed/docs_examples.test.ts index e764a048fa69..129717f85049 100644 --- a/yarn-project/end-to-end/src/composed/docs_examples.test.ts +++ b/yarn-project/end-to-end/src/composed/docs_examples.test.ts @@ -12,6 +12,7 @@ import { TokenContract, TokenContractArtifact } from '@aztec/noir-contracts.js/T describe('docs_examples', () => { it('deploys and interacts with a token contract', async () => { + // docs:start:full_deploy // docs:start:define_account_vars const PXE_URL = process.env.PXE_URL || 'http://localhost:8080'; const secretKey = Fr.random(); @@ -30,7 +31,7 @@ describe('docs_examples', () => { 'TokenName', // constructor arg1 'TokenSymbol', // constructor arg2 18, - ) // constructor arg3 + ) .send() .deployed(); // docs:end:deploy_contract @@ -38,6 +39,7 @@ describe('docs_examples', () => { // docs:start:get_contract const contract = await Contract.at(deployedContract.address, TokenContractArtifact, wallet); // docs:end:get_contract + // docs:end:full_deploy // docs:start:send_transaction const _tx = await contract.methods.mint_public(wallet.getAddress(), 1).send().wait(); From 4355b3f3084696c54f6cd44aed7baf6f4caa925d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Rodr=C3=ADguez?= Date: Wed, 10 Jul 2024 14:54:33 +0200 Subject: [PATCH 03/32] feat: Optimize assert_split_sorted_transformed_value_arrays (#7417) --- ...t_split_sorted_transformed_value_arrays.nr | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr index 6ca1ec6186fd..94e1871ab3f5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr @@ -29,20 +29,26 @@ fn assert_split_sorted_transformed_value_arrays( let value = transformed_value_array[i]; let sorted_index = index_hints[i]; let is_lt = original.counter() < split_counter; - let mut sorted_array = sorted_transformed_value_array_gte; - let mut sorted_counters = sorted_counters_gte; - let mut num = num_gte; - if is_lt { - sorted_array = sorted_transformed_value_array_lt; - sorted_counters = sorted_counters_lt; - num = num_lt; + let (sorted_value, sorted_counter, num) = if is_lt { + ( + sorted_transformed_value_array_lt[sorted_index], sorted_counters_lt[sorted_index], num_lt + ) + } else { + ( + sorted_transformed_value_array_gte[sorted_index], sorted_counters_gte[sorted_index], num_gte + ) }; - assert_eq(value, sorted_array[sorted_index], "mismatch sorted values"); - assert_eq(original.counter(), sorted_counters[sorted_index], "mismatch counters"); + assert_eq(value, sorted_value, "mismatch sorted values"); + assert_eq(original.counter(), sorted_counter, "mismatch counters"); if num != 0 { - let is_incrementing = sorted_counters[num] > sorted_counters[num - 1]; + let (counter, prev_counter) = if is_lt { + (sorted_counters_lt[num], sorted_counters_lt[num - 1]) + } else { + (sorted_counters_gte[num], sorted_counters_gte[num - 1]) + }; + let is_incrementing = counter > prev_counter; assert(ascending == is_incrementing, "value array must be sorted by counter"); - assert(sorted_counters[num] != sorted_counters[num - 1], "counters must not be the same"); + assert(counter != prev_counter, "counters must not be the same"); } if is_lt { num_lt += 1; From d3ee63c2953ce49869a213afbf7aed1e59b499b7 Mon Sep 17 00:00:00 2001 From: Aztec Bot <49558828+AztecBot@users.noreply.github.com> Date: Wed, 10 Jul 2024 09:32:09 -0400 Subject: [PATCH 04/32] chore(master): Release 0.46.2 (#7420) :robot: I have created a release *beep* *boop* ---
aztec-package: 0.46.2 ## [0.46.2](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.46.1...aztec-package-v0.46.2) (2024-07-10) ### Miscellaneous * **aztec-package:** Synchronize aztec-packages versions
barretenberg.js: 0.46.2 ## [0.46.2](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.46.1...barretenberg.js-v0.46.2) (2024-07-10) ### Miscellaneous * **barretenberg.js:** Synchronize aztec-packages versions
aztec-packages: 0.46.2 ## [0.46.2](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.46.1...aztec-packages-v0.46.2) (2024-07-10) ### Features * Optimize assert_split_sorted_transformed_value_arrays ([#7417](https://github.com/AztecProtocol/aztec-packages/issues/7417)) ([4355b3f](https://github.com/AztecProtocol/aztec-packages/commit/4355b3f3084696c54f6cd44aed7baf6f4caa925d)) ### Bug Fixes * Updated docs ([#7418](https://github.com/AztecProtocol/aztec-packages/issues/7418)) ([ad3da14](https://github.com/AztecProtocol/aztec-packages/commit/ad3da14eb715c1ec4a1e3b5ffc3d792eb738e404)) ### Miscellaneous * **docs:** Cleanup voting tutorial and deployment guide ([#7406](https://github.com/AztecProtocol/aztec-packages/issues/7406)) ([60cead2](https://github.com/AztecProtocol/aztec-packages/commit/60cead28dbdc397e80dfa14e180d01e53c202f15))
barretenberg: 0.46.2 ## [0.46.2](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.46.1...barretenberg-v0.46.2) (2024-07-10) ### Miscellaneous * **barretenberg:** Synchronize aztec-packages versions
--- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- .release-please-manifest.json | 8 ++++---- CHANGELOG.md | 17 +++++++++++++++++ barretenberg/CHANGELOG.md | 7 +++++++ barretenberg/cpp/CMakeLists.txt | 2 +- barretenberg/ts/CHANGELOG.md | 7 +++++++ barretenberg/ts/package.json | 2 +- yarn-project/aztec/CHANGELOG.md | 7 +++++++ yarn-project/aztec/package.json | 2 +- 8 files changed, 45 insertions(+), 7 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ea56b558e34b..40a6a4104df1 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,7 +1,7 @@ { - ".": "0.46.1", + ".": "0.46.2", "yarn-project/cli": "0.35.1", - "yarn-project/aztec": "0.46.1", - "barretenberg": "0.46.1", - "barretenberg/ts": "0.46.1" + "yarn-project/aztec": "0.46.2", + "barretenberg": "0.46.2", + "barretenberg/ts": "0.46.2" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 91d4db49bd1c..2fbe4d178fd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [0.46.2](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.46.1...aztec-packages-v0.46.2) (2024-07-10) + + +### Features + +* Optimize assert_split_sorted_transformed_value_arrays ([#7417](https://github.com/AztecProtocol/aztec-packages/issues/7417)) ([4355b3f](https://github.com/AztecProtocol/aztec-packages/commit/4355b3f3084696c54f6cd44aed7baf6f4caa925d)) + + +### Bug Fixes + +* Updated docs ([#7418](https://github.com/AztecProtocol/aztec-packages/issues/7418)) ([ad3da14](https://github.com/AztecProtocol/aztec-packages/commit/ad3da14eb715c1ec4a1e3b5ffc3d792eb738e404)) + + +### Miscellaneous + +* **docs:** Cleanup voting tutorial and deployment guide ([#7406](https://github.com/AztecProtocol/aztec-packages/issues/7406)) ([60cead2](https://github.com/AztecProtocol/aztec-packages/commit/60cead28dbdc397e80dfa14e180d01e53c202f15)) + ## [0.46.1](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.46.0...aztec-packages-v0.46.1) (2024-07-10) diff --git a/barretenberg/CHANGELOG.md b/barretenberg/CHANGELOG.md index c2f2cbe84ab4..2c69bb01e868 100644 --- a/barretenberg/CHANGELOG.md +++ b/barretenberg/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.46.2](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.46.1...barretenberg-v0.46.2) (2024-07-10) + + +### Miscellaneous + +* **barretenberg:** Synchronize aztec-packages versions + ## [0.46.1](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.46.0...barretenberg-v0.46.1) (2024-07-10) diff --git a/barretenberg/cpp/CMakeLists.txt b/barretenberg/cpp/CMakeLists.txt index 3d3c26f11437..23c621aa2d8a 100644 --- a/barretenberg/cpp/CMakeLists.txt +++ b/barretenberg/cpp/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.24 FATAL_ERROR) project( Barretenberg DESCRIPTION "BN254 elliptic curve library, and PLONK SNARK prover" - VERSION 0.46.1 # x-release-please-version + VERSION 0.46.2 # x-release-please-version LANGUAGES CXX C ) # Insert version into `bb` config file diff --git a/barretenberg/ts/CHANGELOG.md b/barretenberg/ts/CHANGELOG.md index 6b48a6dfd0c1..fa618342a086 100644 --- a/barretenberg/ts/CHANGELOG.md +++ b/barretenberg/ts/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.46.2](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.46.1...barretenberg.js-v0.46.2) (2024-07-10) + + +### Miscellaneous + +* **barretenberg.js:** Synchronize aztec-packages versions + ## [0.46.1](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.46.0...barretenberg.js-v0.46.1) (2024-07-10) diff --git a/barretenberg/ts/package.json b/barretenberg/ts/package.json index b3c381a66fa9..822a88c4093c 100644 --- a/barretenberg/ts/package.json +++ b/barretenberg/ts/package.json @@ -1,6 +1,6 @@ { "name": "@aztec/bb.js", - "version": "0.46.1", + "version": "0.46.2", "homepage": "https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg/ts", "license": "MIT", "type": "module", diff --git a/yarn-project/aztec/CHANGELOG.md b/yarn-project/aztec/CHANGELOG.md index 9a25a45a3868..bdacecd0833a 100644 --- a/yarn-project/aztec/CHANGELOG.md +++ b/yarn-project/aztec/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.46.2](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.46.1...aztec-package-v0.46.2) (2024-07-10) + + +### Miscellaneous + +* **aztec-package:** Synchronize aztec-packages versions + ## [0.46.1](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.46.0...aztec-package-v0.46.1) (2024-07-10) diff --git a/yarn-project/aztec/package.json b/yarn-project/aztec/package.json index 2c08cd65b1e0..38418f3faf5c 100644 --- a/yarn-project/aztec/package.json +++ b/yarn-project/aztec/package.json @@ -1,6 +1,6 @@ { "name": "@aztec/aztec", - "version": "0.46.1", + "version": "0.46.2", "type": "module", "exports": { ".": "./dest/index.js" From db960772abfead018e4f6da55ae259c6b3d574ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Wed, 10 Jul 2024 15:50:14 +0200 Subject: [PATCH 05/32] feat: typing return values of embedded_curve_ops (#7413) --- .../aztec/src/keys/point_to_symmetric_key.nr | 4 ++-- .../contracts/avm_test_contract/src/main.nr | 2 +- .../src/types/token_note.nr | 19 +++--------------- .../noir_stdlib/src/embedded_curve_ops.nr | 20 +++++++++---------- noir/noir-repo/noir_stdlib/src/hash/mod.nr | 5 ++--- .../embedded_curve_ops/src/main.nr | 6 +++--- .../regression_5045/src/main.nr | 2 +- .../execution_success/schnorr/src/main.nr | 8 ++++---- .../simple_shield/src/main.nr | 7 +++---- .../embedded_curve_ops/src/main.nr | 10 +++++----- 10 files changed, 34 insertions(+), 49 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr b/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr index 6515b2bca382..caa3173443fe 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr @@ -7,9 +7,9 @@ use std::{hash::sha256, embedded_curve_ops::multi_scalar_mul}; // TODO(#5726): This function is called deriveAESSecret in TS. I don't like point_to_symmetric_key name much since // point is not the only input of the function. Unify naming with TS once we have a better name. pub fn point_to_symmetric_key(secret: Scalar, point: Point) -> [u8; 32] { - let shared_secret_fields = multi_scalar_mul([point], [secret]); + let shared_secret: Point = multi_scalar_mul([point], [secret]); // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6061): make the func return Point struct directly - let shared_secret = pub_key_to_bytes(Point::new(shared_secret_fields[0], shared_secret_fields[1], false)); + let shared_secret = pub_key_to_bytes(shared_secret); let mut shared_secret_bytes_with_separator = [0 as u8; 65]; shared_secret_bytes_with_separator = arr_copy_slice(shared_secret, shared_secret_bytes_with_separator, 0); shared_secret_bytes_with_separator[64] = GENERATOR_INDEX__SYMMETRIC_KEY; diff --git a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr index cb7aef45b53b..eeb04aa75c8d 100644 --- a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr @@ -145,7 +145,7 @@ contract AvmTest { } #[aztec(public)] - fn variable_base_msm() -> [Field; 3] { + fn variable_base_msm() -> Point { let g = Point { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; let scalar = Scalar { lo: 3, hi: 0 }; let scalar2 = Scalar { lo: 20, hi: 0 }; diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr index 0be1dc18f529..30ef7add279a 100644 --- a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr @@ -92,7 +92,7 @@ impl NoteInterface for TokenNote { lo: random_lo, hi: random_hi, }] - )[0] + ).x } } @@ -238,15 +238,7 @@ impl PrivatelyRefundable for TokenNote { ); // 5. At last we represent the points as Points and return them. - (Point { - x: incomplete_fee_payer_point[0], - y: incomplete_fee_payer_point[1], - is_infinite: incomplete_fee_payer_point[2] == 1 - }, Point { - x: incomplete_user_point[0], - y: incomplete_user_point[1], - is_infinite: incomplete_user_point[2] == 1 - }) + (incomplete_fee_payer_point, incomplete_user_point) } fn complete_refund(incomplete_fee_payer_point: Point, incomplete_user_point: Point, transaction_fee: Field) -> (Field, Field) { @@ -254,18 +246,13 @@ impl PrivatelyRefundable for TokenNote { let (transaction_fee_lo, transaction_fee_hi) = decompose(transaction_fee); // 2. We compute the fee point as `G ^ transaction_fee` - let fee_point_raw = multi_scalar_mul( + let fee_point = multi_scalar_mul( [G1], [Scalar { lo: transaction_fee_lo, hi: transaction_fee_hi, }] ); - let fee_point = Point { - x: fee_point_raw[0], - y: fee_point_raw[1], - is_infinite: fee_point_raw[2] == 1 - }; // 3. Now we leverage homomorphism to privately add the fee to fee payer point and subtract it from // the sponsored user point in public. diff --git a/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr b/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr index c791ac884046..916943b737cd 100644 --- a/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr +++ b/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr @@ -61,8 +61,7 @@ impl EmbeddedCurveScalar { } pub fn derive_public_key(self) -> EmbeddedCurvePoint { - let public_key = fixed_base_scalar_mul(self.lo, self.hi); - EmbeddedCurvePoint { x: public_key[0], y: public_key[1], is_infinite: false } + fixed_base_scalar_mul(self) } #[field(bn254)] @@ -84,24 +83,25 @@ impl Eq for EmbeddedCurveScalar { // // The embedded curve being used is decided by the // underlying proof system. -#[foreign(multi_scalar_mul)] // docs:start:multi_scalar_mul pub fn multi_scalar_mul( points: [EmbeddedCurvePoint; N], scalars: [EmbeddedCurveScalar; N] -) -> [Field; 3] +) -> EmbeddedCurvePoint // docs:end:multi_scalar_mul -{} +{ + let point_array = multi_scalar_mul_array_return(points, scalars); + EmbeddedCurvePoint { x: point_array[0], y: point_array[1], is_infinite: point_array[2] as bool } +} + +#[foreign(multi_scalar_mul)] +fn multi_scalar_mul_array_return(points: [EmbeddedCurvePoint; N], scalars: [EmbeddedCurveScalar; N]) -> [Field; 3] {} // docs:start:fixed_base_scalar_mul -pub fn fixed_base_scalar_mul( - scalar_low: Field, - scalar_high: Field -) -> [Field; 3] +pub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint // docs:end:fixed_base_scalar_mul { let g1 = EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; - let scalar = EmbeddedCurveScalar { lo: scalar_low, hi: scalar_high }; multi_scalar_mul([g1], [scalar]) } diff --git a/noir/noir-repo/noir_stdlib/src/hash/mod.nr b/noir/noir-repo/noir_stdlib/src/hash/mod.nr index 65f3b9419ffe..dc82ff08efed 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/mod.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/mod.nr @@ -43,8 +43,7 @@ fn pedersen_commitment_with_separator_noir(input: [Field; N], separa points[i] = EmbeddedCurveScalar::from_field(input[i]); } let generators = derive_generators("DEFAULT_DOMAIN_SEPARATOR".as_bytes(), separator); - let values = multi_scalar_mul(generators, points); - EmbeddedCurvePoint { x: values[0], y: values[1], is_infinite: values[2] as bool } + multi_scalar_mul(generators, points) } #[no_predicates] @@ -80,7 +79,7 @@ fn pedersen_hash_with_separator_noir(input: [Field; N], separator: u multi_scalar_mul( [length_generator[0], v1], [EmbeddedCurveScalar { lo: N as Field, hi: 0 }, EmbeddedCurveScalar { lo: 1, hi: 0 }] - )[0] + ).x } #[foreign(pedersen_hash)] diff --git a/noir/noir-repo/test_programs/execution_success/embedded_curve_ops/src/main.nr b/noir/noir-repo/test_programs/execution_success/embedded_curve_ops/src/main.nr index 4eeda39c6aa4..5372f73df23d 100644 --- a/noir/noir-repo/test_programs/execution_success/embedded_curve_ops/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/embedded_curve_ops/src/main.nr @@ -4,8 +4,8 @@ fn main(priv_key: Field, pub_x: pub Field, pub_y: pub Field) { let scalar = std::embedded_curve_ops::EmbeddedCurveScalar { lo: priv_key, hi: 0 }; // Test that multi_scalar_mul correctly derives the public key let res = std::embedded_curve_ops::multi_scalar_mul([g1], [scalar]); - assert(res[0] == pub_x); - assert(res[1] == pub_y); + assert(res.x == pub_x); + assert(res.y == pub_y); // Test that double function calling embedded_curve_add works as expected let pub_point = std::embedded_curve_ops::EmbeddedCurvePoint { x: pub_x, y: pub_y, is_infinite: false }; @@ -18,5 +18,5 @@ fn main(priv_key: Field, pub_x: pub Field, pub_y: pub Field) { let res = std::embedded_curve_ops::multi_scalar_mul([g1, g1], [scalar, scalar]); // The results should be double the g1 point because the scalars are 1 and we pass in g1 twice - assert(double.x == res[0]); + assert(double.x == res.x); } diff --git a/noir/noir-repo/test_programs/execution_success/regression_5045/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_5045/src/main.nr index cf39b2f97e4c..d1bc4f663fd9 100644 --- a/noir/noir-repo/test_programs/execution_success/regression_5045/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/regression_5045/src/main.nr @@ -15,6 +15,6 @@ fn main(is_active: bool) { [a, bad], [EmbeddedCurveScalar { lo: 1, hi: 0 }, EmbeddedCurveScalar { lo: 1, hi: 0 }] ); - assert(e[0] != d.x); + assert(e.x != d.x); } } diff --git a/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr b/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr index 5bc0ca9fefbf..cf22fd371d16 100644 --- a/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr @@ -50,7 +50,7 @@ pub fn verify_signature_noir(public_key: embedded_curve_ops::EmbeddedCurvePoi let g1 = embedded_curve_ops::EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; let r = embedded_curve_ops::multi_scalar_mul([g1, public_key], [sig_s, sig_e]); // compare the _hashes_ rather than field elements modulo r - let pedersen_hash = std::hash::pedersen_hash([r[0], public_key.x, public_key.y]); + let pedersen_hash = std::hash::pedersen_hash([r.x, public_key.x, public_key.y]); let mut hash_input = [0; M]; let pde = pedersen_hash.to_be_bytes(32); @@ -62,7 +62,7 @@ pub fn verify_signature_noir(public_key: embedded_curve_ops::EmbeddedCurvePoi } let result = std::hash::blake2s(hash_input); - is_ok = (r[2] == 0); + is_ok = !r.is_infinite; for i in 0..32 { if result[i] != signature[32 + i] { is_ok = false; @@ -101,7 +101,7 @@ pub fn assert_valid_signature(public_key: embedded_curve_ops::EmbeddedCurvePo let g1 = embedded_curve_ops::EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; let r = embedded_curve_ops::multi_scalar_mul([g1, public_key], [sig_s, sig_e]); // compare the _hashes_ rather than field elements modulo r - let pedersen_hash = std::hash::pedersen_hash([r[0], public_key.x, public_key.y]); + let pedersen_hash = std::hash::pedersen_hash([r.x, public_key.x, public_key.y]); let mut hash_input = [0; M]; let pde = pedersen_hash.to_be_bytes(32); @@ -113,7 +113,7 @@ pub fn assert_valid_signature(public_key: embedded_curve_ops::EmbeddedCurvePo } let result = std::hash::blake2s(hash_input); - assert(r[2] == 0); + assert(!r.is_infinite); for i in 0..32 { assert(result[i] == signature[32 + i]); } diff --git a/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr b/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr index d84288b9fd6d..66ac0a2b3132 100644 --- a/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr @@ -10,12 +10,11 @@ fn main( to_pubkey_x: Field, to_pubkey_y: Field ) -> pub [Field; 2] { + let priv_key_as_scalar = std::embedded_curve_ops::EmbeddedCurveScalar::new(priv_key, 0); // Compute public key from private key to show ownership - let pubkey = std::embedded_curve_ops::fixed_base_scalar_mul(priv_key, 0); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; + let pubkey = std::embedded_curve_ops::fixed_base_scalar_mul(priv_key_as_scalar); // Compute input note commitment - let note_commitment = std::hash::pedersen_commitment([pubkey_x, pubkey_y]); + let note_commitment = std::hash::pedersen_commitment([pubkey.x, pubkey.y]); // Compute input note nullifier let nullifier = std::hash::pedersen_commitment([note_commitment.x, index, priv_key]); // Compute output note nullifier diff --git a/noir/noir-repo/test_programs/noir_test_success/embedded_curve_ops/src/main.nr b/noir/noir-repo/test_programs/noir_test_success/embedded_curve_ops/src/main.nr index 225e86397fdd..0c2c333fa620 100644 --- a/noir/noir-repo/test_programs/noir_test_success/embedded_curve_ops/src/main.nr +++ b/noir/noir-repo/test_programs/noir_test_success/embedded_curve_ops/src/main.nr @@ -10,28 +10,28 @@ use std::embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_sca let s1 = EmbeddedCurveScalar { lo: 1, hi: 0 }; let a = multi_scalar_mul([g1], [s1]); - assert(a[2] == 0); + assert(!a.is_infinite); assert(g1 + zero == g1); assert(g1 - g1 == zero); assert(g1 - zero == g1); assert(zero + zero == zero); assert( multi_scalar_mul([g1], [s1]) - == [1, 17631683881184975370165255887551781615748388533673675138860, 0] + == EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false } ); - assert(multi_scalar_mul([g1, g1], [s1, s1]) == [g2.x, g2.y, 0]); + assert(multi_scalar_mul([g1, g1], [s1, s1]) == g2); assert( multi_scalar_mul( [g1, zero], [EmbeddedCurveScalar { lo: 2, hi: 0 }, EmbeddedCurveScalar { lo: 42, hi: 25 }] ) - == [g2.x, g2.y, 0] + == g2 ); assert( multi_scalar_mul( [g1, g1, zero], [s1, s1, EmbeddedCurveScalar { lo: 42, hi: 25 }] ) - == [g2.x, g2.y, 0] + == g2 ); } From 2645eab19bac030835c959eb01f8f3af27f89adf Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Wed, 10 Jul 2024 11:03:58 -0300 Subject: [PATCH 06/32] feat: Remove proof from L1 Rollup process (#7347) Moves the proof verification from `Rollup.process` and into a new `submitProof` method, called separately from the sequencer. Eventually we'll want to move it out of the sequencer completely, but this way we don't break the current e2e flow. See #7346 --- l1-contracts/src/core/Rollup.sol | 63 +++++----- l1-contracts/src/core/interfaces/IRollup.sol | 7 +- l1-contracts/test/Rollup.t.sol | 10 +- yarn-project/accounts/package.local.json | 9 +- .../archiver/src/archiver/archiver.test.ts | 4 +- .../archiver/src/archiver/eth_log_handlers.ts | 2 +- yarn-project/circuit-types/src/stats/stats.ts | 22 +++- .../composed/integration_l1_publisher.test.ts | 22 +--- .../integration_proof_verification.test.ts | 2 +- .../package.local.json | 9 +- .../protocol-contracts/package.local.json | 9 +- .../scripts/src/benchmarks/aggregate.ts | 4 +- .../src/publisher/l1-publisher.test.ts | 31 ++--- .../src/publisher/l1-publisher.ts | 110 ++++++++++++++---- .../src/publisher/viem-tx-sender.ts | 33 +++++- .../src/sequencer/sequencer.test.ts | 10 +- .../src/sequencer/sequencer.ts | 16 ++- .../types/src/abi/contract_artifact.ts | 22 ++-- 18 files changed, 232 insertions(+), 153 deletions(-) diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index 4ef4bc843021..8f407c1bbc4b 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -101,14 +101,8 @@ contract Rollup is IRollup { * @notice Process an incoming L2 block and progress the state * @param _header - The L2 block header * @param _archive - A root of the archive tree after the L2 block is applied - * @param _proof - The proof of correct execution */ - function process( - bytes calldata _header, - bytes32 _archive, - bytes calldata _aggregationObject, - bytes calldata _proof - ) external override(IRollup) { + function process(bytes calldata _header, bytes32 _archive) external override(IRollup) { // Decode and validate header HeaderLib.Header memory header = HeaderLib.decode(_header); HeaderLib.validate(header, VERSION, lastBlockTs, archive); @@ -124,6 +118,38 @@ contract Rollup is IRollup { revert Errors.Rollup__InvalidSequencer(msg.sender); } + archive = _archive; + lastBlockTs = block.timestamp; + + bytes32 inHash = INBOX.consume(); + if (header.contentCommitment.inHash != inHash) { + revert Errors.Rollup__InvalidInHash(inHash, header.contentCommitment.inHash); + } + + // TODO(#7218): Revert to fixed height tree for outbox, currently just providing min as interim + // Min size = smallest path of the rollup tree + 1 + (uint256 min,) = MerkleLib.computeMinMaxPathLength(header.contentCommitment.numTxs); + uint256 l2ToL1TreeMinHeight = min + 1; + OUTBOX.insert( + header.globalVariables.blockNumber, header.contentCommitment.outHash, l2ToL1TreeMinHeight + ); + + // pay the coinbase 1 gas token if it is not empty and header.totalFees is not zero + if (header.globalVariables.coinbase != address(0) && header.totalFees > 0) { + GAS_TOKEN.transfer(address(header.globalVariables.coinbase), header.totalFees); + } + + emit L2BlockProcessed(header.globalVariables.blockNumber); + } + + function submitProof( + bytes calldata _header, + bytes32 _archive, + bytes calldata _aggregationObject, + bytes calldata _proof + ) external override(IRollup) { + HeaderLib.Header memory header = HeaderLib.decode(_header); + bytes32[] memory publicInputs = new bytes32[](3 + Constants.HEADER_LENGTH + Constants.AGGREGATION_OBJECT_LENGTH); // the archive tree root @@ -156,28 +182,7 @@ contract Rollup is IRollup { revert Errors.Rollup__InvalidProof(); } - archive = _archive; - lastBlockTs = block.timestamp; - - bytes32 inHash = INBOX.consume(); - if (header.contentCommitment.inHash != inHash) { - revert Errors.Rollup__InvalidInHash(inHash, header.contentCommitment.inHash); - } - - // TODO(#7218): Revert to fixed height tree for outbox, currently just providing min as interim - // Min size = smallest path of the rollup tree + 1 - (uint256 min,) = MerkleLib.computeMinMaxPathLength(header.contentCommitment.numTxs); - uint256 l2ToL1TreeMinHeight = min + 1; - OUTBOX.insert( - header.globalVariables.blockNumber, header.contentCommitment.outHash, l2ToL1TreeMinHeight - ); - - // pay the coinbase 1 gas token if it is not empty and header.totalFees is not zero - if (header.globalVariables.coinbase != address(0) && header.totalFees > 0) { - GAS_TOKEN.transfer(address(header.globalVariables.coinbase), header.totalFees); - } - - emit L2BlockProcessed(header.globalVariables.blockNumber); + emit L2ProofVerified(header.globalVariables.blockNumber); } function _computePublicInputHash(bytes calldata _header, bytes32 _archive) diff --git a/l1-contracts/src/core/interfaces/IRollup.sol b/l1-contracts/src/core/interfaces/IRollup.sol index a53fb47bcb95..006d5ccb2e4b 100644 --- a/l1-contracts/src/core/interfaces/IRollup.sol +++ b/l1-contracts/src/core/interfaces/IRollup.sol @@ -4,12 +4,15 @@ pragma solidity >=0.8.18; interface IRollup { event L2BlockProcessed(uint256 indexed blockNumber); + event L2ProofVerified(uint256 indexed blockNumber); - function process( + function process(bytes calldata _header, bytes32 _archive) external; + + function submitProof( bytes calldata _header, bytes32 _archive, bytes calldata _aggregationObject, - bytes memory _proof + bytes calldata _proof ) external; function setVerifier(address _verifier) external; diff --git a/l1-contracts/test/Rollup.t.sol b/l1-contracts/test/Rollup.t.sol index 50f7d7f66d7b..a9af93381654 100644 --- a/l1-contracts/test/Rollup.t.sol +++ b/l1-contracts/test/Rollup.t.sol @@ -85,7 +85,7 @@ contract RollupTest is DecoderBase { availabilityOracle.publish(body); vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__InvalidChainId.selector, 0x420, 31337)); - rollup.process(header, archive, bytes(""), bytes("")); + rollup.process(header, archive); } function testRevertInvalidVersion() public { @@ -101,7 +101,7 @@ contract RollupTest is DecoderBase { availabilityOracle.publish(body); vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__InvalidVersion.selector, 0x420, 1)); - rollup.process(header, archive, bytes(""), bytes("")); + rollup.process(header, archive); } function testRevertTimestampInFuture() public { @@ -118,7 +118,7 @@ contract RollupTest is DecoderBase { availabilityOracle.publish(body); vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__TimestampInFuture.selector)); - rollup.process(header, archive, bytes(""), bytes("")); + rollup.process(header, archive); } function testRevertTimestampTooOld() public { @@ -133,7 +133,7 @@ contract RollupTest is DecoderBase { availabilityOracle.publish(body); vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__TimestampTooOld.selector)); - rollup.process(header, archive, bytes(""), bytes("")); + rollup.process(header, archive); } function _testBlock(string memory name) public { @@ -153,7 +153,7 @@ contract RollupTest is DecoderBase { uint256 toConsume = inbox.toConsume(); vm.record(); - rollup.process(header, archive, bytes(""), bytes("")); + rollup.process(header, archive); assertEq(inbox.toConsume(), toConsume + 1, "Message subtree not consumed"); diff --git a/yarn-project/accounts/package.local.json b/yarn-project/accounts/package.local.json index 6e3a34a9358f..d442f6c8af9b 100644 --- a/yarn-project/accounts/package.local.json +++ b/yarn-project/accounts/package.local.json @@ -7,10 +7,5 @@ "build:ts": "tsc -b", "clean": "rm -rf ./dest .tsbuildinfo ./artifacts" }, - "files": [ - "dest", - "src", - "artifacts", - "!*.test.*" - ] -} \ No newline at end of file + "files": ["dest", "src", "artifacts", "!*.test.*"] +} diff --git a/yarn-project/archiver/src/archiver/archiver.test.ts b/yarn-project/archiver/src/archiver/archiver.test.ts index 1040f308faea..ea7cbba1883b 100644 --- a/yarn-project/archiver/src/archiver/archiver.test.ts +++ b/yarn-project/archiver/src/archiver/archiver.test.ts @@ -248,12 +248,10 @@ function makeMessageSentEvent(l1BlockNum: bigint, l2BlockNumber: bigint, index: function makeRollupTx(l2Block: L2Block) { const header = toHex(l2Block.header.toBuffer()); const archive = toHex(l2Block.archive.root.toBuffer()); - const aggregationObject = `0x`; - const proof = `0x`; const input = encodeFunctionData({ abi: RollupAbi, functionName: 'process', - args: [header, archive, aggregationObject, proof], + args: [header, archive], }); return { input } as Transaction; } diff --git a/yarn-project/archiver/src/archiver/eth_log_handlers.ts b/yarn-project/archiver/src/archiver/eth_log_handlers.ts index 5fe3fb4d08b7..00d0b6d4bef9 100644 --- a/yarn-project/archiver/src/archiver/eth_log_handlers.ts +++ b/yarn-project/archiver/src/archiver/eth_log_handlers.ts @@ -91,7 +91,7 @@ async function getBlockMetadataFromRollupTx( if (functionName !== 'process') { throw new Error(`Unexpected method called ${functionName}`); } - const [headerHex, archiveRootHex] = args! as readonly [Hex, Hex, Hex, Hex]; + const [headerHex, archiveRootHex] = args! as readonly [Hex, Hex]; const header = Header.fromBuffer(Buffer.from(hexToBytes(headerHex))); diff --git a/yarn-project/circuit-types/src/stats/stats.ts b/yarn-project/circuit-types/src/stats/stats.ts index d5d6f4d6a881..8abab96dde99 100644 --- a/yarn-project/circuit-types/src/stats/stats.ts +++ b/yarn-project/circuit-types/src/stats/stats.ts @@ -26,10 +26,8 @@ export type L2BlockStats = { unencryptedLogSize?: number; }; -/** Stats logged for each L1 rollup publish tx.*/ +/** Stats logged for each L1 publish tx.*/ export type L1PublishStats = { - /** Name of the event for metrics purposes */ - eventName: 'rollup-published-to-l1'; /** Effective gas price of the tx. */ gasPrice: bigint; /** Effective gas used in the tx. */ @@ -40,7 +38,20 @@ export type L1PublishStats = { calldataGas: number; /** Size in bytes of the calldata. */ calldataSize: number; -} & L2BlockStats; +}; + +/** Stats logged for each L1 rollup publish tx.*/ +export type L1PublishBlockStats = { + /** Name of the event for metrics purposes */ + eventName: 'rollup-published-to-l1'; +} & L1PublishStats & + L2BlockStats; + +/** Stats logged for each L1 rollup publish tx.*/ +export type L1PublishProofStats = { + /** Name of the event for metrics purposes */ + eventName: 'proof-published-to-l1'; +} & L1PublishStats; /** Stats logged for synching node chain history. */ export type NodeSyncedChainHistoryStats = { @@ -271,7 +282,8 @@ export type Stats = | CircuitSimulationStats | CircuitWitnessGenerationStats | PublicDBAccessStats - | L1PublishStats + | L1PublishBlockStats + | L1PublishProofStats | L2BlockBuiltStats | L2BlockHandledStats | NodeSyncedChainHistoryStats diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index c797483e3724..9c0ee2dfaa42 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -27,9 +27,7 @@ import { MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, - type Proof, PublicDataUpdateRequest, - makeEmptyProof, } from '@aztec/circuits.js'; import { fr, makeProof } from '@aztec/circuits.js/testing'; import { type L1ContractAddresses, createEthereumChain } from '@aztec/ethereum'; @@ -89,7 +87,6 @@ describe('L1Publisher integration', () => { let outbox: GetContractReturnType>; let publisher: L1Publisher; - let l2Proof: Proof; let builder: TxProver; let builderDb: MerkleTrees; @@ -147,7 +144,6 @@ describe('L1Publisher integration', () => { const worldStateSynchronizer = new ServerWorldStateSynchronizer(tmpStore, builderDb, blockSource, worldStateConfig); await worldStateSynchronizer.start(); builder = await TxProver.new(config, worldStateSynchronizer, new NoopTelemetryClient()); - l2Proof = makeEmptyProof(); publisher = getL1Publisher({ rpcUrl: config.rpcUrl, @@ -411,7 +407,7 @@ describe('L1Publisher integration', () => { writeJson(`mixed_block_${i}`, block, l1ToL2Content, recipientAddress, deployerAccount.address); - await publisher.processL2Block(block, [], l2Proof); + await publisher.processL2Block(block); const logs = await publicClient.getLogs({ address: rollupAddress, @@ -431,12 +427,7 @@ describe('L1Publisher integration', () => { const expectedData = encodeFunctionData({ abi: RollupAbi, functionName: 'process', - args: [ - `0x${block.header.toBuffer().toString('hex')}`, - `0x${block.archive.root.toBuffer().toString('hex')}`, - `0x`, // empty aggregation object - `0x${l2Proof.withoutPublicInputs().toString('hex')}`, - ], + args: [`0x${block.header.toBuffer().toString('hex')}`, `0x${block.archive.root.toBuffer().toString('hex')}`], }); expect(ethTx.input).toEqual(expectedData); @@ -501,7 +492,7 @@ describe('L1Publisher integration', () => { writeJson(`empty_block_${i}`, block, [], AztecAddress.ZERO, deployerAccount.address); - await publisher.processL2Block(block, [], l2Proof); + await publisher.processL2Block(block); const logs = await publicClient.getLogs({ address: rollupAddress, @@ -521,12 +512,7 @@ describe('L1Publisher integration', () => { const expectedData = encodeFunctionData({ abi: RollupAbi, functionName: 'process', - args: [ - `0x${block.header.toBuffer().toString('hex')}`, - `0x${block.archive.root.toBuffer().toString('hex')}`, - `0x`, // empty aggregation object - `0x${l2Proof.withoutPublicInputs().toString('hex')}`, - ], + args: [`0x${block.header.toBuffer().toString('hex')}`, `0x${block.archive.root.toBuffer().toString('hex')}`], }); expect(ethTx.input).toEqual(expectedData); } diff --git a/yarn-project/end-to-end/src/composed/integration_proof_verification.test.ts b/yarn-project/end-to-end/src/composed/integration_proof_verification.test.ts index 85fe77ace572..8dc7b8630df1 100644 --- a/yarn-project/end-to-end/src/composed/integration_proof_verification.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_proof_verification.test.ts @@ -187,7 +187,7 @@ describe('proof_verification', () => { `0x${proof.withoutPublicInputs().toString('hex')}`, ] as const; - await expect(rollupContract.write.process(args)).resolves.toBeDefined(); + await expect(rollupContract.write.submitProof(args)).resolves.toBeDefined(); }); }); }); diff --git a/yarn-project/noir-protocol-circuits-types/package.local.json b/yarn-project/noir-protocol-circuits-types/package.local.json index e3deaa112a7b..d496e2497152 100644 --- a/yarn-project/noir-protocol-circuits-types/package.local.json +++ b/yarn-project/noir-protocol-circuits-types/package.local.json @@ -3,10 +3,5 @@ "build": "yarn clean && yarn generate && tsc -b", "clean": "rm -rf ./dest .tsbuildinfo src/types artifacts" }, - "files": [ - "dest", - "src", - "artifacts", - "!*.test.*" - ] -} \ No newline at end of file + "files": ["dest", "src", "artifacts", "!*.test.*"] +} diff --git a/yarn-project/protocol-contracts/package.local.json b/yarn-project/protocol-contracts/package.local.json index 6e3a34a9358f..d442f6c8af9b 100644 --- a/yarn-project/protocol-contracts/package.local.json +++ b/yarn-project/protocol-contracts/package.local.json @@ -7,10 +7,5 @@ "build:ts": "tsc -b", "clean": "rm -rf ./dest .tsbuildinfo ./artifacts" }, - "files": [ - "dest", - "src", - "artifacts", - "!*.test.*" - ] -} \ No newline at end of file + "files": ["dest", "src", "artifacts", "!*.test.*"] +} diff --git a/yarn-project/scripts/src/benchmarks/aggregate.ts b/yarn-project/scripts/src/benchmarks/aggregate.ts index 5e6f6ab5d897..baae136653ba 100644 --- a/yarn-project/scripts/src/benchmarks/aggregate.ts +++ b/yarn-project/scripts/src/benchmarks/aggregate.ts @@ -19,7 +19,7 @@ import { type CircuitProvingStats, type CircuitSimulationStats, type CircuitWitnessGenerationStats, - type L1PublishStats, + type L1PublishBlockStats, type L2BlockBuiltStats, type L2BlockHandledStats, type MetricName, @@ -87,7 +87,7 @@ function processAcirProofGenerated(entry: ProofConstructed, results: BenchmarkCo } /** Processes an entry with event name 'rollup-published-to-l1' and updates results */ -function processRollupPublished(entry: L1PublishStats, results: BenchmarkCollectedResults) { +function processRollupPublished(entry: L1PublishBlockStats, results: BenchmarkCollectedResults) { const bucket = entry.txCount; if (!BENCHMARK_BLOCK_SIZES.includes(bucket)) { return; diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts index 2e301e40e3dd..6b0012fcb77e 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts @@ -1,5 +1,4 @@ import { L2Block } from '@aztec/circuit-types'; -import { makeEmptyProof } from '@aztec/circuits.js'; import { sleep } from '@aztec/foundation/sleep'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -18,8 +17,6 @@ describe('L1Publisher', () => { let archive: Buffer; let txsEffectsHash: Buffer; let body: Buffer; - let proof: Buffer; - let aggregationObject: Buffer; let publisher: L1Publisher; @@ -30,8 +27,6 @@ describe('L1Publisher', () => { archive = l2Block.archive.root.toBuffer(); txsEffectsHash = l2Block.body.getTxsEffectsHash(); body = l2Block.body.toBuffer(); - aggregationObject = Buffer.alloc(0); - proof = makeEmptyProof().withoutPublicInputs(); txSender = mock(); @@ -56,22 +51,16 @@ describe('L1Publisher', () => { }); it('publishes l2 block to l1', async () => { - const result = await publisher.processL2Block(l2Block, [], makeEmptyProof()); + const result = await publisher.processL2Block(l2Block); expect(result).toEqual(true); - expect(txSender.sendProcessTx).toHaveBeenCalledWith({ - header, - archive, - body, - aggregationObject, - proof, - }); + expect(txSender.sendProcessTx).toHaveBeenCalledWith({ header, archive, body }); expect(txSender.getTransactionReceipt).toHaveBeenCalledWith(processTxHash); }); it('does not publish if last archive root is different to expected', async () => { txSender.getCurrentArchive.mockResolvedValueOnce(L2Block.random(43).archive.root.toBuffer()); - const result = await publisher.processL2Block(l2Block, [], makeEmptyProof()); + const result = await publisher.processL2Block(l2Block); expect(result).toBe(false); expect(txSender.sendPublishTx).not.toHaveBeenCalled(); expect(txSender.sendProcessTx).not.toHaveBeenCalled(); @@ -80,7 +69,7 @@ describe('L1Publisher', () => { it('does not retry if sending a publish tx fails', async () => { txSender.sendPublishTx.mockReset().mockRejectedValueOnce(new Error()).mockResolvedValueOnce(publishTxHash); - const result = await publisher.processL2Block(l2Block, [], makeEmptyProof()); + const result = await publisher.processL2Block(l2Block); expect(result).toEqual(false); expect(txSender.sendPublishTx).toHaveBeenCalledTimes(1); @@ -90,7 +79,7 @@ describe('L1Publisher', () => { it('does not retry if sending a process tx fails', async () => { txSender.sendProcessTx.mockReset().mockRejectedValueOnce(new Error()).mockResolvedValueOnce(processTxHash); - const result = await publisher.processL2Block(l2Block, [], makeEmptyProof()); + const result = await publisher.processL2Block(l2Block); expect(result).toEqual(false); expect(txSender.sendPublishTx).toHaveBeenCalledTimes(1); @@ -105,7 +94,7 @@ describe('L1Publisher', () => { .mockRejectedValueOnce(new Error()) .mockResolvedValueOnce(processTxReceipt); - const result = await publisher.processL2Block(l2Block, [], makeEmptyProof()); + const result = await publisher.processL2Block(l2Block); expect(result).toEqual(true); expect(txSender.getTransactionReceipt).toHaveBeenCalledTimes(4); @@ -114,7 +103,7 @@ describe('L1Publisher', () => { it('returns false if publish tx reverts', async () => { txSender.getTransactionReceipt.mockReset().mockResolvedValueOnce({ ...publishTxReceipt, status: false }); - const result = await publisher.processL2Block(l2Block, [], makeEmptyProof()); + const result = await publisher.processL2Block(l2Block); expect(result).toEqual(false); }); @@ -125,7 +114,7 @@ describe('L1Publisher', () => { .mockResolvedValueOnce(publishTxReceipt) .mockResolvedValueOnce({ ...publishTxReceipt, status: false }); - const result = await publisher.processL2Block(l2Block, [], makeEmptyProof()); + const result = await publisher.processL2Block(l2Block); expect(result).toEqual(false); }); @@ -133,7 +122,7 @@ describe('L1Publisher', () => { it('returns false if sending publish tx is interrupted', async () => { txSender.sendPublishTx.mockReset().mockImplementationOnce(() => sleep(10, publishTxHash)); - const resultPromise = publisher.processL2Block(l2Block, [], makeEmptyProof()); + const resultPromise = publisher.processL2Block(l2Block); publisher.interrupt(); const result = await resultPromise; @@ -144,7 +133,7 @@ describe('L1Publisher', () => { it('returns false if sending process tx is interrupted', async () => { txSender.sendProcessTx.mockReset().mockImplementationOnce(() => sleep(10, processTxHash)); - const resultPromise = publisher.processL2Block(l2Block, [], makeEmptyProof()); + const resultPromise = publisher.processL2Block(l2Block); publisher.interrupt(); const result = await resultPromise; diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 9cc82d3b6e2e..775751f56eb8 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -1,6 +1,7 @@ import { type L2Block } from '@aztec/circuit-types'; -import { type L1PublishStats } from '@aztec/circuit-types/stats'; -import { type EthAddress, type Fr, type Proof } from '@aztec/circuits.js'; +import { type L1PublishBlockStats, type L1PublishProofStats } from '@aztec/circuit-types/stats'; +import { type EthAddress, type Header, type Proof } from '@aztec/circuits.js'; +import { type Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { serializeToBuffer } from '@aztec/foundation/serialize'; import { InterruptibleSleep } from '@aztec/foundation/sleep'; @@ -42,8 +43,10 @@ export type MinimalTransactionReceipt = { * Pushes txs to the L1 chain and waits for their completion. */ export interface L1PublisherTxSender { + /** Returns the EOA used for sending txs to L1. */ getSenderAddress(): Promise; + /** Returns the address elected for submitting a given block number or zero if anyone can submit. */ getSubmitterAddressForBlock(blockNumber: number): Promise; /** @@ -60,6 +63,13 @@ export interface L1PublisherTxSender { */ sendProcessTx(encodedData: L1ProcessArgs): Promise; + /** + * Sends a tx to the L1 rollup contract with a proof. Returns once the tx has been mined. + * @param encodedData - Serialized data for processing the new L2 block. + * @returns The hash of the mined tx. + */ + sendSubmitProofTx(submitProofArgs: L1SubmitProofArgs): Promise; + /** * Returns a tx receipt if the tx has been mined. * @param txHash - Hash of the tx to look for. @@ -87,9 +97,7 @@ export interface L1PublisherTxSender { checkIfTxsAreAvailable(block: L2Block): Promise; } -/** - * Encoded block and proof ready to be pushed to the L1 contract. - */ +/** Arguments to the process method of the rollup contract */ export type L1ProcessArgs = { /** The L2 block header. */ header: Buffer; @@ -97,10 +105,18 @@ export type L1ProcessArgs = { archive: Buffer; /** L2 block body. */ body: Buffer; - /** Aggregation object needed to verify the proof */ - aggregationObject: Buffer; - /** Root rollup proof of the L2 block. */ +}; + +/** Arguments to the submitProof method of the rollup contract */ +export type L1SubmitProofArgs = { + /** The L2 block header. */ + header: Buffer; + /** A root of the archive tree after the L2 block is applied. */ + archive: Buffer; + /** The proof for the block. */ proof: Buffer; + /** The aggregation object for the block's proof. */ + aggregationObject: Buffer; }; /** @@ -132,11 +148,12 @@ export class L1Publisher implements L2BlockReceiver { * @param block - L2 block to publish. * @returns True once the tx has been confirmed and is successful, false on revert or interrupt, blocks otherwise. */ - public async processL2Block(block: L2Block, aggregationObject: Fr[], proof: Proof): Promise { + public async processL2Block(block: L2Block): Promise { + const ctx = { blockNumber: block.number, blockHash: block.hash().toString() }; // TODO(#4148) Remove this block number check, it's here because we don't currently have proper genesis state on the contract const lastArchive = block.header.lastArchive.root.toBuffer(); if (block.number != 1 && !(await this.checkLastArchiveHash(lastArchive))) { - this.log.info(`Detected different last archive prior to publishing a block, aborting publish...`); + this.log.info(`Detected different last archive prior to publishing a block, aborting publish...`, ctx); return false; } @@ -145,7 +162,7 @@ export class L1Publisher implements L2BlockReceiver { // Publish block transaction effects while (!this.interrupted) { if (await this.txSender.checkIfTxsAreAvailable(block)) { - this.log.verbose(`Transaction effects of a block ${block.number} already published.`); + this.log.verbose(`Transaction effects of block ${block.number} already published.`, ctx); break; } @@ -165,14 +182,14 @@ export class L1Publisher implements L2BlockReceiver { // txsEffectsHash from IAvailabilityOracle.TxsPublished event txsEffectsHash = receipt.logs[0].data; } else { - this.log.warn(`Expected 1 log, got ${receipt.logs.length}`); + this.log.warn(`Expected 1 log, got ${receipt.logs.length}`, ctx); } - this.log.info(`Block txs effects published, txsEffectsHash: ${txsEffectsHash}`); + this.log.info(`Block txs effects published`, { ...ctx, txsEffectsHash }); break; } - this.log.error(`AvailabilityOracle.publish tx status failed: ${receipt.transactionHash}`); + this.log.error(`AvailabilityOracle.publish tx status failed: ${receipt.transactionHash}`, ctx); await this.sleepOrInterrupted(); } @@ -180,8 +197,6 @@ export class L1Publisher implements L2BlockReceiver { header: block.header.toBuffer(), archive: block.archive.root.toBuffer(), body: encodedBody, - aggregationObject: serializeToBuffer(aggregationObject), - proof: proof.withoutPublicInputs(), }; // Process block @@ -199,27 +214,69 @@ export class L1Publisher implements L2BlockReceiver { // Tx was mined successfully if (receipt.status) { const tx = await this.txSender.getTransactionStats(txHash); - const stats: L1PublishStats = { + const stats: L1PublishBlockStats = { ...pick(receipt, 'gasPrice', 'gasUsed', 'transactionHash'), ...pick(tx!, 'calldataGas', 'calldataSize'), ...block.getStats(), eventName: 'rollup-published-to-l1', }; - this.log.info(`Published L2 block to L1 rollup contract`, stats); + this.log.info(`Published L2 block to L1 rollup contract`, { ...stats, ...ctx }); return true; } // Check if someone else incremented the block number if (!(await this.checkLastArchiveHash(lastArchive))) { - this.log.warn('Publish failed. Detected different last archive hash.'); + this.log.warn('Publish failed. Detected different last archive hash.', ctx); break; } - this.log.error(`Rollup.process tx status failed: ${receipt.transactionHash}`); + this.log.error(`Rollup.process tx status failed: ${receipt.transactionHash}`, ctx); await this.sleepOrInterrupted(); } - this.log.verbose('L2 block data syncing interrupted while processing blocks.'); + this.log.verbose('L2 block data syncing interrupted while processing blocks.', ctx); + return false; + } + + public async submitProof(header: Header, archiveRoot: Fr, aggregationObject: Fr[], proof: Proof): Promise { + const ctx = { blockNumber: header.globalVariables.blockNumber }; + + const txArgs: L1SubmitProofArgs = { + header: header.toBuffer(), + archive: archiveRoot.toBuffer(), + aggregationObject: serializeToBuffer(aggregationObject), + proof: proof.withoutPublicInputs(), + }; + + // Process block + while (!this.interrupted) { + const txHash = await this.sendSubmitProofTx(txArgs); + if (!txHash) { + break; + } + + const receipt = await this.getTransactionReceipt(txHash); + if (!receipt) { + break; + } + + // Tx was mined successfully + if (receipt.status) { + const tx = await this.txSender.getTransactionStats(txHash); + const stats: L1PublishProofStats = { + ...pick(receipt, 'gasPrice', 'gasUsed', 'transactionHash'), + ...pick(tx!, 'calldataGas', 'calldataSize'), + eventName: 'proof-published-to-l1', + }; + this.log.info(`Published L2 block to L1 rollup contract`, { ...stats, ...ctx }); + return true; + } + + this.log.error(`Rollup.submitProof tx status failed: ${receipt.transactionHash}`, ctx); + await this.sleepOrInterrupted(); + } + + this.log.verbose('L2 block data syncing interrupted while processing blocks.', ctx); return false; } @@ -254,6 +311,17 @@ export class L1Publisher implements L2BlockReceiver { return areSame; } + private async sendSubmitProofTx(submitProofArgs: L1SubmitProofArgs): Promise { + try { + const size = Object.values(submitProofArgs).reduce((acc, arg) => acc + arg.length, 0); + this.log.info(`SubmitProof size=${size} bytes`); + return await this.txSender.sendSubmitProofTx(submitProofArgs); + } catch (err) { + this.log.error(`Rollup submit proof failed`, err); + return undefined; + } + } + private async sendPublishTx(encodedBody: Buffer): Promise { while (!this.interrupted) { try { diff --git a/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts b/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts index c630f0436386..75853b780e62 100644 --- a/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts +++ b/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts @@ -23,6 +23,7 @@ import * as chains from 'viem/chains'; import { type TxSenderConfig } from './config.js'; import { type L1PublisherTxSender, + type L1SubmitProofArgs, type MinimalTransactionReceipt, type L1ProcessArgs as ProcessTxArgs, type TransactionStats, @@ -157,12 +158,7 @@ export class ViemTxSender implements L1PublisherTxSender { * @returns The hash of the mined tx. */ async sendProcessTx(encodedData: ProcessTxArgs): Promise { - const args = [ - `0x${encodedData.header.toString('hex')}`, - `0x${encodedData.archive.toString('hex')}`, - `0x${encodedData.aggregationObject.toString('hex')}`, - `0x${encodedData.proof.toString('hex')}`, - ] as const; + const args = [`0x${encodedData.header.toString('hex')}`, `0x${encodedData.archive.toString('hex')}`] as const; const gas = await this.rollupContract.estimateGas.process(args, { account: this.account, @@ -174,6 +170,31 @@ export class ViemTxSender implements L1PublisherTxSender { return hash; } + /** + * Sends a tx to the L1 rollup contract with a proof. Returns once the tx has been mined. + * @param encodedData - Serialized data for the proof. + * @returns The hash of the mined tx. + */ + async sendSubmitProofTx(submitProofArgs: L1SubmitProofArgs): Promise { + const { header, archive, aggregationObject, proof } = submitProofArgs; + const args = [ + `0x${header.toString('hex')}`, + `0x${archive.toString('hex')}`, + `0x${aggregationObject.toString('hex')}`, + `0x${proof.toString('hex')}`, + ] as const; + + const gas = await this.rollupContract.estimateGas.submitProof(args, { + account: this.account, + }); + const hash = await this.rollupContract.write.submitProof(args, { + gas, + account: this.account, + }); + + return hash; + } + /** * Gets the chain object for the given chain id. * @param chainId - Chain id of the target EVM chain. diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index 89721ceafb92..aef46a70db7c 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -148,7 +148,7 @@ describe('sequencer', () => { new GlobalVariables(chainId, version, new Fr(lastBlockNumber + 1), Fr.ZERO, coinbase, feeRecipient, gasFees), Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, [], proof); + expect(publisher.processL2Block).toHaveBeenCalledWith(block); expect(proverClient.cancelBlock).toHaveBeenCalledTimes(0); }); @@ -186,7 +186,7 @@ describe('sequencer', () => { new GlobalVariables(chainId, version, new Fr(lastBlockNumber + 1), Fr.ZERO, coinbase, feeRecipient, gasFees), Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, [], proof); + expect(publisher.processL2Block).toHaveBeenCalledWith(block); expect(proverClient.cancelBlock).toHaveBeenCalledTimes(0); }); @@ -229,7 +229,7 @@ describe('sequencer', () => { new GlobalVariables(chainId, version, new Fr(lastBlockNumber + 1), Fr.ZERO, coinbase, feeRecipient, gasFees), Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, [], proof); + expect(publisher.processL2Block).toHaveBeenCalledWith(block); expect(p2p.deleteTxs).toHaveBeenCalledWith([doubleSpendTx.getTxHash()]); expect(proverClient.cancelBlock).toHaveBeenCalledTimes(0); }); @@ -268,7 +268,7 @@ describe('sequencer', () => { new GlobalVariables(chainId, version, new Fr(lastBlockNumber + 1), Fr.ZERO, coinbase, feeRecipient, gasFees), Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, [], proof); + expect(publisher.processL2Block).toHaveBeenCalledWith(block); expect(p2p.deleteTxs).toHaveBeenCalledWith([invalidChainTx.getTxHash()]); expect(proverClient.cancelBlock).toHaveBeenCalledTimes(0); }); @@ -307,7 +307,7 @@ describe('sequencer', () => { new GlobalVariables(chainId, version, new Fr(lastBlockNumber + 1), Fr.ZERO, coinbase, feeRecipient, gasFees), Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, [], proof); + expect(publisher.processL2Block).toHaveBeenCalledWith(block); expect(proverClient.cancelBlock).toHaveBeenCalledTimes(0); }); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index fb20cb3507f9..31697c2a0314 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -13,7 +13,7 @@ import { PROVING_STATUS, } from '@aztec/circuit-types/interfaces'; import { type L2BlockBuiltStats } from '@aztec/circuit-types/stats'; -import { AztecAddress, EthAddress, type GlobalVariables, type Header, type Proof } from '@aztec/circuits.js'; +import { AztecAddress, EthAddress, type GlobalVariables, type Header } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { RunningPromise } from '@aztec/foundation/running-promise'; @@ -306,8 +306,16 @@ export class Sequencer { ...block.getStats(), } satisfies L2BlockBuiltStats); - await this.publishL2Block(block, aggregationObject, proof); + await this.publishL2Block(block); this.log.info(`Submitted rollup block ${block.number} with ${processedTxs.length} transactions`); + + // Submit the proof if we have configured this sequencer to run with a prover. + // This is temporary while we submit one proof per block, but will have to change once we + // move onto proving batches of multiple blocks at a time. + if (aggregationObject && proof) { + await this.publisher.submitProof(block.header, block.archive.root, aggregationObject, proof); + this.log.info(`Submitted proof for block ${block.number}`); + } } /** @@ -317,10 +325,10 @@ export class Sequencer { @trackSpan('Sequencer.publishL2Block', block => ({ [Attributes.BLOCK_NUMBER]: block.number, })) - protected async publishL2Block(block: L2Block, aggregationObject: Fr[], proof: Proof) { + protected async publishL2Block(block: L2Block) { // Publishes new block to the network and awaits the tx to be mined this.state = SequencerState.PUBLISHING_BLOCK; - const publishedL2Block = await this.publisher.processL2Block(block, aggregationObject, proof); + const publishedL2Block = await this.publisher.processL2Block(block); if (publishedL2Block) { this.lastPublishedBlock = block.number; } else { diff --git a/yarn-project/types/src/abi/contract_artifact.ts b/yarn-project/types/src/abi/contract_artifact.ts index 861eb227206e..e8cbbb3aabf5 100644 --- a/yarn-project/types/src/abi/contract_artifact.ts +++ b/yarn-project/types/src/abi/contract_artifact.ts @@ -272,13 +272,17 @@ function getNoteTypes(input: NoirCompiledContract) { * @returns Aztec contract build artifact. */ function generateContractArtifact(contract: NoirCompiledContract, aztecNrVersion?: string): ContractArtifact { - return { - name: contract.name, - functions: contract.functions.map(f => generateFunctionArtifact(f, contract)), - outputs: contract.outputs, - storageLayout: getStorageLayout(contract), - notes: getNoteTypes(contract), - fileMap: contract.file_map, - aztecNrVersion, - }; + try { + return { + name: contract.name, + functions: contract.functions.map(f => generateFunctionArtifact(f, contract)), + outputs: contract.outputs, + storageLayout: getStorageLayout(contract), + notes: getNoteTypes(contract), + fileMap: contract.file_map, + aztecNrVersion, + }; + } catch (err) { + throw new Error(`Could not generate contract artifact for ${contract.name}: ${err}`); + } } From ebec8ff48900b48be3fce6bc9a52bcb566c79a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Wed, 10 Jul 2024 16:38:20 +0200 Subject: [PATCH 07/32] refactor: private refund cleanup (#7403) --- .../private_token_contract/src/main.nr | 17 ++++++----------- .../src/e2e_fees/private_refunds.test.ts | 17 +++++++++++------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/main.nr index 688b578eb648..789799211e34 100644 --- a/noir-projects/noir-contracts/contracts/private_token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/main.nr @@ -174,7 +174,7 @@ contract PrivateToken { // 3. Deduct the funded amount from the user's balance - this is a maximum fee a user is willing to pay // (called fee limit in aztec spec). The difference between fee limit and the actual tx fee will be refunded // to the user in the `complete_refund(...)` function. - // TODO(#7324): using npk_m_hash here does not work with key rotation + // TODO(#7324), TODO(#7323): using npk_m_hash here is vulnerable in 2 ways described in the linked issues. storage.balances.sub(user_npk_m_hash, U128::from_integer(funded_amount)).emit(encode_and_encrypt_note_with_keys(&mut context, user_ovpk, user_ivpk)); // 4. We generate the refund points. @@ -190,22 +190,17 @@ contract PrivateToken { // function has access to the final transaction fee, which is needed to compute the actual refund amount. context.set_public_teardown_function( context.this_address(), - FunctionSelector::from_signature("complete_refund(Field,Field,Field,Field)"), - [fee_payer_point.x, fee_payer_point.y, user_point.x, user_point.y] + FunctionSelector::from_signature("complete_refund((Field,Field,bool),(Field,Field,bool))"), + [ + fee_payer_point.x, fee_payer_point.y, fee_payer_point.is_infinite as Field, user_point.x, user_point.y, user_point.is_infinite as Field + ] ); } #[aztec(public)] #[aztec(internal)] - fn complete_refund( - fee_payer_point_x: Field, - fee_payer_point_y: Field, - user_point_x: Field, - user_point_y: Field - ) { + fn complete_refund(fee_payer_point: Point, user_point: Point) { // 1. We get the final note content hashes by calling the `complete_refund` on the note. - let fee_payer_point = Point { x: fee_payer_point_x, y: fee_payer_point_y, is_infinite: false }; - let user_point = Point { x: user_point_x, y: user_point_y, is_infinite: false }; let tx_fee = context.transaction_fee(); let (fee_payer_note_content_hash, user_note_content_hash) = TokenNote::complete_refund(fee_payer_point, user_point, tx_fee); diff --git a/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts b/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts index bbbae0727de7..52076a9703cd 100644 --- a/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts @@ -77,8 +77,13 @@ describe('e2e_fees/private_refunds', () => { expect(tx.transactionFee).toBeGreaterThan(0); - // 3. Now we compute the contents of the note containing the refund for Alice. The refund note value is simply - // the fee limit less the final transaction fee. The other 2 fields in the note are Alice's npk_m_hash and + // 3. We check that randomness for Bob was correctly emitted as an unencrypted log (Bobs needs it to reconstruct his note). + const resp = await aliceWallet.getUnencryptedLogs({ txHash: tx.txHash }); + const bobRandomnessFromLog = Fr.fromBuffer(resp.logs[0].log.data); + expect(bobRandomnessFromLog).toEqual(bobRandomness); + + // 4. Now we compute the contents of the note containing the refund for Alice. The refund note value is simply + // the fee limit minus the final transaction fee. The other 2 fields in the note are Alice's npk_m_hash and // the randomness. const refundNoteValue = t.gasSettings.getFeeLimit().sub(new Fr(tx.transactionFee!)); // TODO(#7324): The values in complete address are currently not updated after the keys are rotated so this does @@ -86,7 +91,7 @@ describe('e2e_fees/private_refunds', () => { const aliceNpkMHash = t.aliceWallet.getCompleteAddress().publicKeys.masterNullifierPublicKey.hash(); const aliceRefundNote = new Note([refundNoteValue, aliceNpkMHash, aliceRandomness]); - // 4. If the refund flow worked it should have added emitted a note hash of the note we constructed above and we + // 5. If the refund flow worked it should have added emitted a note hash of the note we constructed above and we // should be able to add the note to our PXE. Just calling `pxe.addNote(...)` is enough of a check that the note // hash was emitted because the endpoint will compute the hash and then it will try to find it in the note hash // tree. If the note hash is not found in the tree, an error is thrown. @@ -101,13 +106,13 @@ describe('e2e_fees/private_refunds', () => { ), ); - // 5. Now we reconstruct the note for the final fee payment. It should contain the transaction fee, Bob's + // 6. Now we reconstruct the note for the final fee payment. It should contain the transaction fee, Bob's // npk_m_hash (set in the paymentMethod above) and the randomness. // Note that FPC emits randomness as unencrypted log and the tx fee is publicly know so Bob is able to reconstruct // his note just from on-chain data. const bobFeeNote = new Note([new Fr(tx.transactionFee!), bobNpkMHash, bobRandomness]); - // 6. Once again we add the note to PXE which computes the note hash and checks that it is in the note hash tree. + // 7. Once again we add the note to PXE which computes the note hash and checks that it is in the note hash tree. await t.bobWallet.addNote( new ExtendedNote( bobFeeNote, @@ -119,7 +124,7 @@ describe('e2e_fees/private_refunds', () => { ), ); - // 7. At last we check that the gas balance of FPC has decreased exactly by the transaction fee ... + // 8. At last we check that the gas balance of FPC has decreased exactly by the transaction fee ... await expectMapping(t.getGasBalanceFn, [privateFPC.address], [initialFPCGasBalance - tx.transactionFee!]); // ... and that the transaction fee was correctly transferred from Alice to Bob. await expectMapping( From 108fc5f92e44b027b38fa31614e14f2b7a9f650a Mon Sep 17 00:00:00 2001 From: Facundo Date: Wed, 10 Jul 2024 16:02:07 +0100 Subject: [PATCH 08/32] feat(avm): make ProverPolynomials::get_row return references (#7419) This makes the computation of logderivatives ~20x faster, and proving a public token transfer goes from `60s` to `14s`. The cost is verbosity. --- .../cpp/src/barretenberg/common/ref_array.hpp | 5 +- .../barretenberg/vm/generated/avm_flavor.hpp | 1379 ++++++++++++++++- .../bb-pil-backend/templates/flavor.hpp.hbs | 47 +- 3 files changed, 1404 insertions(+), 27 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/common/ref_array.hpp b/barretenberg/cpp/src/barretenberg/common/ref_array.hpp index 3c2fb017dce8..4939b571686e 100644 --- a/barretenberg/cpp/src/barretenberg/common/ref_array.hpp +++ b/barretenberg/cpp/src/barretenberg/common/ref_array.hpp @@ -24,9 +24,8 @@ template class RefArray { RefArray() = default; RefArray(const std::array& ptr_array) { - std::size_t i = 0; - for (T& elem : ptr_array) { - storage[i++] = &elem; + for (std::size_t i = 0; i < N; ++i) { + storage[i++] = ptr_array[i]; } } template RefArray(T& ref, Ts&... rest) diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index a2a58cd49a40..ae9c54f49c16 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -764,12 +764,6 @@ class AvmFlavor { public WitnessEntities, public ShiftedEntities { public: - AllEntities() - : PrecomputedEntities{} - , WitnessEntities{} - , ShiftedEntities{} - {} - DEFINE_COMPOUND_GET_ALL(PrecomputedEntities, WitnessEntities, ShiftedEntities) auto get_unshifted() @@ -867,6 +861,920 @@ class AvmFlavor { using Base::Base; }; + class AllConstRefValues { + public: + using DataType = const FF&; + + DEFINE_FLAVOR_MEMBERS(DataType, + main_clk, + main_sel_first, + kernel_kernel_inputs, + kernel_kernel_value_out, + kernel_kernel_side_effect_out, + kernel_kernel_metadata_out, + main_calldata, + alu_a_hi, + alu_a_lo, + alu_b_hi, + alu_b_lo, + alu_borrow, + alu_cf, + alu_clk, + alu_cmp_rng_ctr, + alu_div_u16_r0, + alu_div_u16_r1, + alu_div_u16_r2, + alu_div_u16_r3, + alu_div_u16_r4, + alu_div_u16_r5, + alu_div_u16_r6, + alu_div_u16_r7, + alu_divisor_hi, + alu_divisor_lo, + alu_ff_tag, + alu_ia, + alu_ib, + alu_ic, + alu_in_tag, + alu_op_add, + alu_op_cast, + alu_op_cast_prev, + alu_op_div, + alu_op_div_a_lt_b, + alu_op_div_std, + alu_op_eq, + alu_op_eq_diff_inv, + alu_op_lt, + alu_op_lte, + alu_op_mul, + alu_op_not, + alu_op_shl, + alu_op_shr, + alu_op_sub, + alu_p_a_borrow, + alu_p_b_borrow, + alu_p_sub_a_hi, + alu_p_sub_a_lo, + alu_p_sub_b_hi, + alu_p_sub_b_lo, + alu_partial_prod_hi, + alu_partial_prod_lo, + alu_quotient_hi, + alu_quotient_lo, + alu_remainder, + alu_res_hi, + alu_res_lo, + alu_sel_alu, + alu_sel_cmp, + alu_sel_div_rng_chk, + alu_sel_rng_chk, + alu_sel_rng_chk_lookup, + alu_sel_shift_which, + alu_shift_lt_bit_len, + alu_t_sub_s_bits, + alu_two_pow_s, + alu_two_pow_t_sub_s, + alu_u128_tag, + alu_u16_r0, + alu_u16_r1, + alu_u16_r10, + alu_u16_r11, + alu_u16_r12, + alu_u16_r13, + alu_u16_r14, + alu_u16_r2, + alu_u16_r3, + alu_u16_r4, + alu_u16_r5, + alu_u16_r6, + alu_u16_r7, + alu_u16_r8, + alu_u16_r9, + alu_u16_tag, + alu_u32_tag, + alu_u64_tag, + alu_u8_r0, + alu_u8_r1, + alu_u8_tag, + binary_acc_ia, + binary_acc_ib, + binary_acc_ic, + binary_clk, + binary_ia_bytes, + binary_ib_bytes, + binary_ic_bytes, + binary_in_tag, + binary_mem_tag_ctr, + binary_mem_tag_ctr_inv, + binary_op_id, + binary_sel_bin, + binary_start, + byte_lookup_sel_bin, + byte_lookup_table_byte_lengths, + byte_lookup_table_in_tags, + byte_lookup_table_input_a, + byte_lookup_table_input_b, + byte_lookup_table_op_id, + byte_lookup_table_output, + conversion_clk, + conversion_input, + conversion_num_limbs, + conversion_radix, + conversion_sel_to_radix_le, + gas_da_gas_fixed_table, + gas_l2_gas_fixed_table, + gas_sel_gas_cost, + keccakf1600_clk, + keccakf1600_input, + keccakf1600_output, + keccakf1600_sel_keccakf1600, + kernel_emit_l2_to_l1_msg_write_offset, + kernel_emit_note_hash_write_offset, + kernel_emit_nullifier_write_offset, + kernel_emit_unencrypted_log_write_offset, + kernel_kernel_in_offset, + kernel_kernel_out_offset, + kernel_l1_to_l2_msg_exists_write_offset, + kernel_note_hash_exist_write_offset, + kernel_nullifier_exists_write_offset, + kernel_nullifier_non_exists_write_offset, + kernel_q_public_input_kernel_add_to_table, + kernel_q_public_input_kernel_out_add_to_table, + kernel_side_effect_counter, + kernel_sload_write_offset, + kernel_sstore_write_offset, + main_abs_da_rem_gas_hi, + main_abs_da_rem_gas_lo, + main_abs_l2_rem_gas_hi, + main_abs_l2_rem_gas_lo, + main_alu_in_tag, + main_bin_op_id, + main_call_ptr, + main_da_gas_op_cost, + main_da_gas_remaining, + main_da_out_of_gas, + main_ia, + main_ib, + main_ic, + main_id, + main_id_zero, + main_ind_addr_a, + main_ind_addr_b, + main_ind_addr_c, + main_ind_addr_d, + main_internal_return_ptr, + main_inv, + main_l2_gas_op_cost, + main_l2_gas_remaining, + main_l2_out_of_gas, + main_mem_addr_a, + main_mem_addr_b, + main_mem_addr_c, + main_mem_addr_d, + main_op_err, + main_opcode_val, + main_pc, + main_r_in_tag, + main_rwa, + main_rwb, + main_rwc, + main_rwd, + main_sel_alu, + main_sel_bin, + main_sel_gas_accounting_active, + main_sel_last, + main_sel_mem_op_a, + main_sel_mem_op_activate_gas, + main_sel_mem_op_b, + main_sel_mem_op_c, + main_sel_mem_op_d, + main_sel_mov_ia_to_ic, + main_sel_mov_ib_to_ic, + main_sel_op_add, + main_sel_op_address, + main_sel_op_and, + main_sel_op_block_number, + main_sel_op_cast, + main_sel_op_chain_id, + main_sel_op_cmov, + main_sel_op_coinbase, + main_sel_op_dagasleft, + main_sel_op_div, + main_sel_op_emit_l2_to_l1_msg, + main_sel_op_emit_note_hash, + main_sel_op_emit_nullifier, + main_sel_op_emit_unencrypted_log, + main_sel_op_eq, + main_sel_op_external_call, + main_sel_op_fdiv, + main_sel_op_fee_per_da_gas, + main_sel_op_fee_per_l2_gas, + main_sel_op_function_selector, + main_sel_op_get_contract_instance, + main_sel_op_halt, + main_sel_op_internal_call, + main_sel_op_internal_return, + main_sel_op_jump, + main_sel_op_jumpi, + main_sel_op_keccak, + main_sel_op_l1_to_l2_msg_exists, + main_sel_op_l2gasleft, + main_sel_op_lt, + main_sel_op_lte, + main_sel_op_mov, + main_sel_op_mul, + main_sel_op_not, + main_sel_op_note_hash_exists, + main_sel_op_nullifier_exists, + main_sel_op_or, + main_sel_op_pedersen, + main_sel_op_poseidon2, + main_sel_op_radix_le, + main_sel_op_sender, + main_sel_op_sha256, + main_sel_op_shl, + main_sel_op_shr, + main_sel_op_sload, + main_sel_op_sstore, + main_sel_op_storage_address, + main_sel_op_sub, + main_sel_op_timestamp, + main_sel_op_transaction_fee, + main_sel_op_version, + main_sel_op_xor, + main_sel_q_kernel_lookup, + main_sel_q_kernel_output_lookup, + main_sel_resolve_ind_addr_a, + main_sel_resolve_ind_addr_b, + main_sel_resolve_ind_addr_c, + main_sel_resolve_ind_addr_d, + main_sel_rng_16, + main_sel_rng_8, + main_space_id, + main_tag_err, + main_w_in_tag, + mem_addr, + mem_clk, + mem_diff_hi, + mem_diff_lo, + mem_diff_mid, + mem_glob_addr, + mem_last, + mem_lastAccess, + mem_one_min_inv, + mem_r_in_tag, + mem_rw, + mem_sel_mem, + mem_sel_mov_ia_to_ic, + mem_sel_mov_ib_to_ic, + mem_sel_op_a, + mem_sel_op_b, + mem_sel_op_c, + mem_sel_op_cmov, + mem_sel_op_d, + mem_sel_resolve_ind_addr_a, + mem_sel_resolve_ind_addr_b, + mem_sel_resolve_ind_addr_c, + mem_sel_resolve_ind_addr_d, + mem_sel_rng_chk, + mem_skip_check_tag, + mem_space_id, + mem_tag, + mem_tag_err, + mem_tsp, + mem_val, + mem_w_in_tag, + pedersen_clk, + pedersen_input, + pedersen_output, + pedersen_sel_pedersen, + poseidon2_clk, + poseidon2_input, + poseidon2_output, + poseidon2_sel_poseidon_perm, + powers_power_of_2, + sha256_clk, + sha256_input, + sha256_output, + sha256_sel_sha256_compression, + sha256_state, + perm_main_alu, + perm_main_bin, + perm_main_conv, + perm_main_pos2_perm, + perm_main_pedersen, + perm_main_mem_a, + perm_main_mem_b, + perm_main_mem_c, + perm_main_mem_d, + perm_main_mem_ind_addr_a, + perm_main_mem_ind_addr_b, + perm_main_mem_ind_addr_c, + perm_main_mem_ind_addr_d, + lookup_byte_lengths, + lookup_byte_operations, + lookup_opcode_gas, + range_check_l2_gas_hi, + range_check_l2_gas_lo, + range_check_da_gas_hi, + range_check_da_gas_lo, + kernel_output_lookup, + lookup_into_kernel, + incl_main_tag_err, + incl_mem_tag_err, + lookup_mem_rng_chk_lo, + lookup_mem_rng_chk_mid, + lookup_mem_rng_chk_hi, + lookup_pow_2_0, + lookup_pow_2_1, + lookup_u8_0, + lookup_u8_1, + lookup_u16_0, + lookup_u16_1, + lookup_u16_2, + lookup_u16_3, + lookup_u16_4, + lookup_u16_5, + lookup_u16_6, + lookup_u16_7, + lookup_u16_8, + lookup_u16_9, + lookup_u16_10, + lookup_u16_11, + lookup_u16_12, + lookup_u16_13, + lookup_u16_14, + lookup_div_u16_0, + lookup_div_u16_1, + lookup_div_u16_2, + lookup_div_u16_3, + lookup_div_u16_4, + lookup_div_u16_5, + lookup_div_u16_6, + lookup_div_u16_7, + lookup_byte_lengths_counts, + lookup_byte_operations_counts, + lookup_opcode_gas_counts, + range_check_l2_gas_hi_counts, + range_check_l2_gas_lo_counts, + range_check_da_gas_hi_counts, + range_check_da_gas_lo_counts, + kernel_output_lookup_counts, + lookup_into_kernel_counts, + incl_main_tag_err_counts, + incl_mem_tag_err_counts, + lookup_mem_rng_chk_lo_counts, + lookup_mem_rng_chk_mid_counts, + lookup_mem_rng_chk_hi_counts, + lookup_pow_2_0_counts, + lookup_pow_2_1_counts, + lookup_u8_0_counts, + lookup_u8_1_counts, + lookup_u16_0_counts, + lookup_u16_1_counts, + lookup_u16_2_counts, + lookup_u16_3_counts, + lookup_u16_4_counts, + lookup_u16_5_counts, + lookup_u16_6_counts, + lookup_u16_7_counts, + lookup_u16_8_counts, + lookup_u16_9_counts, + lookup_u16_10_counts, + lookup_u16_11_counts, + lookup_u16_12_counts, + lookup_u16_13_counts, + lookup_u16_14_counts, + lookup_div_u16_0_counts, + lookup_div_u16_1_counts, + lookup_div_u16_2_counts, + lookup_div_u16_3_counts, + lookup_div_u16_4_counts, + lookup_div_u16_5_counts, + lookup_div_u16_6_counts, + lookup_div_u16_7_counts, + alu_a_hi_shift, + alu_a_lo_shift, + alu_b_hi_shift, + alu_b_lo_shift, + alu_cmp_rng_ctr_shift, + alu_div_u16_r0_shift, + alu_div_u16_r1_shift, + alu_div_u16_r2_shift, + alu_div_u16_r3_shift, + alu_div_u16_r4_shift, + alu_div_u16_r5_shift, + alu_div_u16_r6_shift, + alu_div_u16_r7_shift, + alu_op_add_shift, + alu_op_cast_prev_shift, + alu_op_cast_shift, + alu_op_div_shift, + alu_op_mul_shift, + alu_op_shl_shift, + alu_op_shr_shift, + alu_op_sub_shift, + alu_p_sub_a_hi_shift, + alu_p_sub_a_lo_shift, + alu_p_sub_b_hi_shift, + alu_p_sub_b_lo_shift, + alu_sel_alu_shift, + alu_sel_cmp_shift, + alu_sel_div_rng_chk_shift, + alu_sel_rng_chk_lookup_shift, + alu_sel_rng_chk_shift, + alu_u16_r0_shift, + alu_u16_r1_shift, + alu_u16_r2_shift, + alu_u16_r3_shift, + alu_u16_r4_shift, + alu_u16_r5_shift, + alu_u16_r6_shift, + alu_u8_r0_shift, + alu_u8_r1_shift, + binary_acc_ia_shift, + binary_acc_ib_shift, + binary_acc_ic_shift, + binary_mem_tag_ctr_shift, + binary_op_id_shift, + kernel_emit_l2_to_l1_msg_write_offset_shift, + kernel_emit_note_hash_write_offset_shift, + kernel_emit_nullifier_write_offset_shift, + kernel_emit_unencrypted_log_write_offset_shift, + kernel_l1_to_l2_msg_exists_write_offset_shift, + kernel_note_hash_exist_write_offset_shift, + kernel_nullifier_exists_write_offset_shift, + kernel_nullifier_non_exists_write_offset_shift, + kernel_side_effect_counter_shift, + kernel_sload_write_offset_shift, + kernel_sstore_write_offset_shift, + main_da_gas_remaining_shift, + main_internal_return_ptr_shift, + main_l2_gas_remaining_shift, + main_pc_shift, + mem_glob_addr_shift, + mem_rw_shift, + mem_sel_mem_shift, + mem_tag_shift, + mem_tsp_shift, + mem_val_shift) + + AllConstRefValues(const RefArray& il) + : main_clk(il[0]) + , main_sel_first(il[1]) + , kernel_kernel_inputs(il[2]) + , kernel_kernel_value_out(il[3]) + , kernel_kernel_side_effect_out(il[4]) + , kernel_kernel_metadata_out(il[5]) + , main_calldata(il[6]) + , alu_a_hi(il[7]) + , alu_a_lo(il[8]) + , alu_b_hi(il[9]) + , alu_b_lo(il[10]) + , alu_borrow(il[11]) + , alu_cf(il[12]) + , alu_clk(il[13]) + , alu_cmp_rng_ctr(il[14]) + , alu_div_u16_r0(il[15]) + , alu_div_u16_r1(il[16]) + , alu_div_u16_r2(il[17]) + , alu_div_u16_r3(il[18]) + , alu_div_u16_r4(il[19]) + , alu_div_u16_r5(il[20]) + , alu_div_u16_r6(il[21]) + , alu_div_u16_r7(il[22]) + , alu_divisor_hi(il[23]) + , alu_divisor_lo(il[24]) + , alu_ff_tag(il[25]) + , alu_ia(il[26]) + , alu_ib(il[27]) + , alu_ic(il[28]) + , alu_in_tag(il[29]) + , alu_op_add(il[30]) + , alu_op_cast(il[31]) + , alu_op_cast_prev(il[32]) + , alu_op_div(il[33]) + , alu_op_div_a_lt_b(il[34]) + , alu_op_div_std(il[35]) + , alu_op_eq(il[36]) + , alu_op_eq_diff_inv(il[37]) + , alu_op_lt(il[38]) + , alu_op_lte(il[39]) + , alu_op_mul(il[40]) + , alu_op_not(il[41]) + , alu_op_shl(il[42]) + , alu_op_shr(il[43]) + , alu_op_sub(il[44]) + , alu_p_a_borrow(il[45]) + , alu_p_b_borrow(il[46]) + , alu_p_sub_a_hi(il[47]) + , alu_p_sub_a_lo(il[48]) + , alu_p_sub_b_hi(il[49]) + , alu_p_sub_b_lo(il[50]) + , alu_partial_prod_hi(il[51]) + , alu_partial_prod_lo(il[52]) + , alu_quotient_hi(il[53]) + , alu_quotient_lo(il[54]) + , alu_remainder(il[55]) + , alu_res_hi(il[56]) + , alu_res_lo(il[57]) + , alu_sel_alu(il[58]) + , alu_sel_cmp(il[59]) + , alu_sel_div_rng_chk(il[60]) + , alu_sel_rng_chk(il[61]) + , alu_sel_rng_chk_lookup(il[62]) + , alu_sel_shift_which(il[63]) + , alu_shift_lt_bit_len(il[64]) + , alu_t_sub_s_bits(il[65]) + , alu_two_pow_s(il[66]) + , alu_two_pow_t_sub_s(il[67]) + , alu_u128_tag(il[68]) + , alu_u16_r0(il[69]) + , alu_u16_r1(il[70]) + , alu_u16_r10(il[71]) + , alu_u16_r11(il[72]) + , alu_u16_r12(il[73]) + , alu_u16_r13(il[74]) + , alu_u16_r14(il[75]) + , alu_u16_r2(il[76]) + , alu_u16_r3(il[77]) + , alu_u16_r4(il[78]) + , alu_u16_r5(il[79]) + , alu_u16_r6(il[80]) + , alu_u16_r7(il[81]) + , alu_u16_r8(il[82]) + , alu_u16_r9(il[83]) + , alu_u16_tag(il[84]) + , alu_u32_tag(il[85]) + , alu_u64_tag(il[86]) + , alu_u8_r0(il[87]) + , alu_u8_r1(il[88]) + , alu_u8_tag(il[89]) + , binary_acc_ia(il[90]) + , binary_acc_ib(il[91]) + , binary_acc_ic(il[92]) + , binary_clk(il[93]) + , binary_ia_bytes(il[94]) + , binary_ib_bytes(il[95]) + , binary_ic_bytes(il[96]) + , binary_in_tag(il[97]) + , binary_mem_tag_ctr(il[98]) + , binary_mem_tag_ctr_inv(il[99]) + , binary_op_id(il[100]) + , binary_sel_bin(il[101]) + , binary_start(il[102]) + , byte_lookup_sel_bin(il[103]) + , byte_lookup_table_byte_lengths(il[104]) + , byte_lookup_table_in_tags(il[105]) + , byte_lookup_table_input_a(il[106]) + , byte_lookup_table_input_b(il[107]) + , byte_lookup_table_op_id(il[108]) + , byte_lookup_table_output(il[109]) + , conversion_clk(il[110]) + , conversion_input(il[111]) + , conversion_num_limbs(il[112]) + , conversion_radix(il[113]) + , conversion_sel_to_radix_le(il[114]) + , gas_da_gas_fixed_table(il[115]) + , gas_l2_gas_fixed_table(il[116]) + , gas_sel_gas_cost(il[117]) + , keccakf1600_clk(il[118]) + , keccakf1600_input(il[119]) + , keccakf1600_output(il[120]) + , keccakf1600_sel_keccakf1600(il[121]) + , kernel_emit_l2_to_l1_msg_write_offset(il[122]) + , kernel_emit_note_hash_write_offset(il[123]) + , kernel_emit_nullifier_write_offset(il[124]) + , kernel_emit_unencrypted_log_write_offset(il[125]) + , kernel_kernel_in_offset(il[126]) + , kernel_kernel_out_offset(il[127]) + , kernel_l1_to_l2_msg_exists_write_offset(il[128]) + , kernel_note_hash_exist_write_offset(il[129]) + , kernel_nullifier_exists_write_offset(il[130]) + , kernel_nullifier_non_exists_write_offset(il[131]) + , kernel_q_public_input_kernel_add_to_table(il[132]) + , kernel_q_public_input_kernel_out_add_to_table(il[133]) + , kernel_side_effect_counter(il[134]) + , kernel_sload_write_offset(il[135]) + , kernel_sstore_write_offset(il[136]) + , main_abs_da_rem_gas_hi(il[137]) + , main_abs_da_rem_gas_lo(il[138]) + , main_abs_l2_rem_gas_hi(il[139]) + , main_abs_l2_rem_gas_lo(il[140]) + , main_alu_in_tag(il[141]) + , main_bin_op_id(il[142]) + , main_call_ptr(il[143]) + , main_da_gas_op_cost(il[144]) + , main_da_gas_remaining(il[145]) + , main_da_out_of_gas(il[146]) + , main_ia(il[147]) + , main_ib(il[148]) + , main_ic(il[149]) + , main_id(il[150]) + , main_id_zero(il[151]) + , main_ind_addr_a(il[152]) + , main_ind_addr_b(il[153]) + , main_ind_addr_c(il[154]) + , main_ind_addr_d(il[155]) + , main_internal_return_ptr(il[156]) + , main_inv(il[157]) + , main_l2_gas_op_cost(il[158]) + , main_l2_gas_remaining(il[159]) + , main_l2_out_of_gas(il[160]) + , main_mem_addr_a(il[161]) + , main_mem_addr_b(il[162]) + , main_mem_addr_c(il[163]) + , main_mem_addr_d(il[164]) + , main_op_err(il[165]) + , main_opcode_val(il[166]) + , main_pc(il[167]) + , main_r_in_tag(il[168]) + , main_rwa(il[169]) + , main_rwb(il[170]) + , main_rwc(il[171]) + , main_rwd(il[172]) + , main_sel_alu(il[173]) + , main_sel_bin(il[174]) + , main_sel_gas_accounting_active(il[175]) + , main_sel_last(il[176]) + , main_sel_mem_op_a(il[177]) + , main_sel_mem_op_activate_gas(il[178]) + , main_sel_mem_op_b(il[179]) + , main_sel_mem_op_c(il[180]) + , main_sel_mem_op_d(il[181]) + , main_sel_mov_ia_to_ic(il[182]) + , main_sel_mov_ib_to_ic(il[183]) + , main_sel_op_add(il[184]) + , main_sel_op_address(il[185]) + , main_sel_op_and(il[186]) + , main_sel_op_block_number(il[187]) + , main_sel_op_cast(il[188]) + , main_sel_op_chain_id(il[189]) + , main_sel_op_cmov(il[190]) + , main_sel_op_coinbase(il[191]) + , main_sel_op_dagasleft(il[192]) + , main_sel_op_div(il[193]) + , main_sel_op_emit_l2_to_l1_msg(il[194]) + , main_sel_op_emit_note_hash(il[195]) + , main_sel_op_emit_nullifier(il[196]) + , main_sel_op_emit_unencrypted_log(il[197]) + , main_sel_op_eq(il[198]) + , main_sel_op_external_call(il[199]) + , main_sel_op_fdiv(il[200]) + , main_sel_op_fee_per_da_gas(il[201]) + , main_sel_op_fee_per_l2_gas(il[202]) + , main_sel_op_function_selector(il[203]) + , main_sel_op_get_contract_instance(il[204]) + , main_sel_op_halt(il[205]) + , main_sel_op_internal_call(il[206]) + , main_sel_op_internal_return(il[207]) + , main_sel_op_jump(il[208]) + , main_sel_op_jumpi(il[209]) + , main_sel_op_keccak(il[210]) + , main_sel_op_l1_to_l2_msg_exists(il[211]) + , main_sel_op_l2gasleft(il[212]) + , main_sel_op_lt(il[213]) + , main_sel_op_lte(il[214]) + , main_sel_op_mov(il[215]) + , main_sel_op_mul(il[216]) + , main_sel_op_not(il[217]) + , main_sel_op_note_hash_exists(il[218]) + , main_sel_op_nullifier_exists(il[219]) + , main_sel_op_or(il[220]) + , main_sel_op_pedersen(il[221]) + , main_sel_op_poseidon2(il[222]) + , main_sel_op_radix_le(il[223]) + , main_sel_op_sender(il[224]) + , main_sel_op_sha256(il[225]) + , main_sel_op_shl(il[226]) + , main_sel_op_shr(il[227]) + , main_sel_op_sload(il[228]) + , main_sel_op_sstore(il[229]) + , main_sel_op_storage_address(il[230]) + , main_sel_op_sub(il[231]) + , main_sel_op_timestamp(il[232]) + , main_sel_op_transaction_fee(il[233]) + , main_sel_op_version(il[234]) + , main_sel_op_xor(il[235]) + , main_sel_q_kernel_lookup(il[236]) + , main_sel_q_kernel_output_lookup(il[237]) + , main_sel_resolve_ind_addr_a(il[238]) + , main_sel_resolve_ind_addr_b(il[239]) + , main_sel_resolve_ind_addr_c(il[240]) + , main_sel_resolve_ind_addr_d(il[241]) + , main_sel_rng_16(il[242]) + , main_sel_rng_8(il[243]) + , main_space_id(il[244]) + , main_tag_err(il[245]) + , main_w_in_tag(il[246]) + , mem_addr(il[247]) + , mem_clk(il[248]) + , mem_diff_hi(il[249]) + , mem_diff_lo(il[250]) + , mem_diff_mid(il[251]) + , mem_glob_addr(il[252]) + , mem_last(il[253]) + , mem_lastAccess(il[254]) + , mem_one_min_inv(il[255]) + , mem_r_in_tag(il[256]) + , mem_rw(il[257]) + , mem_sel_mem(il[258]) + , mem_sel_mov_ia_to_ic(il[259]) + , mem_sel_mov_ib_to_ic(il[260]) + , mem_sel_op_a(il[261]) + , mem_sel_op_b(il[262]) + , mem_sel_op_c(il[263]) + , mem_sel_op_cmov(il[264]) + , mem_sel_op_d(il[265]) + , mem_sel_resolve_ind_addr_a(il[266]) + , mem_sel_resolve_ind_addr_b(il[267]) + , mem_sel_resolve_ind_addr_c(il[268]) + , mem_sel_resolve_ind_addr_d(il[269]) + , mem_sel_rng_chk(il[270]) + , mem_skip_check_tag(il[271]) + , mem_space_id(il[272]) + , mem_tag(il[273]) + , mem_tag_err(il[274]) + , mem_tsp(il[275]) + , mem_val(il[276]) + , mem_w_in_tag(il[277]) + , pedersen_clk(il[278]) + , pedersen_input(il[279]) + , pedersen_output(il[280]) + , pedersen_sel_pedersen(il[281]) + , poseidon2_clk(il[282]) + , poseidon2_input(il[283]) + , poseidon2_output(il[284]) + , poseidon2_sel_poseidon_perm(il[285]) + , powers_power_of_2(il[286]) + , sha256_clk(il[287]) + , sha256_input(il[288]) + , sha256_output(il[289]) + , sha256_sel_sha256_compression(il[290]) + , sha256_state(il[291]) + , perm_main_alu(il[292]) + , perm_main_bin(il[293]) + , perm_main_conv(il[294]) + , perm_main_pos2_perm(il[295]) + , perm_main_pedersen(il[296]) + , perm_main_mem_a(il[297]) + , perm_main_mem_b(il[298]) + , perm_main_mem_c(il[299]) + , perm_main_mem_d(il[300]) + , perm_main_mem_ind_addr_a(il[301]) + , perm_main_mem_ind_addr_b(il[302]) + , perm_main_mem_ind_addr_c(il[303]) + , perm_main_mem_ind_addr_d(il[304]) + , lookup_byte_lengths(il[305]) + , lookup_byte_operations(il[306]) + , lookup_opcode_gas(il[307]) + , range_check_l2_gas_hi(il[308]) + , range_check_l2_gas_lo(il[309]) + , range_check_da_gas_hi(il[310]) + , range_check_da_gas_lo(il[311]) + , kernel_output_lookup(il[312]) + , lookup_into_kernel(il[313]) + , incl_main_tag_err(il[314]) + , incl_mem_tag_err(il[315]) + , lookup_mem_rng_chk_lo(il[316]) + , lookup_mem_rng_chk_mid(il[317]) + , lookup_mem_rng_chk_hi(il[318]) + , lookup_pow_2_0(il[319]) + , lookup_pow_2_1(il[320]) + , lookup_u8_0(il[321]) + , lookup_u8_1(il[322]) + , lookup_u16_0(il[323]) + , lookup_u16_1(il[324]) + , lookup_u16_2(il[325]) + , lookup_u16_3(il[326]) + , lookup_u16_4(il[327]) + , lookup_u16_5(il[328]) + , lookup_u16_6(il[329]) + , lookup_u16_7(il[330]) + , lookup_u16_8(il[331]) + , lookup_u16_9(il[332]) + , lookup_u16_10(il[333]) + , lookup_u16_11(il[334]) + , lookup_u16_12(il[335]) + , lookup_u16_13(il[336]) + , lookup_u16_14(il[337]) + , lookup_div_u16_0(il[338]) + , lookup_div_u16_1(il[339]) + , lookup_div_u16_2(il[340]) + , lookup_div_u16_3(il[341]) + , lookup_div_u16_4(il[342]) + , lookup_div_u16_5(il[343]) + , lookup_div_u16_6(il[344]) + , lookup_div_u16_7(il[345]) + , lookup_byte_lengths_counts(il[346]) + , lookup_byte_operations_counts(il[347]) + , lookup_opcode_gas_counts(il[348]) + , range_check_l2_gas_hi_counts(il[349]) + , range_check_l2_gas_lo_counts(il[350]) + , range_check_da_gas_hi_counts(il[351]) + , range_check_da_gas_lo_counts(il[352]) + , kernel_output_lookup_counts(il[353]) + , lookup_into_kernel_counts(il[354]) + , incl_main_tag_err_counts(il[355]) + , incl_mem_tag_err_counts(il[356]) + , lookup_mem_rng_chk_lo_counts(il[357]) + , lookup_mem_rng_chk_mid_counts(il[358]) + , lookup_mem_rng_chk_hi_counts(il[359]) + , lookup_pow_2_0_counts(il[360]) + , lookup_pow_2_1_counts(il[361]) + , lookup_u8_0_counts(il[362]) + , lookup_u8_1_counts(il[363]) + , lookup_u16_0_counts(il[364]) + , lookup_u16_1_counts(il[365]) + , lookup_u16_2_counts(il[366]) + , lookup_u16_3_counts(il[367]) + , lookup_u16_4_counts(il[368]) + , lookup_u16_5_counts(il[369]) + , lookup_u16_6_counts(il[370]) + , lookup_u16_7_counts(il[371]) + , lookup_u16_8_counts(il[372]) + , lookup_u16_9_counts(il[373]) + , lookup_u16_10_counts(il[374]) + , lookup_u16_11_counts(il[375]) + , lookup_u16_12_counts(il[376]) + , lookup_u16_13_counts(il[377]) + , lookup_u16_14_counts(il[378]) + , lookup_div_u16_0_counts(il[379]) + , lookup_div_u16_1_counts(il[380]) + , lookup_div_u16_2_counts(il[381]) + , lookup_div_u16_3_counts(il[382]) + , lookup_div_u16_4_counts(il[383]) + , lookup_div_u16_5_counts(il[384]) + , lookup_div_u16_6_counts(il[385]) + , lookup_div_u16_7_counts(il[386]) + , alu_a_hi_shift(il[387]) + , alu_a_lo_shift(il[388]) + , alu_b_hi_shift(il[389]) + , alu_b_lo_shift(il[390]) + , alu_cmp_rng_ctr_shift(il[391]) + , alu_div_u16_r0_shift(il[392]) + , alu_div_u16_r1_shift(il[393]) + , alu_div_u16_r2_shift(il[394]) + , alu_div_u16_r3_shift(il[395]) + , alu_div_u16_r4_shift(il[396]) + , alu_div_u16_r5_shift(il[397]) + , alu_div_u16_r6_shift(il[398]) + , alu_div_u16_r7_shift(il[399]) + , alu_op_add_shift(il[400]) + , alu_op_cast_prev_shift(il[401]) + , alu_op_cast_shift(il[402]) + , alu_op_div_shift(il[403]) + , alu_op_mul_shift(il[404]) + , alu_op_shl_shift(il[405]) + , alu_op_shr_shift(il[406]) + , alu_op_sub_shift(il[407]) + , alu_p_sub_a_hi_shift(il[408]) + , alu_p_sub_a_lo_shift(il[409]) + , alu_p_sub_b_hi_shift(il[410]) + , alu_p_sub_b_lo_shift(il[411]) + , alu_sel_alu_shift(il[412]) + , alu_sel_cmp_shift(il[413]) + , alu_sel_div_rng_chk_shift(il[414]) + , alu_sel_rng_chk_lookup_shift(il[415]) + , alu_sel_rng_chk_shift(il[416]) + , alu_u16_r0_shift(il[417]) + , alu_u16_r1_shift(il[418]) + , alu_u16_r2_shift(il[419]) + , alu_u16_r3_shift(il[420]) + , alu_u16_r4_shift(il[421]) + , alu_u16_r5_shift(il[422]) + , alu_u16_r6_shift(il[423]) + , alu_u8_r0_shift(il[424]) + , alu_u8_r1_shift(il[425]) + , binary_acc_ia_shift(il[426]) + , binary_acc_ib_shift(il[427]) + , binary_acc_ic_shift(il[428]) + , binary_mem_tag_ctr_shift(il[429]) + , binary_op_id_shift(il[430]) + , kernel_emit_l2_to_l1_msg_write_offset_shift(il[431]) + , kernel_emit_note_hash_write_offset_shift(il[432]) + , kernel_emit_nullifier_write_offset_shift(il[433]) + , kernel_emit_unencrypted_log_write_offset_shift(il[434]) + , kernel_l1_to_l2_msg_exists_write_offset_shift(il[435]) + , kernel_note_hash_exist_write_offset_shift(il[436]) + , kernel_nullifier_exists_write_offset_shift(il[437]) + , kernel_nullifier_non_exists_write_offset_shift(il[438]) + , kernel_side_effect_counter_shift(il[439]) + , kernel_sload_write_offset_shift(il[440]) + , kernel_sstore_write_offset_shift(il[441]) + , main_da_gas_remaining_shift(il[442]) + , main_internal_return_ptr_shift(il[443]) + , main_l2_gas_remaining_shift(il[444]) + , main_pc_shift(il[445]) + , mem_glob_addr_shift(il[446]) + , mem_rw_shift(il[447]) + , mem_sel_mem_shift(il[448]) + , mem_tag_shift(il[449]) + , mem_tsp_shift(il[450]) + , mem_val_shift(il[451]) + {} + }; + /** * @brief A container for the prover polynomials handles. */ @@ -897,13 +1805,460 @@ class AvmFlavor { * @brief Returns the evaluations of all prover polynomials at one point on the boolean hypercube, which * represents one row in the execution trace. */ - [[nodiscard]] AllValues get_row(size_t row_idx) const + [[nodiscard]] AllConstRefValues get_row(size_t row_idx) const { - AllValues result; - for (auto [result_field, polynomial] : zip_view(result.get_all(), this->get_all())) { - result_field = polynomial[row_idx]; - } - return result; + return AllConstRefValues(RefArray{ main_clk[row_idx], + main_sel_first[row_idx], + kernel_kernel_inputs[row_idx], + kernel_kernel_value_out[row_idx], + kernel_kernel_side_effect_out[row_idx], + kernel_kernel_metadata_out[row_idx], + main_calldata[row_idx], + alu_a_hi[row_idx], + alu_a_lo[row_idx], + alu_b_hi[row_idx], + alu_b_lo[row_idx], + alu_borrow[row_idx], + alu_cf[row_idx], + alu_clk[row_idx], + alu_cmp_rng_ctr[row_idx], + alu_div_u16_r0[row_idx], + alu_div_u16_r1[row_idx], + alu_div_u16_r2[row_idx], + alu_div_u16_r3[row_idx], + alu_div_u16_r4[row_idx], + alu_div_u16_r5[row_idx], + alu_div_u16_r6[row_idx], + alu_div_u16_r7[row_idx], + alu_divisor_hi[row_idx], + alu_divisor_lo[row_idx], + alu_ff_tag[row_idx], + alu_ia[row_idx], + alu_ib[row_idx], + alu_ic[row_idx], + alu_in_tag[row_idx], + alu_op_add[row_idx], + alu_op_cast[row_idx], + alu_op_cast_prev[row_idx], + alu_op_div[row_idx], + alu_op_div_a_lt_b[row_idx], + alu_op_div_std[row_idx], + alu_op_eq[row_idx], + alu_op_eq_diff_inv[row_idx], + alu_op_lt[row_idx], + alu_op_lte[row_idx], + alu_op_mul[row_idx], + alu_op_not[row_idx], + alu_op_shl[row_idx], + alu_op_shr[row_idx], + alu_op_sub[row_idx], + alu_p_a_borrow[row_idx], + alu_p_b_borrow[row_idx], + alu_p_sub_a_hi[row_idx], + alu_p_sub_a_lo[row_idx], + alu_p_sub_b_hi[row_idx], + alu_p_sub_b_lo[row_idx], + alu_partial_prod_hi[row_idx], + alu_partial_prod_lo[row_idx], + alu_quotient_hi[row_idx], + alu_quotient_lo[row_idx], + alu_remainder[row_idx], + alu_res_hi[row_idx], + alu_res_lo[row_idx], + alu_sel_alu[row_idx], + alu_sel_cmp[row_idx], + alu_sel_div_rng_chk[row_idx], + alu_sel_rng_chk[row_idx], + alu_sel_rng_chk_lookup[row_idx], + alu_sel_shift_which[row_idx], + alu_shift_lt_bit_len[row_idx], + alu_t_sub_s_bits[row_idx], + alu_two_pow_s[row_idx], + alu_two_pow_t_sub_s[row_idx], + alu_u128_tag[row_idx], + alu_u16_r0[row_idx], + alu_u16_r1[row_idx], + alu_u16_r10[row_idx], + alu_u16_r11[row_idx], + alu_u16_r12[row_idx], + alu_u16_r13[row_idx], + alu_u16_r14[row_idx], + alu_u16_r2[row_idx], + alu_u16_r3[row_idx], + alu_u16_r4[row_idx], + alu_u16_r5[row_idx], + alu_u16_r6[row_idx], + alu_u16_r7[row_idx], + alu_u16_r8[row_idx], + alu_u16_r9[row_idx], + alu_u16_tag[row_idx], + alu_u32_tag[row_idx], + alu_u64_tag[row_idx], + alu_u8_r0[row_idx], + alu_u8_r1[row_idx], + alu_u8_tag[row_idx], + binary_acc_ia[row_idx], + binary_acc_ib[row_idx], + binary_acc_ic[row_idx], + binary_clk[row_idx], + binary_ia_bytes[row_idx], + binary_ib_bytes[row_idx], + binary_ic_bytes[row_idx], + binary_in_tag[row_idx], + binary_mem_tag_ctr[row_idx], + binary_mem_tag_ctr_inv[row_idx], + binary_op_id[row_idx], + binary_sel_bin[row_idx], + binary_start[row_idx], + byte_lookup_sel_bin[row_idx], + byte_lookup_table_byte_lengths[row_idx], + byte_lookup_table_in_tags[row_idx], + byte_lookup_table_input_a[row_idx], + byte_lookup_table_input_b[row_idx], + byte_lookup_table_op_id[row_idx], + byte_lookup_table_output[row_idx], + conversion_clk[row_idx], + conversion_input[row_idx], + conversion_num_limbs[row_idx], + conversion_radix[row_idx], + conversion_sel_to_radix_le[row_idx], + gas_da_gas_fixed_table[row_idx], + gas_l2_gas_fixed_table[row_idx], + gas_sel_gas_cost[row_idx], + keccakf1600_clk[row_idx], + keccakf1600_input[row_idx], + keccakf1600_output[row_idx], + keccakf1600_sel_keccakf1600[row_idx], + kernel_emit_l2_to_l1_msg_write_offset[row_idx], + kernel_emit_note_hash_write_offset[row_idx], + kernel_emit_nullifier_write_offset[row_idx], + kernel_emit_unencrypted_log_write_offset[row_idx], + kernel_kernel_in_offset[row_idx], + kernel_kernel_out_offset[row_idx], + kernel_l1_to_l2_msg_exists_write_offset[row_idx], + kernel_note_hash_exist_write_offset[row_idx], + kernel_nullifier_exists_write_offset[row_idx], + kernel_nullifier_non_exists_write_offset[row_idx], + kernel_q_public_input_kernel_add_to_table[row_idx], + kernel_q_public_input_kernel_out_add_to_table[row_idx], + kernel_side_effect_counter[row_idx], + kernel_sload_write_offset[row_idx], + kernel_sstore_write_offset[row_idx], + main_abs_da_rem_gas_hi[row_idx], + main_abs_da_rem_gas_lo[row_idx], + main_abs_l2_rem_gas_hi[row_idx], + main_abs_l2_rem_gas_lo[row_idx], + main_alu_in_tag[row_idx], + main_bin_op_id[row_idx], + main_call_ptr[row_idx], + main_da_gas_op_cost[row_idx], + main_da_gas_remaining[row_idx], + main_da_out_of_gas[row_idx], + main_ia[row_idx], + main_ib[row_idx], + main_ic[row_idx], + main_id[row_idx], + main_id_zero[row_idx], + main_ind_addr_a[row_idx], + main_ind_addr_b[row_idx], + main_ind_addr_c[row_idx], + main_ind_addr_d[row_idx], + main_internal_return_ptr[row_idx], + main_inv[row_idx], + main_l2_gas_op_cost[row_idx], + main_l2_gas_remaining[row_idx], + main_l2_out_of_gas[row_idx], + main_mem_addr_a[row_idx], + main_mem_addr_b[row_idx], + main_mem_addr_c[row_idx], + main_mem_addr_d[row_idx], + main_op_err[row_idx], + main_opcode_val[row_idx], + main_pc[row_idx], + main_r_in_tag[row_idx], + main_rwa[row_idx], + main_rwb[row_idx], + main_rwc[row_idx], + main_rwd[row_idx], + main_sel_alu[row_idx], + main_sel_bin[row_idx], + main_sel_gas_accounting_active[row_idx], + main_sel_last[row_idx], + main_sel_mem_op_a[row_idx], + main_sel_mem_op_activate_gas[row_idx], + main_sel_mem_op_b[row_idx], + main_sel_mem_op_c[row_idx], + main_sel_mem_op_d[row_idx], + main_sel_mov_ia_to_ic[row_idx], + main_sel_mov_ib_to_ic[row_idx], + main_sel_op_add[row_idx], + main_sel_op_address[row_idx], + main_sel_op_and[row_idx], + main_sel_op_block_number[row_idx], + main_sel_op_cast[row_idx], + main_sel_op_chain_id[row_idx], + main_sel_op_cmov[row_idx], + main_sel_op_coinbase[row_idx], + main_sel_op_dagasleft[row_idx], + main_sel_op_div[row_idx], + main_sel_op_emit_l2_to_l1_msg[row_idx], + main_sel_op_emit_note_hash[row_idx], + main_sel_op_emit_nullifier[row_idx], + main_sel_op_emit_unencrypted_log[row_idx], + main_sel_op_eq[row_idx], + main_sel_op_external_call[row_idx], + main_sel_op_fdiv[row_idx], + main_sel_op_fee_per_da_gas[row_idx], + main_sel_op_fee_per_l2_gas[row_idx], + main_sel_op_function_selector[row_idx], + main_sel_op_get_contract_instance[row_idx], + main_sel_op_halt[row_idx], + main_sel_op_internal_call[row_idx], + main_sel_op_internal_return[row_idx], + main_sel_op_jump[row_idx], + main_sel_op_jumpi[row_idx], + main_sel_op_keccak[row_idx], + main_sel_op_l1_to_l2_msg_exists[row_idx], + main_sel_op_l2gasleft[row_idx], + main_sel_op_lt[row_idx], + main_sel_op_lte[row_idx], + main_sel_op_mov[row_idx], + main_sel_op_mul[row_idx], + main_sel_op_not[row_idx], + main_sel_op_note_hash_exists[row_idx], + main_sel_op_nullifier_exists[row_idx], + main_sel_op_or[row_idx], + main_sel_op_pedersen[row_idx], + main_sel_op_poseidon2[row_idx], + main_sel_op_radix_le[row_idx], + main_sel_op_sender[row_idx], + main_sel_op_sha256[row_idx], + main_sel_op_shl[row_idx], + main_sel_op_shr[row_idx], + main_sel_op_sload[row_idx], + main_sel_op_sstore[row_idx], + main_sel_op_storage_address[row_idx], + main_sel_op_sub[row_idx], + main_sel_op_timestamp[row_idx], + main_sel_op_transaction_fee[row_idx], + main_sel_op_version[row_idx], + main_sel_op_xor[row_idx], + main_sel_q_kernel_lookup[row_idx], + main_sel_q_kernel_output_lookup[row_idx], + main_sel_resolve_ind_addr_a[row_idx], + main_sel_resolve_ind_addr_b[row_idx], + main_sel_resolve_ind_addr_c[row_idx], + main_sel_resolve_ind_addr_d[row_idx], + main_sel_rng_16[row_idx], + main_sel_rng_8[row_idx], + main_space_id[row_idx], + main_tag_err[row_idx], + main_w_in_tag[row_idx], + mem_addr[row_idx], + mem_clk[row_idx], + mem_diff_hi[row_idx], + mem_diff_lo[row_idx], + mem_diff_mid[row_idx], + mem_glob_addr[row_idx], + mem_last[row_idx], + mem_lastAccess[row_idx], + mem_one_min_inv[row_idx], + mem_r_in_tag[row_idx], + mem_rw[row_idx], + mem_sel_mem[row_idx], + mem_sel_mov_ia_to_ic[row_idx], + mem_sel_mov_ib_to_ic[row_idx], + mem_sel_op_a[row_idx], + mem_sel_op_b[row_idx], + mem_sel_op_c[row_idx], + mem_sel_op_cmov[row_idx], + mem_sel_op_d[row_idx], + mem_sel_resolve_ind_addr_a[row_idx], + mem_sel_resolve_ind_addr_b[row_idx], + mem_sel_resolve_ind_addr_c[row_idx], + mem_sel_resolve_ind_addr_d[row_idx], + mem_sel_rng_chk[row_idx], + mem_skip_check_tag[row_idx], + mem_space_id[row_idx], + mem_tag[row_idx], + mem_tag_err[row_idx], + mem_tsp[row_idx], + mem_val[row_idx], + mem_w_in_tag[row_idx], + pedersen_clk[row_idx], + pedersen_input[row_idx], + pedersen_output[row_idx], + pedersen_sel_pedersen[row_idx], + poseidon2_clk[row_idx], + poseidon2_input[row_idx], + poseidon2_output[row_idx], + poseidon2_sel_poseidon_perm[row_idx], + powers_power_of_2[row_idx], + sha256_clk[row_idx], + sha256_input[row_idx], + sha256_output[row_idx], + sha256_sel_sha256_compression[row_idx], + sha256_state[row_idx], + perm_main_alu[row_idx], + perm_main_bin[row_idx], + perm_main_conv[row_idx], + perm_main_pos2_perm[row_idx], + perm_main_pedersen[row_idx], + perm_main_mem_a[row_idx], + perm_main_mem_b[row_idx], + perm_main_mem_c[row_idx], + perm_main_mem_d[row_idx], + perm_main_mem_ind_addr_a[row_idx], + perm_main_mem_ind_addr_b[row_idx], + perm_main_mem_ind_addr_c[row_idx], + perm_main_mem_ind_addr_d[row_idx], + lookup_byte_lengths[row_idx], + lookup_byte_operations[row_idx], + lookup_opcode_gas[row_idx], + range_check_l2_gas_hi[row_idx], + range_check_l2_gas_lo[row_idx], + range_check_da_gas_hi[row_idx], + range_check_da_gas_lo[row_idx], + kernel_output_lookup[row_idx], + lookup_into_kernel[row_idx], + incl_main_tag_err[row_idx], + incl_mem_tag_err[row_idx], + lookup_mem_rng_chk_lo[row_idx], + lookup_mem_rng_chk_mid[row_idx], + lookup_mem_rng_chk_hi[row_idx], + lookup_pow_2_0[row_idx], + lookup_pow_2_1[row_idx], + lookup_u8_0[row_idx], + lookup_u8_1[row_idx], + lookup_u16_0[row_idx], + lookup_u16_1[row_idx], + lookup_u16_2[row_idx], + lookup_u16_3[row_idx], + lookup_u16_4[row_idx], + lookup_u16_5[row_idx], + lookup_u16_6[row_idx], + lookup_u16_7[row_idx], + lookup_u16_8[row_idx], + lookup_u16_9[row_idx], + lookup_u16_10[row_idx], + lookup_u16_11[row_idx], + lookup_u16_12[row_idx], + lookup_u16_13[row_idx], + lookup_u16_14[row_idx], + lookup_div_u16_0[row_idx], + lookup_div_u16_1[row_idx], + lookup_div_u16_2[row_idx], + lookup_div_u16_3[row_idx], + lookup_div_u16_4[row_idx], + lookup_div_u16_5[row_idx], + lookup_div_u16_6[row_idx], + lookup_div_u16_7[row_idx], + lookup_byte_lengths_counts[row_idx], + lookup_byte_operations_counts[row_idx], + lookup_opcode_gas_counts[row_idx], + range_check_l2_gas_hi_counts[row_idx], + range_check_l2_gas_lo_counts[row_idx], + range_check_da_gas_hi_counts[row_idx], + range_check_da_gas_lo_counts[row_idx], + kernel_output_lookup_counts[row_idx], + lookup_into_kernel_counts[row_idx], + incl_main_tag_err_counts[row_idx], + incl_mem_tag_err_counts[row_idx], + lookup_mem_rng_chk_lo_counts[row_idx], + lookup_mem_rng_chk_mid_counts[row_idx], + lookup_mem_rng_chk_hi_counts[row_idx], + lookup_pow_2_0_counts[row_idx], + lookup_pow_2_1_counts[row_idx], + lookup_u8_0_counts[row_idx], + lookup_u8_1_counts[row_idx], + lookup_u16_0_counts[row_idx], + lookup_u16_1_counts[row_idx], + lookup_u16_2_counts[row_idx], + lookup_u16_3_counts[row_idx], + lookup_u16_4_counts[row_idx], + lookup_u16_5_counts[row_idx], + lookup_u16_6_counts[row_idx], + lookup_u16_7_counts[row_idx], + lookup_u16_8_counts[row_idx], + lookup_u16_9_counts[row_idx], + lookup_u16_10_counts[row_idx], + lookup_u16_11_counts[row_idx], + lookup_u16_12_counts[row_idx], + lookup_u16_13_counts[row_idx], + lookup_u16_14_counts[row_idx], + lookup_div_u16_0_counts[row_idx], + lookup_div_u16_1_counts[row_idx], + lookup_div_u16_2_counts[row_idx], + lookup_div_u16_3_counts[row_idx], + lookup_div_u16_4_counts[row_idx], + lookup_div_u16_5_counts[row_idx], + lookup_div_u16_6_counts[row_idx], + lookup_div_u16_7_counts[row_idx], + alu_a_hi_shift[row_idx], + alu_a_lo_shift[row_idx], + alu_b_hi_shift[row_idx], + alu_b_lo_shift[row_idx], + alu_cmp_rng_ctr_shift[row_idx], + alu_div_u16_r0_shift[row_idx], + alu_div_u16_r1_shift[row_idx], + alu_div_u16_r2_shift[row_idx], + alu_div_u16_r3_shift[row_idx], + alu_div_u16_r4_shift[row_idx], + alu_div_u16_r5_shift[row_idx], + alu_div_u16_r6_shift[row_idx], + alu_div_u16_r7_shift[row_idx], + alu_op_add_shift[row_idx], + alu_op_cast_prev_shift[row_idx], + alu_op_cast_shift[row_idx], + alu_op_div_shift[row_idx], + alu_op_mul_shift[row_idx], + alu_op_shl_shift[row_idx], + alu_op_shr_shift[row_idx], + alu_op_sub_shift[row_idx], + alu_p_sub_a_hi_shift[row_idx], + alu_p_sub_a_lo_shift[row_idx], + alu_p_sub_b_hi_shift[row_idx], + alu_p_sub_b_lo_shift[row_idx], + alu_sel_alu_shift[row_idx], + alu_sel_cmp_shift[row_idx], + alu_sel_div_rng_chk_shift[row_idx], + alu_sel_rng_chk_lookup_shift[row_idx], + alu_sel_rng_chk_shift[row_idx], + alu_u16_r0_shift[row_idx], + alu_u16_r1_shift[row_idx], + alu_u16_r2_shift[row_idx], + alu_u16_r3_shift[row_idx], + alu_u16_r4_shift[row_idx], + alu_u16_r5_shift[row_idx], + alu_u16_r6_shift[row_idx], + alu_u8_r0_shift[row_idx], + alu_u8_r1_shift[row_idx], + binary_acc_ia_shift[row_idx], + binary_acc_ib_shift[row_idx], + binary_acc_ic_shift[row_idx], + binary_mem_tag_ctr_shift[row_idx], + binary_op_id_shift[row_idx], + kernel_emit_l2_to_l1_msg_write_offset_shift[row_idx], + kernel_emit_note_hash_write_offset_shift[row_idx], + kernel_emit_nullifier_write_offset_shift[row_idx], + kernel_emit_unencrypted_log_write_offset_shift[row_idx], + kernel_l1_to_l2_msg_exists_write_offset_shift[row_idx], + kernel_note_hash_exist_write_offset_shift[row_idx], + kernel_nullifier_exists_write_offset_shift[row_idx], + kernel_nullifier_non_exists_write_offset_shift[row_idx], + kernel_side_effect_counter_shift[row_idx], + kernel_sload_write_offset_shift[row_idx], + kernel_sstore_write_offset_shift[row_idx], + main_da_gas_remaining_shift[row_idx], + main_internal_return_ptr_shift[row_idx], + main_l2_gas_remaining_shift[row_idx], + main_pc_shift[row_idx], + mem_glob_addr_shift[row_idx], + mem_rw_shift[row_idx], + mem_sel_mem_shift[row_idx], + mem_tag_shift[row_idx], + mem_tsp_shift[row_idx], + mem_val_shift[row_idx] }); } }; diff --git a/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs index 8b3ee2445db1..948fb907d011 100644 --- a/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs @@ -134,12 +134,6 @@ class {{name}}Flavor { , public WitnessEntities , public ShiftedEntities { public: - AllEntities() - : PrecomputedEntities{} - , WitnessEntities{} - , ShiftedEntities{} - {} - DEFINE_COMPOUND_GET_ALL(PrecomputedEntities, WitnessEntities, ShiftedEntities) auto get_unshifted() { @@ -164,12 +158,30 @@ class {{name}}Flavor { using VerificationKey = VerificationKey_, VerifierCommitmentKey>; + {{!-- Used by sumcheck --}} class AllValues : public AllEntities { public: using Base = AllEntities; using Base::Base; }; - + + {{!-- Used by get_row, logderivs, etc --}} + class AllConstRefValues { + public: + using DataType = const FF&; + + {{!-- + We define the flavor members here again to avoid having to make this class inherit from AllEntities. + If we did inherit from AllEntities, we have to define a special constructor for AllEntities, and all + the classes that AllEntities inherits from, in cascade. + --}} + DEFINE_FLAVOR_MEMBERS(DataType, {{#each all_cols_and_shifts as |item|}}{{#if @index}},{{/if}}{{item}}{{/each}}) + + AllConstRefValues(const RefArray& il) : + {{#each all_cols_and_shifts as |item|}}{{item}}(il[{{@index}}]){{#unless @last}},{{/unless}}{{/each}} + {} + }; + /** * @brief A container for the prover polynomials handles. */ @@ -200,13 +212,24 @@ class {{name}}Flavor { * @brief Returns the evaluations of all prover polynomials at one point on the boolean hypercube, which * represents one row in the execution trace. */ - [[nodiscard]] AllValues get_row(size_t row_idx) const + [[nodiscard]] AllConstRefValues get_row(size_t row_idx) const { - AllValues result; - for (auto [result_field, polynomial] : zip_view(result.get_all(), this->get_all())) { - result_field = polynomial[row_idx]; + {{!-- + // TODO: try to make something like this work. + // Right now it's too risky because it relies on the order of the columns in `get_all()`. + RefArray all_cols = get_all(); + std::array refs; + for (size_t i = 0; i < refs.size(); ++i) { + refs[i] = &all_cols[i][row_idx]; } - return result; + // Note: the order of the constructor must match the order of the columns in `get_all()`! + return AllConstRefValues(refs); + --}} + return AllConstRefValues(RefArray{ + {{#each all_cols_and_shifts as |item|}} + {{item}}[row_idx]{{#unless @last}},{{/unless}} + {{/each}} + }); } }; From ec39e4e2ffecb6d6e355eb3963008b710cc11d2c Mon Sep 17 00:00:00 2001 From: Jean M <132435771+jeanmon@users.noreply.github.com> Date: Wed, 10 Jul 2024 18:06:08 +0200 Subject: [PATCH 09/32] feat(avm): calldatacopy and return gadget (#7415) Resolves #7381 Resolves #7211 --- .../cpp/pil/avm/gadgets/mem_slice.pil | 77 ++ barretenberg/cpp/pil/avm/main.pil | 30 +- barretenberg/cpp/pil/avm/mem.pil | 24 +- .../relations/generated/avm/declare_views.hpp | 35 +- .../generated/avm/lookup_cd_value.hpp | 67 + .../generated/avm/lookup_ret_value.hpp | 67 + .../relations/generated/avm/main.hpp | 595 ++++----- .../relations/generated/avm/mem.hpp | 164 +-- .../relations/generated/avm/mem_slice.hpp | 154 +++ .../relations/generated/avm/perm_cd_mem.hpp | 60 + .../generated/avm/perm_main_cd_copy.hpp | 64 + .../generated/avm/perm_main_return.hpp | 106 ++ .../generated/avm/perm_main_slice.hpp | 72 ++ .../generated/avm/perm_return_mem.hpp | 102 ++ .../generated/avm/perm_slice_mem.hpp | 64 + .../vm/avm_trace/avm_execution.cpp | 28 +- .../vm/avm_trace/avm_gas_trace.cpp | 2 +- .../barretenberg/vm/avm_trace/avm_helper.cpp | 42 +- .../barretenberg/vm/avm_trace/avm_helper.hpp | 10 +- .../vm/avm_trace/avm_mem_trace.cpp | 114 +- .../vm/avm_trace/avm_mem_trace.hpp | 12 +- .../barretenberg/vm/avm_trace/avm_trace.cpp | 391 +++--- .../barretenberg/vm/avm_trace/avm_trace.hpp | 3 + .../vm/avm_trace/gadgets/avm_slice_trace.cpp | 74 ++ .../vm/avm_trace/gadgets/avm_slice_trace.hpp | 75 ++ .../vm/generated/avm_circuit_builder.cpp | 853 +++++++++++++ .../vm/generated/avm_circuit_builder.hpp | 54 +- .../barretenberg/vm/generated/avm_flavor.hpp | 1090 ++++++++++------- .../vm/generated/avm_full_row.cpp | 48 + .../vm/generated/avm_full_row.hpp | 24 + .../vm/generated/avm_verifier.cpp | 11 + .../vm/tests/avm_arithmetic.test.cpp | 39 +- .../vm/tests/avm_bitwise.test.cpp | 10 +- .../barretenberg/vm/tests/avm_cast.test.cpp | 92 +- .../vm/tests/avm_control_flow.test.cpp | 2 +- .../vm/tests/avm_execution.test.cpp | 26 +- .../vm/tests/avm_indirect_mem.test.cpp | 2 +- .../vm/tests/avm_inter_table.test.cpp | 202 +-- .../vm/tests/avm_mem_opcodes.test.cpp | 150 ++- .../barretenberg/vm/tests/avm_memory.test.cpp | 2 +- .../barretenberg/vm/tests/avm_slice.test.cpp | 337 +++++ .../barretenberg/vm/tests/helpers.test.cpp | 16 +- .../barretenberg/vm/tests/helpers.test.hpp | 5 +- 43 files changed, 4018 insertions(+), 1377 deletions(-) create mode 100644 barretenberg/cpp/pil/avm/gadgets/mem_slice.pil create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_cd_value.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_ret_value.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/mem_slice.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_cd_mem.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_cd_copy.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_return.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_slice.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_return_mem.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_slice_mem.hpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_slice_trace.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_slice_trace.hpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/tests/avm_slice.test.cpp diff --git a/barretenberg/cpp/pil/avm/gadgets/mem_slice.pil b/barretenberg/cpp/pil/avm/gadgets/mem_slice.pil new file mode 100644 index 000000000000..2fa6f61afe68 --- /dev/null +++ b/barretenberg/cpp/pil/avm/gadgets/mem_slice.pil @@ -0,0 +1,77 @@ +include "../main.pil"; + +namespace slice(256); + + pol commit clk; + + pol commit sel_start; // Selector to indicate the start of calldatacopy/return. Used in permutation with the main trace. + pol commit sel_cd_cpy; // Selector for any row involved in a callatacopy operation. + pol commit sel_return; // Selector for any row involved in a return operation. + pol commit sel_mem_active; // Selector for any row involved in a memory operation + pol commit cnt; // Decreasing counter to track the number of memory operations. + pol commit space_id; // Copied from main trace. + pol commit addr; // Address pertaining to the memory operation. + pol commit val; // Value pertaining to the memory operation. + pol commit col_offset; // Offset of the public column element. It is used to get the correct value from calldata/returndata. + pol commit one_min_inv; // Helper column to assert zero/non-zero equality of cnt; + + // We use a counter corresponding to the number of memory operations. The counter + // is initialized by copying the size argument from the main trace. The counter column + // is shared for CALLDATACOPY and RETURN opcodes. The counter is decreased until + // it reaches the value zero. Each row with a non-zero counter corresponds to + // a memory operation. The following relations ensure that exactly one operation + // selector sel_cd_cpy/sel_return is activated per row with a non-zero counter and + // that within a given operation the pertaining selector is enabled. (One prevents + // to activate sel_return during a callatacopy operation and vice-versa.) + + sel_mem_active = sel_cd_cpy + sel_return; + + // Instruction decomposition guarantees that sel_cd_cpy and sel_return are mutually exclusive on + // the first row of the calldatcopy/return operation. + + // Show that cnt != 0 <==> sel_mem_active == 1 + // one_min_inv == 1 - cnt^(-1) if cnt != 0 else == 0 + #[SLICE_CNT_ZERO_TEST1] + cnt * (1 - one_min_inv) - sel_mem_active = 0; + #[SLICE_CNT_ZERO_TEST2] + (1 - sel_mem_active) * one_min_inv = 0; + + #[SLICE_CNT_DECREMENT] + sel_mem_active * (cnt - 1 - cnt') = 0; + #[ADDR_INCREMENT] + sel_mem_active * (addr + 1 - addr') = 0; + #[COL_OFFSET_INCREMENT] + sel_mem_active * (col_offset + 1 - col_offset') = 0; + #[SAME_CLK] + sel_mem_active * (clk - clk') = 0; + #[SAME_SPACE_ID] + sel_mem_active * (space_id - space_id') = 0; + #[SAME_SEL_RETURN] + sel_mem_active * sel_mem_active' * (sel_return - sel_return') = 0; + #[SAME_SEL_CD_CPY] + sel_mem_active * sel_mem_active' * (sel_cd_cpy - sel_cd_cpy') = 0; + + #[SEL_MEM_INACTIVE] + (1 - sel_mem_active) * sel_mem_active' * (1 - sel_start') = 0; + + // The above relation is crucial to prevent a malicious prover of adding extra active rows + // after the row with cnt == 0 unless another operation starts (sel_start == 1). This relation + // implies that whenever sel_mem_active == 0 and sel_start' != 1, sel_mem_active' == 0. + // Note that the malicious prover can fill other columns such as clk or even sel_cd_cpy + // but as long sel_mem_active == 0, it does not lead to any memory operations. The latter + // is guarded by sel_mem_active in #[PERM_SLICE_MEM] below. + + #[LOOKUP_CD_VALUE] + sel_cd_cpy {col_offset, val} in main.sel_calldata {main.clk, main.calldata}; + + #[PERM_SLICE_MEM] + sel_mem_active {clk, space_id, addr, val, sel_cd_cpy} + is + mem.sel_op_slice {mem.clk, mem.space_id, mem.addr, mem.val, mem.rw}; + + // Caution: sel_op_slice disables the tag check during a read. This is required for the RETURN opcode + // but could have bad consequences if one adds additional "read" operations as part of this gadget. + // In such a case, we have to disable tag check specifically for RETURN opcode. + + #[LOOKUP_RET_VALUE] + sel_return {col_offset, val} in main.sel_returndata {main.clk, main.returndata}; \ No newline at end of file diff --git a/barretenberg/cpp/pil/avm/main.pil b/barretenberg/cpp/pil/avm/main.pil index 7858269448b4..c498e242b814 100644 --- a/barretenberg/cpp/pil/avm/main.pil +++ b/barretenberg/cpp/pil/avm/main.pil @@ -11,6 +11,7 @@ include "gadgets/sha256.pil"; include "gadgets/poseidon2.pil"; include "gadgets/keccakf1600.pil"; include "gadgets/pedersen.pil"; +include "gadgets/mem_slice.pil"; namespace main(256); //===== CONSTANT POLYNOMIALS ================================================== @@ -20,6 +21,9 @@ namespace main(256); //===== PUBLIC COLUMNS========================================================= pol public calldata; + pol commit sel_calldata; // Selector used for lookup in calldata. TODO: Might be removed or made constant. + pol public returndata; + pol commit sel_returndata; // Selector used for lookup in returndata. TODO: Might be removed or made constant. //===== KERNEL INPUTS ========================================================= // Kernel lookup selector opcodes @@ -139,6 +143,10 @@ namespace main(256); pol commit sel_op_keccak; pol commit sel_op_pedersen; + //===== Memory Slice Gadget Selectors ========================================= + pol commit sel_op_calldata_copy; + pol commit sel_op_external_return; + //===== Fix Range Checks Selectors============================================= // We re-use the clk column for the lookup values of 8-bit resp. 16-bit range check. pol commit sel_rng_8; // Boolean selector for the 8-bit range check lookup @@ -321,6 +329,9 @@ namespace main(256); sel_op_halt * (1 - sel_op_halt) = 0; sel_op_external_call * (1 - sel_op_external_call) = 0; + sel_op_calldata_copy * (1 - sel_op_calldata_copy) = 0; + sel_op_external_return * (1 - sel_op_external_return) = 0; + // Might be removed if derived from opcode based on a lookup of constants sel_op_mov * ( 1 - sel_op_mov) = 0; sel_op_cmov * ( 1 - sel_op_cmov) = 0; @@ -473,12 +484,13 @@ namespace main(256); pol SEL_ALL_BINARY = sel_op_and + sel_op_or + sel_op_xor; pol SEL_ALL_GADGET = sel_op_radix_le + sel_op_sha256 + sel_op_poseidon2 + sel_op_keccak + sel_op_pedersen; pol SEL_ALL_MEMORY = sel_op_cmov + sel_op_mov; + pol SEL_ALL_MEM_SLICE = sel_op_calldata_copy + sel_op_external_return; pol OPCODE_SELECTORS = sel_op_fdiv + SEL_ALU_ALL + SEL_ALL_BINARY + SEL_ALL_MEMORY + SEL_ALL_GADGET - + KERNEL_INPUT_SELECTORS + KERNEL_OUTPUT_SELECTORS + SEL_ALL_LEFTGAS; + + KERNEL_INPUT_SELECTORS + KERNEL_OUTPUT_SELECTORS + SEL_ALL_LEFTGAS + SEL_ALL_MEM_SLICE; // TODO: sel_gas_accounting_active is activating gas accounting on a given row. All opcode with selectors // are activated through the relation below. The other opcodes which are implemented purely - // through memory sub-operations such as CALLDATACOPY, RETURN, SET are activated by + // through memory sub-operations such as RETURN, SET are activated by // setting a newly introduced boolean sel_mem_op_activate_gas which is set in witness generation. // We should remove this shortcut and constrain this activation through bytecode decomposition. // Alternatively, we introduce a boolean selector for the three opcodes mentioned above. @@ -656,13 +668,20 @@ namespace main(256); // We increment the side effect counter by 1 KERNEL_OUTPUT_SELECTORS * (kernel.side_effect_counter' - (kernel.side_effect_counter + 1)) = 0; + //===== Memory Slice Constraints ============================================ + pol commit sel_slice_gadget; // Selector to activate a slice gadget operation in the gadget (#[PERM_MAIN_SLICE]). + + // Activate only if tag_err is disabled + sel_slice_gadget = (sel_op_calldata_copy + sel_op_external_return) * (1 - tag_err); + + //====== Inter-table Constraints ============================================ + #[KERNEL_OUTPUT_LOOKUP] sel_q_kernel_output_lookup {kernel.kernel_out_offset, ia, kernel.side_effect_counter, ib} in kernel.q_public_input_kernel_out_add_to_table {clk, kernel.kernel_value_out, kernel.kernel_side_effect_out, kernel.kernel_metadata_out}; #[LOOKUP_INTO_KERNEL] sel_q_kernel_lookup { main.ia, kernel.kernel_in_offset } in kernel.q_public_input_kernel_add_to_table { kernel.kernel_inputs, clk }; - //====== Inter-table Constraints ============================================ #[INCL_MAIN_TAG_ERR] mem.tag_err {mem.clk} in tag_err {clk}; @@ -723,6 +742,11 @@ namespace main(256); is pedersen.sel_pedersen {pedersen.clk, pedersen.input}; + #[PERM_MAIN_SLICE] + sel_slice_gadget {clk, space_id, ia, ib, mem_addr_c, sel_op_calldata_copy, sel_op_external_return} + is + slice.sel_start {slice.clk, slice.space_id, slice.col_offset, slice.cnt, slice.addr, slice.sel_cd_cpy, slice.sel_return}; + #[PERM_MAIN_MEM_A] sel_mem_op_a {clk, space_id, mem_addr_a, ia, rwa, r_in_tag, w_in_tag, sel_mov_ia_to_ic, sel_op_cmov} is diff --git a/barretenberg/cpp/pil/avm/mem.pil b/barretenberg/cpp/pil/avm/mem.pil index 0cb9d7c491ae..781d2891add9 100644 --- a/barretenberg/cpp/pil/avm/mem.pil +++ b/barretenberg/cpp/pil/avm/mem.pil @@ -32,6 +32,9 @@ namespace mem(256); pol commit sel_resolve_ind_addr_c; pol commit sel_resolve_ind_addr_d; + // Selector for calldata_copy/return memory operations triggered from memory slice gadget. + pol commit sel_op_slice; + // Selectors related to MOV/CMOV opcodes (copied from main trace for loading operation on intermediated register ia/ib) // Boolean constraint is performed in main trace. pol commit sel_mov_ia_to_ic; @@ -57,6 +60,7 @@ namespace mem(256); sel_op_b * (1 - sel_op_b) = 0; sel_op_c * (1 - sel_op_c) = 0; sel_op_d * (1 - sel_op_d) = 0; + sel_op_slice * (1 - sel_op_slice) = 0; sel_resolve_ind_addr_a * (1 - sel_resolve_ind_addr_a) = 0; sel_resolve_ind_addr_b * (1 - sel_resolve_ind_addr_b) = 0; sel_resolve_ind_addr_c * (1 - sel_resolve_ind_addr_c) = 0; @@ -66,8 +70,9 @@ namespace mem(256); // 2) Ensure that tag, r_in_tag, w_in_tag are properly constrained by the main trace and/or bytecode decomposition // Definition of sel_mem - sel_mem = sel_op_a + sel_op_b + sel_op_c + sel_op_d + - sel_resolve_ind_addr_a + sel_resolve_ind_addr_b + sel_resolve_ind_addr_c + sel_resolve_ind_addr_d; + sel_mem = sel_op_a + sel_op_b + sel_op_c + sel_op_d + + sel_resolve_ind_addr_a + sel_resolve_ind_addr_b + sel_resolve_ind_addr_c + sel_resolve_ind_addr_d + + sel_op_slice; // Maximum one memory operation enabled per row sel_mem * (sel_mem - 1) = 0; // TODO: might be infered by the main trace @@ -99,6 +104,12 @@ namespace mem(256); pol SUB_CLK = sel_mem * (sel_resolve_ind_addr_b + sel_op_b + 2 * (sel_resolve_ind_addr_c + sel_op_c) + 3 * (sel_resolve_ind_addr_d + sel_op_d) + 4 * (1 - IND_OP + rw)); // We need the sel_mem factor as the right factor is not zero when all columns are zero. + // Calldata_copy memory slice operations will have a sub_clk value of 8 as rw == 1 which is outside of the range of + // indirect memory operations. This is crucial as a main trace entry for calldata_copy triggers an indirect memory + // load operation for intermediate register c. The write slice memory operations will have the same sub_clk which in + // this particular case is not a problem as all addresses are different. Similarly return memory slice operations + // will have a sub_clk value of 4. + #[TIMESTAMP] tsp = NUM_SUB_CLK * clk + SUB_CLK; @@ -154,9 +165,10 @@ namespace mem(256); #[MEM_ZERO_INIT] lastAccess * (1 - rw') * val' = 0; - // Skip check tag + // TODO: Verfiy that skip_check_tag cannot be enabled maliciously by the prover. + // Skip check tag enabled for some MOV/CMOV opcodes and RETURN opcode (sel_op_slice) #[SKIP_CHECK_TAG] - skip_check_tag = sel_op_cmov * (sel_op_d + sel_op_a * (1-sel_mov_ia_to_ic) + sel_op_b * (1-sel_mov_ib_to_ic)); + skip_check_tag = sel_op_cmov * (sel_op_d + sel_op_a * (1-sel_mov_ia_to_ic) + sel_op_b * (1-sel_mov_ib_to_ic)) + sel_op_slice; // Memory tag consistency check for load operations, i.e., rw == 0. // We want to prove that r_in_tag == tag <==> tag_err == 0 @@ -207,6 +219,10 @@ namespace mem(256); sel_resolve_ind_addr_c * rw = 0; sel_resolve_ind_addr_d * rw = 0; + //====== CALLDATACOPY/RETURN specific constraints ================================== + sel_op_slice * (w_in_tag - 6) = 0; // Only write elements of type FF + sel_op_slice * (r_in_tag - 6) = 0; // Only read elements of type FF + //====== MOV/CMOV Opcode Tag Constraint ===================================== // The following constraint ensures that the r_in_tag is set to tag for // the load operation pertaining to Ia resp. Ib. diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp index f0c272ca4f7f..60916f5b0433 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp @@ -10,6 +10,7 @@ [[maybe_unused]] auto kernel_kernel_side_effect_out = View(new_term.kernel_kernel_side_effect_out); \ [[maybe_unused]] auto kernel_kernel_metadata_out = View(new_term.kernel_kernel_metadata_out); \ [[maybe_unused]] auto main_calldata = View(new_term.main_calldata); \ + [[maybe_unused]] auto main_returndata = View(new_term.main_returndata); \ [[maybe_unused]] auto alu_a_hi = View(new_term.alu_a_hi); \ [[maybe_unused]] auto alu_a_lo = View(new_term.alu_a_lo); \ [[maybe_unused]] auto alu_b_hi = View(new_term.alu_b_hi); \ @@ -184,6 +185,7 @@ [[maybe_unused]] auto main_rwd = View(new_term.main_rwd); \ [[maybe_unused]] auto main_sel_alu = View(new_term.main_sel_alu); \ [[maybe_unused]] auto main_sel_bin = View(new_term.main_sel_bin); \ + [[maybe_unused]] auto main_sel_calldata = View(new_term.main_sel_calldata); \ [[maybe_unused]] auto main_sel_gas_accounting_active = View(new_term.main_sel_gas_accounting_active); \ [[maybe_unused]] auto main_sel_last = View(new_term.main_sel_last); \ [[maybe_unused]] auto main_sel_mem_op_a = View(new_term.main_sel_mem_op_a); \ @@ -197,6 +199,7 @@ [[maybe_unused]] auto main_sel_op_address = View(new_term.main_sel_op_address); \ [[maybe_unused]] auto main_sel_op_and = View(new_term.main_sel_op_and); \ [[maybe_unused]] auto main_sel_op_block_number = View(new_term.main_sel_op_block_number); \ + [[maybe_unused]] auto main_sel_op_calldata_copy = View(new_term.main_sel_op_calldata_copy); \ [[maybe_unused]] auto main_sel_op_cast = View(new_term.main_sel_op_cast); \ [[maybe_unused]] auto main_sel_op_chain_id = View(new_term.main_sel_op_chain_id); \ [[maybe_unused]] auto main_sel_op_cmov = View(new_term.main_sel_op_cmov); \ @@ -209,6 +212,7 @@ [[maybe_unused]] auto main_sel_op_emit_unencrypted_log = View(new_term.main_sel_op_emit_unencrypted_log); \ [[maybe_unused]] auto main_sel_op_eq = View(new_term.main_sel_op_eq); \ [[maybe_unused]] auto main_sel_op_external_call = View(new_term.main_sel_op_external_call); \ + [[maybe_unused]] auto main_sel_op_external_return = View(new_term.main_sel_op_external_return); \ [[maybe_unused]] auto main_sel_op_fdiv = View(new_term.main_sel_op_fdiv); \ [[maybe_unused]] auto main_sel_op_fee_per_da_gas = View(new_term.main_sel_op_fee_per_da_gas); \ [[maybe_unused]] auto main_sel_op_fee_per_l2_gas = View(new_term.main_sel_op_fee_per_l2_gas); \ @@ -251,8 +255,10 @@ [[maybe_unused]] auto main_sel_resolve_ind_addr_b = View(new_term.main_sel_resolve_ind_addr_b); \ [[maybe_unused]] auto main_sel_resolve_ind_addr_c = View(new_term.main_sel_resolve_ind_addr_c); \ [[maybe_unused]] auto main_sel_resolve_ind_addr_d = View(new_term.main_sel_resolve_ind_addr_d); \ + [[maybe_unused]] auto main_sel_returndata = View(new_term.main_sel_returndata); \ [[maybe_unused]] auto main_sel_rng_16 = View(new_term.main_sel_rng_16); \ [[maybe_unused]] auto main_sel_rng_8 = View(new_term.main_sel_rng_8); \ + [[maybe_unused]] auto main_sel_slice_gadget = View(new_term.main_sel_slice_gadget); \ [[maybe_unused]] auto main_space_id = View(new_term.main_space_id); \ [[maybe_unused]] auto main_tag_err = View(new_term.main_tag_err); \ [[maybe_unused]] auto main_w_in_tag = View(new_term.main_w_in_tag); \ @@ -275,6 +281,7 @@ [[maybe_unused]] auto mem_sel_op_c = View(new_term.mem_sel_op_c); \ [[maybe_unused]] auto mem_sel_op_cmov = View(new_term.mem_sel_op_cmov); \ [[maybe_unused]] auto mem_sel_op_d = View(new_term.mem_sel_op_d); \ + [[maybe_unused]] auto mem_sel_op_slice = View(new_term.mem_sel_op_slice); \ [[maybe_unused]] auto mem_sel_resolve_ind_addr_a = View(new_term.mem_sel_resolve_ind_addr_a); \ [[maybe_unused]] auto mem_sel_resolve_ind_addr_b = View(new_term.mem_sel_resolve_ind_addr_b); \ [[maybe_unused]] auto mem_sel_resolve_ind_addr_c = View(new_term.mem_sel_resolve_ind_addr_c); \ @@ -301,11 +308,24 @@ [[maybe_unused]] auto sha256_output = View(new_term.sha256_output); \ [[maybe_unused]] auto sha256_sel_sha256_compression = View(new_term.sha256_sel_sha256_compression); \ [[maybe_unused]] auto sha256_state = View(new_term.sha256_state); \ + [[maybe_unused]] auto slice_addr = View(new_term.slice_addr); \ + [[maybe_unused]] auto slice_clk = View(new_term.slice_clk); \ + [[maybe_unused]] auto slice_cnt = View(new_term.slice_cnt); \ + [[maybe_unused]] auto slice_col_offset = View(new_term.slice_col_offset); \ + [[maybe_unused]] auto slice_one_min_inv = View(new_term.slice_one_min_inv); \ + [[maybe_unused]] auto slice_sel_cd_cpy = View(new_term.slice_sel_cd_cpy); \ + [[maybe_unused]] auto slice_sel_mem_active = View(new_term.slice_sel_mem_active); \ + [[maybe_unused]] auto slice_sel_return = View(new_term.slice_sel_return); \ + [[maybe_unused]] auto slice_sel_start = View(new_term.slice_sel_start); \ + [[maybe_unused]] auto slice_space_id = View(new_term.slice_space_id); \ + [[maybe_unused]] auto slice_val = View(new_term.slice_val); \ + [[maybe_unused]] auto perm_slice_mem = View(new_term.perm_slice_mem); \ [[maybe_unused]] auto perm_main_alu = View(new_term.perm_main_alu); \ [[maybe_unused]] auto perm_main_bin = View(new_term.perm_main_bin); \ [[maybe_unused]] auto perm_main_conv = View(new_term.perm_main_conv); \ [[maybe_unused]] auto perm_main_pos2_perm = View(new_term.perm_main_pos2_perm); \ [[maybe_unused]] auto perm_main_pedersen = View(new_term.perm_main_pedersen); \ + [[maybe_unused]] auto perm_main_slice = View(new_term.perm_main_slice); \ [[maybe_unused]] auto perm_main_mem_a = View(new_term.perm_main_mem_a); \ [[maybe_unused]] auto perm_main_mem_b = View(new_term.perm_main_mem_b); \ [[maybe_unused]] auto perm_main_mem_c = View(new_term.perm_main_mem_c); \ @@ -316,6 +336,8 @@ [[maybe_unused]] auto perm_main_mem_ind_addr_d = View(new_term.perm_main_mem_ind_addr_d); \ [[maybe_unused]] auto lookup_byte_lengths = View(new_term.lookup_byte_lengths); \ [[maybe_unused]] auto lookup_byte_operations = View(new_term.lookup_byte_operations); \ + [[maybe_unused]] auto lookup_cd_value = View(new_term.lookup_cd_value); \ + [[maybe_unused]] auto lookup_ret_value = View(new_term.lookup_ret_value); \ [[maybe_unused]] auto lookup_opcode_gas = View(new_term.lookup_opcode_gas); \ [[maybe_unused]] auto range_check_l2_gas_hi = View(new_term.range_check_l2_gas_hi); \ [[maybe_unused]] auto range_check_l2_gas_lo = View(new_term.range_check_l2_gas_lo); \ @@ -357,6 +379,8 @@ [[maybe_unused]] auto lookup_div_u16_7 = View(new_term.lookup_div_u16_7); \ [[maybe_unused]] auto lookup_byte_lengths_counts = View(new_term.lookup_byte_lengths_counts); \ [[maybe_unused]] auto lookup_byte_operations_counts = View(new_term.lookup_byte_operations_counts); \ + [[maybe_unused]] auto lookup_cd_value_counts = View(new_term.lookup_cd_value_counts); \ + [[maybe_unused]] auto lookup_ret_value_counts = View(new_term.lookup_ret_value_counts); \ [[maybe_unused]] auto lookup_opcode_gas_counts = View(new_term.lookup_opcode_gas_counts); \ [[maybe_unused]] auto range_check_l2_gas_hi_counts = View(new_term.range_check_l2_gas_hi_counts); \ [[maybe_unused]] auto range_check_l2_gas_lo_counts = View(new_term.range_check_l2_gas_lo_counts); \ @@ -468,4 +492,13 @@ [[maybe_unused]] auto mem_sel_mem_shift = View(new_term.mem_sel_mem_shift); \ [[maybe_unused]] auto mem_tag_shift = View(new_term.mem_tag_shift); \ [[maybe_unused]] auto mem_tsp_shift = View(new_term.mem_tsp_shift); \ - [[maybe_unused]] auto mem_val_shift = View(new_term.mem_val_shift); + [[maybe_unused]] auto mem_val_shift = View(new_term.mem_val_shift); \ + [[maybe_unused]] auto slice_addr_shift = View(new_term.slice_addr_shift); \ + [[maybe_unused]] auto slice_clk_shift = View(new_term.slice_clk_shift); \ + [[maybe_unused]] auto slice_cnt_shift = View(new_term.slice_cnt_shift); \ + [[maybe_unused]] auto slice_col_offset_shift = View(new_term.slice_col_offset_shift); \ + [[maybe_unused]] auto slice_sel_cd_cpy_shift = View(new_term.slice_sel_cd_cpy_shift); \ + [[maybe_unused]] auto slice_sel_mem_active_shift = View(new_term.slice_sel_mem_active_shift); \ + [[maybe_unused]] auto slice_sel_return_shift = View(new_term.slice_sel_return_shift); \ + [[maybe_unused]] auto slice_sel_start_shift = View(new_term.slice_sel_start_shift); \ + [[maybe_unused]] auto slice_space_id_shift = View(new_term.slice_space_id_shift); diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_cd_value.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_cd_value.hpp new file mode 100644 index 000000000000..86247444cf0c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_cd_value.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" + +#include +#include + +namespace bb { + +class lookup_cd_value_lookup_settings { + public: + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; + static constexpr size_t LOOKUP_TUPLE_SIZE = 2; + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; + static constexpr size_t READ_TERM_DEGREE = 0; + static constexpr size_t WRITE_TERM_DEGREE = 0; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.slice_sel_cd_cpy == 1 || in.main_sel_calldata == 1); + } + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in.slice_sel_cd_cpy); + const auto is_table_entry = View(in.main_sel_calldata); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return std::forward_as_tuple(in.lookup_cd_value, + in.lookup_cd_value_counts, + in.slice_sel_cd_cpy, + in.main_sel_calldata, + in.slice_col_offset, + in.slice_val, + in.main_clk, + in.main_calldata); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return std::forward_as_tuple(in.lookup_cd_value, + in.lookup_cd_value_counts, + in.slice_sel_cd_cpy, + in.main_sel_calldata, + in.slice_col_offset, + in.slice_val, + in.main_clk, + in.main_calldata); + } +}; + +template +class lookup_cd_value_relation : public GenericLookupRelation { + public: + static constexpr const char* NAME = "lookup_cd_value"; +}; +template using lookup_cd_value = GenericLookup; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_ret_value.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_ret_value.hpp new file mode 100644 index 000000000000..7e341860cb99 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_ret_value.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" + +#include +#include + +namespace bb { + +class lookup_ret_value_lookup_settings { + public: + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; + static constexpr size_t LOOKUP_TUPLE_SIZE = 2; + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; + static constexpr size_t READ_TERM_DEGREE = 0; + static constexpr size_t WRITE_TERM_DEGREE = 0; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.slice_sel_return == 1 || in.main_sel_returndata == 1); + } + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in.slice_sel_return); + const auto is_table_entry = View(in.main_sel_returndata); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return std::forward_as_tuple(in.lookup_ret_value, + in.lookup_ret_value_counts, + in.slice_sel_return, + in.main_sel_returndata, + in.slice_col_offset, + in.slice_val, + in.main_clk, + in.main_returndata); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return std::forward_as_tuple(in.lookup_ret_value, + in.lookup_ret_value_counts, + in.slice_sel_return, + in.main_sel_returndata, + in.slice_col_offset, + in.slice_val, + in.main_clk, + in.main_returndata); + } +}; + +template +class lookup_ret_value_relation : public GenericLookupRelation { + public: + static constexpr const char* NAME = "lookup_ret_value"; +}; +template using lookup_ret_value = GenericLookup; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp index bb16f6812c35..65065fe1f2dd 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp @@ -69,6 +69,7 @@ template struct MainRow { FF main_sel_op_address{}; FF main_sel_op_and{}; FF main_sel_op_block_number{}; + FF main_sel_op_calldata_copy{}; FF main_sel_op_cast{}; FF main_sel_op_chain_id{}; FF main_sel_op_cmov{}; @@ -81,6 +82,7 @@ template struct MainRow { FF main_sel_op_emit_unencrypted_log{}; FF main_sel_op_eq{}; FF main_sel_op_external_call{}; + FF main_sel_op_external_return{}; FF main_sel_op_fdiv{}; FF main_sel_op_fee_per_da_gas{}; FF main_sel_op_fee_per_l2_gas{}; @@ -123,6 +125,7 @@ template struct MainRow { FF main_sel_resolve_ind_addr_b{}; FF main_sel_resolve_ind_addr_c{}; FF main_sel_resolve_ind_addr_d{}; + FF main_sel_slice_gadget{}; FF main_space_id{}; FF main_tag_err{}; FF main_w_in_tag{}; @@ -139,99 +142,99 @@ inline std::string get_relation_label_main(int index) return "L2_GAS_INACTIVE"; case 5: return "DA_GAS_INACTIVE"; - case 75: + case 77: return "OUTPUT_U8"; - case 76: + case 78: return "SUBOP_FDIV"; - case 77: + case 79: return "SUBOP_FDIV_ZERO_ERR1"; - case 78: + case 80: return "SUBOP_FDIV_ZERO_ERR2"; - case 79: + case 81: return "SUBOP_FDIV_R_IN_TAG_FF"; - case 80: + case 82: return "SUBOP_FDIV_W_IN_TAG_FF"; - case 81: + case 83: return "SUBOP_ERROR_RELEVANT_OP"; - case 82: + case 84: return "KERNEL_INPUT_ACTIVE_CHECK"; - case 83: + case 85: return "KERNEL_OUTPUT_ACTIVE_CHECK"; - case 84: + case 86: return "PC_JUMP"; - case 85: + case 87: return "PC_JUMPI"; - case 86: + case 88: return "RETURN_POINTER_INCREMENT"; - case 92: + case 94: return "RETURN_POINTER_DECREMENT"; - case 98: + case 100: return "PC_INCREMENT"; - case 99: + case 101: return "INTERNAL_RETURN_POINTER_CONSISTENCY"; - case 100: + case 102: return "SPACE_ID_INTERNAL"; - case 101: + case 103: return "SPACE_ID_STANDARD_OPCODES"; - case 102: + case 104: return "CMOV_CONDITION_RES_1"; - case 103: + case 105: return "CMOV_CONDITION_RES_2"; - case 106: + case 108: return "MOV_SAME_VALUE_A"; - case 107: + case 109: return "MOV_SAME_VALUE_B"; - case 108: + case 110: return "MOV_MAIN_SAME_TAG"; - case 112: + case 114: return "L2GASLEFT"; - case 113: + case 115: return "DAGASLEFT"; - case 114: + case 116: return "ADDRESS_KERNEL"; - case 115: + case 117: return "STORAGE_ADDRESS_KERNEL"; - case 116: + case 118: return "SENDER_KERNEL"; - case 117: + case 119: return "FUNCTION_SELECTOR_KERNEL"; - case 118: + case 120: return "FEE_TRANSACTION_FEE_KERNEL"; - case 119: + case 121: return "CHAIN_ID_KERNEL"; - case 120: + case 122: return "VERSION_KERNEL"; - case 121: + case 123: return "BLOCK_NUMBER_KERNEL"; - case 122: + case 124: return "TIMESTAMP_KERNEL"; - case 123: + case 125: return "COINBASE_KERNEL"; - case 124: + case 126: return "FEE_DA_GAS_KERNEL"; - case 125: + case 127: return "FEE_L2_GAS_KERNEL"; - case 126: - return "NOTE_HASH_KERNEL_OUTPUT"; case 128: - return "EMIT_NOTE_HASH_KERNEL_OUTPUT"; + return "NOTE_HASH_KERNEL_OUTPUT"; case 130: + return "EMIT_NOTE_HASH_KERNEL_OUTPUT"; + case 132: return "NULLIFIER_EXISTS_KERNEL_OUTPUT"; - case 133: - return "EMIT_NULLIFIER_KERNEL_OUTPUT"; case 135: - return "L1_TO_L2_MSG_EXISTS_KERNEL_OUTPUT"; + return "EMIT_NULLIFIER_KERNEL_OUTPUT"; case 137: - return "EMIT_UNENCRYPTED_LOG_KERNEL_OUTPUT"; + return "L1_TO_L2_MSG_EXISTS_KERNEL_OUTPUT"; case 139: - return "EMIT_L2_TO_L1_MSGS_KERNEL_OUTPUT"; + return "EMIT_UNENCRYPTED_LOG_KERNEL_OUTPUT"; case 141: - return "SLOAD_KERNEL_OUTPUT"; + return "EMIT_L2_TO_L1_MSGS_KERNEL_OUTPUT"; case 143: + return "SLOAD_KERNEL_OUTPUT"; + case 145: return "SSTORE_KERNEL_OUTPUT"; - case 146: + case 149: return "BIN_SEL_1"; - case 147: + case 150: return "BIN_SEL_2"; } return std::to_string(index); @@ -241,11 +244,12 @@ template class mainImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { - 3, 3, 3, 3, 3, 3, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 5, 4, 4, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 5, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2 + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { + 3, 3, 3, 3, 3, 3, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 2, 5, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2 }; template @@ -671,174 +675,188 @@ template class mainImpl { // Contribution 58 { Avm_DECLARE_VIEWS(58); - auto tmp = (main_sel_op_mov * (-main_sel_op_mov + FF(1))); + auto tmp = (main_sel_op_calldata_copy * (-main_sel_op_calldata_copy + FF(1))); tmp *= scaling_factor; std::get<58>(evals) += tmp; } // Contribution 59 { Avm_DECLARE_VIEWS(59); - auto tmp = (main_sel_op_cmov * (-main_sel_op_cmov + FF(1))); + auto tmp = (main_sel_op_external_return * (-main_sel_op_external_return + FF(1))); tmp *= scaling_factor; std::get<59>(evals) += tmp; } // Contribution 60 { Avm_DECLARE_VIEWS(60); - auto tmp = (main_op_err * (-main_op_err + FF(1))); + auto tmp = (main_sel_op_mov * (-main_sel_op_mov + FF(1))); tmp *= scaling_factor; std::get<60>(evals) += tmp; } // Contribution 61 { Avm_DECLARE_VIEWS(61); - auto tmp = (main_tag_err * (-main_tag_err + FF(1))); + auto tmp = (main_sel_op_cmov * (-main_sel_op_cmov + FF(1))); tmp *= scaling_factor; std::get<61>(evals) += tmp; } // Contribution 62 { Avm_DECLARE_VIEWS(62); - auto tmp = (main_id_zero * (-main_id_zero + FF(1))); + auto tmp = (main_op_err * (-main_op_err + FF(1))); tmp *= scaling_factor; std::get<62>(evals) += tmp; } // Contribution 63 { Avm_DECLARE_VIEWS(63); - auto tmp = (main_sel_mem_op_a * (-main_sel_mem_op_a + FF(1))); + auto tmp = (main_tag_err * (-main_tag_err + FF(1))); tmp *= scaling_factor; std::get<63>(evals) += tmp; } // Contribution 64 { Avm_DECLARE_VIEWS(64); - auto tmp = (main_sel_mem_op_b * (-main_sel_mem_op_b + FF(1))); + auto tmp = (main_id_zero * (-main_id_zero + FF(1))); tmp *= scaling_factor; std::get<64>(evals) += tmp; } // Contribution 65 { Avm_DECLARE_VIEWS(65); - auto tmp = (main_sel_mem_op_c * (-main_sel_mem_op_c + FF(1))); + auto tmp = (main_sel_mem_op_a * (-main_sel_mem_op_a + FF(1))); tmp *= scaling_factor; std::get<65>(evals) += tmp; } // Contribution 66 { Avm_DECLARE_VIEWS(66); - auto tmp = (main_sel_mem_op_d * (-main_sel_mem_op_d + FF(1))); + auto tmp = (main_sel_mem_op_b * (-main_sel_mem_op_b + FF(1))); tmp *= scaling_factor; std::get<66>(evals) += tmp; } // Contribution 67 { Avm_DECLARE_VIEWS(67); - auto tmp = (main_rwa * (-main_rwa + FF(1))); + auto tmp = (main_sel_mem_op_c * (-main_sel_mem_op_c + FF(1))); tmp *= scaling_factor; std::get<67>(evals) += tmp; } // Contribution 68 { Avm_DECLARE_VIEWS(68); - auto tmp = (main_rwb * (-main_rwb + FF(1))); + auto tmp = (main_sel_mem_op_d * (-main_sel_mem_op_d + FF(1))); tmp *= scaling_factor; std::get<68>(evals) += tmp; } // Contribution 69 { Avm_DECLARE_VIEWS(69); - auto tmp = (main_rwc * (-main_rwc + FF(1))); + auto tmp = (main_rwa * (-main_rwa + FF(1))); tmp *= scaling_factor; std::get<69>(evals) += tmp; } // Contribution 70 { Avm_DECLARE_VIEWS(70); - auto tmp = (main_rwd * (-main_rwd + FF(1))); + auto tmp = (main_rwb * (-main_rwb + FF(1))); tmp *= scaling_factor; std::get<70>(evals) += tmp; } // Contribution 71 { Avm_DECLARE_VIEWS(71); - auto tmp = (main_sel_resolve_ind_addr_a * (-main_sel_resolve_ind_addr_a + FF(1))); + auto tmp = (main_rwc * (-main_rwc + FF(1))); tmp *= scaling_factor; std::get<71>(evals) += tmp; } // Contribution 72 { Avm_DECLARE_VIEWS(72); - auto tmp = (main_sel_resolve_ind_addr_b * (-main_sel_resolve_ind_addr_b + FF(1))); + auto tmp = (main_rwd * (-main_rwd + FF(1))); tmp *= scaling_factor; std::get<72>(evals) += tmp; } // Contribution 73 { Avm_DECLARE_VIEWS(73); - auto tmp = (main_sel_resolve_ind_addr_c * (-main_sel_resolve_ind_addr_c + FF(1))); + auto tmp = (main_sel_resolve_ind_addr_a * (-main_sel_resolve_ind_addr_a + FF(1))); tmp *= scaling_factor; std::get<73>(evals) += tmp; } // Contribution 74 { Avm_DECLARE_VIEWS(74); - auto tmp = (main_sel_resolve_ind_addr_d * (-main_sel_resolve_ind_addr_d + FF(1))); + auto tmp = (main_sel_resolve_ind_addr_b * (-main_sel_resolve_ind_addr_b + FF(1))); tmp *= scaling_factor; std::get<74>(evals) += tmp; } // Contribution 75 { Avm_DECLARE_VIEWS(75); - auto tmp = (((main_sel_op_eq + main_sel_op_lte) + main_sel_op_lt) * (main_w_in_tag - FF(1))); + auto tmp = (main_sel_resolve_ind_addr_c * (-main_sel_resolve_ind_addr_c + FF(1))); tmp *= scaling_factor; std::get<75>(evals) += tmp; } // Contribution 76 { Avm_DECLARE_VIEWS(76); - auto tmp = ((main_sel_op_fdiv * (-main_op_err + FF(1))) * ((main_ic * main_ib) - main_ia)); + auto tmp = (main_sel_resolve_ind_addr_d * (-main_sel_resolve_ind_addr_d + FF(1))); tmp *= scaling_factor; std::get<76>(evals) += tmp; } // Contribution 77 { Avm_DECLARE_VIEWS(77); - auto tmp = ((main_sel_op_fdiv + main_sel_op_div) * (((main_ib * main_inv) - FF(1)) + main_op_err)); + auto tmp = (((main_sel_op_eq + main_sel_op_lte) + main_sel_op_lt) * (main_w_in_tag - FF(1))); tmp *= scaling_factor; std::get<77>(evals) += tmp; } // Contribution 78 { Avm_DECLARE_VIEWS(78); - auto tmp = (((main_sel_op_fdiv + main_sel_op_div) * main_op_err) * (-main_inv + FF(1))); + auto tmp = ((main_sel_op_fdiv * (-main_op_err + FF(1))) * ((main_ic * main_ib) - main_ia)); tmp *= scaling_factor; std::get<78>(evals) += tmp; } // Contribution 79 { Avm_DECLARE_VIEWS(79); - auto tmp = (main_sel_op_fdiv * (main_r_in_tag - FF(6))); + auto tmp = ((main_sel_op_fdiv + main_sel_op_div) * (((main_ib * main_inv) - FF(1)) + main_op_err)); tmp *= scaling_factor; std::get<79>(evals) += tmp; } // Contribution 80 { Avm_DECLARE_VIEWS(80); - auto tmp = (main_sel_op_fdiv * (main_w_in_tag - FF(6))); + auto tmp = (((main_sel_op_fdiv + main_sel_op_div) * main_op_err) * (-main_inv + FF(1))); tmp *= scaling_factor; std::get<80>(evals) += tmp; } // Contribution 81 { Avm_DECLARE_VIEWS(81); - auto tmp = (main_op_err * ((main_sel_op_fdiv + main_sel_op_div) - FF(1))); + auto tmp = (main_sel_op_fdiv * (main_r_in_tag - FF(6))); tmp *= scaling_factor; std::get<81>(evals) += tmp; } // Contribution 82 { Avm_DECLARE_VIEWS(82); + auto tmp = (main_sel_op_fdiv * (main_w_in_tag - FF(6))); + tmp *= scaling_factor; + std::get<82>(evals) += tmp; + } + // Contribution 83 + { + Avm_DECLARE_VIEWS(83); + auto tmp = (main_op_err * ((main_sel_op_fdiv + main_sel_op_div) - FF(1))); + tmp *= scaling_factor; + std::get<83>(evals) += tmp; + } + // Contribution 84 + { + Avm_DECLARE_VIEWS(84); auto tmp = ((((((((((((main_sel_op_address + main_sel_op_storage_address) + main_sel_op_sender) + main_sel_op_function_selector) + main_sel_op_transaction_fee) + @@ -851,11 +869,11 @@ template class mainImpl { main_sel_op_fee_per_da_gas) * (-main_sel_q_kernel_lookup + FF(1))); tmp *= scaling_factor; - std::get<82>(evals) += tmp; + std::get<84>(evals) += tmp; } - // Contribution 83 + // Contribution 85 { - Avm_DECLARE_VIEWS(83); + Avm_DECLARE_VIEWS(85); auto tmp = (((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + main_sel_op_emit_nullifier) + @@ -864,197 +882,182 @@ template class mainImpl { main_sel_op_emit_l2_to_l1_msg) * (-main_sel_q_kernel_output_lookup + FF(1))); tmp *= scaling_factor; - std::get<83>(evals) += tmp; - } - // Contribution 84 - { - Avm_DECLARE_VIEWS(84); - auto tmp = (main_sel_op_jump * (main_pc_shift - main_ia)); - tmp *= scaling_factor; - std::get<84>(evals) += tmp; - } - // Contribution 85 - { - Avm_DECLARE_VIEWS(85); - auto tmp = (main_sel_op_jumpi * (((-main_id_zero + FF(1)) * (main_pc_shift - main_ia)) + - (main_id_zero * ((main_pc_shift - main_pc) - FF(1))))); - tmp *= scaling_factor; std::get<85>(evals) += tmp; } // Contribution 86 { Avm_DECLARE_VIEWS(86); - auto tmp = - (main_sel_op_internal_call * (main_internal_return_ptr_shift - (main_internal_return_ptr + FF(1)))); + auto tmp = (main_sel_op_jump * (main_pc_shift - main_ia)); tmp *= scaling_factor; std::get<86>(evals) += tmp; } // Contribution 87 { Avm_DECLARE_VIEWS(87); - auto tmp = (main_sel_op_internal_call * (main_internal_return_ptr - main_mem_addr_b)); + auto tmp = (main_sel_op_jumpi * (((-main_id_zero + FF(1)) * (main_pc_shift - main_ia)) + + (main_id_zero * ((main_pc_shift - main_pc) - FF(1))))); tmp *= scaling_factor; std::get<87>(evals) += tmp; } // Contribution 88 { Avm_DECLARE_VIEWS(88); - auto tmp = (main_sel_op_internal_call * (main_pc_shift - main_ia)); + auto tmp = + (main_sel_op_internal_call * (main_internal_return_ptr_shift - (main_internal_return_ptr + FF(1)))); tmp *= scaling_factor; std::get<88>(evals) += tmp; } // Contribution 89 { Avm_DECLARE_VIEWS(89); - auto tmp = (main_sel_op_internal_call * ((main_pc + FF(1)) - main_ib)); + auto tmp = (main_sel_op_internal_call * (main_internal_return_ptr - main_mem_addr_b)); tmp *= scaling_factor; std::get<89>(evals) += tmp; } // Contribution 90 { Avm_DECLARE_VIEWS(90); - auto tmp = (main_sel_op_internal_call * (main_rwb - FF(1))); + auto tmp = (main_sel_op_internal_call * (main_pc_shift - main_ia)); tmp *= scaling_factor; std::get<90>(evals) += tmp; } // Contribution 91 { Avm_DECLARE_VIEWS(91); - auto tmp = (main_sel_op_internal_call * (main_sel_mem_op_b - FF(1))); + auto tmp = (main_sel_op_internal_call * ((main_pc + FF(1)) - main_ib)); tmp *= scaling_factor; std::get<91>(evals) += tmp; } // Contribution 92 { Avm_DECLARE_VIEWS(92); - auto tmp = - (main_sel_op_internal_return * (main_internal_return_ptr_shift - (main_internal_return_ptr - FF(1)))); + auto tmp = (main_sel_op_internal_call * (main_rwb - FF(1))); tmp *= scaling_factor; std::get<92>(evals) += tmp; } // Contribution 93 { Avm_DECLARE_VIEWS(93); - auto tmp = (main_sel_op_internal_return * ((main_internal_return_ptr - FF(1)) - main_mem_addr_a)); + auto tmp = (main_sel_op_internal_call * (main_sel_mem_op_b - FF(1))); tmp *= scaling_factor; std::get<93>(evals) += tmp; } // Contribution 94 { Avm_DECLARE_VIEWS(94); - auto tmp = (main_sel_op_internal_return * (main_pc_shift - main_ia)); + auto tmp = + (main_sel_op_internal_return * (main_internal_return_ptr_shift - (main_internal_return_ptr - FF(1)))); tmp *= scaling_factor; std::get<94>(evals) += tmp; } // Contribution 95 { Avm_DECLARE_VIEWS(95); - auto tmp = (main_sel_op_internal_return * main_rwa); + auto tmp = (main_sel_op_internal_return * ((main_internal_return_ptr - FF(1)) - main_mem_addr_a)); tmp *= scaling_factor; std::get<95>(evals) += tmp; } // Contribution 96 { Avm_DECLARE_VIEWS(96); - auto tmp = (main_sel_op_internal_return * (main_sel_mem_op_a - FF(1))); + auto tmp = (main_sel_op_internal_return * (main_pc_shift - main_ia)); tmp *= scaling_factor; std::get<96>(evals) += tmp; } // Contribution 97 { Avm_DECLARE_VIEWS(97); - auto tmp = - (((((main_sel_gas_accounting_active - - (((((((main_sel_op_fdiv + - ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + - main_sel_op_not) + - main_sel_op_eq) + - main_sel_op_lt) + - main_sel_op_lte) + - main_sel_op_shr) + - main_sel_op_shl) + - main_sel_op_cast)) + - ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)) + - (main_sel_op_cmov + main_sel_op_mov)) + - ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + main_sel_op_keccak) + - main_sel_op_pedersen)) + - (((((((((((main_sel_op_address + main_sel_op_storage_address) + main_sel_op_sender) + - main_sel_op_function_selector) + - main_sel_op_transaction_fee) + - main_sel_op_chain_id) + - main_sel_op_version) + - main_sel_op_block_number) + - main_sel_op_coinbase) + - main_sel_op_timestamp) + - main_sel_op_fee_per_l2_gas) + - main_sel_op_fee_per_da_gas)) + - ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + - main_sel_op_nullifier_exists) + - main_sel_op_emit_nullifier) + - main_sel_op_l1_to_l2_msg_exists) + - main_sel_op_emit_unencrypted_log) + - main_sel_op_emit_l2_to_l1_msg)) + - (main_sel_op_dagasleft + main_sel_op_l2gasleft))) - - (((main_sel_op_jump + main_sel_op_jumpi) + main_sel_op_internal_call) + - main_sel_op_internal_return)) - - main_sel_op_sload) - - main_sel_op_sstore) - - main_sel_mem_op_activate_gas); + auto tmp = (main_sel_op_internal_return * main_rwa); tmp *= scaling_factor; std::get<97>(evals) += tmp; } // Contribution 98 { Avm_DECLARE_VIEWS(98); - auto tmp = - ((((-main_sel_first + FF(1)) * (-main_sel_op_halt + FF(1))) * - (((((((main_sel_op_fdiv + - ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + - main_sel_op_not) + - main_sel_op_eq) + - main_sel_op_lt) + - main_sel_op_lte) + - main_sel_op_shr) + - main_sel_op_shl) + - main_sel_op_cast)) + - ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)) + - (main_sel_op_cmov + main_sel_op_mov)) + - ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + main_sel_op_keccak) + - main_sel_op_pedersen)) + - (((((((((((main_sel_op_address + main_sel_op_storage_address) + main_sel_op_sender) + - main_sel_op_function_selector) + - main_sel_op_transaction_fee) + - main_sel_op_chain_id) + - main_sel_op_version) + - main_sel_op_block_number) + - main_sel_op_coinbase) + - main_sel_op_timestamp) + - main_sel_op_fee_per_l2_gas) + - main_sel_op_fee_per_da_gas)) + - ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + - main_sel_op_emit_nullifier) + - main_sel_op_l1_to_l2_msg_exists) + - main_sel_op_emit_unencrypted_log) + - main_sel_op_emit_l2_to_l1_msg)) + - (main_sel_op_dagasleft + main_sel_op_l2gasleft))) * - (main_pc_shift - (main_pc + FF(1)))); + auto tmp = (main_sel_op_internal_return * (main_sel_mem_op_a - FF(1))); tmp *= scaling_factor; std::get<98>(evals) += tmp; } // Contribution 99 { Avm_DECLARE_VIEWS(99); - auto tmp = - ((-(((main_sel_first + main_sel_op_internal_call) + main_sel_op_internal_return) + main_sel_op_halt) + - FF(1)) * - (main_internal_return_ptr_shift - main_internal_return_ptr)); + auto tmp = (((((main_sel_gas_accounting_active - + ((((((((main_sel_op_fdiv + + ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + + main_sel_op_not) + + main_sel_op_eq) + + main_sel_op_lt) + + main_sel_op_lte) + + main_sel_op_shr) + + main_sel_op_shl) + + main_sel_op_cast)) + + ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)) + + (main_sel_op_cmov + main_sel_op_mov)) + + ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + + main_sel_op_keccak) + + main_sel_op_pedersen)) + + (((((((((((main_sel_op_address + main_sel_op_storage_address) + main_sel_op_sender) + + main_sel_op_function_selector) + + main_sel_op_transaction_fee) + + main_sel_op_chain_id) + + main_sel_op_version) + + main_sel_op_block_number) + + main_sel_op_coinbase) + + main_sel_op_timestamp) + + main_sel_op_fee_per_l2_gas) + + main_sel_op_fee_per_da_gas)) + + ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + + main_sel_op_nullifier_exists) + + main_sel_op_emit_nullifier) + + main_sel_op_l1_to_l2_msg_exists) + + main_sel_op_emit_unencrypted_log) + + main_sel_op_emit_l2_to_l1_msg)) + + (main_sel_op_dagasleft + main_sel_op_l2gasleft)) + + (main_sel_op_calldata_copy + main_sel_op_external_return))) - + (((main_sel_op_jump + main_sel_op_jumpi) + main_sel_op_internal_call) + + main_sel_op_internal_return)) - + main_sel_op_sload) - + main_sel_op_sstore) - + main_sel_mem_op_activate_gas); tmp *= scaling_factor; std::get<99>(evals) += tmp; } // Contribution 100 { Avm_DECLARE_VIEWS(100); - auto tmp = ((main_sel_op_internal_call + main_sel_op_internal_return) * (main_space_id - FF(255))); + auto tmp = + ((((-main_sel_first + FF(1)) * (-main_sel_op_halt + FF(1))) * + ((((((((main_sel_op_fdiv + + ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + + main_sel_op_not) + + main_sel_op_eq) + + main_sel_op_lt) + + main_sel_op_lte) + + main_sel_op_shr) + + main_sel_op_shl) + + main_sel_op_cast)) + + ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)) + + (main_sel_op_cmov + main_sel_op_mov)) + + ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + main_sel_op_keccak) + + main_sel_op_pedersen)) + + (((((((((((main_sel_op_address + main_sel_op_storage_address) + main_sel_op_sender) + + main_sel_op_function_selector) + + main_sel_op_transaction_fee) + + main_sel_op_chain_id) + + main_sel_op_version) + + main_sel_op_block_number) + + main_sel_op_coinbase) + + main_sel_op_timestamp) + + main_sel_op_fee_per_l2_gas) + + main_sel_op_fee_per_da_gas)) + + ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + + main_sel_op_emit_nullifier) + + main_sel_op_l1_to_l2_msg_exists) + + main_sel_op_emit_unencrypted_log) + + main_sel_op_emit_l2_to_l1_msg)) + + (main_sel_op_dagasleft + main_sel_op_l2gasleft)) + + (main_sel_op_calldata_copy + main_sel_op_external_return))) * + (main_pc_shift - (main_pc + FF(1)))); tmp *= scaling_factor; std::get<100>(evals) += tmp; } @@ -1062,91 +1065,109 @@ template class mainImpl { { Avm_DECLARE_VIEWS(101); auto tmp = - ((((((((main_sel_op_fdiv + - ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + - main_sel_op_not) + - main_sel_op_eq) + - main_sel_op_lt) + - main_sel_op_lte) + - main_sel_op_shr) + - main_sel_op_shl) + - main_sel_op_cast)) + - ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)) + - (main_sel_op_cmov + main_sel_op_mov)) + - ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + main_sel_op_keccak) + - main_sel_op_pedersen)) + - (((((((((((main_sel_op_address + main_sel_op_storage_address) + main_sel_op_sender) + - main_sel_op_function_selector) + - main_sel_op_transaction_fee) + - main_sel_op_chain_id) + - main_sel_op_version) + - main_sel_op_block_number) + - main_sel_op_coinbase) + - main_sel_op_timestamp) + - main_sel_op_fee_per_l2_gas) + - main_sel_op_fee_per_da_gas)) + - ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + - main_sel_op_emit_nullifier) + - main_sel_op_l1_to_l2_msg_exists) + - main_sel_op_emit_unencrypted_log) + - main_sel_op_emit_l2_to_l1_msg)) + - (main_sel_op_dagasleft + main_sel_op_l2gasleft)) * - (main_call_ptr - main_space_id)); + ((-(((main_sel_first + main_sel_op_internal_call) + main_sel_op_internal_return) + main_sel_op_halt) + + FF(1)) * + (main_internal_return_ptr_shift - main_internal_return_ptr)); tmp *= scaling_factor; std::get<101>(evals) += tmp; } // Contribution 102 { Avm_DECLARE_VIEWS(102); - auto tmp = ((main_sel_op_cmov + main_sel_op_jumpi) * (((main_id * main_inv) - FF(1)) + main_id_zero)); + auto tmp = ((main_sel_op_internal_call + main_sel_op_internal_return) * (main_space_id - FF(255))); tmp *= scaling_factor; std::get<102>(evals) += tmp; } // Contribution 103 { Avm_DECLARE_VIEWS(103); - auto tmp = (((main_sel_op_cmov + main_sel_op_jumpi) * main_id_zero) * (-main_inv + FF(1))); + auto tmp = + (((((((((main_sel_op_fdiv + + ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + + main_sel_op_not) + + main_sel_op_eq) + + main_sel_op_lt) + + main_sel_op_lte) + + main_sel_op_shr) + + main_sel_op_shl) + + main_sel_op_cast)) + + ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)) + + (main_sel_op_cmov + main_sel_op_mov)) + + ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + main_sel_op_keccak) + + main_sel_op_pedersen)) + + (((((((((((main_sel_op_address + main_sel_op_storage_address) + main_sel_op_sender) + + main_sel_op_function_selector) + + main_sel_op_transaction_fee) + + main_sel_op_chain_id) + + main_sel_op_version) + + main_sel_op_block_number) + + main_sel_op_coinbase) + + main_sel_op_timestamp) + + main_sel_op_fee_per_l2_gas) + + main_sel_op_fee_per_da_gas)) + + ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + + main_sel_op_emit_nullifier) + + main_sel_op_l1_to_l2_msg_exists) + + main_sel_op_emit_unencrypted_log) + + main_sel_op_emit_l2_to_l1_msg)) + + (main_sel_op_dagasleft + main_sel_op_l2gasleft)) + + (main_sel_op_calldata_copy + main_sel_op_external_return)) * + (main_call_ptr - main_space_id)); tmp *= scaling_factor; std::get<103>(evals) += tmp; } // Contribution 104 { Avm_DECLARE_VIEWS(104); - auto tmp = (main_sel_mov_ia_to_ic - (main_sel_op_mov + (main_sel_op_cmov * (-main_id_zero + FF(1))))); + auto tmp = ((main_sel_op_cmov + main_sel_op_jumpi) * (((main_id * main_inv) - FF(1)) + main_id_zero)); tmp *= scaling_factor; std::get<104>(evals) += tmp; } // Contribution 105 { Avm_DECLARE_VIEWS(105); - auto tmp = (main_sel_mov_ib_to_ic - (main_sel_op_cmov * main_id_zero)); + auto tmp = (((main_sel_op_cmov + main_sel_op_jumpi) * main_id_zero) * (-main_inv + FF(1))); tmp *= scaling_factor; std::get<105>(evals) += tmp; } // Contribution 106 { Avm_DECLARE_VIEWS(106); - auto tmp = (main_sel_mov_ia_to_ic * (main_ia - main_ic)); + auto tmp = (main_sel_mov_ia_to_ic - (main_sel_op_mov + (main_sel_op_cmov * (-main_id_zero + FF(1))))); tmp *= scaling_factor; std::get<106>(evals) += tmp; } // Contribution 107 { Avm_DECLARE_VIEWS(107); - auto tmp = (main_sel_mov_ib_to_ic * (main_ib - main_ic)); + auto tmp = (main_sel_mov_ib_to_ic - (main_sel_op_cmov * main_id_zero)); tmp *= scaling_factor; std::get<107>(evals) += tmp; } // Contribution 108 { Avm_DECLARE_VIEWS(108); - auto tmp = ((main_sel_op_mov + main_sel_op_cmov) * (main_r_in_tag - main_w_in_tag)); + auto tmp = (main_sel_mov_ia_to_ic * (main_ia - main_ic)); tmp *= scaling_factor; std::get<108>(evals) += tmp; } // Contribution 109 { Avm_DECLARE_VIEWS(109); + auto tmp = (main_sel_mov_ib_to_ic * (main_ib - main_ic)); + tmp *= scaling_factor; + std::get<109>(evals) += tmp; + } + // Contribution 110 + { + Avm_DECLARE_VIEWS(110); + auto tmp = ((main_sel_op_mov + main_sel_op_cmov) * (main_r_in_tag - main_w_in_tag)); + tmp *= scaling_factor; + std::get<110>(evals) += tmp; + } + // Contribution 111 + { + Avm_DECLARE_VIEWS(111); auto tmp = (main_sel_alu - ((((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + main_sel_op_not) + @@ -1159,11 +1180,11 @@ template class mainImpl { (-main_tag_err + FF(1))) * (-main_op_err + FF(1)))); tmp *= scaling_factor; - std::get<109>(evals) += tmp; + std::get<111>(evals) += tmp; } - // Contribution 110 + // Contribution 112 { - Avm_DECLARE_VIEWS(110); + Avm_DECLARE_VIEWS(112); auto tmp = ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + main_sel_op_not) + main_sel_op_eq) + @@ -1173,258 +1194,258 @@ template class mainImpl { main_sel_op_shl) * (main_alu_in_tag - main_r_in_tag)); tmp *= scaling_factor; - std::get<110>(evals) += tmp; - } - // Contribution 111 - { - Avm_DECLARE_VIEWS(111); - auto tmp = (main_sel_op_cast * (main_alu_in_tag - main_w_in_tag)); - tmp *= scaling_factor; - std::get<111>(evals) += tmp; - } - // Contribution 112 - { - Avm_DECLARE_VIEWS(112); - auto tmp = (main_sel_op_l2gasleft * (main_ia - main_l2_gas_remaining_shift)); - tmp *= scaling_factor; std::get<112>(evals) += tmp; } // Contribution 113 { Avm_DECLARE_VIEWS(113); - auto tmp = (main_sel_op_dagasleft * (main_ia - main_da_gas_remaining_shift)); + auto tmp = (main_sel_op_cast * (main_alu_in_tag - main_w_in_tag)); tmp *= scaling_factor; std::get<113>(evals) += tmp; } // Contribution 114 { Avm_DECLARE_VIEWS(114); - auto tmp = (main_sel_op_address * (kernel_kernel_in_offset - FF(1))); + auto tmp = (main_sel_op_l2gasleft * (main_ia - main_l2_gas_remaining_shift)); tmp *= scaling_factor; std::get<114>(evals) += tmp; } // Contribution 115 { Avm_DECLARE_VIEWS(115); - auto tmp = (main_sel_op_storage_address * (kernel_kernel_in_offset - FF(1))); + auto tmp = (main_sel_op_dagasleft * (main_ia - main_da_gas_remaining_shift)); tmp *= scaling_factor; std::get<115>(evals) += tmp; } // Contribution 116 { Avm_DECLARE_VIEWS(116); - auto tmp = (main_sel_op_sender * kernel_kernel_in_offset); + auto tmp = (main_sel_op_address * (kernel_kernel_in_offset - FF(1))); tmp *= scaling_factor; std::get<116>(evals) += tmp; } // Contribution 117 { Avm_DECLARE_VIEWS(117); - auto tmp = (main_sel_op_function_selector * (kernel_kernel_in_offset - FF(2))); + auto tmp = (main_sel_op_storage_address * (kernel_kernel_in_offset - FF(1))); tmp *= scaling_factor; std::get<117>(evals) += tmp; } // Contribution 118 { Avm_DECLARE_VIEWS(118); - auto tmp = (main_sel_op_transaction_fee * (kernel_kernel_in_offset - FF(39))); + auto tmp = (main_sel_op_sender * kernel_kernel_in_offset); tmp *= scaling_factor; std::get<118>(evals) += tmp; } // Contribution 119 { Avm_DECLARE_VIEWS(119); - auto tmp = (main_sel_op_chain_id * (kernel_kernel_in_offset - FF(28))); + auto tmp = (main_sel_op_function_selector * (kernel_kernel_in_offset - FF(2))); tmp *= scaling_factor; std::get<119>(evals) += tmp; } // Contribution 120 { Avm_DECLARE_VIEWS(120); - auto tmp = (main_sel_op_version * (kernel_kernel_in_offset - FF(29))); + auto tmp = (main_sel_op_transaction_fee * (kernel_kernel_in_offset - FF(39))); tmp *= scaling_factor; std::get<120>(evals) += tmp; } // Contribution 121 { Avm_DECLARE_VIEWS(121); - auto tmp = (main_sel_op_block_number * (kernel_kernel_in_offset - FF(30))); + auto tmp = (main_sel_op_chain_id * (kernel_kernel_in_offset - FF(28))); tmp *= scaling_factor; std::get<121>(evals) += tmp; } // Contribution 122 { Avm_DECLARE_VIEWS(122); - auto tmp = (main_sel_op_timestamp * (kernel_kernel_in_offset - FF(31))); + auto tmp = (main_sel_op_version * (kernel_kernel_in_offset - FF(29))); tmp *= scaling_factor; std::get<122>(evals) += tmp; } // Contribution 123 { Avm_DECLARE_VIEWS(123); - auto tmp = (main_sel_op_coinbase * (kernel_kernel_in_offset - FF(32))); + auto tmp = (main_sel_op_block_number * (kernel_kernel_in_offset - FF(30))); tmp *= scaling_factor; std::get<123>(evals) += tmp; } // Contribution 124 { Avm_DECLARE_VIEWS(124); - auto tmp = (main_sel_op_fee_per_da_gas * (kernel_kernel_in_offset - FF(34))); + auto tmp = (main_sel_op_timestamp * (kernel_kernel_in_offset - FF(31))); tmp *= scaling_factor; std::get<124>(evals) += tmp; } // Contribution 125 { Avm_DECLARE_VIEWS(125); - auto tmp = (main_sel_op_fee_per_l2_gas * (kernel_kernel_in_offset - FF(35))); + auto tmp = (main_sel_op_coinbase * (kernel_kernel_in_offset - FF(32))); tmp *= scaling_factor; std::get<125>(evals) += tmp; } // Contribution 126 { Avm_DECLARE_VIEWS(126); - auto tmp = (main_sel_op_note_hash_exists * - (kernel_kernel_out_offset - (kernel_note_hash_exist_write_offset + FF(0)))); + auto tmp = (main_sel_op_fee_per_da_gas * (kernel_kernel_in_offset - FF(34))); tmp *= scaling_factor; std::get<126>(evals) += tmp; } // Contribution 127 { Avm_DECLARE_VIEWS(127); - auto tmp = (main_sel_first * kernel_note_hash_exist_write_offset); + auto tmp = (main_sel_op_fee_per_l2_gas * (kernel_kernel_in_offset - FF(35))); tmp *= scaling_factor; std::get<127>(evals) += tmp; } // Contribution 128 { Avm_DECLARE_VIEWS(128); - auto tmp = (main_sel_op_emit_note_hash * - (kernel_kernel_out_offset - (kernel_emit_note_hash_write_offset + FF(128)))); + auto tmp = (main_sel_op_note_hash_exists * + (kernel_kernel_out_offset - (kernel_note_hash_exist_write_offset + FF(0)))); tmp *= scaling_factor; std::get<128>(evals) += tmp; } // Contribution 129 { Avm_DECLARE_VIEWS(129); - auto tmp = (main_sel_first * kernel_emit_note_hash_write_offset); + auto tmp = (main_sel_first * kernel_note_hash_exist_write_offset); tmp *= scaling_factor; std::get<129>(evals) += tmp; } // Contribution 130 { Avm_DECLARE_VIEWS(130); - auto tmp = (main_sel_op_nullifier_exists * - (kernel_kernel_out_offset - - ((main_ib * (kernel_nullifier_exists_write_offset + FF(16))) + - ((-main_ib + FF(1)) * (kernel_nullifier_non_exists_write_offset + FF(32)))))); + auto tmp = (main_sel_op_emit_note_hash * + (kernel_kernel_out_offset - (kernel_emit_note_hash_write_offset + FF(128)))); tmp *= scaling_factor; std::get<130>(evals) += tmp; } // Contribution 131 { Avm_DECLARE_VIEWS(131); - auto tmp = (main_sel_first * kernel_nullifier_exists_write_offset); + auto tmp = (main_sel_first * kernel_emit_note_hash_write_offset); tmp *= scaling_factor; std::get<131>(evals) += tmp; } // Contribution 132 { Avm_DECLARE_VIEWS(132); - auto tmp = (main_sel_first * kernel_nullifier_non_exists_write_offset); + auto tmp = (main_sel_op_nullifier_exists * + (kernel_kernel_out_offset - + ((main_ib * (kernel_nullifier_exists_write_offset + FF(16))) + + ((-main_ib + FF(1)) * (kernel_nullifier_non_exists_write_offset + FF(32)))))); tmp *= scaling_factor; std::get<132>(evals) += tmp; } // Contribution 133 { Avm_DECLARE_VIEWS(133); - auto tmp = (main_sel_op_emit_nullifier * - (kernel_kernel_out_offset - (kernel_emit_nullifier_write_offset + FF(144)))); + auto tmp = (main_sel_first * kernel_nullifier_exists_write_offset); tmp *= scaling_factor; std::get<133>(evals) += tmp; } // Contribution 134 { Avm_DECLARE_VIEWS(134); - auto tmp = (main_sel_first * kernel_emit_nullifier_write_offset); + auto tmp = (main_sel_first * kernel_nullifier_non_exists_write_offset); tmp *= scaling_factor; std::get<134>(evals) += tmp; } // Contribution 135 { Avm_DECLARE_VIEWS(135); - auto tmp = (main_sel_op_l1_to_l2_msg_exists * - (kernel_kernel_out_offset - (kernel_l1_to_l2_msg_exists_write_offset + FF(48)))); + auto tmp = (main_sel_op_emit_nullifier * + (kernel_kernel_out_offset - (kernel_emit_nullifier_write_offset + FF(144)))); tmp *= scaling_factor; std::get<135>(evals) += tmp; } // Contribution 136 { Avm_DECLARE_VIEWS(136); - auto tmp = (main_sel_first * kernel_l1_to_l2_msg_exists_write_offset); + auto tmp = (main_sel_first * kernel_emit_nullifier_write_offset); tmp *= scaling_factor; std::get<136>(evals) += tmp; } // Contribution 137 { Avm_DECLARE_VIEWS(137); - auto tmp = (main_sel_op_emit_unencrypted_log * - (kernel_kernel_out_offset - (kernel_emit_unencrypted_log_write_offset + FF(162)))); + auto tmp = (main_sel_op_l1_to_l2_msg_exists * + (kernel_kernel_out_offset - (kernel_l1_to_l2_msg_exists_write_offset + FF(48)))); tmp *= scaling_factor; std::get<137>(evals) += tmp; } // Contribution 138 { Avm_DECLARE_VIEWS(138); - auto tmp = (main_sel_first * kernel_emit_unencrypted_log_write_offset); + auto tmp = (main_sel_first * kernel_l1_to_l2_msg_exists_write_offset); tmp *= scaling_factor; std::get<138>(evals) += tmp; } // Contribution 139 { Avm_DECLARE_VIEWS(139); - auto tmp = (main_sel_op_emit_l2_to_l1_msg * - (kernel_kernel_out_offset - (kernel_emit_l2_to_l1_msg_write_offset + FF(160)))); + auto tmp = (main_sel_op_emit_unencrypted_log * + (kernel_kernel_out_offset - (kernel_emit_unencrypted_log_write_offset + FF(162)))); tmp *= scaling_factor; std::get<139>(evals) += tmp; } // Contribution 140 { Avm_DECLARE_VIEWS(140); - auto tmp = (main_sel_first * kernel_emit_l2_to_l1_msg_write_offset); + auto tmp = (main_sel_first * kernel_emit_unencrypted_log_write_offset); tmp *= scaling_factor; std::get<140>(evals) += tmp; } // Contribution 141 { Avm_DECLARE_VIEWS(141); - auto tmp = (main_sel_op_sload * (kernel_kernel_out_offset - (kernel_sload_write_offset + FF(96)))); + auto tmp = (main_sel_op_emit_l2_to_l1_msg * + (kernel_kernel_out_offset - (kernel_emit_l2_to_l1_msg_write_offset + FF(160)))); tmp *= scaling_factor; std::get<141>(evals) += tmp; } // Contribution 142 { Avm_DECLARE_VIEWS(142); - auto tmp = (main_sel_first * kernel_sload_write_offset); + auto tmp = (main_sel_first * kernel_emit_l2_to_l1_msg_write_offset); tmp *= scaling_factor; std::get<142>(evals) += tmp; } // Contribution 143 { Avm_DECLARE_VIEWS(143); - auto tmp = (main_sel_op_sstore * (kernel_kernel_out_offset - (kernel_sstore_write_offset + FF(64)))); + auto tmp = (main_sel_op_sload * (kernel_kernel_out_offset - (kernel_sload_write_offset + FF(96)))); tmp *= scaling_factor; std::get<143>(evals) += tmp; } // Contribution 144 { Avm_DECLARE_VIEWS(144); - auto tmp = (main_sel_first * kernel_sstore_write_offset); + auto tmp = (main_sel_first * kernel_sload_write_offset); tmp *= scaling_factor; std::get<144>(evals) += tmp; } // Contribution 145 { Avm_DECLARE_VIEWS(145); + auto tmp = (main_sel_op_sstore * (kernel_kernel_out_offset - (kernel_sstore_write_offset + FF(64)))); + tmp *= scaling_factor; + std::get<145>(evals) += tmp; + } + // Contribution 146 + { + Avm_DECLARE_VIEWS(146); + auto tmp = (main_sel_first * kernel_sstore_write_offset); + tmp *= scaling_factor; + std::get<146>(evals) += tmp; + } + // Contribution 147 + { + Avm_DECLARE_VIEWS(147); auto tmp = (((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + main_sel_op_emit_nullifier) + @@ -1433,21 +1454,29 @@ template class mainImpl { main_sel_op_emit_l2_to_l1_msg) * (kernel_side_effect_counter_shift - (kernel_side_effect_counter + FF(1)))); tmp *= scaling_factor; - std::get<145>(evals) += tmp; + std::get<147>(evals) += tmp; } - // Contribution 146 + // Contribution 148 { - Avm_DECLARE_VIEWS(146); + Avm_DECLARE_VIEWS(148); + auto tmp = (main_sel_slice_gadget - + ((main_sel_op_calldata_copy + main_sel_op_external_return) * (-main_tag_err + FF(1)))); + tmp *= scaling_factor; + std::get<148>(evals) += tmp; + } + // Contribution 149 + { + Avm_DECLARE_VIEWS(149); auto tmp = (main_bin_op_id - (main_sel_op_or + (main_sel_op_xor * FF(2)))); tmp *= scaling_factor; - std::get<146>(evals) += tmp; + std::get<149>(evals) += tmp; } - // Contribution 147 + // Contribution 150 { - Avm_DECLARE_VIEWS(147); + Avm_DECLARE_VIEWS(150); auto tmp = (main_sel_bin - ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)); tmp *= scaling_factor; - std::get<147>(evals) += tmp; + std::get<150>(evals) += tmp; } } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp index 232d79fe1906..31eba07d6ae9 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp @@ -30,6 +30,7 @@ template struct MemRow { FF mem_sel_op_c{}; FF mem_sel_op_cmov{}; FF mem_sel_op_d{}; + FF mem_sel_op_slice{}; FF mem_sel_resolve_ind_addr_a{}; FF mem_sel_resolve_ind_addr_b{}; FF mem_sel_resolve_ind_addr_c{}; @@ -50,39 +51,39 @@ template struct MemRow { inline std::string get_relation_label_mem(int index) { switch (index) { - case 14: - return "MEM_CONTIGUOUS"; case 15: - return "MEM_FIRST_EMPTY"; + return "MEM_CONTIGUOUS"; case 16: + return "MEM_FIRST_EMPTY"; + case 17: return "MEM_LAST"; - case 18: - return "TIMESTAMP"; case 19: - return "GLOBAL_ADDR"; + return "TIMESTAMP"; case 20: - return "LAST_ACCESS_FIRST_ROW"; + return "GLOBAL_ADDR"; case 21: - return "MEM_LAST_ACCESS_DELIMITER"; + return "LAST_ACCESS_FIRST_ROW"; case 22: - return "DIFF_RNG_CHK_DEC"; + return "MEM_LAST_ACCESS_DELIMITER"; case 23: - return "MEM_READ_WRITE_VAL_CONSISTENCY"; + return "DIFF_RNG_CHK_DEC"; case 24: - return "MEM_READ_WRITE_TAG_CONSISTENCY"; + return "MEM_READ_WRITE_VAL_CONSISTENCY"; case 25: - return "MEM_ZERO_INIT"; + return "MEM_READ_WRITE_TAG_CONSISTENCY"; case 26: - return "SKIP_CHECK_TAG"; + return "MEM_ZERO_INIT"; case 27: - return "MEM_IN_TAG_CONSISTENCY_1"; + return "SKIP_CHECK_TAG"; case 28: - return "MEM_IN_TAG_CONSISTENCY_2"; + return "MEM_IN_TAG_CONSISTENCY_1"; case 29: + return "MEM_IN_TAG_CONSISTENCY_2"; + case 30: return "NO_TAG_ERR_WRITE_OR_SKIP"; - case 31: + case 32: return "NO_TAG_ERR_WRITE"; - case 40: + case 43: return "MOV_SAME_TAG"; } return std::to_string(index); @@ -92,9 +93,9 @@ template class memImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, - 4, 3, 4, 3, 4, 3, 3, 3, 4, 4, 4, 4, 4, 6, - 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, + 4, 3, 4, 3, 4, 3, 3, 3, 4, 4, 4, 4, 4, 6, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; template void static accumulate(ContainerOverSubrelations& evals, @@ -161,81 +162,89 @@ template class memImpl { // Contribution 8 { Avm_DECLARE_VIEWS(8); - auto tmp = (mem_sel_resolve_ind_addr_a * (-mem_sel_resolve_ind_addr_a + FF(1))); + auto tmp = (mem_sel_op_slice * (-mem_sel_op_slice + FF(1))); tmp *= scaling_factor; std::get<8>(evals) += tmp; } // Contribution 9 { Avm_DECLARE_VIEWS(9); - auto tmp = (mem_sel_resolve_ind_addr_b * (-mem_sel_resolve_ind_addr_b + FF(1))); + auto tmp = (mem_sel_resolve_ind_addr_a * (-mem_sel_resolve_ind_addr_a + FF(1))); tmp *= scaling_factor; std::get<9>(evals) += tmp; } // Contribution 10 { Avm_DECLARE_VIEWS(10); - auto tmp = (mem_sel_resolve_ind_addr_c * (-mem_sel_resolve_ind_addr_c + FF(1))); + auto tmp = (mem_sel_resolve_ind_addr_b * (-mem_sel_resolve_ind_addr_b + FF(1))); tmp *= scaling_factor; std::get<10>(evals) += tmp; } // Contribution 11 { Avm_DECLARE_VIEWS(11); - auto tmp = (mem_sel_resolve_ind_addr_d * (-mem_sel_resolve_ind_addr_d + FF(1))); + auto tmp = (mem_sel_resolve_ind_addr_c * (-mem_sel_resolve_ind_addr_c + FF(1))); tmp *= scaling_factor; std::get<11>(evals) += tmp; } // Contribution 12 { Avm_DECLARE_VIEWS(12); - auto tmp = - (mem_sel_mem - - (((((((mem_sel_op_a + mem_sel_op_b) + mem_sel_op_c) + mem_sel_op_d) + mem_sel_resolve_ind_addr_a) + - mem_sel_resolve_ind_addr_b) + - mem_sel_resolve_ind_addr_c) + - mem_sel_resolve_ind_addr_d)); + auto tmp = (mem_sel_resolve_ind_addr_d * (-mem_sel_resolve_ind_addr_d + FF(1))); tmp *= scaling_factor; std::get<12>(evals) += tmp; } // Contribution 13 { Avm_DECLARE_VIEWS(13); - auto tmp = (mem_sel_mem * (mem_sel_mem - FF(1))); + auto tmp = + (mem_sel_mem - + ((((((((mem_sel_op_a + mem_sel_op_b) + mem_sel_op_c) + mem_sel_op_d) + mem_sel_resolve_ind_addr_a) + + mem_sel_resolve_ind_addr_b) + + mem_sel_resolve_ind_addr_c) + + mem_sel_resolve_ind_addr_d) + + mem_sel_op_slice)); tmp *= scaling_factor; std::get<13>(evals) += tmp; } // Contribution 14 { Avm_DECLARE_VIEWS(14); - auto tmp = (((-main_sel_first + FF(1)) * mem_sel_mem_shift) * (-mem_sel_mem + FF(1))); + auto tmp = (mem_sel_mem * (mem_sel_mem - FF(1))); tmp *= scaling_factor; std::get<14>(evals) += tmp; } // Contribution 15 { Avm_DECLARE_VIEWS(15); - auto tmp = (main_sel_first * mem_sel_mem); + auto tmp = (((-main_sel_first + FF(1)) * mem_sel_mem_shift) * (-mem_sel_mem + FF(1))); tmp *= scaling_factor; std::get<15>(evals) += tmp; } // Contribution 16 { Avm_DECLARE_VIEWS(16); - auto tmp = (((-mem_last + FF(1)) * mem_sel_mem) * (-mem_sel_mem_shift + FF(1))); + auto tmp = (main_sel_first * mem_sel_mem); tmp *= scaling_factor; std::get<16>(evals) += tmp; } // Contribution 17 { Avm_DECLARE_VIEWS(17); - auto tmp = (mem_sel_rng_chk - (mem_sel_mem * (-mem_last + FF(1)))); + auto tmp = (((-mem_last + FF(1)) * mem_sel_mem) * (-mem_sel_mem_shift + FF(1))); tmp *= scaling_factor; std::get<17>(evals) += tmp; } // Contribution 18 { Avm_DECLARE_VIEWS(18); + auto tmp = (mem_sel_rng_chk - (mem_sel_mem * (-mem_last + FF(1)))); + tmp *= scaling_factor; + std::get<18>(evals) += tmp; + } + // Contribution 19 + { + Avm_DECLARE_VIEWS(19); auto tmp = (mem_tsp - ((mem_clk * FF(12)) + @@ -249,169 +258,184 @@ template class memImpl { mem_rw) * FF(4)))))); tmp *= scaling_factor; - std::get<18>(evals) += tmp; - } - // Contribution 19 - { - Avm_DECLARE_VIEWS(19); - auto tmp = (mem_glob_addr - ((mem_space_id * FF(4294967296UL)) + mem_addr)); - tmp *= scaling_factor; std::get<19>(evals) += tmp; } // Contribution 20 { Avm_DECLARE_VIEWS(20); - auto tmp = (main_sel_first * (-mem_lastAccess + FF(1))); + auto tmp = (mem_glob_addr - ((mem_space_id * FF(4294967296UL)) + mem_addr)); tmp *= scaling_factor; std::get<20>(evals) += tmp; } // Contribution 21 { Avm_DECLARE_VIEWS(21); - auto tmp = ((-mem_lastAccess + FF(1)) * (mem_glob_addr_shift - mem_glob_addr)); + auto tmp = (main_sel_first * (-mem_lastAccess + FF(1))); tmp *= scaling_factor; std::get<21>(evals) += tmp; } // Contribution 22 { Avm_DECLARE_VIEWS(22); - auto tmp = (mem_sel_rng_chk * (((((mem_lastAccess * (mem_glob_addr_shift - mem_glob_addr)) + - ((-mem_lastAccess + FF(1)) * (mem_tsp_shift - mem_tsp))) - - (mem_diff_hi * FF(4294967296UL))) - - (mem_diff_mid * FF(65536))) - - mem_diff_lo)); + auto tmp = ((-mem_lastAccess + FF(1)) * (mem_glob_addr_shift - mem_glob_addr)); tmp *= scaling_factor; std::get<22>(evals) += tmp; } // Contribution 23 { Avm_DECLARE_VIEWS(23); - auto tmp = (((-mem_lastAccess + FF(1)) * (-mem_rw_shift + FF(1))) * (mem_val_shift - mem_val)); + auto tmp = (mem_sel_rng_chk * (((((mem_lastAccess * (mem_glob_addr_shift - mem_glob_addr)) + + ((-mem_lastAccess + FF(1)) * (mem_tsp_shift - mem_tsp))) - + (mem_diff_hi * FF(4294967296UL))) - + (mem_diff_mid * FF(65536))) - + mem_diff_lo)); tmp *= scaling_factor; std::get<23>(evals) += tmp; } // Contribution 24 { Avm_DECLARE_VIEWS(24); - auto tmp = (((-mem_lastAccess + FF(1)) * (-mem_rw_shift + FF(1))) * (mem_tag_shift - mem_tag)); + auto tmp = (((-mem_lastAccess + FF(1)) * (-mem_rw_shift + FF(1))) * (mem_val_shift - mem_val)); tmp *= scaling_factor; std::get<24>(evals) += tmp; } // Contribution 25 { Avm_DECLARE_VIEWS(25); - auto tmp = ((mem_lastAccess * (-mem_rw_shift + FF(1))) * mem_val_shift); + auto tmp = (((-mem_lastAccess + FF(1)) * (-mem_rw_shift + FF(1))) * (mem_tag_shift - mem_tag)); tmp *= scaling_factor; std::get<25>(evals) += tmp; } // Contribution 26 { Avm_DECLARE_VIEWS(26); - auto tmp = (mem_skip_check_tag - - (mem_sel_op_cmov * ((mem_sel_op_d + (mem_sel_op_a * (-mem_sel_mov_ia_to_ic + FF(1)))) + - (mem_sel_op_b * (-mem_sel_mov_ib_to_ic + FF(1)))))); + auto tmp = ((mem_lastAccess * (-mem_rw_shift + FF(1))) * mem_val_shift); tmp *= scaling_factor; std::get<26>(evals) += tmp; } // Contribution 27 { Avm_DECLARE_VIEWS(27); - auto tmp = (((mem_tag * (-mem_skip_check_tag + FF(1))) * (-mem_rw + FF(1))) * - (((mem_r_in_tag - mem_tag) * (-mem_one_min_inv + FF(1))) - mem_tag_err)); + auto tmp = (mem_skip_check_tag - + ((mem_sel_op_cmov * ((mem_sel_op_d + (mem_sel_op_a * (-mem_sel_mov_ia_to_ic + FF(1)))) + + (mem_sel_op_b * (-mem_sel_mov_ib_to_ic + FF(1))))) + + mem_sel_op_slice)); tmp *= scaling_factor; std::get<27>(evals) += tmp; } // Contribution 28 { Avm_DECLARE_VIEWS(28); - auto tmp = ((mem_tag * (-mem_tag_err + FF(1))) * mem_one_min_inv); + auto tmp = (((mem_tag * (-mem_skip_check_tag + FF(1))) * (-mem_rw + FF(1))) * + (((mem_r_in_tag - mem_tag) * (-mem_one_min_inv + FF(1))) - mem_tag_err)); tmp *= scaling_factor; std::get<28>(evals) += tmp; } // Contribution 29 { Avm_DECLARE_VIEWS(29); - auto tmp = ((mem_skip_check_tag + mem_rw) * mem_tag_err); + auto tmp = ((mem_tag * (-mem_tag_err + FF(1))) * mem_one_min_inv); tmp *= scaling_factor; std::get<29>(evals) += tmp; } // Contribution 30 { Avm_DECLARE_VIEWS(30); - auto tmp = (mem_rw * (mem_w_in_tag - mem_tag)); + auto tmp = ((mem_skip_check_tag + mem_rw) * mem_tag_err); tmp *= scaling_factor; std::get<30>(evals) += tmp; } // Contribution 31 { Avm_DECLARE_VIEWS(31); - auto tmp = (mem_rw * mem_tag_err); + auto tmp = (mem_rw * (mem_w_in_tag - mem_tag)); tmp *= scaling_factor; std::get<31>(evals) += tmp; } // Contribution 32 { Avm_DECLARE_VIEWS(32); - auto tmp = (mem_sel_resolve_ind_addr_a * (mem_r_in_tag - FF(3))); + auto tmp = (mem_rw * mem_tag_err); tmp *= scaling_factor; std::get<32>(evals) += tmp; } // Contribution 33 { Avm_DECLARE_VIEWS(33); - auto tmp = (mem_sel_resolve_ind_addr_b * (mem_r_in_tag - FF(3))); + auto tmp = (mem_sel_resolve_ind_addr_a * (mem_r_in_tag - FF(3))); tmp *= scaling_factor; std::get<33>(evals) += tmp; } // Contribution 34 { Avm_DECLARE_VIEWS(34); - auto tmp = (mem_sel_resolve_ind_addr_c * (mem_r_in_tag - FF(3))); + auto tmp = (mem_sel_resolve_ind_addr_b * (mem_r_in_tag - FF(3))); tmp *= scaling_factor; std::get<34>(evals) += tmp; } // Contribution 35 { Avm_DECLARE_VIEWS(35); - auto tmp = (mem_sel_resolve_ind_addr_d * (mem_r_in_tag - FF(3))); + auto tmp = (mem_sel_resolve_ind_addr_c * (mem_r_in_tag - FF(3))); tmp *= scaling_factor; std::get<35>(evals) += tmp; } // Contribution 36 { Avm_DECLARE_VIEWS(36); - auto tmp = (mem_sel_resolve_ind_addr_a * mem_rw); + auto tmp = (mem_sel_resolve_ind_addr_d * (mem_r_in_tag - FF(3))); tmp *= scaling_factor; std::get<36>(evals) += tmp; } // Contribution 37 { Avm_DECLARE_VIEWS(37); - auto tmp = (mem_sel_resolve_ind_addr_b * mem_rw); + auto tmp = (mem_sel_resolve_ind_addr_a * mem_rw); tmp *= scaling_factor; std::get<37>(evals) += tmp; } // Contribution 38 { Avm_DECLARE_VIEWS(38); - auto tmp = (mem_sel_resolve_ind_addr_c * mem_rw); + auto tmp = (mem_sel_resolve_ind_addr_b * mem_rw); tmp *= scaling_factor; std::get<38>(evals) += tmp; } // Contribution 39 { Avm_DECLARE_VIEWS(39); - auto tmp = (mem_sel_resolve_ind_addr_d * mem_rw); + auto tmp = (mem_sel_resolve_ind_addr_c * mem_rw); tmp *= scaling_factor; std::get<39>(evals) += tmp; } // Contribution 40 { Avm_DECLARE_VIEWS(40); - auto tmp = ((mem_sel_mov_ia_to_ic + mem_sel_mov_ib_to_ic) * mem_tag_err); + auto tmp = (mem_sel_resolve_ind_addr_d * mem_rw); tmp *= scaling_factor; std::get<40>(evals) += tmp; } + // Contribution 41 + { + Avm_DECLARE_VIEWS(41); + auto tmp = (mem_sel_op_slice * (mem_w_in_tag - FF(6))); + tmp *= scaling_factor; + std::get<41>(evals) += tmp; + } + // Contribution 42 + { + Avm_DECLARE_VIEWS(42); + auto tmp = (mem_sel_op_slice * (mem_r_in_tag - FF(6))); + tmp *= scaling_factor; + std::get<42>(evals) += tmp; + } + // Contribution 43 + { + Avm_DECLARE_VIEWS(43); + auto tmp = ((mem_sel_mov_ia_to_ic + mem_sel_mov_ib_to_ic) * mem_tag_err); + tmp *= scaling_factor; + std::get<43>(evals) += tmp; + } } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem_slice.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem_slice.hpp new file mode 100644 index 000000000000..5ad94a5d5fa6 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem_slice.hpp @@ -0,0 +1,154 @@ +#pragma once + +#include "barretenberg/relations/generated/avm/declare_views.hpp" +#include "barretenberg/relations/relation_parameters.hpp" +#include "barretenberg/relations/relation_types.hpp" + +namespace bb::Avm_vm { + +template struct MemSliceRow { + FF slice_addr{}; + FF slice_addr_shift{}; + FF slice_clk{}; + FF slice_clk_shift{}; + FF slice_cnt{}; + FF slice_cnt_shift{}; + FF slice_col_offset{}; + FF slice_col_offset_shift{}; + FF slice_one_min_inv{}; + FF slice_sel_cd_cpy{}; + FF slice_sel_cd_cpy_shift{}; + FF slice_sel_mem_active{}; + FF slice_sel_mem_active_shift{}; + FF slice_sel_return{}; + FF slice_sel_return_shift{}; + FF slice_sel_start_shift{}; + FF slice_space_id{}; + FF slice_space_id_shift{}; +}; + +inline std::string get_relation_label_mem_slice(int index) +{ + switch (index) { + case 1: + return "SLICE_CNT_ZERO_TEST1"; + case 2: + return "SLICE_CNT_ZERO_TEST2"; + case 3: + return "SLICE_CNT_DECREMENT"; + case 4: + return "ADDR_INCREMENT"; + case 5: + return "COL_OFFSET_INCREMENT"; + case 6: + return "SAME_CLK"; + case 7: + return "SAME_SPACE_ID"; + case 8: + return "SAME_SEL_RETURN"; + case 9: + return "SAME_SEL_CD_CPY"; + case 10: + return "SEL_MEM_INACTIVE"; + } + return std::to_string(index); +} + +template class mem_sliceImpl { + public: + using FF = FF_; + + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4 }; + + template + void static accumulate(ContainerOverSubrelations& evals, + const AllEntities& new_term, + [[maybe_unused]] const RelationParameters&, + [[maybe_unused]] const FF& scaling_factor) + { + // Contribution 0 + { + Avm_DECLARE_VIEWS(0); + auto tmp = (slice_sel_mem_active - (slice_sel_cd_cpy + slice_sel_return)); + tmp *= scaling_factor; + std::get<0>(evals) += tmp; + } + // Contribution 1 + { + Avm_DECLARE_VIEWS(1); + auto tmp = ((slice_cnt * (-slice_one_min_inv + FF(1))) - slice_sel_mem_active); + tmp *= scaling_factor; + std::get<1>(evals) += tmp; + } + // Contribution 2 + { + Avm_DECLARE_VIEWS(2); + auto tmp = ((-slice_sel_mem_active + FF(1)) * slice_one_min_inv); + tmp *= scaling_factor; + std::get<2>(evals) += tmp; + } + // Contribution 3 + { + Avm_DECLARE_VIEWS(3); + auto tmp = (slice_sel_mem_active * ((slice_cnt - FF(1)) - slice_cnt_shift)); + tmp *= scaling_factor; + std::get<3>(evals) += tmp; + } + // Contribution 4 + { + Avm_DECLARE_VIEWS(4); + auto tmp = (slice_sel_mem_active * ((slice_addr + FF(1)) - slice_addr_shift)); + tmp *= scaling_factor; + std::get<4>(evals) += tmp; + } + // Contribution 5 + { + Avm_DECLARE_VIEWS(5); + auto tmp = (slice_sel_mem_active * ((slice_col_offset + FF(1)) - slice_col_offset_shift)); + tmp *= scaling_factor; + std::get<5>(evals) += tmp; + } + // Contribution 6 + { + Avm_DECLARE_VIEWS(6); + auto tmp = (slice_sel_mem_active * (slice_clk - slice_clk_shift)); + tmp *= scaling_factor; + std::get<6>(evals) += tmp; + } + // Contribution 7 + { + Avm_DECLARE_VIEWS(7); + auto tmp = (slice_sel_mem_active * (slice_space_id - slice_space_id_shift)); + tmp *= scaling_factor; + std::get<7>(evals) += tmp; + } + // Contribution 8 + { + Avm_DECLARE_VIEWS(8); + auto tmp = + ((slice_sel_mem_active * slice_sel_mem_active_shift) * (slice_sel_return - slice_sel_return_shift)); + tmp *= scaling_factor; + std::get<8>(evals) += tmp; + } + // Contribution 9 + { + Avm_DECLARE_VIEWS(9); + auto tmp = + ((slice_sel_mem_active * slice_sel_mem_active_shift) * (slice_sel_cd_cpy - slice_sel_cd_cpy_shift)); + tmp *= scaling_factor; + std::get<9>(evals) += tmp; + } + // Contribution 10 + { + Avm_DECLARE_VIEWS(10); + auto tmp = + (((-slice_sel_mem_active + FF(1)) * slice_sel_mem_active_shift) * (-slice_sel_start_shift + FF(1))); + tmp *= scaling_factor; + std::get<10>(evals) += tmp; + } + } +}; + +template using mem_slice = Relation>; + +} // namespace bb::Avm_vm \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_cd_mem.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_cd_mem.hpp new file mode 100644 index 000000000000..fa14ab3a16ca --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_cd_mem.hpp @@ -0,0 +1,60 @@ +#pragma once + +#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" + +#include +#include + +namespace bb { + +class perm_cd_mem_permutation_settings { + public: + // This constant defines how many columns are bundled together to form each set. + constexpr static size_t COLUMNS_PER_SET = 4; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.slice_sel_cd_cpy == 1 || in.mem_sel_op_cd_cpy == 1); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return std::forward_as_tuple(in.perm_cd_mem, + in.slice_sel_cd_cpy, + in.slice_sel_cd_cpy, + in.mem_sel_op_cd_cpy, + in.slice_clk, + in.slice_space_id, + in.slice_addr, + in.slice_val, + in.mem_clk, + in.mem_space_id, + in.mem_addr, + in.mem_val); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return std::forward_as_tuple(in.perm_cd_mem, + in.slice_sel_cd_cpy, + in.slice_sel_cd_cpy, + in.mem_sel_op_cd_cpy, + in.slice_clk, + in.slice_space_id, + in.slice_addr, + in.slice_val, + in.mem_clk, + in.mem_space_id, + in.mem_addr, + in.mem_val); + } +}; + +template +class perm_cd_mem_relation : public GenericPermutationRelation { + public: + static constexpr const char* NAME = "perm_cd_mem"; +}; +template using perm_cd_mem = GenericPermutation; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_cd_copy.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_cd_copy.hpp new file mode 100644 index 000000000000..fa58cde51ec4 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_cd_copy.hpp @@ -0,0 +1,64 @@ +#pragma once + +#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" + +#include +#include + +namespace bb { + +class perm_main_cd_copy_permutation_settings { + public: + // This constant defines how many columns are bundled together to form each set. + constexpr static size_t COLUMNS_PER_SET = 5; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.main_sel_cd_cpy_gadget == 1 || in.slice_sel_start_cd_cpy == 1); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return std::forward_as_tuple(in.perm_main_cd_copy, + in.main_sel_cd_cpy_gadget, + in.main_sel_cd_cpy_gadget, + in.slice_sel_start_cd_cpy, + in.main_clk, + in.main_space_id, + in.main_ia, + in.main_ib, + in.main_mem_addr_c, + in.slice_clk, + in.slice_space_id, + in.slice_col_offset, + in.slice_cnt, + in.slice_addr); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return std::forward_as_tuple(in.perm_main_cd_copy, + in.main_sel_cd_cpy_gadget, + in.main_sel_cd_cpy_gadget, + in.slice_sel_start_cd_cpy, + in.main_clk, + in.main_space_id, + in.main_ia, + in.main_ib, + in.main_mem_addr_c, + in.slice_clk, + in.slice_space_id, + in.slice_col_offset, + in.slice_cnt, + in.slice_addr); + } +}; + +template +class perm_main_cd_copy_relation : public GenericPermutationRelation { + public: + static constexpr const char* NAME = "perm_main_cd_copy"; +}; +template using perm_main_cd_copy = GenericPermutation; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_return.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_return.hpp new file mode 100644 index 000000000000..7a9ab3ad5d39 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_return.hpp @@ -0,0 +1,106 @@ + + +#pragma once + +#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" + +#include +#include + +namespace bb { + +class perm_main_return_permutation_settings { + public: + // This constant defines how many columns are bundled together to form each set. + constexpr static size_t COLUMNS_PER_SET = 5; + + /** + * @brief If this method returns true on a row of values, then the inverse polynomial at this index. Otherwise the + * value needs to be set to zero. + * + * @details If this is true then permutation takes place in this row + */ + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.main_sel_return_gadget == 1 || in.slice_sel_start_return == 1); + } + + /** + * @brief Get all the entities for the permutation when we don't need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + + template static inline auto get_const_entities(const AllEntities& in) + { + + return std::forward_as_tuple(in.perm_main_return, + in.main_sel_return_gadget, + in.main_sel_return_gadget, + in.slice_sel_start_return, + in.main_clk, + in.main_space_id, + in.main_ia, + in.main_ib, + in.main_mem_addr_c, + in.slice_clk, + in.slice_space_id, + in.slice_col_offset, + in.slice_cnt, + in.slice_addr); + } + + /** + * @brief Get all the entities for the permutation when need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + + template static inline auto get_nonconst_entities(AllEntities& in) + { + + return std::forward_as_tuple(in.perm_main_return, + in.main_sel_return_gadget, + in.main_sel_return_gadget, + in.slice_sel_start_return, + in.main_clk, + in.main_space_id, + in.main_ia, + in.main_ib, + in.main_mem_addr_c, + in.slice_clk, + in.slice_space_id, + in.slice_col_offset, + in.slice_cnt, + in.slice_addr); + } +}; + +template +using perm_main_return_relation = GenericPermutationRelation; +template using perm_main_return = GenericPermutation; + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_slice.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_slice.hpp new file mode 100644 index 000000000000..6297b546d918 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_slice.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" + +#include +#include + +namespace bb { + +class perm_main_slice_permutation_settings { + public: + // This constant defines how many columns are bundled together to form each set. + constexpr static size_t COLUMNS_PER_SET = 7; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.main_sel_slice_gadget == 1 || in.slice_sel_start == 1); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return std::forward_as_tuple(in.perm_main_slice, + in.main_sel_slice_gadget, + in.main_sel_slice_gadget, + in.slice_sel_start, + in.main_clk, + in.main_space_id, + in.main_ia, + in.main_ib, + in.main_mem_addr_c, + in.main_sel_op_calldata_copy, + in.main_sel_op_external_return, + in.slice_clk, + in.slice_space_id, + in.slice_col_offset, + in.slice_cnt, + in.slice_addr, + in.slice_sel_cd_cpy, + in.slice_sel_return); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return std::forward_as_tuple(in.perm_main_slice, + in.main_sel_slice_gadget, + in.main_sel_slice_gadget, + in.slice_sel_start, + in.main_clk, + in.main_space_id, + in.main_ia, + in.main_ib, + in.main_mem_addr_c, + in.main_sel_op_calldata_copy, + in.main_sel_op_external_return, + in.slice_clk, + in.slice_space_id, + in.slice_col_offset, + in.slice_cnt, + in.slice_addr, + in.slice_sel_cd_cpy, + in.slice_sel_return); + } +}; + +template +class perm_main_slice_relation : public GenericPermutationRelation { + public: + static constexpr const char* NAME = "perm_main_slice"; +}; +template using perm_main_slice = GenericPermutation; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_return_mem.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_return_mem.hpp new file mode 100644 index 000000000000..8b9c5f5ec1e0 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_return_mem.hpp @@ -0,0 +1,102 @@ + + +#pragma once + +#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" + +#include +#include + +namespace bb { + +class perm_return_mem_permutation_settings { + public: + // This constant defines how many columns are bundled together to form each set. + constexpr static size_t COLUMNS_PER_SET = 4; + + /** + * @brief If this method returns true on a row of values, then the inverse polynomial at this index. Otherwise the + * value needs to be set to zero. + * + * @details If this is true then permutation takes place in this row + */ + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.slice_sel_return == 1 || in.mem_sel_op_return == 1); + } + + /** + * @brief Get all the entities for the permutation when we don't need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + + template static inline auto get_const_entities(const AllEntities& in) + { + + return std::forward_as_tuple(in.perm_return_mem, + in.slice_sel_return, + in.slice_sel_return, + in.mem_sel_op_return, + in.slice_clk, + in.slice_space_id, + in.slice_addr, + in.slice_val, + in.mem_clk, + in.mem_space_id, + in.mem_addr, + in.mem_val); + } + + /** + * @brief Get all the entities for the permutation when need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + + template static inline auto get_nonconst_entities(AllEntities& in) + { + + return std::forward_as_tuple(in.perm_return_mem, + in.slice_sel_return, + in.slice_sel_return, + in.mem_sel_op_return, + in.slice_clk, + in.slice_space_id, + in.slice_addr, + in.slice_val, + in.mem_clk, + in.mem_space_id, + in.mem_addr, + in.mem_val); + } +}; + +template +using perm_return_mem_relation = GenericPermutationRelation; +template using perm_return_mem = GenericPermutation; + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_slice_mem.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_slice_mem.hpp new file mode 100644 index 000000000000..e0b871a779bf --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_slice_mem.hpp @@ -0,0 +1,64 @@ +#pragma once + +#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" + +#include +#include + +namespace bb { + +class perm_slice_mem_permutation_settings { + public: + // This constant defines how many columns are bundled together to form each set. + constexpr static size_t COLUMNS_PER_SET = 5; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.slice_sel_mem_active == 1 || in.mem_sel_op_slice == 1); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return std::forward_as_tuple(in.perm_slice_mem, + in.slice_sel_mem_active, + in.slice_sel_mem_active, + in.mem_sel_op_slice, + in.slice_clk, + in.slice_space_id, + in.slice_addr, + in.slice_val, + in.slice_sel_cd_cpy, + in.mem_clk, + in.mem_space_id, + in.mem_addr, + in.mem_val, + in.mem_rw); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return std::forward_as_tuple(in.perm_slice_mem, + in.slice_sel_mem_active, + in.slice_sel_mem_active, + in.mem_sel_op_slice, + in.slice_clk, + in.slice_space_id, + in.slice_addr, + in.slice_val, + in.slice_sel_cd_cpy, + in.mem_clk, + in.mem_space_id, + in.mem_addr, + in.mem_val, + in.mem_rw); + } +}; + +template +class perm_slice_mem_relation : public GenericPermutationRelation { + public: + static constexpr const char* NAME = "perm_slice_mem"; +}; +template using perm_slice_mem = GenericPermutation; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp index 8ba8765aa5cc..21401f2fe0a8 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -78,10 +78,12 @@ std::tuple Execution::prove(std::vector public_inputs_vec; std::vector calldata; + std::vector returndata; std::vector raw_proof; // This can be made nicer using BB's serialize::read, probably. const auto public_inputs_offset = proof.begin(); const auto calldata_size_offset = public_inputs_offset + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH; const auto calldata_offset = calldata_size_offset + 1; - const auto raw_proof_offset = calldata_offset + static_cast(uint64_t(*calldata_size_offset)); + const auto returndata_size_offset = calldata_offset + static_cast(uint64_t(*calldata_size_offset)); + const auto returndata_offset = returndata_size_offset + 1; + const auto raw_proof_offset = returndata_offset + static_cast(uint64_t(*returndata_size_offset)); std::copy(public_inputs_offset, calldata_size_offset, std::back_inserter(public_inputs_vec)); - std::copy(calldata_offset, raw_proof_offset, std::back_inserter(calldata)); + std::copy(calldata_offset, returndata_size_offset, std::back_inserter(calldata)); + std::copy(returndata_offset, raw_proof_offset, std::back_inserter(returndata)); std::copy(raw_proof_offset, proof.end(), std::back_inserter(raw_proof)); VmPublicInputs public_inputs = convert_public_inputs(public_inputs_vec); - std::vector> public_inputs_columns = copy_public_inputs_columns(public_inputs, calldata); + std::vector> public_inputs_columns = + copy_public_inputs_columns(public_inputs, calldata, returndata); return verifier.verify_proof(raw_proof, public_inputs_columns); } @@ -647,11 +654,14 @@ std::vector Execution::gen_trace(std::vector const& instructio break; } - case OpCode::REVERT: - trace_builder.op_revert(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2))); + case OpCode::REVERT: { + auto ret = trace_builder.op_revert(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2))); + returndata.insert(returndata.end(), ret.begin(), ret.end()); + break; + } // Misc case OpCode::DEBUGLOG: diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.cpp index 59b0c41d9bac..241ee80c3578 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.cpp @@ -16,7 +16,7 @@ void AvmGasTraceBuilder::reset() std::vector AvmGasTraceBuilder::finalize() { return std::move(gas_trace); -}; +} void AvmGasTraceBuilder::set_initial_gas(uint32_t l2_gas, uint32_t da_gas) { diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp index 231b62278a9b..82b730ad0171 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp @@ -3,7 +3,6 @@ #include #include "barretenberg/vm/avm_trace/avm_mem_trace.hpp" -#include "barretenberg/vm/generated/avm_circuit_builder.hpp" namespace bb::avm_trace { @@ -19,7 +18,6 @@ void log_avm_trace([[maybe_unused]] std::vector const& trace, [[maybe_unused]] size_t end, [[maybe_unused]] bool enable_selectors) { - /* info("Built circuit with ", trace.size(), " rows"); for (size_t i = beg; i < end; i++) { @@ -42,7 +40,6 @@ void log_avm_trace([[maybe_unused]] std::vector const& trace, info("m_lastAccess: ", trace.at(i).mem_lastAccess); info("m_last: ", trace.at(i).mem_last); - info("m_val_shift: ", trace.at(i).mem_val_shift); info("=======CONTROL_FLOW==================================================================="); info("pc: ", trace.at(i).main_pc); @@ -68,29 +65,31 @@ void log_avm_trace([[maybe_unused]] std::vector const& trace, info("last: ", trace.at(i).main_sel_last); info("=======MEM_OP_A======================================================================"); - info("mem_op_a: ", trace.at(i).main_mem_op_a); - info("mem_idx_a: ", trace.at(i).main_mem_idx_a); + info("mem_op_a: ", trace.at(i).main_sel_mem_op_a); + info("mem_addr_a: ", trace.at(i).main_mem_addr_a); info("rwa: ", trace.at(i).main_rwa); info("=======MEM_OP_B======================================================================"); - info("mem_op_b: ", trace.at(i).main_mem_op_b); - info("mem_idx_b: ", trace.at(i).main_mem_idx_b); + info("mem_op_b: ", trace.at(i).main_sel_mem_op_b); + info("mem_addr_b: ", trace.at(i).main_mem_addr_b); info("rwb: ", trace.at(i).main_rwb); info("=======MEM_OP_C======================================================================"); - info("mem_op_c: ", trace.at(i).main_mem_op_c); - info("mem_idx_c: ", trace.at(i).main_mem_idx_c); + info("mem_op_c: ", trace.at(i).main_sel_mem_op_c); + info("mem_addr_c: ", trace.at(i).main_mem_addr_c); info("rwc: ", trace.at(i).main_rwc); + + info("=======MEM_DIFF======================================================================"); info("diff_hi: ", trace.at(i).mem_diff_hi); info("diff_mid: ", trace.at(i).mem_diff_mid); info("diff_lo: ", trace.at(i).mem_diff_lo); info("=======GAS ACCOUNTING================================================================"); - info("opcode active: ", trace.at(i).main_gas_cost_active); + info("opcode active: ", trace.at(i).main_sel_mem_op_activate_gas); info("l2_gas_remaining: ", trace.at(i).main_l2_gas_remaining); info("da_gas_remaining: ", trace.at(i).main_da_gas_remaining); - info("l2_gas_op: ", trace.at(i).main_l2_gas_op); - info("da_gas_op: ", trace.at(i).main_da_gas_op); + info("l2_gas_op_cost: ", trace.at(i).main_l2_gas_op_cost); + info("da_gas_op_cost: ", trace.at(i).main_da_gas_op_cost); info("l2_out_of_gas: ", trace.at(i).main_l2_out_of_gas); info("da_out_of_gas: ", trace.at(i).main_da_out_of_gas); info("abs_l2_hi_rem_gas: ", trace.at(i).main_abs_l2_rem_gas_hi); @@ -105,11 +104,10 @@ void log_avm_trace([[maybe_unused]] std::vector const& trace, info("sel_op_mul: ", trace.at(i).main_sel_op_mul); info("sel_op_eq: ", trace.at(i).main_sel_op_eq); info("sel_op_not: ", trace.at(i).main_sel_op_not); - info("sel_op_sel_alu: ", trace.at(i).main_alu_sel); + info("sel_sel_alu: ", trace.at(i).main_sel_alu); } info("\n"); } - */ } void dump_trace_as_csv(std::vector const& trace, std::filesystem::path const& filename) @@ -137,7 +135,8 @@ bool is_operand_indirect(uint8_t ind_value, uint8_t operand_idx) } std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs, - std::vector const& calldata) + std::vector const& calldata, + std::vector const& returndata) { // We convert to a vector as the pil generated verifier is generic and unaware of the KERNEL_INPUTS_LENGTH // For each of the public input vectors @@ -156,11 +155,14 @@ std::vector> copy_public_inputs_columns(VmPublicInputs const& pu assert(public_inputs_kernel_side_effect_outputs.size() == KERNEL_OUTPUTS_LENGTH); assert(public_inputs_kernel_metadata_outputs.size() == KERNEL_OUTPUTS_LENGTH); - return { std::move(public_inputs_kernel_inputs), - std::move(public_inputs_kernel_value_outputs), - std::move(public_inputs_kernel_side_effect_outputs), - std::move(public_inputs_kernel_metadata_outputs), - calldata }; + return { + std::move(public_inputs_kernel_inputs), + std::move(public_inputs_kernel_value_outputs), + std::move(public_inputs_kernel_side_effect_outputs), + std::move(public_inputs_kernel_metadata_outputs), + calldata, + returndata, + }; } } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp index d982ee258a97..aadc0dba1174 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp @@ -13,10 +13,12 @@ void dump_trace_as_csv(const std::vector& trace, const std::filesystem::pat bool is_operand_indirect(uint8_t ind_value, uint8_t operand_idx); // Copy Public Input Columns -// There are 4 public input columns, one for inputs, and 3 for the kernel outputs {value, side effect counter, metadata} -// The verifier is generic, and so accepts vectors of these values rather than the fixed length arrays that are used -// during circuit building. This method copies each array into a vector to be used by the verifier. +// There are 5 public input columns, one for inputs, one for returndata and 3 for the kernel outputs +// {value, side effect counter, metadata}. The verifier is generic, and so accepts vectors of these values +// rather than the fixed length arrays that are used during circuit building. This method copies each array +// into a vector to be used by the verifier. std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs, - std::vector const& calldata); + std::vector const& calldata, + std::vector const& returndata); } // namespace bb::avm_trace \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp index e46fb93d6706..e75aa34d2fde 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp @@ -49,28 +49,29 @@ std::vector AvmMemTraceBuilder::finalize() * @param r_in_tag Read memory tag pertaining to the instruction * @param w_in_tag Write memory tag pertaining to the instruction * @param m_rw Boolean telling whether it is a load (false) or store operation (true). + * @param sel_op_cd_cpy Specific boolean selector for calldata_copy memory slice */ void AvmMemTraceBuilder::insert_in_mem_trace(uint8_t space_id, - uint32_t const m_clk, - uint32_t const m_sub_clk, - uint32_t const m_addr, + uint32_t m_clk, + uint32_t m_sub_clk, + uint32_t m_addr, FF const& m_val, - AvmMemoryTag const m_tag, - AvmMemoryTag const r_in_tag, - AvmMemoryTag const w_in_tag, - bool const m_rw) + AvmMemoryTag m_tag, + AvmMemoryTag r_in_tag, + AvmMemoryTag w_in_tag, + bool m_rw, + bool m_sel_op_slice) { - mem_trace.emplace_back(MemoryTraceEntry{ - .m_space_id = space_id, - .m_clk = m_clk, - .m_sub_clk = m_sub_clk, - .m_addr = m_addr, - .m_val = m_val, - .m_tag = m_tag, - .r_in_tag = r_in_tag, - .w_in_tag = w_in_tag, - .m_rw = m_rw, - }); + mem_trace.emplace_back(MemoryTraceEntry{ .m_space_id = space_id, + .m_clk = m_clk, + .m_sub_clk = m_sub_clk, + .m_addr = m_addr, + .m_val = m_val, + .m_tag = m_tag, + .r_in_tag = r_in_tag, + .w_in_tag = w_in_tag, + .m_rw = m_rw, + .m_sel_op_slice = m_sel_op_slice }); } // Memory operations need to be performed before the addition of the corresponding row in @@ -472,17 +473,63 @@ void AvmMemTraceBuilder::write_into_memory(uint8_t space_id, AvmMemoryTag r_in_tag, AvmMemoryTag w_in_tag) { - MemEntry memEntry{ val, w_in_tag }; - auto& mem_space = memory.at(space_id); - auto it = mem_space.find(addr); - if (it != mem_space.end()) { - it->second = memEntry; - } else { - mem_space.emplace(addr, memEntry); - } + write_in_simulated_mem_table(space_id, addr, val, w_in_tag); store_in_mem_trace(space_id, clk, interm_reg, addr, val, r_in_tag, w_in_tag); } +void AvmMemTraceBuilder::write_calldata_copy(std::vector const& calldata, + uint32_t clk, + uint8_t space_id, + uint32_t cd_offset, + uint32_t copy_size, + uint32_t direct_dst_offset) +{ + for (uint32_t i = 0; i < copy_size; i++) { + auto addr = direct_dst_offset + i; + auto val = calldata.at(cd_offset + i); + write_in_simulated_mem_table(space_id, addr, val, AvmMemoryTag::FF); + insert_in_mem_trace(space_id, + clk, + SUB_CLK_STORE_A, // Specific re-use of this value for calldatacopy write slice. + addr, + val, + AvmMemoryTag::FF, + AvmMemoryTag::FF, + AvmMemoryTag::FF, + true, + true); + } +} + +std::vector AvmMemTraceBuilder::read_return_opcode(uint32_t clk, + uint8_t space_id, + uint32_t direct_ret_offset, + uint32_t ret_size) +{ + std::vector returndata; + for (uint32_t i = 0; i < ret_size; i++) { + auto addr = direct_ret_offset + i; + auto& mem_space = memory.at(space_id); + FF val = mem_space.contains(addr) ? mem_space.at(addr).val : 0; + AvmMemoryTag tag = mem_space.contains(addr) ? mem_space.at(addr).tag : AvmMemoryTag::U0; + + // No tag checking is performed for RETURN opcode. + insert_in_mem_trace(space_id, + clk, + SUB_CLK_LOAD_A, // Specific re-use of this value for return read slice. + addr, + val, + tag, + AvmMemoryTag::FF, + AvmMemoryTag::FF, + false, + true); + + returndata.push_back(val); + } + return returndata; +} + bool AvmMemTraceBuilder::MemoryTraceEntry::operator<(const AvmMemTraceBuilder::MemoryTraceEntry& other) const { if (m_space_id < other.m_space_id) { @@ -514,4 +561,19 @@ bool AvmMemTraceBuilder::MemoryTraceEntry::operator<(const AvmMemTraceBuilder::M return m_sub_clk < other.m_sub_clk; } +void AvmMemTraceBuilder::write_in_simulated_mem_table(uint8_t space_id, + uint32_t addr, + FF const& val, + AvmMemoryTag w_in_tag) +{ + MemEntry memEntry{ val, w_in_tag }; + auto& mem_space = memory.at(space_id); + auto it = mem_space.find(addr); + if (it != mem_space.end()) { + it->second = memEntry; + } else { + mem_space.emplace(addr, memEntry); + } +} + } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.hpp index bd8e4b121e9c..6f8af5a60e28 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.hpp @@ -43,6 +43,7 @@ class AvmMemTraceBuilder { bool m_sel_mov_ib_to_ic = false; bool m_sel_cmov = false; bool m_tag_err_count_relevant = false; + bool m_sel_op_slice = false; /** * @brief A comparator on MemoryTraceEntry to be used by sorting algorithm. We sort first by @@ -88,6 +89,13 @@ class AvmMemTraceBuilder { FF const& val, AvmMemoryTag r_in_tag, AvmMemoryTag w_in_tag); + void write_calldata_copy(std::vector const& calldata, + uint32_t clk, + uint8_t space_id, + uint32_t cd_offset, + uint32_t copy_size, + uint32_t direct_dst_offset); + std::vector read_return_opcode(uint32_t clk, uint8_t space_id, uint32_t direct_ret_offset, uint32_t ret_size); private: std::vector mem_trace; // Entries will be sorted by m_clk, m_sub_clk after finalize(). @@ -103,7 +111,8 @@ class AvmMemTraceBuilder { AvmMemoryTag m_tag, AvmMemoryTag r_in_tag, AvmMemoryTag w_in_tag, - bool m_rw); + bool m_rw, + bool m_sel_op_slice = false); void load_mismatch_tag_in_mem_trace(uint8_t space_id, uint32_t m_clk, @@ -128,5 +137,6 @@ class AvmMemTraceBuilder { FF const& val, AvmMemoryTag r_in_tag, AvmMemoryTag w_in_tag); + void write_in_simulated_mem_table(uint8_t space_id, uint32_t addr, FF const& val, AvmMemoryTag w_in_tag); }; } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp index 805381a34e96..eee16a419a10 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -23,6 +23,7 @@ #include "barretenberg/vm/avm_trace/avm_trace.hpp" #include "barretenberg/vm/avm_trace/fixed_gas.hpp" #include "barretenberg/vm/avm_trace/fixed_powers.hpp" +#include "barretenberg/vm/avm_trace/gadgets/avm_slice_trace.hpp" namespace bb::avm_trace { @@ -1638,108 +1639,50 @@ void AvmTraceBuilder::op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset) */ void AvmTraceBuilder::op_calldata_copy(uint8_t indirect, uint32_t cd_offset, uint32_t copy_size, uint32_t dst_offset) { - // We parallelize storing memory operations in chunk of 3, i.e., 1 per intermediate register. - // The variable pos is an index pointing to the first storing operation (pertaining to intermediate - // register Ia) relative to cd_offset: - // cd_offset + pos: Ia memory store operation - // cd_offset + pos + 1: Ib memory store operation - // cd_offset + pos + 2: Ic memory store operation - - uint32_t pos = 0; - uint32_t direct_dst_offset = dst_offset; // Will be overwritten in indirect mode. - - while (pos < copy_size) { - FF ib(0); - FF ic(0); - uint32_t mem_op_b(0); - uint32_t mem_op_c(0); - uint32_t mem_addr_b(0); - uint32_t mem_addr_c(0); - uint32_t rwb(0); - uint32_t rwc(0); - auto clk = static_cast(main_trace.size()) + 1; - - FF ia = calldata.at(cd_offset + pos); - uint32_t mem_op_a(1); - uint32_t rwa = 1; - - bool indirect_flag = false; - bool tag_match = true; - - if (pos == 0 && is_operand_indirect(indirect, 0)) { - indirect_flag = true; - auto ind_read = mem_trace_builder.indirect_read_and_load_from_memory( - call_ptr, clk, IndirectRegister::IND_A, dst_offset); - direct_dst_offset = uint32_t(ind_read.val); - tag_match = ind_read.tag_match; - } - - uint32_t mem_addr_a = direct_dst_offset + pos; - - // Storing from Ia - mem_trace_builder.write_into_memory( - call_ptr, clk, IntermRegister::IA, mem_addr_a, ia, AvmMemoryTag::U0, AvmMemoryTag::FF); - - if (copy_size - pos > 1) { - ib = calldata.at(cd_offset + pos + 1); - mem_op_b = 1; - mem_addr_b = direct_dst_offset + pos + 1; - rwb = 1; + auto clk = static_cast(main_trace.size()) + 1; - // Storing from Ib - mem_trace_builder.write_into_memory( - call_ptr, clk, IntermRegister::IB, mem_addr_b, ib, AvmMemoryTag::U0, AvmMemoryTag::FF); - } + uint32_t direct_dst_offset = dst_offset; // Will be overwritten in indirect mode. - if (copy_size - pos > 2) { - ic = calldata.at(cd_offset + pos + 2); - mem_op_c = 1; - mem_addr_c = direct_dst_offset + pos + 2; - rwc = 1; + bool indirect_flag = false; + bool tag_match = true; - // Storing from Ic - mem_trace_builder.write_into_memory( - call_ptr, clk, IntermRegister::IC, mem_addr_c, ic, AvmMemoryTag::U0, AvmMemoryTag::FF); - } + // The only memory operation performed from the main trace is a possible indirect load for resolving the + // direct destination offset stored in main_mem_addr_c. + // All the other memory operations are triggered by the slice gadget. - // Constrain gas cost on the first row - if (pos == 0) { - gas_trace_builder.constrain_gas_lookup(clk, OpCode::CALLDATACOPY); - } - - main_trace.push_back(Row{ - .main_clk = clk, - .main_call_ptr = call_ptr, - .main_ia = ia, - .main_ib = ib, - .main_ic = ic, - .main_ind_addr_a = indirect_flag ? FF(dst_offset) : FF(0), - .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(mem_addr_a), - .main_mem_addr_b = FF(mem_addr_b), - .main_mem_addr_c = FF(mem_addr_c), - .main_pc = FF(pc), - .main_rwa = FF(rwa), - .main_rwb = FF(rwb), - .main_rwc = FF(rwc), - .main_sel_mem_op_a = FF(mem_op_a), - .main_sel_mem_op_activate_gas = FF(static_cast( - pos == 0)), // TODO: remove in the long term. This activate gas only for the first row. - .main_sel_mem_op_b = FF(mem_op_b), - .main_sel_mem_op_c = FF(mem_op_c), - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_flag)), - .main_tag_err = FF(static_cast(!tag_match)), - .main_w_in_tag = FF(static_cast(AvmMemoryTag::FF)), - }); + if (is_operand_indirect(indirect, 0)) { + indirect_flag = true; + auto ind_read = + mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_C, dst_offset); + direct_dst_offset = uint32_t(ind_read.val); + tag_match = ind_read.tag_match; + } - if (copy_size - pos > 2) { // Guard to prevent overflow if copy_size is close to uint32_t maximum value. - pos += 3; - } else { - pos = copy_size; - } + if (tag_match) { + slice_trace_builder.create_calldata_copy_slice( + calldata, clk, call_ptr, cd_offset, copy_size, direct_dst_offset); + mem_trace_builder.write_calldata_copy(calldata, clk, call_ptr, cd_offset, copy_size, direct_dst_offset); } - pc++; + // Constrain gas cost + gas_trace_builder.constrain_gas_lookup(clk, OpCode::CALLDATACOPY); + + main_trace.push_back(Row{ + .main_clk = clk, + .main_call_ptr = call_ptr, + .main_ia = cd_offset, + .main_ib = copy_size, + .main_ind_addr_c = indirect_flag ? dst_offset : 0, + .main_internal_return_ptr = FF(internal_return_ptr), + .main_mem_addr_c = direct_dst_offset, + .main_pc = pc++, + .main_r_in_tag = static_cast(AvmMemoryTag::FF), + .main_sel_op_calldata_copy = 1, + .main_sel_resolve_ind_addr_c = static_cast(indirect_flag), + .main_sel_slice_gadget = static_cast(tag_match), + .main_tag_err = static_cast(!tag_match), + .main_w_in_tag = static_cast(AvmMemoryTag::FF), + }); } /************************************************************************************************** @@ -2310,7 +2253,6 @@ Row AvmTraceBuilder::create_kernel_output_opcode_with_set_metadata_output_from_h uint32_t data_offset, uint32_t metadata_offset) { - FF exists = execution_hints.get_side_effect_hints().at(side_effect_counter); // TODO: throw error if incorrect @@ -2839,110 +2781,52 @@ std::vector AvmTraceBuilder::op_return(uint8_t indirect, uint32_t ret_offset return {}; } - // We parallelize loading memory operations in chunk of 3, i.e., 1 per intermediate register. - // The variable pos is an index pointing to the first storing operation (pertaining to intermediate - // register Ia) relative to ret_offset: - // ret_offset + pos: Ia memory load operation - // ret_offset + pos + 1: Ib memory load operation - // ret_offset + pos + 2: Ic memory load operation - // In indirect mode, ret_offset is first resolved by the first indirect load. + auto clk = static_cast(main_trace.size()) + 1; - uint32_t pos = 0; - std::vector returnMem; uint32_t direct_ret_offset = ret_offset; // Will be overwritten in indirect mode. - while (pos < ret_size) { - FF ib(0); - FF ic(0); - uint32_t mem_op_b(0); - uint32_t mem_op_c(0); - uint32_t mem_addr_b(0); - uint32_t mem_addr_c(0); - auto clk = static_cast(main_trace.size()) + 1; - - uint32_t mem_op_a(1); - bool indirect_flag = false; - bool tag_match = true; - - if (pos == 0 && is_operand_indirect(indirect, 0)) { - indirect_flag = true; - auto ind_read = mem_trace_builder.indirect_read_and_load_from_memory( - call_ptr, clk, IndirectRegister::IND_A, ret_offset); - direct_ret_offset = uint32_t(ind_read.val); - tag_match = ind_read.tag_match; - } - - uint32_t mem_addr_a = direct_ret_offset + pos; - - // Reading and loading to Ia - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, mem_addr_a, AvmMemoryTag::FF, AvmMemoryTag::FF); - tag_match = tag_match && read_a.tag_match; - - FF ia = read_a.val; - returnMem.push_back(ia); - - if (ret_size - pos > 1) { - mem_op_b = 1; - mem_addr_b = direct_ret_offset + pos + 1; + bool indirect_flag = false; + bool tag_match = true; - // Reading and loading to Ib - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, mem_addr_b, AvmMemoryTag::FF, AvmMemoryTag::FF); - tag_match = tag_match && read_b.tag_match; - ib = read_b.val; - returnMem.push_back(ib); - } + // The only memory operation performed from the main trace is a possible indirect load for resolving the + // direct destination offset stored in main_mem_addr_c. + // All the other memory operations are triggered by the slice gadget. - if (ret_size - pos > 2) { - mem_op_c = 1; - mem_addr_c = direct_ret_offset + pos + 2; + if (is_operand_indirect(indirect, 0)) { + indirect_flag = true; + auto ind_read = + mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_C, ret_offset); + direct_ret_offset = uint32_t(ind_read.val); + tag_match = ind_read.tag_match; + } - // Reading and loading to Ic - auto read_c = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IC, mem_addr_c, AvmMemoryTag::FF, AvmMemoryTag::FF); - tag_match = tag_match && read_c.tag_match; - ic = read_c.val; - returnMem.push_back(ic); - } + if (tag_match) { + returndata = mem_trace_builder.read_return_opcode(clk, call_ptr, direct_ret_offset, ret_size); + slice_trace_builder.create_return_slice(returndata, clk, call_ptr, direct_ret_offset, ret_size); + } - // Constrain gas cost on the first row - if (pos == 0) { - gas_trace_builder.constrain_gas_lookup(clk, OpCode::RETURN); - } + // Constrain gas cost + gas_trace_builder.constrain_gas_lookup(clk, OpCode::RETURN); - main_trace.push_back(Row{ - .main_clk = clk, - .main_call_ptr = call_ptr, - .main_ia = ia, - .main_ib = ib, - .main_ic = ic, - .main_ind_addr_a = indirect_flag ? FF(ret_offset) : FF(0), - .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(mem_addr_a), - .main_mem_addr_b = FF(mem_addr_b), - .main_mem_addr_c = FF(mem_addr_c), - .main_pc = FF(pc), - .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), - .main_sel_mem_op_a = FF(mem_op_a), - .main_sel_mem_op_activate_gas = FF(static_cast( - pos == 0)), // TODO: remove in the long term. This activate gas only for the first row. - .main_sel_mem_op_b = FF(mem_op_b), - .main_sel_mem_op_c = FF(mem_op_c), - .main_sel_op_halt = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_flag)), - .main_tag_err = FF(static_cast(!tag_match)), - .main_w_in_tag = FF(static_cast(AvmMemoryTag::FF)), - }); + main_trace.push_back(Row{ + .main_clk = clk, + .main_call_ptr = call_ptr, + .main_ib = ret_size, + .main_ind_addr_c = indirect_flag ? ret_offset : 0, + .main_internal_return_ptr = FF(internal_return_ptr), + .main_mem_addr_c = direct_ret_offset, + .main_pc = pc, + .main_r_in_tag = static_cast(AvmMemoryTag::FF), + .main_sel_op_external_return = 1, + .main_sel_op_halt = 1, + .main_sel_resolve_ind_addr_c = static_cast(indirect_flag), + .main_sel_slice_gadget = static_cast(tag_match), + .main_tag_err = static_cast(!tag_match), + .main_w_in_tag = static_cast(AvmMemoryTag::FF), + }); - if (ret_size - pos > 2) { // Guard to prevent overflow if ret_size is close to uint32_t maximum value. - pos += 3; - } else { - pos = ret_size; - } - } pc = UINT32_MAX; // This ensures that no subsequent opcode will be executed. - return returnMem; + return returndata; } std::vector AvmTraceBuilder::op_revert(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size) @@ -3407,11 +3291,11 @@ void AvmTraceBuilder::op_variable_msm(uint8_t indirect, std::vector points_inf_vec; std::vector scalars_vec; AddressWithMode coords_offset = resolved_points_offset; - // Loading the points is a bit more complex since we need to read the coordinates and the infinity flags separately - // The current circuit constraints does not allow for multiple memory tags to be loaded from within the same row. - // If we could we would be able to replace the following loops with a single read_slice_to_memory call. - // For now we load the coordinates first and then the infinity flags, and finally splice them together when creating - // the points + // Loading the points is a bit more complex since we need to read the coordinates and the infinity flags + // separately The current circuit constraints does not allow for multiple memory tags to be loaded from within + // the same row. If we could we would be able to replace the following loops with a single read_slice_to_memory + // call. For now we load the coordinates first and then the infinity flags, and finally splice them together + // when creating the points // Read the coordinates first, +2 since we read 2 points per row, the first load could be indirect for (uint32_t i = 0; i < num_points; i++) { @@ -3465,7 +3349,8 @@ void AvmTraceBuilder::op_variable_msm(uint8_t indirect, } // Scalar read length is num_points* 2 since scalars are stored as lo and hi limbs uint32_t scalar_read_length = num_points * 2; - // Scalars are easy to read since they are stored as [lo1, hi1, lo2, hi2, ...] with the types [FF, FF, FF,FF, ...] + // Scalars are easy to read since they are stored as [lo1, hi1, lo2, hi2, ...] with the types [FF, FF, FF,FF, + // ...] auto num_scalar_rows = read_slice_to_memory(call_ptr, clk, resolved_scalars_offset, @@ -3857,6 +3742,7 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c auto pedersen_trace = pedersen_trace_builder.finalize(); auto bin_trace = bin_trace_builder.finalize(); auto gas_trace = gas_trace_builder.finalize(); + auto slice_trace = slice_trace_builder.finalize(); const auto& fixed_gas_table = FixedGasTable::get(); size_t mem_trace_size = mem_trace.size(); size_t main_trace_size = main_trace.size(); @@ -3868,6 +3754,7 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c size_t pedersen_trace_size = pedersen_trace.size(); size_t bin_trace_size = bin_trace.size(); size_t gas_trace_size = gas_trace.size(); + size_t slice_trace_size = slice_trace.size(); // Data structure to collect all lookup counts pertaining to 16-bit/32-bit range checks in memory trace std::unordered_map mem_rng_check_lo_counts; @@ -3879,11 +3766,12 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c // 2**16 long) size_t const lookup_table_size = (bin_trace_size > 0 && range_check_required) ? 3 * (1 << 16) : 0; size_t const range_check_size = range_check_required ? UINT16_MAX + 1 : 0; - std::vector trace_sizes = { mem_trace_size, main_trace_size, alu_trace_size, - range_check_size, conv_trace_size, lookup_table_size, - sha256_trace_size, poseidon2_trace_size, pedersen_trace_size, - gas_trace_size + 1, KERNEL_INPUTS_LENGTH, KERNEL_OUTPUTS_LENGTH, - min_trace_size, fixed_gas_table.size() }; + std::vector trace_sizes = { mem_trace_size, main_trace_size, alu_trace_size, + range_check_size, conv_trace_size, lookup_table_size, + sha256_trace_size, poseidon2_trace_size, pedersen_trace_size, + gas_trace_size + 1, KERNEL_INPUTS_LENGTH, KERNEL_OUTPUTS_LENGTH, + min_trace_size, fixed_gas_table.size(), slice_trace_size, + calldata.size() }; auto trace_size = std::max_element(trace_sizes.begin(), trace_sizes.end()); // We only need to pad with zeroes to the size to the largest trace here, pow_2 padding is handled in the @@ -3925,45 +3813,51 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c dest.mem_sel_mov_ia_to_ic = FF(static_cast(src.m_sel_mov_ia_to_ic)); dest.mem_sel_mov_ib_to_ic = FF(static_cast(src.m_sel_mov_ib_to_ic)); dest.mem_sel_op_cmov = FF(static_cast(src.m_sel_cmov)); + dest.mem_sel_op_slice = FF(static_cast(src.m_sel_op_slice)); dest.incl_mem_tag_err_counts = FF(static_cast(src.m_tag_err_count_relevant)); - switch (src.m_sub_clk) { - case AvmMemTraceBuilder::SUB_CLK_LOAD_A: - case AvmMemTraceBuilder::SUB_CLK_STORE_A: - dest.mem_sel_op_a = 1; - break; - case AvmMemTraceBuilder::SUB_CLK_LOAD_B: - case AvmMemTraceBuilder::SUB_CLK_STORE_B: - dest.mem_sel_op_b = 1; - break; - case AvmMemTraceBuilder::SUB_CLK_LOAD_C: - case AvmMemTraceBuilder::SUB_CLK_STORE_C: - dest.mem_sel_op_c = 1; - break; - case AvmMemTraceBuilder::SUB_CLK_LOAD_D: - case AvmMemTraceBuilder::SUB_CLK_STORE_D: - dest.mem_sel_op_d = 1; - break; - case AvmMemTraceBuilder::SUB_CLK_IND_LOAD_A: - dest.mem_sel_resolve_ind_addr_a = 1; - break; - case AvmMemTraceBuilder::SUB_CLK_IND_LOAD_B: - dest.mem_sel_resolve_ind_addr_b = 1; - break; - case AvmMemTraceBuilder::SUB_CLK_IND_LOAD_C: - dest.mem_sel_resolve_ind_addr_c = 1; - break; - case AvmMemTraceBuilder::SUB_CLK_IND_LOAD_D: - dest.mem_sel_resolve_ind_addr_d = 1; - break; - default: - break; + // Calldatacopy/return memory operations are handled differently and are activated by m_sel_op_slice. + if (!src.m_sel_op_slice) { + switch (src.m_sub_clk) { + case AvmMemTraceBuilder::SUB_CLK_LOAD_A: + case AvmMemTraceBuilder::SUB_CLK_STORE_A: + dest.mem_sel_op_a = 1; + break; + case AvmMemTraceBuilder::SUB_CLK_LOAD_B: + case AvmMemTraceBuilder::SUB_CLK_STORE_B: + dest.mem_sel_op_b = 1; + break; + case AvmMemTraceBuilder::SUB_CLK_LOAD_C: + case AvmMemTraceBuilder::SUB_CLK_STORE_C: + dest.mem_sel_op_c = 1; + break; + case AvmMemTraceBuilder::SUB_CLK_LOAD_D: + case AvmMemTraceBuilder::SUB_CLK_STORE_D: + dest.mem_sel_op_d = 1; + break; + case AvmMemTraceBuilder::SUB_CLK_IND_LOAD_A: + dest.mem_sel_resolve_ind_addr_a = 1; + break; + case AvmMemTraceBuilder::SUB_CLK_IND_LOAD_B: + dest.mem_sel_resolve_ind_addr_b = 1; + break; + case AvmMemTraceBuilder::SUB_CLK_IND_LOAD_C: + dest.mem_sel_resolve_ind_addr_c = 1; + break; + case AvmMemTraceBuilder::SUB_CLK_IND_LOAD_D: + dest.mem_sel_resolve_ind_addr_d = 1; + break; + default: + break; + } } - if (src.m_sel_cmov) { - dest.mem_skip_check_tag = dest.mem_sel_op_d + dest.mem_sel_op_a * (-dest.mem_sel_mov_ia_to_ic + 1) + - dest.mem_sel_op_b * (-dest.mem_sel_mov_ib_to_ic + 1); + if (src.m_sel_cmov || src.m_sel_op_slice) { + dest.mem_skip_check_tag = + dest.mem_sel_op_cmov * (dest.mem_sel_op_d + dest.mem_sel_op_a * (-dest.mem_sel_mov_ia_to_ic + 1) + + dest.mem_sel_op_b * (-dest.mem_sel_mov_ib_to_ic + 1)) + + dest.mem_sel_op_slice; } if (i + 1 < mem_trace_size) { @@ -4208,6 +4102,13 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c dest.pedersen_sel_pedersen = FF(1); } + /********************************************************************************************** + * SLICE TRACE INCLUSION + **********************************************************************************************/ + for (size_t i = 0; i < slice_trace_size; i++) { + merge_into(main_trace.at(i), slice_trace.at(i)); + } + /********************************************************************************************** * BINARY TRACE INCLUSION **********************************************************************************************/ @@ -4648,9 +4549,26 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c std::get(kernel_trace_builder.public_inputs).at(i); } - // calldata column inclusion + // calldata column inclusion and selector for (size_t i = 0; i < calldata.size(); i++) { main_trace.at(i).main_calldata = calldata.at(i); + main_trace.at(i).main_sel_calldata = 1; + } + + // calldata loookup counts for calldatacopy operations + for (auto const& [cd_offset, count] : slice_trace_builder.cd_lookup_counts) { + main_trace.at(cd_offset).lookup_cd_value_counts = count; + } + + // returndata column inclusion and selector + for (size_t i = 0; i < returndata.size(); i++) { + main_trace.at(i).main_returndata = returndata.at(i); + main_trace.at(i).main_sel_returndata = 1; + } + + // returndata loookup counts for return operations + for (auto const& [cd_offset, count] : slice_trace_builder.ret_lookup_counts) { + main_trace.at(cd_offset).lookup_ret_value_counts = count; } // Get tag_err counts from the mem_trace_builder @@ -4692,6 +4610,7 @@ void AvmTraceBuilder::reset() poseidon2_trace_builder.reset(); keccak_trace_builder.reset(); pedersen_trace_builder.reset(); + slice_trace_builder.reset(); external_call_counter = 0; } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp index 01392ef683ca..5ec749707034 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp @@ -16,6 +16,7 @@ #include "barretenberg/vm/avm_trace/gadgets/avm_pedersen.hpp" #include "barretenberg/vm/avm_trace/gadgets/avm_poseidon2.hpp" #include "barretenberg/vm/avm_trace/gadgets/avm_sha256.hpp" +#include "barretenberg/vm/avm_trace/gadgets/avm_slice_trace.hpp" namespace bb::avm_trace { @@ -185,8 +186,10 @@ class AvmTraceBuilder { AvmKeccakTraceBuilder keccak_trace_builder; AvmPedersenTraceBuilder pedersen_trace_builder; AvmEccTraceBuilder ecc_trace_builder; + AvmSliceTraceBuilder slice_trace_builder; std::vector calldata{}; + std::vector returndata{}; Row create_kernel_lookup_opcode( uint8_t indirect, uint32_t dst_offset, uint32_t selector, FF value, AvmMemoryTag w_tag); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_slice_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_slice_trace.cpp new file mode 100644 index 000000000000..5a71af4bf302 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_slice_trace.cpp @@ -0,0 +1,74 @@ +#include "barretenberg/vm/avm_trace/gadgets/avm_slice_trace.hpp" + +#include +#include + +namespace bb::avm_trace { + +void AvmSliceTraceBuilder::reset() +{ + slice_trace.clear(); + cd_lookup_counts.clear(); + ret_lookup_counts.clear(); +} + +std::vector AvmSliceTraceBuilder::finalize() +{ + return std::move(slice_trace); +} + +void AvmSliceTraceBuilder::create_calldata_copy_slice(std::vector const& calldata, + uint32_t clk, + uint8_t space_id, + uint32_t col_offset, + uint32_t copy_size, + uint32_t direct_dst_offset) +{ + create_slice(calldata, clk, space_id, col_offset, copy_size, direct_dst_offset, true); +} + +void AvmSliceTraceBuilder::create_return_slice( + std::vector const& returndata, uint32_t clk, uint8_t space_id, uint32_t direct_ret_offset, uint32_t ret_size) +{ + create_slice(returndata, clk, space_id, 0, ret_size, direct_ret_offset, false); +} + +void AvmSliceTraceBuilder::create_slice(std::vector const& col_data, + uint32_t clk, + uint8_t space_id, + uint32_t col_offset, + uint32_t copy_size, + uint32_t addr, + bool rw) +{ + for (uint32_t i = 0; i < copy_size; i++) { + slice_trace.push_back({ + .clk = clk, + .space_id = space_id, + .addr_ff = FF(addr + i), + .val = col_data.at(col_offset + i), + .col_offset = col_offset + i, + .cnt = copy_size - i, + .one_min_inv = FF(1) - FF(copy_size - i).invert(), + .sel_start = i == 0, + .sel_cd_cpy = rw, + .sel_return = !rw, + }); + + rw ? cd_lookup_counts[col_offset + i]++ : ret_lookup_counts[col_offset + i]++; + } + + // Last extra row for a slice operation. cnt is zero and we have to add extra dummy + // values for addr and col_offset to satisfy the constraints: #[ADDR_INCREMENT] and #[COL_OFFSET_INCREMENT] + // Alternatively, we would have to increase the degree of these two relations. + // Note that addr = 2^32 would be a valid value here, therefore we do not wrap modulo 2^32. + // col_offset is fine as the circuit trace cannot reach a size of 2^32. + slice_trace.emplace_back(SliceTraceEntry{ + .clk = clk, + .space_id = space_id, + .addr_ff = FF(addr + copy_size - 1) + 1, + .col_offset = col_offset + copy_size, + }); +} + +} // namespace bb::avm_trace \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_slice_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_slice_trace.hpp new file mode 100644 index 000000000000..b67666881b38 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/gadgets/avm_slice_trace.hpp @@ -0,0 +1,75 @@ +#pragma once + +#include "barretenberg/vm/avm_trace/avm_common.hpp" + +#include + +namespace bb::avm_trace { + +class AvmSliceTraceBuilder { + + public: + // Keeps track of the number of times a calldata/returndata value is copied. + // column offset -> count + std::unordered_map cd_lookup_counts; + std::unordered_map ret_lookup_counts; + + struct SliceTraceEntry { + uint32_t clk = 0; + uint8_t space_id = 0; + FF addr_ff = 0; // Should normally be uint32_t but the last witness addr of a calldatacopy/return operation + // row might be FF(2^32). + FF val{}; + uint32_t col_offset = 0; + uint32_t cnt = 0; + FF one_min_inv{}; + + bool sel_start = false; + bool sel_cd_cpy = false; + bool sel_return = false; + }; + + AvmSliceTraceBuilder() = default; + + void reset(); + std::vector finalize(); + + void create_calldata_copy_slice(std::vector const& calldata, + uint32_t clk, + uint8_t space_id, + uint32_t col_offset, + uint32_t copy_size, + uint32_t direct_dst_offset); + void create_return_slice(std::vector const& returndata, + uint32_t clk, + uint8_t space_id, + uint32_t direct_ret_offset, + uint32_t ret_size); + + private: + std::vector slice_trace; + void create_slice(std::vector const& col_data, + uint32_t clk, + uint8_t space_id, + uint32_t col_offset, + uint32_t copy_size, + uint32_t addr, + bool rw); +}; + +template void merge_into(DestRow& dest, AvmSliceTraceBuilder::SliceTraceEntry const& src) +{ + dest.slice_clk = src.clk; + dest.slice_space_id = src.space_id; + dest.slice_addr = src.addr_ff; + dest.slice_val = src.val; + dest.slice_col_offset = src.col_offset; + dest.slice_cnt = src.cnt; + dest.slice_one_min_inv = src.one_min_inv; + dest.slice_sel_start = static_cast(src.sel_start); + dest.slice_sel_cd_cpy = static_cast(src.sel_cd_cpy); + dest.slice_sel_return = static_cast(src.sel_return); + dest.slice_sel_mem_active = static_cast(src.sel_return || src.sel_cd_cpy); +} + +} // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp new file mode 100644 index 000000000000..f39307155a5c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp @@ -0,0 +1,853 @@ +#include "barretenberg/vm/generated/avm_circuit_builder.hpp" + +namespace bb { +namespace { + +template std::string field_to_string(const FF& ff) +{ + std::ostringstream os; + os << ff; + std::string raw = os.str(); + auto first_not_zero = raw.find_first_not_of('0', 2); + std::string result = "0x" + (first_not_zero != std::string::npos ? raw.substr(first_not_zero) : "0"); + return result; +} + +} // namespace + +template std::vector AvmFullRow::names() +{ + return { "main_clk", + "main_sel_first", + "kernel_kernel_inputs", + "kernel_kernel_value_out", + "kernel_kernel_side_effect_out", + "kernel_kernel_metadata_out", + "main_calldata", + "main_returndata", + "alu_a_hi", + "alu_a_lo", + "alu_b_hi", + "alu_b_lo", + "alu_borrow", + "alu_cf", + "alu_clk", + "alu_cmp_rng_ctr", + "alu_div_u16_r0", + "alu_div_u16_r1", + "alu_div_u16_r2", + "alu_div_u16_r3", + "alu_div_u16_r4", + "alu_div_u16_r5", + "alu_div_u16_r6", + "alu_div_u16_r7", + "alu_divisor_hi", + "alu_divisor_lo", + "alu_ff_tag", + "alu_ia", + "alu_ib", + "alu_ic", + "alu_in_tag", + "alu_op_add", + "alu_op_cast", + "alu_op_cast_prev", + "alu_op_div", + "alu_op_div_a_lt_b", + "alu_op_div_std", + "alu_op_eq", + "alu_op_eq_diff_inv", + "alu_op_lt", + "alu_op_lte", + "alu_op_mul", + "alu_op_not", + "alu_op_shl", + "alu_op_shr", + "alu_op_sub", + "alu_p_a_borrow", + "alu_p_b_borrow", + "alu_p_sub_a_hi", + "alu_p_sub_a_lo", + "alu_p_sub_b_hi", + "alu_p_sub_b_lo", + "alu_partial_prod_hi", + "alu_partial_prod_lo", + "alu_quotient_hi", + "alu_quotient_lo", + "alu_remainder", + "alu_res_hi", + "alu_res_lo", + "alu_sel_alu", + "alu_sel_cmp", + "alu_sel_div_rng_chk", + "alu_sel_rng_chk", + "alu_sel_rng_chk_lookup", + "alu_sel_shift_which", + "alu_shift_lt_bit_len", + "alu_t_sub_s_bits", + "alu_two_pow_s", + "alu_two_pow_t_sub_s", + "alu_u128_tag", + "alu_u16_r0", + "alu_u16_r1", + "alu_u16_r10", + "alu_u16_r11", + "alu_u16_r12", + "alu_u16_r13", + "alu_u16_r14", + "alu_u16_r2", + "alu_u16_r3", + "alu_u16_r4", + "alu_u16_r5", + "alu_u16_r6", + "alu_u16_r7", + "alu_u16_r8", + "alu_u16_r9", + "alu_u16_tag", + "alu_u32_tag", + "alu_u64_tag", + "alu_u8_r0", + "alu_u8_r1", + "alu_u8_tag", + "binary_acc_ia", + "binary_acc_ib", + "binary_acc_ic", + "binary_clk", + "binary_ia_bytes", + "binary_ib_bytes", + "binary_ic_bytes", + "binary_in_tag", + "binary_mem_tag_ctr", + "binary_mem_tag_ctr_inv", + "binary_op_id", + "binary_sel_bin", + "binary_start", + "byte_lookup_sel_bin", + "byte_lookup_table_byte_lengths", + "byte_lookup_table_in_tags", + "byte_lookup_table_input_a", + "byte_lookup_table_input_b", + "byte_lookup_table_op_id", + "byte_lookup_table_output", + "conversion_clk", + "conversion_input", + "conversion_num_limbs", + "conversion_radix", + "conversion_sel_to_radix_le", + "gas_da_gas_fixed_table", + "gas_l2_gas_fixed_table", + "gas_sel_gas_cost", + "keccakf1600_clk", + "keccakf1600_input", + "keccakf1600_output", + "keccakf1600_sel_keccakf1600", + "kernel_emit_l2_to_l1_msg_write_offset", + "kernel_emit_note_hash_write_offset", + "kernel_emit_nullifier_write_offset", + "kernel_emit_unencrypted_log_write_offset", + "kernel_kernel_in_offset", + "kernel_kernel_out_offset", + "kernel_l1_to_l2_msg_exists_write_offset", + "kernel_note_hash_exist_write_offset", + "kernel_nullifier_exists_write_offset", + "kernel_nullifier_non_exists_write_offset", + "kernel_q_public_input_kernel_add_to_table", + "kernel_q_public_input_kernel_out_add_to_table", + "kernel_side_effect_counter", + "kernel_sload_write_offset", + "kernel_sstore_write_offset", + "main_abs_da_rem_gas_hi", + "main_abs_da_rem_gas_lo", + "main_abs_l2_rem_gas_hi", + "main_abs_l2_rem_gas_lo", + "main_alu_in_tag", + "main_bin_op_id", + "main_call_ptr", + "main_da_gas_op_cost", + "main_da_gas_remaining", + "main_da_out_of_gas", + "main_ia", + "main_ib", + "main_ic", + "main_id", + "main_id_zero", + "main_ind_addr_a", + "main_ind_addr_b", + "main_ind_addr_c", + "main_ind_addr_d", + "main_internal_return_ptr", + "main_inv", + "main_l2_gas_op_cost", + "main_l2_gas_remaining", + "main_l2_out_of_gas", + "main_mem_addr_a", + "main_mem_addr_b", + "main_mem_addr_c", + "main_mem_addr_d", + "main_op_err", + "main_opcode_val", + "main_pc", + "main_r_in_tag", + "main_rwa", + "main_rwb", + "main_rwc", + "main_rwd", + "main_sel_alu", + "main_sel_bin", + "main_sel_calldata", + "main_sel_gas_accounting_active", + "main_sel_last", + "main_sel_mem_op_a", + "main_sel_mem_op_activate_gas", + "main_sel_mem_op_b", + "main_sel_mem_op_c", + "main_sel_mem_op_d", + "main_sel_mov_ia_to_ic", + "main_sel_mov_ib_to_ic", + "main_sel_op_add", + "main_sel_op_address", + "main_sel_op_and", + "main_sel_op_block_number", + "main_sel_op_calldata_copy", + "main_sel_op_cast", + "main_sel_op_chain_id", + "main_sel_op_cmov", + "main_sel_op_coinbase", + "main_sel_op_dagasleft", + "main_sel_op_div", + "main_sel_op_emit_l2_to_l1_msg", + "main_sel_op_emit_note_hash", + "main_sel_op_emit_nullifier", + "main_sel_op_emit_unencrypted_log", + "main_sel_op_eq", + "main_sel_op_external_call", + "main_sel_op_external_return", + "main_sel_op_fdiv", + "main_sel_op_fee_per_da_gas", + "main_sel_op_fee_per_l2_gas", + "main_sel_op_function_selector", + "main_sel_op_get_contract_instance", + "main_sel_op_halt", + "main_sel_op_internal_call", + "main_sel_op_internal_return", + "main_sel_op_jump", + "main_sel_op_jumpi", + "main_sel_op_keccak", + "main_sel_op_l1_to_l2_msg_exists", + "main_sel_op_l2gasleft", + "main_sel_op_lt", + "main_sel_op_lte", + "main_sel_op_mov", + "main_sel_op_mul", + "main_sel_op_not", + "main_sel_op_note_hash_exists", + "main_sel_op_nullifier_exists", + "main_sel_op_or", + "main_sel_op_pedersen", + "main_sel_op_poseidon2", + "main_sel_op_radix_le", + "main_sel_op_sender", + "main_sel_op_sha256", + "main_sel_op_shl", + "main_sel_op_shr", + "main_sel_op_sload", + "main_sel_op_sstore", + "main_sel_op_storage_address", + "main_sel_op_sub", + "main_sel_op_timestamp", + "main_sel_op_transaction_fee", + "main_sel_op_version", + "main_sel_op_xor", + "main_sel_q_kernel_lookup", + "main_sel_q_kernel_output_lookup", + "main_sel_resolve_ind_addr_a", + "main_sel_resolve_ind_addr_b", + "main_sel_resolve_ind_addr_c", + "main_sel_resolve_ind_addr_d", + "main_sel_returndata", + "main_sel_rng_16", + "main_sel_rng_8", + "main_sel_slice_gadget", + "main_space_id", + "main_tag_err", + "main_w_in_tag", + "mem_addr", + "mem_clk", + "mem_diff_hi", + "mem_diff_lo", + "mem_diff_mid", + "mem_glob_addr", + "mem_last", + "mem_lastAccess", + "mem_one_min_inv", + "mem_r_in_tag", + "mem_rw", + "mem_sel_mem", + "mem_sel_mov_ia_to_ic", + "mem_sel_mov_ib_to_ic", + "mem_sel_op_a", + "mem_sel_op_b", + "mem_sel_op_c", + "mem_sel_op_cmov", + "mem_sel_op_d", + "mem_sel_op_slice", + "mem_sel_resolve_ind_addr_a", + "mem_sel_resolve_ind_addr_b", + "mem_sel_resolve_ind_addr_c", + "mem_sel_resolve_ind_addr_d", + "mem_sel_rng_chk", + "mem_skip_check_tag", + "mem_space_id", + "mem_tag", + "mem_tag_err", + "mem_tsp", + "mem_val", + "mem_w_in_tag", + "pedersen_clk", + "pedersen_input", + "pedersen_output", + "pedersen_sel_pedersen", + "poseidon2_clk", + "poseidon2_input", + "poseidon2_output", + "poseidon2_sel_poseidon_perm", + "powers_power_of_2", + "sha256_clk", + "sha256_input", + "sha256_output", + "sha256_sel_sha256_compression", + "sha256_state", + "slice_addr", + "slice_clk", + "slice_cnt", + "slice_col_offset", + "slice_one_min_inv", + "slice_sel_cd_cpy", + "slice_sel_mem_active", + "slice_sel_return", + "slice_sel_start", + "slice_space_id", + "slice_val", + "perm_slice_mem", + "perm_main_alu", + "perm_main_bin", + "perm_main_conv", + "perm_main_pos2_perm", + "perm_main_pedersen", + "perm_main_slice", + "perm_main_mem_a", + "perm_main_mem_b", + "perm_main_mem_c", + "perm_main_mem_d", + "perm_main_mem_ind_addr_a", + "perm_main_mem_ind_addr_b", + "perm_main_mem_ind_addr_c", + "perm_main_mem_ind_addr_d", + "lookup_byte_lengths", + "lookup_byte_operations", + "lookup_cd_value", + "lookup_ret_value", + "lookup_opcode_gas", + "range_check_l2_gas_hi", + "range_check_l2_gas_lo", + "range_check_da_gas_hi", + "range_check_da_gas_lo", + "kernel_output_lookup", + "lookup_into_kernel", + "incl_main_tag_err", + "incl_mem_tag_err", + "lookup_mem_rng_chk_lo", + "lookup_mem_rng_chk_mid", + "lookup_mem_rng_chk_hi", + "lookup_pow_2_0", + "lookup_pow_2_1", + "lookup_u8_0", + "lookup_u8_1", + "lookup_u16_0", + "lookup_u16_1", + "lookup_u16_2", + "lookup_u16_3", + "lookup_u16_4", + "lookup_u16_5", + "lookup_u16_6", + "lookup_u16_7", + "lookup_u16_8", + "lookup_u16_9", + "lookup_u16_10", + "lookup_u16_11", + "lookup_u16_12", + "lookup_u16_13", + "lookup_u16_14", + "lookup_div_u16_0", + "lookup_div_u16_1", + "lookup_div_u16_2", + "lookup_div_u16_3", + "lookup_div_u16_4", + "lookup_div_u16_5", + "lookup_div_u16_6", + "lookup_div_u16_7", + "lookup_byte_lengths_counts", + "lookup_byte_operations_counts", + "lookup_cd_value_counts", + "lookup_ret_value_counts", + "lookup_opcode_gas_counts", + "range_check_l2_gas_hi_counts", + "range_check_l2_gas_lo_counts", + "range_check_da_gas_hi_counts", + "range_check_da_gas_lo_counts", + "kernel_output_lookup_counts", + "lookup_into_kernel_counts", + "incl_main_tag_err_counts", + "incl_mem_tag_err_counts", + "lookup_mem_rng_chk_lo_counts", + "lookup_mem_rng_chk_mid_counts", + "lookup_mem_rng_chk_hi_counts", + "lookup_pow_2_0_counts", + "lookup_pow_2_1_counts", + "lookup_u8_0_counts", + "lookup_u8_1_counts", + "lookup_u16_0_counts", + "lookup_u16_1_counts", + "lookup_u16_2_counts", + "lookup_u16_3_counts", + "lookup_u16_4_counts", + "lookup_u16_5_counts", + "lookup_u16_6_counts", + "lookup_u16_7_counts", + "lookup_u16_8_counts", + "lookup_u16_9_counts", + "lookup_u16_10_counts", + "lookup_u16_11_counts", + "lookup_u16_12_counts", + "lookup_u16_13_counts", + "lookup_u16_14_counts", + "lookup_div_u16_0_counts", + "lookup_div_u16_1_counts", + "lookup_div_u16_2_counts", + "lookup_div_u16_3_counts", + "lookup_div_u16_4_counts", + "lookup_div_u16_5_counts", + "lookup_div_u16_6_counts", + "lookup_div_u16_7_counts" }; +} + +template std::ostream& operator<<(std::ostream& os, AvmFullRow const& row) +{ + return os << field_to_string(row.main_clk) // + << "," << field_to_string(row.main_sel_first) // + << "," << field_to_string(row.kernel_kernel_inputs) // + << "," << field_to_string(row.kernel_kernel_value_out) // + << "," << field_to_string(row.kernel_kernel_side_effect_out) // + << "," << field_to_string(row.kernel_kernel_metadata_out) // + << "," << field_to_string(row.main_calldata) // + << "," << field_to_string(row.main_returndata) // + << "," << field_to_string(row.alu_a_hi) // + << "," << field_to_string(row.alu_a_lo) // + << "," << field_to_string(row.alu_b_hi) // + << "," << field_to_string(row.alu_b_lo) // + << "," << field_to_string(row.alu_borrow) // + << "," << field_to_string(row.alu_cf) // + << "," << field_to_string(row.alu_clk) // + << "," << field_to_string(row.alu_cmp_rng_ctr) // + << "," << field_to_string(row.alu_div_u16_r0) // + << "," << field_to_string(row.alu_div_u16_r1) // + << "," << field_to_string(row.alu_div_u16_r2) // + << "," << field_to_string(row.alu_div_u16_r3) // + << "," << field_to_string(row.alu_div_u16_r4) // + << "," << field_to_string(row.alu_div_u16_r5) // + << "," << field_to_string(row.alu_div_u16_r6) // + << "," << field_to_string(row.alu_div_u16_r7) // + << "," << field_to_string(row.alu_divisor_hi) // + << "," << field_to_string(row.alu_divisor_lo) // + << "," << field_to_string(row.alu_ff_tag) // + << "," << field_to_string(row.alu_ia) // + << "," << field_to_string(row.alu_ib) // + << "," << field_to_string(row.alu_ic) // + << "," << field_to_string(row.alu_in_tag) // + << "," << field_to_string(row.alu_op_add) // + << "," << field_to_string(row.alu_op_cast) // + << "," << field_to_string(row.alu_op_cast_prev) // + << "," << field_to_string(row.alu_op_div) // + << "," << field_to_string(row.alu_op_div_a_lt_b) // + << "," << field_to_string(row.alu_op_div_std) // + << "," << field_to_string(row.alu_op_eq) // + << "," << field_to_string(row.alu_op_eq_diff_inv) // + << "," << field_to_string(row.alu_op_lt) // + << "," << field_to_string(row.alu_op_lte) // + << "," << field_to_string(row.alu_op_mul) // + << "," << field_to_string(row.alu_op_not) // + << "," << field_to_string(row.alu_op_shl) // + << "," << field_to_string(row.alu_op_shr) // + << "," << field_to_string(row.alu_op_sub) // + << "," << field_to_string(row.alu_p_a_borrow) // + << "," << field_to_string(row.alu_p_b_borrow) // + << "," << field_to_string(row.alu_p_sub_a_hi) // + << "," << field_to_string(row.alu_p_sub_a_lo) // + << "," << field_to_string(row.alu_p_sub_b_hi) // + << "," << field_to_string(row.alu_p_sub_b_lo) // + << "," << field_to_string(row.alu_partial_prod_hi) // + << "," << field_to_string(row.alu_partial_prod_lo) // + << "," << field_to_string(row.alu_quotient_hi) // + << "," << field_to_string(row.alu_quotient_lo) // + << "," << field_to_string(row.alu_remainder) // + << "," << field_to_string(row.alu_res_hi) // + << "," << field_to_string(row.alu_res_lo) // + << "," << field_to_string(row.alu_sel_alu) // + << "," << field_to_string(row.alu_sel_cmp) // + << "," << field_to_string(row.alu_sel_div_rng_chk) // + << "," << field_to_string(row.alu_sel_rng_chk) // + << "," << field_to_string(row.alu_sel_rng_chk_lookup) // + << "," << field_to_string(row.alu_sel_shift_which) // + << "," << field_to_string(row.alu_shift_lt_bit_len) // + << "," << field_to_string(row.alu_t_sub_s_bits) // + << "," << field_to_string(row.alu_two_pow_s) // + << "," << field_to_string(row.alu_two_pow_t_sub_s) // + << "," << field_to_string(row.alu_u128_tag) // + << "," << field_to_string(row.alu_u16_r0) // + << "," << field_to_string(row.alu_u16_r1) // + << "," << field_to_string(row.alu_u16_r10) // + << "," << field_to_string(row.alu_u16_r11) // + << "," << field_to_string(row.alu_u16_r12) // + << "," << field_to_string(row.alu_u16_r13) // + << "," << field_to_string(row.alu_u16_r14) // + << "," << field_to_string(row.alu_u16_r2) // + << "," << field_to_string(row.alu_u16_r3) // + << "," << field_to_string(row.alu_u16_r4) // + << "," << field_to_string(row.alu_u16_r5) // + << "," << field_to_string(row.alu_u16_r6) // + << "," << field_to_string(row.alu_u16_r7) // + << "," << field_to_string(row.alu_u16_r8) // + << "," << field_to_string(row.alu_u16_r9) // + << "," << field_to_string(row.alu_u16_tag) // + << "," << field_to_string(row.alu_u32_tag) // + << "," << field_to_string(row.alu_u64_tag) // + << "," << field_to_string(row.alu_u8_r0) // + << "," << field_to_string(row.alu_u8_r1) // + << "," << field_to_string(row.alu_u8_tag) // + << "," << field_to_string(row.binary_acc_ia) // + << "," << field_to_string(row.binary_acc_ib) // + << "," << field_to_string(row.binary_acc_ic) // + << "," << field_to_string(row.binary_clk) // + << "," << field_to_string(row.binary_ia_bytes) // + << "," << field_to_string(row.binary_ib_bytes) // + << "," << field_to_string(row.binary_ic_bytes) // + << "," << field_to_string(row.binary_in_tag) // + << "," << field_to_string(row.binary_mem_tag_ctr) // + << "," << field_to_string(row.binary_mem_tag_ctr_inv) // + << "," << field_to_string(row.binary_op_id) // + << "," << field_to_string(row.binary_sel_bin) // + << "," << field_to_string(row.binary_start) // + << "," << field_to_string(row.byte_lookup_sel_bin) // + << "," << field_to_string(row.byte_lookup_table_byte_lengths) // + << "," << field_to_string(row.byte_lookup_table_in_tags) // + << "," << field_to_string(row.byte_lookup_table_input_a) // + << "," << field_to_string(row.byte_lookup_table_input_b) // + << "," << field_to_string(row.byte_lookup_table_op_id) // + << "," << field_to_string(row.byte_lookup_table_output) // + << "," << field_to_string(row.conversion_clk) // + << "," << field_to_string(row.conversion_input) // + << "," << field_to_string(row.conversion_num_limbs) // + << "," << field_to_string(row.conversion_radix) // + << "," << field_to_string(row.conversion_sel_to_radix_le) // + << "," << field_to_string(row.gas_da_gas_fixed_table) // + << "," << field_to_string(row.gas_l2_gas_fixed_table) // + << "," << field_to_string(row.gas_sel_gas_cost) // + << "," << field_to_string(row.keccakf1600_clk) // + << "," << field_to_string(row.keccakf1600_input) // + << "," << field_to_string(row.keccakf1600_output) // + << "," << field_to_string(row.keccakf1600_sel_keccakf1600) // + << "," << field_to_string(row.kernel_emit_l2_to_l1_msg_write_offset) // + << "," << field_to_string(row.kernel_emit_note_hash_write_offset) // + << "," << field_to_string(row.kernel_emit_nullifier_write_offset) // + << "," << field_to_string(row.kernel_emit_unencrypted_log_write_offset) // + << "," << field_to_string(row.kernel_kernel_in_offset) // + << "," << field_to_string(row.kernel_kernel_out_offset) // + << "," << field_to_string(row.kernel_l1_to_l2_msg_exists_write_offset) // + << "," << field_to_string(row.kernel_note_hash_exist_write_offset) // + << "," << field_to_string(row.kernel_nullifier_exists_write_offset) // + << "," << field_to_string(row.kernel_nullifier_non_exists_write_offset) // + << "," << field_to_string(row.kernel_q_public_input_kernel_add_to_table) // + << "," << field_to_string(row.kernel_q_public_input_kernel_out_add_to_table) // + << "," << field_to_string(row.kernel_side_effect_counter) // + << "," << field_to_string(row.kernel_sload_write_offset) // + << "," << field_to_string(row.kernel_sstore_write_offset) // + << "," << field_to_string(row.main_abs_da_rem_gas_hi) // + << "," << field_to_string(row.main_abs_da_rem_gas_lo) // + << "," << field_to_string(row.main_abs_l2_rem_gas_hi) // + << "," << field_to_string(row.main_abs_l2_rem_gas_lo) // + << "," << field_to_string(row.main_alu_in_tag) // + << "," << field_to_string(row.main_bin_op_id) // + << "," << field_to_string(row.main_call_ptr) // + << "," << field_to_string(row.main_da_gas_op_cost) // + << "," << field_to_string(row.main_da_gas_remaining) // + << "," << field_to_string(row.main_da_out_of_gas) // + << "," << field_to_string(row.main_ia) // + << "," << field_to_string(row.main_ib) // + << "," << field_to_string(row.main_ic) // + << "," << field_to_string(row.main_id) // + << "," << field_to_string(row.main_id_zero) // + << "," << field_to_string(row.main_ind_addr_a) // + << "," << field_to_string(row.main_ind_addr_b) // + << "," << field_to_string(row.main_ind_addr_c) // + << "," << field_to_string(row.main_ind_addr_d) // + << "," << field_to_string(row.main_internal_return_ptr) // + << "," << field_to_string(row.main_inv) // + << "," << field_to_string(row.main_l2_gas_op_cost) // + << "," << field_to_string(row.main_l2_gas_remaining) // + << "," << field_to_string(row.main_l2_out_of_gas) // + << "," << field_to_string(row.main_mem_addr_a) // + << "," << field_to_string(row.main_mem_addr_b) // + << "," << field_to_string(row.main_mem_addr_c) // + << "," << field_to_string(row.main_mem_addr_d) // + << "," << field_to_string(row.main_op_err) // + << "," << field_to_string(row.main_opcode_val) // + << "," << field_to_string(row.main_pc) // + << "," << field_to_string(row.main_r_in_tag) // + << "," << field_to_string(row.main_rwa) // + << "," << field_to_string(row.main_rwb) // + << "," << field_to_string(row.main_rwc) // + << "," << field_to_string(row.main_rwd) // + << "," << field_to_string(row.main_sel_alu) // + << "," << field_to_string(row.main_sel_bin) // + << "," << field_to_string(row.main_sel_calldata) // + << "," << field_to_string(row.main_sel_gas_accounting_active) // + << "," << field_to_string(row.main_sel_last) // + << "," << field_to_string(row.main_sel_mem_op_a) // + << "," << field_to_string(row.main_sel_mem_op_activate_gas) // + << "," << field_to_string(row.main_sel_mem_op_b) // + << "," << field_to_string(row.main_sel_mem_op_c) // + << "," << field_to_string(row.main_sel_mem_op_d) // + << "," << field_to_string(row.main_sel_mov_ia_to_ic) // + << "," << field_to_string(row.main_sel_mov_ib_to_ic) // + << "," << field_to_string(row.main_sel_op_add) // + << "," << field_to_string(row.main_sel_op_address) // + << "," << field_to_string(row.main_sel_op_and) // + << "," << field_to_string(row.main_sel_op_block_number) // + << "," << field_to_string(row.main_sel_op_calldata_copy) // + << "," << field_to_string(row.main_sel_op_cast) // + << "," << field_to_string(row.main_sel_op_chain_id) // + << "," << field_to_string(row.main_sel_op_cmov) // + << "," << field_to_string(row.main_sel_op_coinbase) // + << "," << field_to_string(row.main_sel_op_dagasleft) // + << "," << field_to_string(row.main_sel_op_div) // + << "," << field_to_string(row.main_sel_op_emit_l2_to_l1_msg) // + << "," << field_to_string(row.main_sel_op_emit_note_hash) // + << "," << field_to_string(row.main_sel_op_emit_nullifier) // + << "," << field_to_string(row.main_sel_op_emit_unencrypted_log) // + << "," << field_to_string(row.main_sel_op_eq) // + << "," << field_to_string(row.main_sel_op_external_call) // + << "," << field_to_string(row.main_sel_op_external_return) // + << "," << field_to_string(row.main_sel_op_fdiv) // + << "," << field_to_string(row.main_sel_op_fee_per_da_gas) // + << "," << field_to_string(row.main_sel_op_fee_per_l2_gas) // + << "," << field_to_string(row.main_sel_op_function_selector) // + << "," << field_to_string(row.main_sel_op_get_contract_instance) // + << "," << field_to_string(row.main_sel_op_halt) // + << "," << field_to_string(row.main_sel_op_internal_call) // + << "," << field_to_string(row.main_sel_op_internal_return) // + << "," << field_to_string(row.main_sel_op_jump) // + << "," << field_to_string(row.main_sel_op_jumpi) // + << "," << field_to_string(row.main_sel_op_keccak) // + << "," << field_to_string(row.main_sel_op_l1_to_l2_msg_exists) // + << "," << field_to_string(row.main_sel_op_l2gasleft) // + << "," << field_to_string(row.main_sel_op_lt) // + << "," << field_to_string(row.main_sel_op_lte) // + << "," << field_to_string(row.main_sel_op_mov) // + << "," << field_to_string(row.main_sel_op_mul) // + << "," << field_to_string(row.main_sel_op_not) // + << "," << field_to_string(row.main_sel_op_note_hash_exists) // + << "," << field_to_string(row.main_sel_op_nullifier_exists) // + << "," << field_to_string(row.main_sel_op_or) // + << "," << field_to_string(row.main_sel_op_pedersen) // + << "," << field_to_string(row.main_sel_op_poseidon2) // + << "," << field_to_string(row.main_sel_op_radix_le) // + << "," << field_to_string(row.main_sel_op_sender) // + << "," << field_to_string(row.main_sel_op_sha256) // + << "," << field_to_string(row.main_sel_op_shl) // + << "," << field_to_string(row.main_sel_op_shr) // + << "," << field_to_string(row.main_sel_op_sload) // + << "," << field_to_string(row.main_sel_op_sstore) // + << "," << field_to_string(row.main_sel_op_storage_address) // + << "," << field_to_string(row.main_sel_op_sub) // + << "," << field_to_string(row.main_sel_op_timestamp) // + << "," << field_to_string(row.main_sel_op_transaction_fee) // + << "," << field_to_string(row.main_sel_op_version) // + << "," << field_to_string(row.main_sel_op_xor) // + << "," << field_to_string(row.main_sel_q_kernel_lookup) // + << "," << field_to_string(row.main_sel_q_kernel_output_lookup) // + << "," << field_to_string(row.main_sel_resolve_ind_addr_a) // + << "," << field_to_string(row.main_sel_resolve_ind_addr_b) // + << "," << field_to_string(row.main_sel_resolve_ind_addr_c) // + << "," << field_to_string(row.main_sel_resolve_ind_addr_d) // + << "," << field_to_string(row.main_sel_returndata) // + << "," << field_to_string(row.main_sel_rng_16) // + << "," << field_to_string(row.main_sel_rng_8) // + << "," << field_to_string(row.main_sel_slice_gadget) // + << "," << field_to_string(row.main_space_id) // + << "," << field_to_string(row.main_tag_err) // + << "," << field_to_string(row.main_w_in_tag) // + << "," << field_to_string(row.mem_addr) // + << "," << field_to_string(row.mem_clk) // + << "," << field_to_string(row.mem_diff_hi) // + << "," << field_to_string(row.mem_diff_lo) // + << "," << field_to_string(row.mem_diff_mid) // + << "," << field_to_string(row.mem_glob_addr) // + << "," << field_to_string(row.mem_last) // + << "," << field_to_string(row.mem_lastAccess) // + << "," << field_to_string(row.mem_one_min_inv) // + << "," << field_to_string(row.mem_r_in_tag) // + << "," << field_to_string(row.mem_rw) // + << "," << field_to_string(row.mem_sel_mem) // + << "," << field_to_string(row.mem_sel_mov_ia_to_ic) // + << "," << field_to_string(row.mem_sel_mov_ib_to_ic) // + << "," << field_to_string(row.mem_sel_op_a) // + << "," << field_to_string(row.mem_sel_op_b) // + << "," << field_to_string(row.mem_sel_op_c) // + << "," << field_to_string(row.mem_sel_op_cmov) // + << "," << field_to_string(row.mem_sel_op_d) // + << "," << field_to_string(row.mem_sel_op_slice) // + << "," << field_to_string(row.mem_sel_resolve_ind_addr_a) // + << "," << field_to_string(row.mem_sel_resolve_ind_addr_b) // + << "," << field_to_string(row.mem_sel_resolve_ind_addr_c) // + << "," << field_to_string(row.mem_sel_resolve_ind_addr_d) // + << "," << field_to_string(row.mem_sel_rng_chk) // + << "," << field_to_string(row.mem_skip_check_tag) // + << "," << field_to_string(row.mem_space_id) // + << "," << field_to_string(row.mem_tag) // + << "," << field_to_string(row.mem_tag_err) // + << "," << field_to_string(row.mem_tsp) // + << "," << field_to_string(row.mem_val) // + << "," << field_to_string(row.mem_w_in_tag) // + << "," << field_to_string(row.pedersen_clk) // + << "," << field_to_string(row.pedersen_input) // + << "," << field_to_string(row.pedersen_output) // + << "," << field_to_string(row.pedersen_sel_pedersen) // + << "," << field_to_string(row.poseidon2_clk) // + << "," << field_to_string(row.poseidon2_input) // + << "," << field_to_string(row.poseidon2_output) // + << "," << field_to_string(row.poseidon2_sel_poseidon_perm) // + << "," << field_to_string(row.powers_power_of_2) // + << "," << field_to_string(row.sha256_clk) // + << "," << field_to_string(row.sha256_input) // + << "," << field_to_string(row.sha256_output) // + << "," << field_to_string(row.sha256_sel_sha256_compression) // + << "," << field_to_string(row.sha256_state) // + << "," << field_to_string(row.slice_addr) // + << "," << field_to_string(row.slice_clk) // + << "," << field_to_string(row.slice_cnt) // + << "," << field_to_string(row.slice_col_offset) // + << "," << field_to_string(row.slice_one_min_inv) // + << "," << field_to_string(row.slice_sel_cd_cpy) // + << "," << field_to_string(row.slice_sel_mem_active) // + << "," << field_to_string(row.slice_sel_return) // + << "," << field_to_string(row.slice_sel_start) // + << "," << field_to_string(row.slice_space_id) // + << "," << field_to_string(row.slice_val) // + << "," << field_to_string(row.perm_slice_mem) // + << "," << field_to_string(row.perm_main_alu) // + << "," << field_to_string(row.perm_main_bin) // + << "," << field_to_string(row.perm_main_conv) // + << "," << field_to_string(row.perm_main_pos2_perm) // + << "," << field_to_string(row.perm_main_pedersen) // + << "," << field_to_string(row.perm_main_slice) // + << "," << field_to_string(row.perm_main_mem_a) // + << "," << field_to_string(row.perm_main_mem_b) // + << "," << field_to_string(row.perm_main_mem_c) // + << "," << field_to_string(row.perm_main_mem_d) // + << "," << field_to_string(row.perm_main_mem_ind_addr_a) // + << "," << field_to_string(row.perm_main_mem_ind_addr_b) // + << "," << field_to_string(row.perm_main_mem_ind_addr_c) // + << "," << field_to_string(row.perm_main_mem_ind_addr_d) // + << "," << field_to_string(row.lookup_byte_lengths) // + << "," << field_to_string(row.lookup_byte_operations) // + << "," << field_to_string(row.lookup_cd_value) // + << "," << field_to_string(row.lookup_ret_value) // + << "," << field_to_string(row.lookup_opcode_gas) // + << "," << field_to_string(row.range_check_l2_gas_hi) // + << "," << field_to_string(row.range_check_l2_gas_lo) // + << "," << field_to_string(row.range_check_da_gas_hi) // + << "," << field_to_string(row.range_check_da_gas_lo) // + << "," << field_to_string(row.kernel_output_lookup) // + << "," << field_to_string(row.lookup_into_kernel) // + << "," << field_to_string(row.incl_main_tag_err) // + << "," << field_to_string(row.incl_mem_tag_err) // + << "," << field_to_string(row.lookup_mem_rng_chk_lo) // + << "," << field_to_string(row.lookup_mem_rng_chk_mid) // + << "," << field_to_string(row.lookup_mem_rng_chk_hi) // + << "," << field_to_string(row.lookup_pow_2_0) // + << "," << field_to_string(row.lookup_pow_2_1) // + << "," << field_to_string(row.lookup_u8_0) // + << "," << field_to_string(row.lookup_u8_1) // + << "," << field_to_string(row.lookup_u16_0) // + << "," << field_to_string(row.lookup_u16_1) // + << "," << field_to_string(row.lookup_u16_2) // + << "," << field_to_string(row.lookup_u16_3) // + << "," << field_to_string(row.lookup_u16_4) // + << "," << field_to_string(row.lookup_u16_5) // + << "," << field_to_string(row.lookup_u16_6) // + << "," << field_to_string(row.lookup_u16_7) // + << "," << field_to_string(row.lookup_u16_8) // + << "," << field_to_string(row.lookup_u16_9) // + << "," << field_to_string(row.lookup_u16_10) // + << "," << field_to_string(row.lookup_u16_11) // + << "," << field_to_string(row.lookup_u16_12) // + << "," << field_to_string(row.lookup_u16_13) // + << "," << field_to_string(row.lookup_u16_14) // + << "," << field_to_string(row.lookup_div_u16_0) // + << "," << field_to_string(row.lookup_div_u16_1) // + << "," << field_to_string(row.lookup_div_u16_2) // + << "," << field_to_string(row.lookup_div_u16_3) // + << "," << field_to_string(row.lookup_div_u16_4) // + << "," << field_to_string(row.lookup_div_u16_5) // + << "," << field_to_string(row.lookup_div_u16_6) // + << "," << field_to_string(row.lookup_div_u16_7) // + << "," << field_to_string(row.lookup_byte_lengths_counts) // + << "," << field_to_string(row.lookup_byte_operations_counts) // + << "," << field_to_string(row.lookup_cd_value_counts) // + << "," << field_to_string(row.lookup_ret_value_counts) // + << "," << field_to_string(row.lookup_opcode_gas_counts) // + << "," << field_to_string(row.range_check_l2_gas_hi_counts) // + << "," << field_to_string(row.range_check_l2_gas_lo_counts) // + << "," << field_to_string(row.range_check_da_gas_hi_counts) // + << "," << field_to_string(row.range_check_da_gas_lo_counts) // + << "," << field_to_string(row.kernel_output_lookup_counts) // + << "," << field_to_string(row.lookup_into_kernel_counts) // + << "," << field_to_string(row.incl_main_tag_err_counts) // + << "," << field_to_string(row.incl_mem_tag_err_counts) // + << "," << field_to_string(row.lookup_mem_rng_chk_lo_counts) // + << "," << field_to_string(row.lookup_mem_rng_chk_mid_counts) // + << "," << field_to_string(row.lookup_mem_rng_chk_hi_counts) // + << "," << field_to_string(row.lookup_pow_2_0_counts) // + << "," << field_to_string(row.lookup_pow_2_1_counts) // + << "," << field_to_string(row.lookup_u8_0_counts) // + << "," << field_to_string(row.lookup_u8_1_counts) // + << "," << field_to_string(row.lookup_u16_0_counts) // + << "," << field_to_string(row.lookup_u16_1_counts) // + << "," << field_to_string(row.lookup_u16_2_counts) // + << "," << field_to_string(row.lookup_u16_3_counts) // + << "," << field_to_string(row.lookup_u16_4_counts) // + << "," << field_to_string(row.lookup_u16_5_counts) // + << "," << field_to_string(row.lookup_u16_6_counts) // + << "," << field_to_string(row.lookup_u16_7_counts) // + << "," << field_to_string(row.lookup_u16_8_counts) // + << "," << field_to_string(row.lookup_u16_9_counts) // + << "," << field_to_string(row.lookup_u16_10_counts) // + << "," << field_to_string(row.lookup_u16_11_counts) // + << "," << field_to_string(row.lookup_u16_12_counts) // + << "," << field_to_string(row.lookup_u16_13_counts) // + << "," << field_to_string(row.lookup_u16_14_counts) // + << "," << field_to_string(row.lookup_div_u16_0_counts) // + << "," << field_to_string(row.lookup_div_u16_1_counts) // + << "," << field_to_string(row.lookup_div_u16_2_counts) // + << "," << field_to_string(row.lookup_div_u16_3_counts) // + << "," << field_to_string(row.lookup_div_u16_4_counts) // + << "," << field_to_string(row.lookup_div_u16_5_counts) // + << "," << field_to_string(row.lookup_div_u16_6_counts) // + << "," << field_to_string(row.lookup_div_u16_7_counts) // + ; +} + +// Explicit template instantiation. +template std::ostream& operator<<(std::ostream& os, AvmFullRow const& row); +template std::vector AvmFullRow::names(); + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp index 2bfabec72734..9a2382b1d0fd 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp @@ -29,8 +29,8 @@ class AvmCircuitBuilder { using Polynomial = Flavor::Polynomial; using ProverPolynomials = Flavor::ProverPolynomials; - static constexpr size_t num_fixed_columns = 387; - static constexpr size_t num_polys = 387 + 65; + static constexpr size_t num_fixed_columns = 411; + static constexpr size_t num_polys = 411 + 74; std::vector rows; void set_trace(std::vector&& trace) { rows = std::move(trace); } @@ -53,6 +53,7 @@ class AvmCircuitBuilder { polys.kernel_kernel_side_effect_out[i] = rows[i].kernel_kernel_side_effect_out; polys.kernel_kernel_metadata_out[i] = rows[i].kernel_kernel_metadata_out; polys.main_calldata[i] = rows[i].main_calldata; + polys.main_returndata[i] = rows[i].main_returndata; polys.alu_a_hi[i] = rows[i].alu_a_hi; polys.alu_a_lo[i] = rows[i].alu_a_lo; polys.alu_b_hi[i] = rows[i].alu_b_hi; @@ -222,6 +223,7 @@ class AvmCircuitBuilder { polys.main_rwd[i] = rows[i].main_rwd; polys.main_sel_alu[i] = rows[i].main_sel_alu; polys.main_sel_bin[i] = rows[i].main_sel_bin; + polys.main_sel_calldata[i] = rows[i].main_sel_calldata; polys.main_sel_gas_accounting_active[i] = rows[i].main_sel_gas_accounting_active; polys.main_sel_last[i] = rows[i].main_sel_last; polys.main_sel_mem_op_a[i] = rows[i].main_sel_mem_op_a; @@ -235,6 +237,7 @@ class AvmCircuitBuilder { polys.main_sel_op_address[i] = rows[i].main_sel_op_address; polys.main_sel_op_and[i] = rows[i].main_sel_op_and; polys.main_sel_op_block_number[i] = rows[i].main_sel_op_block_number; + polys.main_sel_op_calldata_copy[i] = rows[i].main_sel_op_calldata_copy; polys.main_sel_op_cast[i] = rows[i].main_sel_op_cast; polys.main_sel_op_chain_id[i] = rows[i].main_sel_op_chain_id; polys.main_sel_op_cmov[i] = rows[i].main_sel_op_cmov; @@ -247,6 +250,7 @@ class AvmCircuitBuilder { polys.main_sel_op_emit_unencrypted_log[i] = rows[i].main_sel_op_emit_unencrypted_log; polys.main_sel_op_eq[i] = rows[i].main_sel_op_eq; polys.main_sel_op_external_call[i] = rows[i].main_sel_op_external_call; + polys.main_sel_op_external_return[i] = rows[i].main_sel_op_external_return; polys.main_sel_op_fdiv[i] = rows[i].main_sel_op_fdiv; polys.main_sel_op_fee_per_da_gas[i] = rows[i].main_sel_op_fee_per_da_gas; polys.main_sel_op_fee_per_l2_gas[i] = rows[i].main_sel_op_fee_per_l2_gas; @@ -289,8 +293,10 @@ class AvmCircuitBuilder { polys.main_sel_resolve_ind_addr_b[i] = rows[i].main_sel_resolve_ind_addr_b; polys.main_sel_resolve_ind_addr_c[i] = rows[i].main_sel_resolve_ind_addr_c; polys.main_sel_resolve_ind_addr_d[i] = rows[i].main_sel_resolve_ind_addr_d; + polys.main_sel_returndata[i] = rows[i].main_sel_returndata; polys.main_sel_rng_16[i] = rows[i].main_sel_rng_16; polys.main_sel_rng_8[i] = rows[i].main_sel_rng_8; + polys.main_sel_slice_gadget[i] = rows[i].main_sel_slice_gadget; polys.main_space_id[i] = rows[i].main_space_id; polys.main_tag_err[i] = rows[i].main_tag_err; polys.main_w_in_tag[i] = rows[i].main_w_in_tag; @@ -313,6 +319,7 @@ class AvmCircuitBuilder { polys.mem_sel_op_c[i] = rows[i].mem_sel_op_c; polys.mem_sel_op_cmov[i] = rows[i].mem_sel_op_cmov; polys.mem_sel_op_d[i] = rows[i].mem_sel_op_d; + polys.mem_sel_op_slice[i] = rows[i].mem_sel_op_slice; polys.mem_sel_resolve_ind_addr_a[i] = rows[i].mem_sel_resolve_ind_addr_a; polys.mem_sel_resolve_ind_addr_b[i] = rows[i].mem_sel_resolve_ind_addr_b; polys.mem_sel_resolve_ind_addr_c[i] = rows[i].mem_sel_resolve_ind_addr_c; @@ -339,8 +346,21 @@ class AvmCircuitBuilder { polys.sha256_output[i] = rows[i].sha256_output; polys.sha256_sel_sha256_compression[i] = rows[i].sha256_sel_sha256_compression; polys.sha256_state[i] = rows[i].sha256_state; + polys.slice_addr[i] = rows[i].slice_addr; + polys.slice_clk[i] = rows[i].slice_clk; + polys.slice_cnt[i] = rows[i].slice_cnt; + polys.slice_col_offset[i] = rows[i].slice_col_offset; + polys.slice_one_min_inv[i] = rows[i].slice_one_min_inv; + polys.slice_sel_cd_cpy[i] = rows[i].slice_sel_cd_cpy; + polys.slice_sel_mem_active[i] = rows[i].slice_sel_mem_active; + polys.slice_sel_return[i] = rows[i].slice_sel_return; + polys.slice_sel_start[i] = rows[i].slice_sel_start; + polys.slice_space_id[i] = rows[i].slice_space_id; + polys.slice_val[i] = rows[i].slice_val; polys.lookup_byte_lengths_counts[i] = rows[i].lookup_byte_lengths_counts; polys.lookup_byte_operations_counts[i] = rows[i].lookup_byte_operations_counts; + polys.lookup_cd_value_counts[i] = rows[i].lookup_cd_value_counts; + polys.lookup_ret_value_counts[i] = rows[i].lookup_ret_value_counts; polys.lookup_opcode_gas_counts[i] = rows[i].lookup_opcode_gas_counts; polys.range_check_l2_gas_hi_counts[i] = rows[i].range_check_l2_gas_hi_counts; polys.range_check_l2_gas_lo_counts[i] = rows[i].range_check_l2_gas_lo_counts; @@ -453,6 +473,15 @@ class AvmCircuitBuilder { polys.mem_tag_shift = Polynomial(polys.mem_tag.shifted()); polys.mem_tsp_shift = Polynomial(polys.mem_tsp.shifted()); polys.mem_val_shift = Polynomial(polys.mem_val.shifted()); + polys.slice_addr_shift = Polynomial(polys.slice_addr.shifted()); + polys.slice_clk_shift = Polynomial(polys.slice_clk.shifted()); + polys.slice_cnt_shift = Polynomial(polys.slice_cnt.shifted()); + polys.slice_col_offset_shift = Polynomial(polys.slice_col_offset.shifted()); + polys.slice_sel_cd_cpy_shift = Polynomial(polys.slice_sel_cd_cpy.shifted()); + polys.slice_sel_mem_active_shift = Polynomial(polys.slice_sel_mem_active.shifted()); + polys.slice_sel_return_shift = Polynomial(polys.slice_sel_return.shifted()); + polys.slice_sel_start_shift = Polynomial(polys.slice_sel_start.shifted()); + polys.slice_space_id_shift = Polynomial(polys.slice_space_id.shifted()); return polys; } @@ -552,6 +581,10 @@ class AvmCircuitBuilder { auto mem = [=]() { return evaluate_relation.template operator()>("mem", Avm_vm::get_relation_label_mem); }; + auto mem_slice = [=]() { + return evaluate_relation.template operator()>("mem_slice", + Avm_vm::get_relation_label_mem_slice); + }; auto pedersen = [=]() { return evaluate_relation.template operator()>("pedersen", Avm_vm::get_relation_label_pedersen); @@ -570,6 +603,9 @@ class AvmCircuitBuilder { }; // Check lookups + auto perm_slice_mem = [=]() { + return evaluate_logderivative.template operator()>("PERM_SLICE_MEM"); + }; auto perm_main_alu = [=]() { return evaluate_logderivative.template operator()>("PERM_MAIN_ALU"); }; @@ -585,6 +621,9 @@ class AvmCircuitBuilder { auto perm_main_pedersen = [=]() { return evaluate_logderivative.template operator()>("PERM_MAIN_PEDERSEN"); }; + auto perm_main_slice = [=]() { + return evaluate_logderivative.template operator()>("PERM_MAIN_SLICE"); + }; auto perm_main_mem_a = [=]() { return evaluate_logderivative.template operator()>("PERM_MAIN_MEM_A"); }; @@ -620,6 +659,12 @@ class AvmCircuitBuilder { return evaluate_logderivative.template operator()>( "LOOKUP_BYTE_OPERATIONS"); }; + auto lookup_cd_value = [=]() { + return evaluate_logderivative.template operator()>("LOOKUP_CD_VALUE"); + }; + auto lookup_ret_value = [=]() { + return evaluate_logderivative.template operator()>("LOOKUP_RET_VALUE"); + }; auto lookup_opcode_gas = [=]() { return evaluate_logderivative.template operator()>("LOOKUP_OPCODE_GAS"); }; @@ -757,15 +802,18 @@ class AvmCircuitBuilder { relation_futures.emplace_back(std::async(std::launch::async, kernel)); relation_futures.emplace_back(std::async(std::launch::async, main)); relation_futures.emplace_back(std::async(std::launch::async, mem)); + relation_futures.emplace_back(std::async(std::launch::async, mem_slice)); relation_futures.emplace_back(std::async(std::launch::async, pedersen)); relation_futures.emplace_back(std::async(std::launch::async, poseidon2)); relation_futures.emplace_back(std::async(std::launch::async, powers)); relation_futures.emplace_back(std::async(std::launch::async, sha256)); + relation_futures.emplace_back(std::async(std::launch::async, perm_slice_mem)); relation_futures.emplace_back(std::async(std::launch::async, perm_main_alu)); relation_futures.emplace_back(std::async(std::launch::async, perm_main_bin)); relation_futures.emplace_back(std::async(std::launch::async, perm_main_conv)); relation_futures.emplace_back(std::async(std::launch::async, perm_main_pos2_perm)); relation_futures.emplace_back(std::async(std::launch::async, perm_main_pedersen)); + relation_futures.emplace_back(std::async(std::launch::async, perm_main_slice)); relation_futures.emplace_back(std::async(std::launch::async, perm_main_mem_a)); relation_futures.emplace_back(std::async(std::launch::async, perm_main_mem_b)); relation_futures.emplace_back(std::async(std::launch::async, perm_main_mem_c)); @@ -776,6 +824,8 @@ class AvmCircuitBuilder { relation_futures.emplace_back(std::async(std::launch::async, perm_main_mem_ind_addr_d)); relation_futures.emplace_back(std::async(std::launch::async, lookup_byte_lengths)); relation_futures.emplace_back(std::async(std::launch::async, lookup_byte_operations)); + relation_futures.emplace_back(std::async(std::launch::async, lookup_cd_value)); + relation_futures.emplace_back(std::async(std::launch::async, lookup_ret_value)); relation_futures.emplace_back(std::async(std::launch::async, lookup_opcode_gas)); relation_futures.emplace_back(std::async(std::launch::async, range_check_l2_gas_hi)); relation_futures.emplace_back(std::async(std::launch::async, range_check_l2_gas_lo)); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index ae9c54f49c16..7ea67f9bfb65 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -23,6 +23,7 @@ #include "barretenberg/relations/generated/avm/kernel.hpp" #include "barretenberg/relations/generated/avm/main.hpp" #include "barretenberg/relations/generated/avm/mem.hpp" +#include "barretenberg/relations/generated/avm/mem_slice.hpp" #include "barretenberg/relations/generated/avm/pedersen.hpp" #include "barretenberg/relations/generated/avm/poseidon2.hpp" #include "barretenberg/relations/generated/avm/powers.hpp" @@ -34,6 +35,7 @@ #include "barretenberg/relations/generated/avm/kernel_output_lookup.hpp" #include "barretenberg/relations/generated/avm/lookup_byte_lengths.hpp" #include "barretenberg/relations/generated/avm/lookup_byte_operations.hpp" +#include "barretenberg/relations/generated/avm/lookup_cd_value.hpp" #include "barretenberg/relations/generated/avm/lookup_div_u16_0.hpp" #include "barretenberg/relations/generated/avm/lookup_div_u16_1.hpp" #include "barretenberg/relations/generated/avm/lookup_div_u16_2.hpp" @@ -49,6 +51,7 @@ #include "barretenberg/relations/generated/avm/lookup_opcode_gas.hpp" #include "barretenberg/relations/generated/avm/lookup_pow_2_0.hpp" #include "barretenberg/relations/generated/avm/lookup_pow_2_1.hpp" +#include "barretenberg/relations/generated/avm/lookup_ret_value.hpp" #include "barretenberg/relations/generated/avm/lookup_u16_0.hpp" #include "barretenberg/relations/generated/avm/lookup_u16_1.hpp" #include "barretenberg/relations/generated/avm/lookup_u16_10.hpp" @@ -79,6 +82,8 @@ #include "barretenberg/relations/generated/avm/perm_main_mem_ind_addr_d.hpp" #include "barretenberg/relations/generated/avm/perm_main_pedersen.hpp" #include "barretenberg/relations/generated/avm/perm_main_pos2_perm.hpp" +#include "barretenberg/relations/generated/avm/perm_main_slice.hpp" +#include "barretenberg/relations/generated/avm/perm_slice_mem.hpp" #include "barretenberg/relations/generated/avm/range_check_da_gas_hi.hpp" #include "barretenberg/relations/generated/avm/range_check_da_gas_lo.hpp" #include "barretenberg/relations/generated/avm/range_check_l2_gas_hi.hpp" @@ -107,11 +112,11 @@ class AvmFlavor { using RelationSeparator = AvmFlavorSettings::RelationSeparator; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 385; + static constexpr size_t NUM_WITNESS_ENTITIES = 409; static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES; // We have two copies of the witness entities, so we subtract the number of fixed ones (they have no shift), one for // the unshifted and one for the shifted - static constexpr size_t NUM_ALL_ENTITIES = 452; + static constexpr size_t NUM_ALL_ENTITIES = 485; using MainRelations = std::tuple< // Relations @@ -123,6 +128,7 @@ class AvmFlavor { Avm_vm::kernel, Avm_vm::main, Avm_vm::mem, + Avm_vm::mem_slice, Avm_vm::pedersen, Avm_vm::poseidon2, Avm_vm::powers, @@ -130,11 +136,13 @@ class AvmFlavor { using LookupRelations = std::tuple< // Lookups + perm_slice_mem_relation, perm_main_alu_relation, perm_main_bin_relation, perm_main_conv_relation, perm_main_pos2_perm_relation, perm_main_pedersen_relation, + perm_main_slice_relation, perm_main_mem_a_relation, perm_main_mem_b_relation, perm_main_mem_c_relation, @@ -145,6 +153,8 @@ class AvmFlavor { perm_main_mem_ind_addr_d_relation, lookup_byte_lengths_relation, lookup_byte_operations_relation, + lookup_cd_value_relation, + lookup_ret_value_relation, lookup_opcode_gas_relation, range_check_l2_gas_hi_relation, range_check_l2_gas_lo_relation, @@ -224,6 +234,7 @@ class AvmFlavor { kernel_kernel_side_effect_out, kernel_kernel_metadata_out, main_calldata, + main_returndata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -392,6 +403,7 @@ class AvmFlavor { main_rwd, main_sel_alu, main_sel_bin, + main_sel_calldata, main_sel_gas_accounting_active, main_sel_last, main_sel_mem_op_a, @@ -405,6 +417,7 @@ class AvmFlavor { main_sel_op_address, main_sel_op_and, main_sel_op_block_number, + main_sel_op_calldata_copy, main_sel_op_cast, main_sel_op_chain_id, main_sel_op_cmov, @@ -417,6 +430,7 @@ class AvmFlavor { main_sel_op_emit_unencrypted_log, main_sel_op_eq, main_sel_op_external_call, + main_sel_op_external_return, main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, @@ -459,8 +473,10 @@ class AvmFlavor { main_sel_resolve_ind_addr_b, main_sel_resolve_ind_addr_c, main_sel_resolve_ind_addr_d, + main_sel_returndata, main_sel_rng_16, main_sel_rng_8, + main_sel_slice_gadget, main_space_id, main_tag_err, main_w_in_tag, @@ -483,6 +499,7 @@ class AvmFlavor { mem_sel_op_c, mem_sel_op_cmov, mem_sel_op_d, + mem_sel_op_slice, mem_sel_resolve_ind_addr_a, mem_sel_resolve_ind_addr_b, mem_sel_resolve_ind_addr_c, @@ -509,8 +526,21 @@ class AvmFlavor { sha256_output, sha256_sel_sha256_compression, sha256_state, + slice_addr, + slice_clk, + slice_cnt, + slice_col_offset, + slice_one_min_inv, + slice_sel_cd_cpy, + slice_sel_mem_active, + slice_sel_return, + slice_sel_start, + slice_space_id, + slice_val, lookup_byte_lengths_counts, lookup_byte_operations_counts, + lookup_cd_value_counts, + lookup_ret_value_counts, lookup_opcode_gas_counts, range_check_l2_gas_hi_counts, range_check_l2_gas_lo_counts, @@ -555,11 +585,13 @@ class AvmFlavor { template class DerivedWitnessEntities { public: DEFINE_FLAVOR_MEMBERS(DataType, + perm_slice_mem, perm_main_alu, perm_main_bin, perm_main_conv, perm_main_pos2_perm, perm_main_pedersen, + perm_main_slice, perm_main_mem_a, perm_main_mem_b, perm_main_mem_c, @@ -570,6 +602,8 @@ class AvmFlavor { perm_main_mem_ind_addr_d, lookup_byte_lengths, lookup_byte_operations, + lookup_cd_value, + lookup_ret_value, lookup_opcode_gas, range_check_l2_gas_hi, range_check_l2_gas_lo, @@ -678,7 +712,16 @@ class AvmFlavor { mem_sel_mem_shift, mem_tag_shift, mem_tsp_shift, - mem_val_shift) + mem_val_shift, + slice_addr_shift, + slice_clk_shift, + slice_cnt_shift, + slice_col_offset_shift, + slice_sel_cd_cpy_shift, + slice_sel_mem_active_shift, + slice_sel_return_shift, + slice_sel_start_shift, + slice_space_id_shift) }; template @@ -748,7 +791,16 @@ class AvmFlavor { entities.mem_sel_mem, entities.mem_tag, entities.mem_tsp, - entities.mem_val }; + entities.mem_val, + entities.slice_addr, + entities.slice_clk, + entities.slice_cnt, + entities.slice_col_offset, + entities.slice_sel_cd_cpy, + entities.slice_sel_mem_active, + entities.slice_sel_return, + entities.slice_sel_start, + entities.slice_space_id }; } template @@ -849,7 +901,16 @@ class AvmFlavor { mem_sel_mem, mem_tag, mem_tsp, - mem_val }; + mem_val, + slice_addr, + slice_clk, + slice_cnt, + slice_col_offset, + slice_sel_cd_cpy, + slice_sel_mem_active, + slice_sel_return, + slice_sel_start, + slice_space_id }; } }; @@ -873,6 +934,7 @@ class AvmFlavor { kernel_kernel_side_effect_out, kernel_kernel_metadata_out, main_calldata, + main_returndata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -1041,6 +1103,7 @@ class AvmFlavor { main_rwd, main_sel_alu, main_sel_bin, + main_sel_calldata, main_sel_gas_accounting_active, main_sel_last, main_sel_mem_op_a, @@ -1054,6 +1117,7 @@ class AvmFlavor { main_sel_op_address, main_sel_op_and, main_sel_op_block_number, + main_sel_op_calldata_copy, main_sel_op_cast, main_sel_op_chain_id, main_sel_op_cmov, @@ -1066,6 +1130,7 @@ class AvmFlavor { main_sel_op_emit_unencrypted_log, main_sel_op_eq, main_sel_op_external_call, + main_sel_op_external_return, main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, @@ -1108,8 +1173,10 @@ class AvmFlavor { main_sel_resolve_ind_addr_b, main_sel_resolve_ind_addr_c, main_sel_resolve_ind_addr_d, + main_sel_returndata, main_sel_rng_16, main_sel_rng_8, + main_sel_slice_gadget, main_space_id, main_tag_err, main_w_in_tag, @@ -1132,6 +1199,7 @@ class AvmFlavor { mem_sel_op_c, mem_sel_op_cmov, mem_sel_op_d, + mem_sel_op_slice, mem_sel_resolve_ind_addr_a, mem_sel_resolve_ind_addr_b, mem_sel_resolve_ind_addr_c, @@ -1158,11 +1226,24 @@ class AvmFlavor { sha256_output, sha256_sel_sha256_compression, sha256_state, + slice_addr, + slice_clk, + slice_cnt, + slice_col_offset, + slice_one_min_inv, + slice_sel_cd_cpy, + slice_sel_mem_active, + slice_sel_return, + slice_sel_start, + slice_space_id, + slice_val, + perm_slice_mem, perm_main_alu, perm_main_bin, perm_main_conv, perm_main_pos2_perm, perm_main_pedersen, + perm_main_slice, perm_main_mem_a, perm_main_mem_b, perm_main_mem_c, @@ -1173,6 +1254,8 @@ class AvmFlavor { perm_main_mem_ind_addr_d, lookup_byte_lengths, lookup_byte_operations, + lookup_cd_value, + lookup_ret_value, lookup_opcode_gas, range_check_l2_gas_hi, range_check_l2_gas_lo, @@ -1214,6 +1297,8 @@ class AvmFlavor { lookup_div_u16_7, lookup_byte_lengths_counts, lookup_byte_operations_counts, + lookup_cd_value_counts, + lookup_ret_value_counts, lookup_opcode_gas_counts, range_check_l2_gas_hi_counts, range_check_l2_gas_lo_counts, @@ -1317,9 +1402,18 @@ class AvmFlavor { mem_sel_mem_shift, mem_tag_shift, mem_tsp_shift, - mem_val_shift) + mem_val_shift, + slice_addr_shift, + slice_clk_shift, + slice_cnt_shift, + slice_col_offset_shift, + slice_sel_cd_cpy_shift, + slice_sel_mem_active_shift, + slice_sel_return_shift, + slice_sel_start_shift, + slice_space_id_shift) - AllConstRefValues(const RefArray& il) + AllConstRefValues(const RefArray& il) : main_clk(il[0]) , main_sel_first(il[1]) , kernel_kernel_inputs(il[2]) @@ -1327,451 +1421,484 @@ class AvmFlavor { , kernel_kernel_side_effect_out(il[4]) , kernel_kernel_metadata_out(il[5]) , main_calldata(il[6]) - , alu_a_hi(il[7]) - , alu_a_lo(il[8]) - , alu_b_hi(il[9]) - , alu_b_lo(il[10]) - , alu_borrow(il[11]) - , alu_cf(il[12]) - , alu_clk(il[13]) - , alu_cmp_rng_ctr(il[14]) - , alu_div_u16_r0(il[15]) - , alu_div_u16_r1(il[16]) - , alu_div_u16_r2(il[17]) - , alu_div_u16_r3(il[18]) - , alu_div_u16_r4(il[19]) - , alu_div_u16_r5(il[20]) - , alu_div_u16_r6(il[21]) - , alu_div_u16_r7(il[22]) - , alu_divisor_hi(il[23]) - , alu_divisor_lo(il[24]) - , alu_ff_tag(il[25]) - , alu_ia(il[26]) - , alu_ib(il[27]) - , alu_ic(il[28]) - , alu_in_tag(il[29]) - , alu_op_add(il[30]) - , alu_op_cast(il[31]) - , alu_op_cast_prev(il[32]) - , alu_op_div(il[33]) - , alu_op_div_a_lt_b(il[34]) - , alu_op_div_std(il[35]) - , alu_op_eq(il[36]) - , alu_op_eq_diff_inv(il[37]) - , alu_op_lt(il[38]) - , alu_op_lte(il[39]) - , alu_op_mul(il[40]) - , alu_op_not(il[41]) - , alu_op_shl(il[42]) - , alu_op_shr(il[43]) - , alu_op_sub(il[44]) - , alu_p_a_borrow(il[45]) - , alu_p_b_borrow(il[46]) - , alu_p_sub_a_hi(il[47]) - , alu_p_sub_a_lo(il[48]) - , alu_p_sub_b_hi(il[49]) - , alu_p_sub_b_lo(il[50]) - , alu_partial_prod_hi(il[51]) - , alu_partial_prod_lo(il[52]) - , alu_quotient_hi(il[53]) - , alu_quotient_lo(il[54]) - , alu_remainder(il[55]) - , alu_res_hi(il[56]) - , alu_res_lo(il[57]) - , alu_sel_alu(il[58]) - , alu_sel_cmp(il[59]) - , alu_sel_div_rng_chk(il[60]) - , alu_sel_rng_chk(il[61]) - , alu_sel_rng_chk_lookup(il[62]) - , alu_sel_shift_which(il[63]) - , alu_shift_lt_bit_len(il[64]) - , alu_t_sub_s_bits(il[65]) - , alu_two_pow_s(il[66]) - , alu_two_pow_t_sub_s(il[67]) - , alu_u128_tag(il[68]) - , alu_u16_r0(il[69]) - , alu_u16_r1(il[70]) - , alu_u16_r10(il[71]) - , alu_u16_r11(il[72]) - , alu_u16_r12(il[73]) - , alu_u16_r13(il[74]) - , alu_u16_r14(il[75]) - , alu_u16_r2(il[76]) - , alu_u16_r3(il[77]) - , alu_u16_r4(il[78]) - , alu_u16_r5(il[79]) - , alu_u16_r6(il[80]) - , alu_u16_r7(il[81]) - , alu_u16_r8(il[82]) - , alu_u16_r9(il[83]) - , alu_u16_tag(il[84]) - , alu_u32_tag(il[85]) - , alu_u64_tag(il[86]) - , alu_u8_r0(il[87]) - , alu_u8_r1(il[88]) - , alu_u8_tag(il[89]) - , binary_acc_ia(il[90]) - , binary_acc_ib(il[91]) - , binary_acc_ic(il[92]) - , binary_clk(il[93]) - , binary_ia_bytes(il[94]) - , binary_ib_bytes(il[95]) - , binary_ic_bytes(il[96]) - , binary_in_tag(il[97]) - , binary_mem_tag_ctr(il[98]) - , binary_mem_tag_ctr_inv(il[99]) - , binary_op_id(il[100]) - , binary_sel_bin(il[101]) - , binary_start(il[102]) - , byte_lookup_sel_bin(il[103]) - , byte_lookup_table_byte_lengths(il[104]) - , byte_lookup_table_in_tags(il[105]) - , byte_lookup_table_input_a(il[106]) - , byte_lookup_table_input_b(il[107]) - , byte_lookup_table_op_id(il[108]) - , byte_lookup_table_output(il[109]) - , conversion_clk(il[110]) - , conversion_input(il[111]) - , conversion_num_limbs(il[112]) - , conversion_radix(il[113]) - , conversion_sel_to_radix_le(il[114]) - , gas_da_gas_fixed_table(il[115]) - , gas_l2_gas_fixed_table(il[116]) - , gas_sel_gas_cost(il[117]) - , keccakf1600_clk(il[118]) - , keccakf1600_input(il[119]) - , keccakf1600_output(il[120]) - , keccakf1600_sel_keccakf1600(il[121]) - , kernel_emit_l2_to_l1_msg_write_offset(il[122]) - , kernel_emit_note_hash_write_offset(il[123]) - , kernel_emit_nullifier_write_offset(il[124]) - , kernel_emit_unencrypted_log_write_offset(il[125]) - , kernel_kernel_in_offset(il[126]) - , kernel_kernel_out_offset(il[127]) - , kernel_l1_to_l2_msg_exists_write_offset(il[128]) - , kernel_note_hash_exist_write_offset(il[129]) - , kernel_nullifier_exists_write_offset(il[130]) - , kernel_nullifier_non_exists_write_offset(il[131]) - , kernel_q_public_input_kernel_add_to_table(il[132]) - , kernel_q_public_input_kernel_out_add_to_table(il[133]) - , kernel_side_effect_counter(il[134]) - , kernel_sload_write_offset(il[135]) - , kernel_sstore_write_offset(il[136]) - , main_abs_da_rem_gas_hi(il[137]) - , main_abs_da_rem_gas_lo(il[138]) - , main_abs_l2_rem_gas_hi(il[139]) - , main_abs_l2_rem_gas_lo(il[140]) - , main_alu_in_tag(il[141]) - , main_bin_op_id(il[142]) - , main_call_ptr(il[143]) - , main_da_gas_op_cost(il[144]) - , main_da_gas_remaining(il[145]) - , main_da_out_of_gas(il[146]) - , main_ia(il[147]) - , main_ib(il[148]) - , main_ic(il[149]) - , main_id(il[150]) - , main_id_zero(il[151]) - , main_ind_addr_a(il[152]) - , main_ind_addr_b(il[153]) - , main_ind_addr_c(il[154]) - , main_ind_addr_d(il[155]) - , main_internal_return_ptr(il[156]) - , main_inv(il[157]) - , main_l2_gas_op_cost(il[158]) - , main_l2_gas_remaining(il[159]) - , main_l2_out_of_gas(il[160]) - , main_mem_addr_a(il[161]) - , main_mem_addr_b(il[162]) - , main_mem_addr_c(il[163]) - , main_mem_addr_d(il[164]) - , main_op_err(il[165]) - , main_opcode_val(il[166]) - , main_pc(il[167]) - , main_r_in_tag(il[168]) - , main_rwa(il[169]) - , main_rwb(il[170]) - , main_rwc(il[171]) - , main_rwd(il[172]) - , main_sel_alu(il[173]) - , main_sel_bin(il[174]) - , main_sel_gas_accounting_active(il[175]) - , main_sel_last(il[176]) - , main_sel_mem_op_a(il[177]) - , main_sel_mem_op_activate_gas(il[178]) - , main_sel_mem_op_b(il[179]) - , main_sel_mem_op_c(il[180]) - , main_sel_mem_op_d(il[181]) - , main_sel_mov_ia_to_ic(il[182]) - , main_sel_mov_ib_to_ic(il[183]) - , main_sel_op_add(il[184]) - , main_sel_op_address(il[185]) - , main_sel_op_and(il[186]) - , main_sel_op_block_number(il[187]) - , main_sel_op_cast(il[188]) - , main_sel_op_chain_id(il[189]) - , main_sel_op_cmov(il[190]) - , main_sel_op_coinbase(il[191]) - , main_sel_op_dagasleft(il[192]) - , main_sel_op_div(il[193]) - , main_sel_op_emit_l2_to_l1_msg(il[194]) - , main_sel_op_emit_note_hash(il[195]) - , main_sel_op_emit_nullifier(il[196]) - , main_sel_op_emit_unencrypted_log(il[197]) - , main_sel_op_eq(il[198]) - , main_sel_op_external_call(il[199]) - , main_sel_op_fdiv(il[200]) - , main_sel_op_fee_per_da_gas(il[201]) - , main_sel_op_fee_per_l2_gas(il[202]) - , main_sel_op_function_selector(il[203]) - , main_sel_op_get_contract_instance(il[204]) - , main_sel_op_halt(il[205]) - , main_sel_op_internal_call(il[206]) - , main_sel_op_internal_return(il[207]) - , main_sel_op_jump(il[208]) - , main_sel_op_jumpi(il[209]) - , main_sel_op_keccak(il[210]) - , main_sel_op_l1_to_l2_msg_exists(il[211]) - , main_sel_op_l2gasleft(il[212]) - , main_sel_op_lt(il[213]) - , main_sel_op_lte(il[214]) - , main_sel_op_mov(il[215]) - , main_sel_op_mul(il[216]) - , main_sel_op_not(il[217]) - , main_sel_op_note_hash_exists(il[218]) - , main_sel_op_nullifier_exists(il[219]) - , main_sel_op_or(il[220]) - , main_sel_op_pedersen(il[221]) - , main_sel_op_poseidon2(il[222]) - , main_sel_op_radix_le(il[223]) - , main_sel_op_sender(il[224]) - , main_sel_op_sha256(il[225]) - , main_sel_op_shl(il[226]) - , main_sel_op_shr(il[227]) - , main_sel_op_sload(il[228]) - , main_sel_op_sstore(il[229]) - , main_sel_op_storage_address(il[230]) - , main_sel_op_sub(il[231]) - , main_sel_op_timestamp(il[232]) - , main_sel_op_transaction_fee(il[233]) - , main_sel_op_version(il[234]) - , main_sel_op_xor(il[235]) - , main_sel_q_kernel_lookup(il[236]) - , main_sel_q_kernel_output_lookup(il[237]) - , main_sel_resolve_ind_addr_a(il[238]) - , main_sel_resolve_ind_addr_b(il[239]) - , main_sel_resolve_ind_addr_c(il[240]) - , main_sel_resolve_ind_addr_d(il[241]) - , main_sel_rng_16(il[242]) - , main_sel_rng_8(il[243]) - , main_space_id(il[244]) - , main_tag_err(il[245]) - , main_w_in_tag(il[246]) - , mem_addr(il[247]) - , mem_clk(il[248]) - , mem_diff_hi(il[249]) - , mem_diff_lo(il[250]) - , mem_diff_mid(il[251]) - , mem_glob_addr(il[252]) - , mem_last(il[253]) - , mem_lastAccess(il[254]) - , mem_one_min_inv(il[255]) - , mem_r_in_tag(il[256]) - , mem_rw(il[257]) - , mem_sel_mem(il[258]) - , mem_sel_mov_ia_to_ic(il[259]) - , mem_sel_mov_ib_to_ic(il[260]) - , mem_sel_op_a(il[261]) - , mem_sel_op_b(il[262]) - , mem_sel_op_c(il[263]) - , mem_sel_op_cmov(il[264]) - , mem_sel_op_d(il[265]) - , mem_sel_resolve_ind_addr_a(il[266]) - , mem_sel_resolve_ind_addr_b(il[267]) - , mem_sel_resolve_ind_addr_c(il[268]) - , mem_sel_resolve_ind_addr_d(il[269]) - , mem_sel_rng_chk(il[270]) - , mem_skip_check_tag(il[271]) - , mem_space_id(il[272]) - , mem_tag(il[273]) - , mem_tag_err(il[274]) - , mem_tsp(il[275]) - , mem_val(il[276]) - , mem_w_in_tag(il[277]) - , pedersen_clk(il[278]) - , pedersen_input(il[279]) - , pedersen_output(il[280]) - , pedersen_sel_pedersen(il[281]) - , poseidon2_clk(il[282]) - , poseidon2_input(il[283]) - , poseidon2_output(il[284]) - , poseidon2_sel_poseidon_perm(il[285]) - , powers_power_of_2(il[286]) - , sha256_clk(il[287]) - , sha256_input(il[288]) - , sha256_output(il[289]) - , sha256_sel_sha256_compression(il[290]) - , sha256_state(il[291]) - , perm_main_alu(il[292]) - , perm_main_bin(il[293]) - , perm_main_conv(il[294]) - , perm_main_pos2_perm(il[295]) - , perm_main_pedersen(il[296]) - , perm_main_mem_a(il[297]) - , perm_main_mem_b(il[298]) - , perm_main_mem_c(il[299]) - , perm_main_mem_d(il[300]) - , perm_main_mem_ind_addr_a(il[301]) - , perm_main_mem_ind_addr_b(il[302]) - , perm_main_mem_ind_addr_c(il[303]) - , perm_main_mem_ind_addr_d(il[304]) - , lookup_byte_lengths(il[305]) - , lookup_byte_operations(il[306]) - , lookup_opcode_gas(il[307]) - , range_check_l2_gas_hi(il[308]) - , range_check_l2_gas_lo(il[309]) - , range_check_da_gas_hi(il[310]) - , range_check_da_gas_lo(il[311]) - , kernel_output_lookup(il[312]) - , lookup_into_kernel(il[313]) - , incl_main_tag_err(il[314]) - , incl_mem_tag_err(il[315]) - , lookup_mem_rng_chk_lo(il[316]) - , lookup_mem_rng_chk_mid(il[317]) - , lookup_mem_rng_chk_hi(il[318]) - , lookup_pow_2_0(il[319]) - , lookup_pow_2_1(il[320]) - , lookup_u8_0(il[321]) - , lookup_u8_1(il[322]) - , lookup_u16_0(il[323]) - , lookup_u16_1(il[324]) - , lookup_u16_2(il[325]) - , lookup_u16_3(il[326]) - , lookup_u16_4(il[327]) - , lookup_u16_5(il[328]) - , lookup_u16_6(il[329]) - , lookup_u16_7(il[330]) - , lookup_u16_8(il[331]) - , lookup_u16_9(il[332]) - , lookup_u16_10(il[333]) - , lookup_u16_11(il[334]) - , lookup_u16_12(il[335]) - , lookup_u16_13(il[336]) - , lookup_u16_14(il[337]) - , lookup_div_u16_0(il[338]) - , lookup_div_u16_1(il[339]) - , lookup_div_u16_2(il[340]) - , lookup_div_u16_3(il[341]) - , lookup_div_u16_4(il[342]) - , lookup_div_u16_5(il[343]) - , lookup_div_u16_6(il[344]) - , lookup_div_u16_7(il[345]) - , lookup_byte_lengths_counts(il[346]) - , lookup_byte_operations_counts(il[347]) - , lookup_opcode_gas_counts(il[348]) - , range_check_l2_gas_hi_counts(il[349]) - , range_check_l2_gas_lo_counts(il[350]) - , range_check_da_gas_hi_counts(il[351]) - , range_check_da_gas_lo_counts(il[352]) - , kernel_output_lookup_counts(il[353]) - , lookup_into_kernel_counts(il[354]) - , incl_main_tag_err_counts(il[355]) - , incl_mem_tag_err_counts(il[356]) - , lookup_mem_rng_chk_lo_counts(il[357]) - , lookup_mem_rng_chk_mid_counts(il[358]) - , lookup_mem_rng_chk_hi_counts(il[359]) - , lookup_pow_2_0_counts(il[360]) - , lookup_pow_2_1_counts(il[361]) - , lookup_u8_0_counts(il[362]) - , lookup_u8_1_counts(il[363]) - , lookup_u16_0_counts(il[364]) - , lookup_u16_1_counts(il[365]) - , lookup_u16_2_counts(il[366]) - , lookup_u16_3_counts(il[367]) - , lookup_u16_4_counts(il[368]) - , lookup_u16_5_counts(il[369]) - , lookup_u16_6_counts(il[370]) - , lookup_u16_7_counts(il[371]) - , lookup_u16_8_counts(il[372]) - , lookup_u16_9_counts(il[373]) - , lookup_u16_10_counts(il[374]) - , lookup_u16_11_counts(il[375]) - , lookup_u16_12_counts(il[376]) - , lookup_u16_13_counts(il[377]) - , lookup_u16_14_counts(il[378]) - , lookup_div_u16_0_counts(il[379]) - , lookup_div_u16_1_counts(il[380]) - , lookup_div_u16_2_counts(il[381]) - , lookup_div_u16_3_counts(il[382]) - , lookup_div_u16_4_counts(il[383]) - , lookup_div_u16_5_counts(il[384]) - , lookup_div_u16_6_counts(il[385]) - , lookup_div_u16_7_counts(il[386]) - , alu_a_hi_shift(il[387]) - , alu_a_lo_shift(il[388]) - , alu_b_hi_shift(il[389]) - , alu_b_lo_shift(il[390]) - , alu_cmp_rng_ctr_shift(il[391]) - , alu_div_u16_r0_shift(il[392]) - , alu_div_u16_r1_shift(il[393]) - , alu_div_u16_r2_shift(il[394]) - , alu_div_u16_r3_shift(il[395]) - , alu_div_u16_r4_shift(il[396]) - , alu_div_u16_r5_shift(il[397]) - , alu_div_u16_r6_shift(il[398]) - , alu_div_u16_r7_shift(il[399]) - , alu_op_add_shift(il[400]) - , alu_op_cast_prev_shift(il[401]) - , alu_op_cast_shift(il[402]) - , alu_op_div_shift(il[403]) - , alu_op_mul_shift(il[404]) - , alu_op_shl_shift(il[405]) - , alu_op_shr_shift(il[406]) - , alu_op_sub_shift(il[407]) - , alu_p_sub_a_hi_shift(il[408]) - , alu_p_sub_a_lo_shift(il[409]) - , alu_p_sub_b_hi_shift(il[410]) - , alu_p_sub_b_lo_shift(il[411]) - , alu_sel_alu_shift(il[412]) - , alu_sel_cmp_shift(il[413]) - , alu_sel_div_rng_chk_shift(il[414]) - , alu_sel_rng_chk_lookup_shift(il[415]) - , alu_sel_rng_chk_shift(il[416]) - , alu_u16_r0_shift(il[417]) - , alu_u16_r1_shift(il[418]) - , alu_u16_r2_shift(il[419]) - , alu_u16_r3_shift(il[420]) - , alu_u16_r4_shift(il[421]) - , alu_u16_r5_shift(il[422]) - , alu_u16_r6_shift(il[423]) - , alu_u8_r0_shift(il[424]) - , alu_u8_r1_shift(il[425]) - , binary_acc_ia_shift(il[426]) - , binary_acc_ib_shift(il[427]) - , binary_acc_ic_shift(il[428]) - , binary_mem_tag_ctr_shift(il[429]) - , binary_op_id_shift(il[430]) - , kernel_emit_l2_to_l1_msg_write_offset_shift(il[431]) - , kernel_emit_note_hash_write_offset_shift(il[432]) - , kernel_emit_nullifier_write_offset_shift(il[433]) - , kernel_emit_unencrypted_log_write_offset_shift(il[434]) - , kernel_l1_to_l2_msg_exists_write_offset_shift(il[435]) - , kernel_note_hash_exist_write_offset_shift(il[436]) - , kernel_nullifier_exists_write_offset_shift(il[437]) - , kernel_nullifier_non_exists_write_offset_shift(il[438]) - , kernel_side_effect_counter_shift(il[439]) - , kernel_sload_write_offset_shift(il[440]) - , kernel_sstore_write_offset_shift(il[441]) - , main_da_gas_remaining_shift(il[442]) - , main_internal_return_ptr_shift(il[443]) - , main_l2_gas_remaining_shift(il[444]) - , main_pc_shift(il[445]) - , mem_glob_addr_shift(il[446]) - , mem_rw_shift(il[447]) - , mem_sel_mem_shift(il[448]) - , mem_tag_shift(il[449]) - , mem_tsp_shift(il[450]) - , mem_val_shift(il[451]) + , main_returndata(il[7]) + , alu_a_hi(il[8]) + , alu_a_lo(il[9]) + , alu_b_hi(il[10]) + , alu_b_lo(il[11]) + , alu_borrow(il[12]) + , alu_cf(il[13]) + , alu_clk(il[14]) + , alu_cmp_rng_ctr(il[15]) + , alu_div_u16_r0(il[16]) + , alu_div_u16_r1(il[17]) + , alu_div_u16_r2(il[18]) + , alu_div_u16_r3(il[19]) + , alu_div_u16_r4(il[20]) + , alu_div_u16_r5(il[21]) + , alu_div_u16_r6(il[22]) + , alu_div_u16_r7(il[23]) + , alu_divisor_hi(il[24]) + , alu_divisor_lo(il[25]) + , alu_ff_tag(il[26]) + , alu_ia(il[27]) + , alu_ib(il[28]) + , alu_ic(il[29]) + , alu_in_tag(il[30]) + , alu_op_add(il[31]) + , alu_op_cast(il[32]) + , alu_op_cast_prev(il[33]) + , alu_op_div(il[34]) + , alu_op_div_a_lt_b(il[35]) + , alu_op_div_std(il[36]) + , alu_op_eq(il[37]) + , alu_op_eq_diff_inv(il[38]) + , alu_op_lt(il[39]) + , alu_op_lte(il[40]) + , alu_op_mul(il[41]) + , alu_op_not(il[42]) + , alu_op_shl(il[43]) + , alu_op_shr(il[44]) + , alu_op_sub(il[45]) + , alu_p_a_borrow(il[46]) + , alu_p_b_borrow(il[47]) + , alu_p_sub_a_hi(il[48]) + , alu_p_sub_a_lo(il[49]) + , alu_p_sub_b_hi(il[50]) + , alu_p_sub_b_lo(il[51]) + , alu_partial_prod_hi(il[52]) + , alu_partial_prod_lo(il[53]) + , alu_quotient_hi(il[54]) + , alu_quotient_lo(il[55]) + , alu_remainder(il[56]) + , alu_res_hi(il[57]) + , alu_res_lo(il[58]) + , alu_sel_alu(il[59]) + , alu_sel_cmp(il[60]) + , alu_sel_div_rng_chk(il[61]) + , alu_sel_rng_chk(il[62]) + , alu_sel_rng_chk_lookup(il[63]) + , alu_sel_shift_which(il[64]) + , alu_shift_lt_bit_len(il[65]) + , alu_t_sub_s_bits(il[66]) + , alu_two_pow_s(il[67]) + , alu_two_pow_t_sub_s(il[68]) + , alu_u128_tag(il[69]) + , alu_u16_r0(il[70]) + , alu_u16_r1(il[71]) + , alu_u16_r10(il[72]) + , alu_u16_r11(il[73]) + , alu_u16_r12(il[74]) + , alu_u16_r13(il[75]) + , alu_u16_r14(il[76]) + , alu_u16_r2(il[77]) + , alu_u16_r3(il[78]) + , alu_u16_r4(il[79]) + , alu_u16_r5(il[80]) + , alu_u16_r6(il[81]) + , alu_u16_r7(il[82]) + , alu_u16_r8(il[83]) + , alu_u16_r9(il[84]) + , alu_u16_tag(il[85]) + , alu_u32_tag(il[86]) + , alu_u64_tag(il[87]) + , alu_u8_r0(il[88]) + , alu_u8_r1(il[89]) + , alu_u8_tag(il[90]) + , binary_acc_ia(il[91]) + , binary_acc_ib(il[92]) + , binary_acc_ic(il[93]) + , binary_clk(il[94]) + , binary_ia_bytes(il[95]) + , binary_ib_bytes(il[96]) + , binary_ic_bytes(il[97]) + , binary_in_tag(il[98]) + , binary_mem_tag_ctr(il[99]) + , binary_mem_tag_ctr_inv(il[100]) + , binary_op_id(il[101]) + , binary_sel_bin(il[102]) + , binary_start(il[103]) + , byte_lookup_sel_bin(il[104]) + , byte_lookup_table_byte_lengths(il[105]) + , byte_lookup_table_in_tags(il[106]) + , byte_lookup_table_input_a(il[107]) + , byte_lookup_table_input_b(il[108]) + , byte_lookup_table_op_id(il[109]) + , byte_lookup_table_output(il[110]) + , conversion_clk(il[111]) + , conversion_input(il[112]) + , conversion_num_limbs(il[113]) + , conversion_radix(il[114]) + , conversion_sel_to_radix_le(il[115]) + , gas_da_gas_fixed_table(il[116]) + , gas_l2_gas_fixed_table(il[117]) + , gas_sel_gas_cost(il[118]) + , keccakf1600_clk(il[119]) + , keccakf1600_input(il[120]) + , keccakf1600_output(il[121]) + , keccakf1600_sel_keccakf1600(il[122]) + , kernel_emit_l2_to_l1_msg_write_offset(il[123]) + , kernel_emit_note_hash_write_offset(il[124]) + , kernel_emit_nullifier_write_offset(il[125]) + , kernel_emit_unencrypted_log_write_offset(il[126]) + , kernel_kernel_in_offset(il[127]) + , kernel_kernel_out_offset(il[128]) + , kernel_l1_to_l2_msg_exists_write_offset(il[129]) + , kernel_note_hash_exist_write_offset(il[130]) + , kernel_nullifier_exists_write_offset(il[131]) + , kernel_nullifier_non_exists_write_offset(il[132]) + , kernel_q_public_input_kernel_add_to_table(il[133]) + , kernel_q_public_input_kernel_out_add_to_table(il[134]) + , kernel_side_effect_counter(il[135]) + , kernel_sload_write_offset(il[136]) + , kernel_sstore_write_offset(il[137]) + , main_abs_da_rem_gas_hi(il[138]) + , main_abs_da_rem_gas_lo(il[139]) + , main_abs_l2_rem_gas_hi(il[140]) + , main_abs_l2_rem_gas_lo(il[141]) + , main_alu_in_tag(il[142]) + , main_bin_op_id(il[143]) + , main_call_ptr(il[144]) + , main_da_gas_op_cost(il[145]) + , main_da_gas_remaining(il[146]) + , main_da_out_of_gas(il[147]) + , main_ia(il[148]) + , main_ib(il[149]) + , main_ic(il[150]) + , main_id(il[151]) + , main_id_zero(il[152]) + , main_ind_addr_a(il[153]) + , main_ind_addr_b(il[154]) + , main_ind_addr_c(il[155]) + , main_ind_addr_d(il[156]) + , main_internal_return_ptr(il[157]) + , main_inv(il[158]) + , main_l2_gas_op_cost(il[159]) + , main_l2_gas_remaining(il[160]) + , main_l2_out_of_gas(il[161]) + , main_mem_addr_a(il[162]) + , main_mem_addr_b(il[163]) + , main_mem_addr_c(il[164]) + , main_mem_addr_d(il[165]) + , main_op_err(il[166]) + , main_opcode_val(il[167]) + , main_pc(il[168]) + , main_r_in_tag(il[169]) + , main_rwa(il[170]) + , main_rwb(il[171]) + , main_rwc(il[172]) + , main_rwd(il[173]) + , main_sel_alu(il[174]) + , main_sel_bin(il[175]) + , main_sel_calldata(il[176]) + , main_sel_gas_accounting_active(il[177]) + , main_sel_last(il[178]) + , main_sel_mem_op_a(il[179]) + , main_sel_mem_op_activate_gas(il[180]) + , main_sel_mem_op_b(il[181]) + , main_sel_mem_op_c(il[182]) + , main_sel_mem_op_d(il[183]) + , main_sel_mov_ia_to_ic(il[184]) + , main_sel_mov_ib_to_ic(il[185]) + , main_sel_op_add(il[186]) + , main_sel_op_address(il[187]) + , main_sel_op_and(il[188]) + , main_sel_op_block_number(il[189]) + , main_sel_op_calldata_copy(il[190]) + , main_sel_op_cast(il[191]) + , main_sel_op_chain_id(il[192]) + , main_sel_op_cmov(il[193]) + , main_sel_op_coinbase(il[194]) + , main_sel_op_dagasleft(il[195]) + , main_sel_op_div(il[196]) + , main_sel_op_emit_l2_to_l1_msg(il[197]) + , main_sel_op_emit_note_hash(il[198]) + , main_sel_op_emit_nullifier(il[199]) + , main_sel_op_emit_unencrypted_log(il[200]) + , main_sel_op_eq(il[201]) + , main_sel_op_external_call(il[202]) + , main_sel_op_external_return(il[203]) + , main_sel_op_fdiv(il[204]) + , main_sel_op_fee_per_da_gas(il[205]) + , main_sel_op_fee_per_l2_gas(il[206]) + , main_sel_op_function_selector(il[207]) + , main_sel_op_get_contract_instance(il[208]) + , main_sel_op_halt(il[209]) + , main_sel_op_internal_call(il[210]) + , main_sel_op_internal_return(il[211]) + , main_sel_op_jump(il[212]) + , main_sel_op_jumpi(il[213]) + , main_sel_op_keccak(il[214]) + , main_sel_op_l1_to_l2_msg_exists(il[215]) + , main_sel_op_l2gasleft(il[216]) + , main_sel_op_lt(il[217]) + , main_sel_op_lte(il[218]) + , main_sel_op_mov(il[219]) + , main_sel_op_mul(il[220]) + , main_sel_op_not(il[221]) + , main_sel_op_note_hash_exists(il[222]) + , main_sel_op_nullifier_exists(il[223]) + , main_sel_op_or(il[224]) + , main_sel_op_pedersen(il[225]) + , main_sel_op_poseidon2(il[226]) + , main_sel_op_radix_le(il[227]) + , main_sel_op_sender(il[228]) + , main_sel_op_sha256(il[229]) + , main_sel_op_shl(il[230]) + , main_sel_op_shr(il[231]) + , main_sel_op_sload(il[232]) + , main_sel_op_sstore(il[233]) + , main_sel_op_storage_address(il[234]) + , main_sel_op_sub(il[235]) + , main_sel_op_timestamp(il[236]) + , main_sel_op_transaction_fee(il[237]) + , main_sel_op_version(il[238]) + , main_sel_op_xor(il[239]) + , main_sel_q_kernel_lookup(il[240]) + , main_sel_q_kernel_output_lookup(il[241]) + , main_sel_resolve_ind_addr_a(il[242]) + , main_sel_resolve_ind_addr_b(il[243]) + , main_sel_resolve_ind_addr_c(il[244]) + , main_sel_resolve_ind_addr_d(il[245]) + , main_sel_returndata(il[246]) + , main_sel_rng_16(il[247]) + , main_sel_rng_8(il[248]) + , main_sel_slice_gadget(il[249]) + , main_space_id(il[250]) + , main_tag_err(il[251]) + , main_w_in_tag(il[252]) + , mem_addr(il[253]) + , mem_clk(il[254]) + , mem_diff_hi(il[255]) + , mem_diff_lo(il[256]) + , mem_diff_mid(il[257]) + , mem_glob_addr(il[258]) + , mem_last(il[259]) + , mem_lastAccess(il[260]) + , mem_one_min_inv(il[261]) + , mem_r_in_tag(il[262]) + , mem_rw(il[263]) + , mem_sel_mem(il[264]) + , mem_sel_mov_ia_to_ic(il[265]) + , mem_sel_mov_ib_to_ic(il[266]) + , mem_sel_op_a(il[267]) + , mem_sel_op_b(il[268]) + , mem_sel_op_c(il[269]) + , mem_sel_op_cmov(il[270]) + , mem_sel_op_d(il[271]) + , mem_sel_op_slice(il[272]) + , mem_sel_resolve_ind_addr_a(il[273]) + , mem_sel_resolve_ind_addr_b(il[274]) + , mem_sel_resolve_ind_addr_c(il[275]) + , mem_sel_resolve_ind_addr_d(il[276]) + , mem_sel_rng_chk(il[277]) + , mem_skip_check_tag(il[278]) + , mem_space_id(il[279]) + , mem_tag(il[280]) + , mem_tag_err(il[281]) + , mem_tsp(il[282]) + , mem_val(il[283]) + , mem_w_in_tag(il[284]) + , pedersen_clk(il[285]) + , pedersen_input(il[286]) + , pedersen_output(il[287]) + , pedersen_sel_pedersen(il[288]) + , poseidon2_clk(il[289]) + , poseidon2_input(il[290]) + , poseidon2_output(il[291]) + , poseidon2_sel_poseidon_perm(il[292]) + , powers_power_of_2(il[293]) + , sha256_clk(il[294]) + , sha256_input(il[295]) + , sha256_output(il[296]) + , sha256_sel_sha256_compression(il[297]) + , sha256_state(il[298]) + , slice_addr(il[299]) + , slice_clk(il[300]) + , slice_cnt(il[301]) + , slice_col_offset(il[302]) + , slice_one_min_inv(il[303]) + , slice_sel_cd_cpy(il[304]) + , slice_sel_mem_active(il[305]) + , slice_sel_return(il[306]) + , slice_sel_start(il[307]) + , slice_space_id(il[308]) + , slice_val(il[309]) + , perm_slice_mem(il[310]) + , perm_main_alu(il[311]) + , perm_main_bin(il[312]) + , perm_main_conv(il[313]) + , perm_main_pos2_perm(il[314]) + , perm_main_pedersen(il[315]) + , perm_main_slice(il[316]) + , perm_main_mem_a(il[317]) + , perm_main_mem_b(il[318]) + , perm_main_mem_c(il[319]) + , perm_main_mem_d(il[320]) + , perm_main_mem_ind_addr_a(il[321]) + , perm_main_mem_ind_addr_b(il[322]) + , perm_main_mem_ind_addr_c(il[323]) + , perm_main_mem_ind_addr_d(il[324]) + , lookup_byte_lengths(il[325]) + , lookup_byte_operations(il[326]) + , lookup_cd_value(il[327]) + , lookup_ret_value(il[328]) + , lookup_opcode_gas(il[329]) + , range_check_l2_gas_hi(il[330]) + , range_check_l2_gas_lo(il[331]) + , range_check_da_gas_hi(il[332]) + , range_check_da_gas_lo(il[333]) + , kernel_output_lookup(il[334]) + , lookup_into_kernel(il[335]) + , incl_main_tag_err(il[336]) + , incl_mem_tag_err(il[337]) + , lookup_mem_rng_chk_lo(il[338]) + , lookup_mem_rng_chk_mid(il[339]) + , lookup_mem_rng_chk_hi(il[340]) + , lookup_pow_2_0(il[341]) + , lookup_pow_2_1(il[342]) + , lookup_u8_0(il[343]) + , lookup_u8_1(il[344]) + , lookup_u16_0(il[345]) + , lookup_u16_1(il[346]) + , lookup_u16_2(il[347]) + , lookup_u16_3(il[348]) + , lookup_u16_4(il[349]) + , lookup_u16_5(il[350]) + , lookup_u16_6(il[351]) + , lookup_u16_7(il[352]) + , lookup_u16_8(il[353]) + , lookup_u16_9(il[354]) + , lookup_u16_10(il[355]) + , lookup_u16_11(il[356]) + , lookup_u16_12(il[357]) + , lookup_u16_13(il[358]) + , lookup_u16_14(il[359]) + , lookup_div_u16_0(il[360]) + , lookup_div_u16_1(il[361]) + , lookup_div_u16_2(il[362]) + , lookup_div_u16_3(il[363]) + , lookup_div_u16_4(il[364]) + , lookup_div_u16_5(il[365]) + , lookup_div_u16_6(il[366]) + , lookup_div_u16_7(il[367]) + , lookup_byte_lengths_counts(il[368]) + , lookup_byte_operations_counts(il[369]) + , lookup_cd_value_counts(il[370]) + , lookup_ret_value_counts(il[371]) + , lookup_opcode_gas_counts(il[372]) + , range_check_l2_gas_hi_counts(il[373]) + , range_check_l2_gas_lo_counts(il[374]) + , range_check_da_gas_hi_counts(il[375]) + , range_check_da_gas_lo_counts(il[376]) + , kernel_output_lookup_counts(il[377]) + , lookup_into_kernel_counts(il[378]) + , incl_main_tag_err_counts(il[379]) + , incl_mem_tag_err_counts(il[380]) + , lookup_mem_rng_chk_lo_counts(il[381]) + , lookup_mem_rng_chk_mid_counts(il[382]) + , lookup_mem_rng_chk_hi_counts(il[383]) + , lookup_pow_2_0_counts(il[384]) + , lookup_pow_2_1_counts(il[385]) + , lookup_u8_0_counts(il[386]) + , lookup_u8_1_counts(il[387]) + , lookup_u16_0_counts(il[388]) + , lookup_u16_1_counts(il[389]) + , lookup_u16_2_counts(il[390]) + , lookup_u16_3_counts(il[391]) + , lookup_u16_4_counts(il[392]) + , lookup_u16_5_counts(il[393]) + , lookup_u16_6_counts(il[394]) + , lookup_u16_7_counts(il[395]) + , lookup_u16_8_counts(il[396]) + , lookup_u16_9_counts(il[397]) + , lookup_u16_10_counts(il[398]) + , lookup_u16_11_counts(il[399]) + , lookup_u16_12_counts(il[400]) + , lookup_u16_13_counts(il[401]) + , lookup_u16_14_counts(il[402]) + , lookup_div_u16_0_counts(il[403]) + , lookup_div_u16_1_counts(il[404]) + , lookup_div_u16_2_counts(il[405]) + , lookup_div_u16_3_counts(il[406]) + , lookup_div_u16_4_counts(il[407]) + , lookup_div_u16_5_counts(il[408]) + , lookup_div_u16_6_counts(il[409]) + , lookup_div_u16_7_counts(il[410]) + , alu_a_hi_shift(il[411]) + , alu_a_lo_shift(il[412]) + , alu_b_hi_shift(il[413]) + , alu_b_lo_shift(il[414]) + , alu_cmp_rng_ctr_shift(il[415]) + , alu_div_u16_r0_shift(il[416]) + , alu_div_u16_r1_shift(il[417]) + , alu_div_u16_r2_shift(il[418]) + , alu_div_u16_r3_shift(il[419]) + , alu_div_u16_r4_shift(il[420]) + , alu_div_u16_r5_shift(il[421]) + , alu_div_u16_r6_shift(il[422]) + , alu_div_u16_r7_shift(il[423]) + , alu_op_add_shift(il[424]) + , alu_op_cast_prev_shift(il[425]) + , alu_op_cast_shift(il[426]) + , alu_op_div_shift(il[427]) + , alu_op_mul_shift(il[428]) + , alu_op_shl_shift(il[429]) + , alu_op_shr_shift(il[430]) + , alu_op_sub_shift(il[431]) + , alu_p_sub_a_hi_shift(il[432]) + , alu_p_sub_a_lo_shift(il[433]) + , alu_p_sub_b_hi_shift(il[434]) + , alu_p_sub_b_lo_shift(il[435]) + , alu_sel_alu_shift(il[436]) + , alu_sel_cmp_shift(il[437]) + , alu_sel_div_rng_chk_shift(il[438]) + , alu_sel_rng_chk_lookup_shift(il[439]) + , alu_sel_rng_chk_shift(il[440]) + , alu_u16_r0_shift(il[441]) + , alu_u16_r1_shift(il[442]) + , alu_u16_r2_shift(il[443]) + , alu_u16_r3_shift(il[444]) + , alu_u16_r4_shift(il[445]) + , alu_u16_r5_shift(il[446]) + , alu_u16_r6_shift(il[447]) + , alu_u8_r0_shift(il[448]) + , alu_u8_r1_shift(il[449]) + , binary_acc_ia_shift(il[450]) + , binary_acc_ib_shift(il[451]) + , binary_acc_ic_shift(il[452]) + , binary_mem_tag_ctr_shift(il[453]) + , binary_op_id_shift(il[454]) + , kernel_emit_l2_to_l1_msg_write_offset_shift(il[455]) + , kernel_emit_note_hash_write_offset_shift(il[456]) + , kernel_emit_nullifier_write_offset_shift(il[457]) + , kernel_emit_unencrypted_log_write_offset_shift(il[458]) + , kernel_l1_to_l2_msg_exists_write_offset_shift(il[459]) + , kernel_note_hash_exist_write_offset_shift(il[460]) + , kernel_nullifier_exists_write_offset_shift(il[461]) + , kernel_nullifier_non_exists_write_offset_shift(il[462]) + , kernel_side_effect_counter_shift(il[463]) + , kernel_sload_write_offset_shift(il[464]) + , kernel_sstore_write_offset_shift(il[465]) + , main_da_gas_remaining_shift(il[466]) + , main_internal_return_ptr_shift(il[467]) + , main_l2_gas_remaining_shift(il[468]) + , main_pc_shift(il[469]) + , mem_glob_addr_shift(il[470]) + , mem_rw_shift(il[471]) + , mem_sel_mem_shift(il[472]) + , mem_tag_shift(il[473]) + , mem_tsp_shift(il[474]) + , mem_val_shift(il[475]) + , slice_addr_shift(il[476]) + , slice_clk_shift(il[477]) + , slice_cnt_shift(il[478]) + , slice_col_offset_shift(il[479]) + , slice_sel_cd_cpy_shift(il[480]) + , slice_sel_mem_active_shift(il[481]) + , slice_sel_return_shift(il[482]) + , slice_sel_start_shift(il[483]) + , slice_space_id_shift(il[484]) {} }; @@ -1814,6 +1941,7 @@ class AvmFlavor { kernel_kernel_side_effect_out[row_idx], kernel_kernel_metadata_out[row_idx], main_calldata[row_idx], + main_returndata[row_idx], alu_a_hi[row_idx], alu_a_lo[row_idx], alu_b_hi[row_idx], @@ -1982,6 +2110,7 @@ class AvmFlavor { main_rwd[row_idx], main_sel_alu[row_idx], main_sel_bin[row_idx], + main_sel_calldata[row_idx], main_sel_gas_accounting_active[row_idx], main_sel_last[row_idx], main_sel_mem_op_a[row_idx], @@ -1995,6 +2124,7 @@ class AvmFlavor { main_sel_op_address[row_idx], main_sel_op_and[row_idx], main_sel_op_block_number[row_idx], + main_sel_op_calldata_copy[row_idx], main_sel_op_cast[row_idx], main_sel_op_chain_id[row_idx], main_sel_op_cmov[row_idx], @@ -2007,6 +2137,7 @@ class AvmFlavor { main_sel_op_emit_unencrypted_log[row_idx], main_sel_op_eq[row_idx], main_sel_op_external_call[row_idx], + main_sel_op_external_return[row_idx], main_sel_op_fdiv[row_idx], main_sel_op_fee_per_da_gas[row_idx], main_sel_op_fee_per_l2_gas[row_idx], @@ -2049,8 +2180,10 @@ class AvmFlavor { main_sel_resolve_ind_addr_b[row_idx], main_sel_resolve_ind_addr_c[row_idx], main_sel_resolve_ind_addr_d[row_idx], + main_sel_returndata[row_idx], main_sel_rng_16[row_idx], main_sel_rng_8[row_idx], + main_sel_slice_gadget[row_idx], main_space_id[row_idx], main_tag_err[row_idx], main_w_in_tag[row_idx], @@ -2073,6 +2206,7 @@ class AvmFlavor { mem_sel_op_c[row_idx], mem_sel_op_cmov[row_idx], mem_sel_op_d[row_idx], + mem_sel_op_slice[row_idx], mem_sel_resolve_ind_addr_a[row_idx], mem_sel_resolve_ind_addr_b[row_idx], mem_sel_resolve_ind_addr_c[row_idx], @@ -2099,11 +2233,24 @@ class AvmFlavor { sha256_output[row_idx], sha256_sel_sha256_compression[row_idx], sha256_state[row_idx], + slice_addr[row_idx], + slice_clk[row_idx], + slice_cnt[row_idx], + slice_col_offset[row_idx], + slice_one_min_inv[row_idx], + slice_sel_cd_cpy[row_idx], + slice_sel_mem_active[row_idx], + slice_sel_return[row_idx], + slice_sel_start[row_idx], + slice_space_id[row_idx], + slice_val[row_idx], + perm_slice_mem[row_idx], perm_main_alu[row_idx], perm_main_bin[row_idx], perm_main_conv[row_idx], perm_main_pos2_perm[row_idx], perm_main_pedersen[row_idx], + perm_main_slice[row_idx], perm_main_mem_a[row_idx], perm_main_mem_b[row_idx], perm_main_mem_c[row_idx], @@ -2114,6 +2261,8 @@ class AvmFlavor { perm_main_mem_ind_addr_d[row_idx], lookup_byte_lengths[row_idx], lookup_byte_operations[row_idx], + lookup_cd_value[row_idx], + lookup_ret_value[row_idx], lookup_opcode_gas[row_idx], range_check_l2_gas_hi[row_idx], range_check_l2_gas_lo[row_idx], @@ -2155,6 +2304,8 @@ class AvmFlavor { lookup_div_u16_7[row_idx], lookup_byte_lengths_counts[row_idx], lookup_byte_operations_counts[row_idx], + lookup_cd_value_counts[row_idx], + lookup_ret_value_counts[row_idx], lookup_opcode_gas_counts[row_idx], range_check_l2_gas_hi_counts[row_idx], range_check_l2_gas_lo_counts[row_idx], @@ -2258,7 +2409,16 @@ class AvmFlavor { mem_sel_mem_shift[row_idx], mem_tag_shift[row_idx], mem_tsp_shift[row_idx], - mem_val_shift[row_idx] }); + mem_val_shift[row_idx], + slice_addr_shift[row_idx], + slice_clk_shift[row_idx], + slice_cnt_shift[row_idx], + slice_col_offset_shift[row_idx], + slice_sel_cd_cpy_shift[row_idx], + slice_sel_mem_active_shift[row_idx], + slice_sel_return_shift[row_idx], + slice_sel_start_shift[row_idx], + slice_space_id_shift[row_idx] }); } }; @@ -2313,6 +2473,7 @@ class AvmFlavor { Base::kernel_kernel_side_effect_out = "KERNEL_KERNEL_SIDE_EFFECT_OUT"; Base::kernel_kernel_metadata_out = "KERNEL_KERNEL_METADATA_OUT"; Base::main_calldata = "MAIN_CALLDATA"; + Base::main_returndata = "MAIN_RETURNDATA"; Base::alu_a_hi = "ALU_A_HI"; Base::alu_a_lo = "ALU_A_LO"; Base::alu_b_hi = "ALU_B_HI"; @@ -2481,6 +2642,7 @@ class AvmFlavor { Base::main_rwd = "MAIN_RWD"; Base::main_sel_alu = "MAIN_SEL_ALU"; Base::main_sel_bin = "MAIN_SEL_BIN"; + Base::main_sel_calldata = "MAIN_SEL_CALLDATA"; Base::main_sel_gas_accounting_active = "MAIN_SEL_GAS_ACCOUNTING_ACTIVE"; Base::main_sel_last = "MAIN_SEL_LAST"; Base::main_sel_mem_op_a = "MAIN_SEL_MEM_OP_A"; @@ -2494,6 +2656,7 @@ class AvmFlavor { Base::main_sel_op_address = "MAIN_SEL_OP_ADDRESS"; Base::main_sel_op_and = "MAIN_SEL_OP_AND"; Base::main_sel_op_block_number = "MAIN_SEL_OP_BLOCK_NUMBER"; + Base::main_sel_op_calldata_copy = "MAIN_SEL_OP_CALLDATA_COPY"; Base::main_sel_op_cast = "MAIN_SEL_OP_CAST"; Base::main_sel_op_chain_id = "MAIN_SEL_OP_CHAIN_ID"; Base::main_sel_op_cmov = "MAIN_SEL_OP_CMOV"; @@ -2506,6 +2669,7 @@ class AvmFlavor { Base::main_sel_op_emit_unencrypted_log = "MAIN_SEL_OP_EMIT_UNENCRYPTED_LOG"; Base::main_sel_op_eq = "MAIN_SEL_OP_EQ"; Base::main_sel_op_external_call = "MAIN_SEL_OP_EXTERNAL_CALL"; + Base::main_sel_op_external_return = "MAIN_SEL_OP_EXTERNAL_RETURN"; Base::main_sel_op_fdiv = "MAIN_SEL_OP_FDIV"; Base::main_sel_op_fee_per_da_gas = "MAIN_SEL_OP_FEE_PER_DA_GAS"; Base::main_sel_op_fee_per_l2_gas = "MAIN_SEL_OP_FEE_PER_L2_GAS"; @@ -2548,8 +2712,10 @@ class AvmFlavor { Base::main_sel_resolve_ind_addr_b = "MAIN_SEL_RESOLVE_IND_ADDR_B"; Base::main_sel_resolve_ind_addr_c = "MAIN_SEL_RESOLVE_IND_ADDR_C"; Base::main_sel_resolve_ind_addr_d = "MAIN_SEL_RESOLVE_IND_ADDR_D"; + Base::main_sel_returndata = "MAIN_SEL_RETURNDATA"; Base::main_sel_rng_16 = "MAIN_SEL_RNG_16"; Base::main_sel_rng_8 = "MAIN_SEL_RNG_8"; + Base::main_sel_slice_gadget = "MAIN_SEL_SLICE_GADGET"; Base::main_space_id = "MAIN_SPACE_ID"; Base::main_tag_err = "MAIN_TAG_ERR"; Base::main_w_in_tag = "MAIN_W_IN_TAG"; @@ -2572,6 +2738,7 @@ class AvmFlavor { Base::mem_sel_op_c = "MEM_SEL_OP_C"; Base::mem_sel_op_cmov = "MEM_SEL_OP_CMOV"; Base::mem_sel_op_d = "MEM_SEL_OP_D"; + Base::mem_sel_op_slice = "MEM_SEL_OP_SLICE"; Base::mem_sel_resolve_ind_addr_a = "MEM_SEL_RESOLVE_IND_ADDR_A"; Base::mem_sel_resolve_ind_addr_b = "MEM_SEL_RESOLVE_IND_ADDR_B"; Base::mem_sel_resolve_ind_addr_c = "MEM_SEL_RESOLVE_IND_ADDR_C"; @@ -2598,11 +2765,24 @@ class AvmFlavor { Base::sha256_output = "SHA256_OUTPUT"; Base::sha256_sel_sha256_compression = "SHA256_SEL_SHA256_COMPRESSION"; Base::sha256_state = "SHA256_STATE"; + Base::slice_addr = "SLICE_ADDR"; + Base::slice_clk = "SLICE_CLK"; + Base::slice_cnt = "SLICE_CNT"; + Base::slice_col_offset = "SLICE_COL_OFFSET"; + Base::slice_one_min_inv = "SLICE_ONE_MIN_INV"; + Base::slice_sel_cd_cpy = "SLICE_SEL_CD_CPY"; + Base::slice_sel_mem_active = "SLICE_SEL_MEM_ACTIVE"; + Base::slice_sel_return = "SLICE_SEL_RETURN"; + Base::slice_sel_start = "SLICE_SEL_START"; + Base::slice_space_id = "SLICE_SPACE_ID"; + Base::slice_val = "SLICE_VAL"; + Base::perm_slice_mem = "PERM_SLICE_MEM"; Base::perm_main_alu = "PERM_MAIN_ALU"; Base::perm_main_bin = "PERM_MAIN_BIN"; Base::perm_main_conv = "PERM_MAIN_CONV"; Base::perm_main_pos2_perm = "PERM_MAIN_POS2_PERM"; Base::perm_main_pedersen = "PERM_MAIN_PEDERSEN"; + Base::perm_main_slice = "PERM_MAIN_SLICE"; Base::perm_main_mem_a = "PERM_MAIN_MEM_A"; Base::perm_main_mem_b = "PERM_MAIN_MEM_B"; Base::perm_main_mem_c = "PERM_MAIN_MEM_C"; @@ -2613,6 +2793,8 @@ class AvmFlavor { Base::perm_main_mem_ind_addr_d = "PERM_MAIN_MEM_IND_ADDR_D"; Base::lookup_byte_lengths = "LOOKUP_BYTE_LENGTHS"; Base::lookup_byte_operations = "LOOKUP_BYTE_OPERATIONS"; + Base::lookup_cd_value = "LOOKUP_CD_VALUE"; + Base::lookup_ret_value = "LOOKUP_RET_VALUE"; Base::lookup_opcode_gas = "LOOKUP_OPCODE_GAS"; Base::range_check_l2_gas_hi = "RANGE_CHECK_L2_GAS_HI"; Base::range_check_l2_gas_lo = "RANGE_CHECK_L2_GAS_LO"; @@ -2654,6 +2836,8 @@ class AvmFlavor { Base::lookup_div_u16_7 = "LOOKUP_DIV_U16_7"; Base::lookup_byte_lengths_counts = "LOOKUP_BYTE_LENGTHS_COUNTS"; Base::lookup_byte_operations_counts = "LOOKUP_BYTE_OPERATIONS_COUNTS"; + Base::lookup_cd_value_counts = "LOOKUP_CD_VALUE_COUNTS"; + Base::lookup_ret_value_counts = "LOOKUP_RET_VALUE_COUNTS"; Base::lookup_opcode_gas_counts = "LOOKUP_OPCODE_GAS_COUNTS"; Base::range_check_l2_gas_hi_counts = "RANGE_CHECK_L2_GAS_HI_COUNTS"; Base::range_check_l2_gas_lo_counts = "RANGE_CHECK_L2_GAS_LO_COUNTS"; diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.cpp index 3cda79780a3e..fcb1803a2cbf 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.cpp @@ -25,6 +25,7 @@ template std::vector AvmFullRow::names() "kernel_kernel_side_effect_out", "kernel_kernel_metadata_out", "main_calldata", + "main_returndata", "alu_a_hi", "alu_a_lo", "alu_b_hi", @@ -193,6 +194,7 @@ template std::vector AvmFullRow::names() "main_rwd", "main_sel_alu", "main_sel_bin", + "main_sel_calldata", "main_sel_gas_accounting_active", "main_sel_last", "main_sel_mem_op_a", @@ -206,6 +208,7 @@ template std::vector AvmFullRow::names() "main_sel_op_address", "main_sel_op_and", "main_sel_op_block_number", + "main_sel_op_calldata_copy", "main_sel_op_cast", "main_sel_op_chain_id", "main_sel_op_cmov", @@ -218,6 +221,7 @@ template std::vector AvmFullRow::names() "main_sel_op_emit_unencrypted_log", "main_sel_op_eq", "main_sel_op_external_call", + "main_sel_op_external_return", "main_sel_op_fdiv", "main_sel_op_fee_per_da_gas", "main_sel_op_fee_per_l2_gas", @@ -260,8 +264,10 @@ template std::vector AvmFullRow::names() "main_sel_resolve_ind_addr_b", "main_sel_resolve_ind_addr_c", "main_sel_resolve_ind_addr_d", + "main_sel_returndata", "main_sel_rng_16", "main_sel_rng_8", + "main_sel_slice_gadget", "main_space_id", "main_tag_err", "main_w_in_tag", @@ -284,6 +290,7 @@ template std::vector AvmFullRow::names() "mem_sel_op_c", "mem_sel_op_cmov", "mem_sel_op_d", + "mem_sel_op_slice", "mem_sel_resolve_ind_addr_a", "mem_sel_resolve_ind_addr_b", "mem_sel_resolve_ind_addr_c", @@ -310,11 +317,24 @@ template std::vector AvmFullRow::names() "sha256_output", "sha256_sel_sha256_compression", "sha256_state", + "slice_addr", + "slice_clk", + "slice_cnt", + "slice_col_offset", + "slice_one_min_inv", + "slice_sel_cd_cpy", + "slice_sel_mem_active", + "slice_sel_return", + "slice_sel_start", + "slice_space_id", + "slice_val", + "perm_slice_mem", "perm_main_alu", "perm_main_bin", "perm_main_conv", "perm_main_pos2_perm", "perm_main_pedersen", + "perm_main_slice", "perm_main_mem_a", "perm_main_mem_b", "perm_main_mem_c", @@ -325,6 +345,8 @@ template std::vector AvmFullRow::names() "perm_main_mem_ind_addr_d", "lookup_byte_lengths", "lookup_byte_operations", + "lookup_cd_value", + "lookup_ret_value", "lookup_opcode_gas", "range_check_l2_gas_hi", "range_check_l2_gas_lo", @@ -366,6 +388,8 @@ template std::vector AvmFullRow::names() "lookup_div_u16_7", "lookup_byte_lengths_counts", "lookup_byte_operations_counts", + "lookup_cd_value_counts", + "lookup_ret_value_counts", "lookup_opcode_gas_counts", "range_check_l2_gas_hi_counts", "range_check_l2_gas_lo_counts", @@ -416,6 +440,7 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << "," << field_to_string(row.kernel_kernel_side_effect_out) // << "," << field_to_string(row.kernel_kernel_metadata_out) // << "," << field_to_string(row.main_calldata) // + << "," << field_to_string(row.main_returndata) // << "," << field_to_string(row.alu_a_hi) // << "," << field_to_string(row.alu_a_lo) // << "," << field_to_string(row.alu_b_hi) // @@ -584,6 +609,7 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << "," << field_to_string(row.main_rwd) // << "," << field_to_string(row.main_sel_alu) // << "," << field_to_string(row.main_sel_bin) // + << "," << field_to_string(row.main_sel_calldata) // << "," << field_to_string(row.main_sel_gas_accounting_active) // << "," << field_to_string(row.main_sel_last) // << "," << field_to_string(row.main_sel_mem_op_a) // @@ -597,6 +623,7 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << "," << field_to_string(row.main_sel_op_address) // << "," << field_to_string(row.main_sel_op_and) // << "," << field_to_string(row.main_sel_op_block_number) // + << "," << field_to_string(row.main_sel_op_calldata_copy) // << "," << field_to_string(row.main_sel_op_cast) // << "," << field_to_string(row.main_sel_op_chain_id) // << "," << field_to_string(row.main_sel_op_cmov) // @@ -609,6 +636,7 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << "," << field_to_string(row.main_sel_op_emit_unencrypted_log) // << "," << field_to_string(row.main_sel_op_eq) // << "," << field_to_string(row.main_sel_op_external_call) // + << "," << field_to_string(row.main_sel_op_external_return) // << "," << field_to_string(row.main_sel_op_fdiv) // << "," << field_to_string(row.main_sel_op_fee_per_da_gas) // << "," << field_to_string(row.main_sel_op_fee_per_l2_gas) // @@ -651,8 +679,10 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << "," << field_to_string(row.main_sel_resolve_ind_addr_b) // << "," << field_to_string(row.main_sel_resolve_ind_addr_c) // << "," << field_to_string(row.main_sel_resolve_ind_addr_d) // + << "," << field_to_string(row.main_sel_returndata) // << "," << field_to_string(row.main_sel_rng_16) // << "," << field_to_string(row.main_sel_rng_8) // + << "," << field_to_string(row.main_sel_slice_gadget) // << "," << field_to_string(row.main_space_id) // << "," << field_to_string(row.main_tag_err) // << "," << field_to_string(row.main_w_in_tag) // @@ -675,6 +705,7 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << "," << field_to_string(row.mem_sel_op_c) // << "," << field_to_string(row.mem_sel_op_cmov) // << "," << field_to_string(row.mem_sel_op_d) // + << "," << field_to_string(row.mem_sel_op_slice) // << "," << field_to_string(row.mem_sel_resolve_ind_addr_a) // << "," << field_to_string(row.mem_sel_resolve_ind_addr_b) // << "," << field_to_string(row.mem_sel_resolve_ind_addr_c) // @@ -701,11 +732,24 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << "," << field_to_string(row.sha256_output) // << "," << field_to_string(row.sha256_sel_sha256_compression) // << "," << field_to_string(row.sha256_state) // + << "," << field_to_string(row.slice_addr) // + << "," << field_to_string(row.slice_clk) // + << "," << field_to_string(row.slice_cnt) // + << "," << field_to_string(row.slice_col_offset) // + << "," << field_to_string(row.slice_one_min_inv) // + << "," << field_to_string(row.slice_sel_cd_cpy) // + << "," << field_to_string(row.slice_sel_mem_active) // + << "," << field_to_string(row.slice_sel_return) // + << "," << field_to_string(row.slice_sel_start) // + << "," << field_to_string(row.slice_space_id) // + << "," << field_to_string(row.slice_val) // + << "," << field_to_string(row.perm_slice_mem) // << "," << field_to_string(row.perm_main_alu) // << "," << field_to_string(row.perm_main_bin) // << "," << field_to_string(row.perm_main_conv) // << "," << field_to_string(row.perm_main_pos2_perm) // << "," << field_to_string(row.perm_main_pedersen) // + << "," << field_to_string(row.perm_main_slice) // << "," << field_to_string(row.perm_main_mem_a) // << "," << field_to_string(row.perm_main_mem_b) // << "," << field_to_string(row.perm_main_mem_c) // @@ -716,6 +760,8 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << "," << field_to_string(row.perm_main_mem_ind_addr_d) // << "," << field_to_string(row.lookup_byte_lengths) // << "," << field_to_string(row.lookup_byte_operations) // + << "," << field_to_string(row.lookup_cd_value) // + << "," << field_to_string(row.lookup_ret_value) // << "," << field_to_string(row.lookup_opcode_gas) // << "," << field_to_string(row.range_check_l2_gas_hi) // << "," << field_to_string(row.range_check_l2_gas_lo) // @@ -757,6 +803,8 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << "," << field_to_string(row.lookup_div_u16_7) // << "," << field_to_string(row.lookup_byte_lengths_counts) // << "," << field_to_string(row.lookup_byte_operations_counts) // + << "," << field_to_string(row.lookup_cd_value_counts) // + << "," << field_to_string(row.lookup_ret_value_counts) // << "," << field_to_string(row.lookup_opcode_gas_counts) // << "," << field_to_string(row.range_check_l2_gas_hi_counts) // << "," << field_to_string(row.range_check_l2_gas_lo_counts) // diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.hpp index 6499381c1814..053deb3a1afb 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.hpp @@ -14,6 +14,7 @@ template struct AvmFullRow { FF kernel_kernel_side_effect_out{}; FF kernel_kernel_metadata_out{}; FF main_calldata{}; + FF main_returndata{}; FF alu_a_hi{}; FF alu_a_lo{}; FF alu_b_hi{}; @@ -182,6 +183,7 @@ template struct AvmFullRow { FF main_rwd{}; FF main_sel_alu{}; FF main_sel_bin{}; + FF main_sel_calldata{}; FF main_sel_gas_accounting_active{}; FF main_sel_last{}; FF main_sel_mem_op_a{}; @@ -195,6 +197,7 @@ template struct AvmFullRow { FF main_sel_op_address{}; FF main_sel_op_and{}; FF main_sel_op_block_number{}; + FF main_sel_op_calldata_copy{}; FF main_sel_op_cast{}; FF main_sel_op_chain_id{}; FF main_sel_op_cmov{}; @@ -207,6 +210,7 @@ template struct AvmFullRow { FF main_sel_op_emit_unencrypted_log{}; FF main_sel_op_eq{}; FF main_sel_op_external_call{}; + FF main_sel_op_external_return{}; FF main_sel_op_fdiv{}; FF main_sel_op_fee_per_da_gas{}; FF main_sel_op_fee_per_l2_gas{}; @@ -249,8 +253,10 @@ template struct AvmFullRow { FF main_sel_resolve_ind_addr_b{}; FF main_sel_resolve_ind_addr_c{}; FF main_sel_resolve_ind_addr_d{}; + FF main_sel_returndata{}; FF main_sel_rng_16{}; FF main_sel_rng_8{}; + FF main_sel_slice_gadget{}; FF main_space_id{}; FF main_tag_err{}; FF main_w_in_tag{}; @@ -273,6 +279,7 @@ template struct AvmFullRow { FF mem_sel_op_c{}; FF mem_sel_op_cmov{}; FF mem_sel_op_d{}; + FF mem_sel_op_slice{}; FF mem_sel_resolve_ind_addr_a{}; FF mem_sel_resolve_ind_addr_b{}; FF mem_sel_resolve_ind_addr_c{}; @@ -299,11 +306,24 @@ template struct AvmFullRow { FF sha256_output{}; FF sha256_sel_sha256_compression{}; FF sha256_state{}; + FF slice_addr{}; + FF slice_clk{}; + FF slice_cnt{}; + FF slice_col_offset{}; + FF slice_one_min_inv{}; + FF slice_sel_cd_cpy{}; + FF slice_sel_mem_active{}; + FF slice_sel_return{}; + FF slice_sel_start{}; + FF slice_space_id{}; + FF slice_val{}; + FF perm_slice_mem{}; FF perm_main_alu{}; FF perm_main_bin{}; FF perm_main_conv{}; FF perm_main_pos2_perm{}; FF perm_main_pedersen{}; + FF perm_main_slice{}; FF perm_main_mem_a{}; FF perm_main_mem_b{}; FF perm_main_mem_c{}; @@ -314,6 +334,8 @@ template struct AvmFullRow { FF perm_main_mem_ind_addr_d{}; FF lookup_byte_lengths{}; FF lookup_byte_operations{}; + FF lookup_cd_value{}; + FF lookup_ret_value{}; FF lookup_opcode_gas{}; FF range_check_l2_gas_hi{}; FF range_check_l2_gas_lo{}; @@ -355,6 +377,8 @@ template struct AvmFullRow { FF lookup_div_u16_7{}; FF lookup_byte_lengths_counts{}; FF lookup_byte_operations_counts{}; + FF lookup_cd_value_counts{}; + FF lookup_ret_value_counts{}; FF lookup_opcode_gas_counts{}; FF range_check_l2_gas_hi_counts{}; FF range_check_l2_gas_lo_counts{}; diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index b1046c8400a7..a795633e1e39 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -79,6 +79,7 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.perm_slice_mem); commitments.perm_main_alu = transcript->template receive_from_prover(commitment_labels.perm_main_alu); commitments.perm_main_bin = transcript->template receive_from_prover(commitment_labels.perm_main_bin); commitments.perm_main_conv = transcript->template receive_from_prover(commitment_labels.perm_main_conv); @@ -86,6 +87,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.perm_main_pos2_perm); commitments.perm_main_pedersen = transcript->template receive_from_prover(commitment_labels.perm_main_pedersen); + commitments.perm_main_slice = + transcript->template receive_from_prover(commitment_labels.perm_main_slice); commitments.perm_main_mem_a = transcript->template receive_from_prover(commitment_labels.perm_main_mem_a); commitments.perm_main_mem_b = @@ -106,6 +109,10 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.lookup_byte_lengths); commitments.lookup_byte_operations = transcript->template receive_from_prover(commitment_labels.lookup_byte_operations); + commitments.lookup_cd_value = + transcript->template receive_from_prover(commitment_labels.lookup_cd_value); + commitments.lookup_ret_value = + transcript->template receive_from_prover(commitment_labels.lookup_ret_value); commitments.lookup_opcode_gas = transcript->template receive_from_prover(commitment_labels.lookup_opcode_gas); commitments.range_check_l2_gas_hi = @@ -211,6 +218,10 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vector const returndata = { 37, 4, 11, 0, 41 }; + + validate_trace(std::move(trace), public_inputs, calldata, returndata, true); } // Test on basic subtraction over finite field type. @@ -409,6 +411,7 @@ TEST_F(AvmArithmeticTestsFF, subtraction) EXPECT_EQ(alu_row.alu_cf, FF(0)); EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); + std::vector const returndata = { 8, 9, 17 }; validate_trace(std::move(trace), public_inputs, calldata); } @@ -431,7 +434,8 @@ TEST_F(AvmArithmeticTestsFF, multiplication) EXPECT_EQ(alu_row.alu_cf, FF(0)); EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); - validate_trace(std::move(trace), public_inputs, calldata); + std::vector const returndata = { 5, 100, 20 }; + validate_trace(std::move(trace), public_inputs, calldata, returndata); } // Test on multiplication by zero over finite field type. @@ -453,7 +457,8 @@ TEST_F(AvmArithmeticTestsFF, multiplicationByZero) EXPECT_EQ(alu_row.alu_cf, FF(0)); EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); - validate_trace(std::move(trace), public_inputs, calldata); + std::vector const returndata = { 127, 0, 0 }; + validate_trace(std::move(trace), public_inputs, calldata, returndata); } // Test on basic division over finite field type. @@ -478,7 +483,8 @@ TEST_F(AvmArithmeticTestsFF, fDivision) EXPECT_EQ(row->main_sel_mem_op_c, FF(1)); EXPECT_EQ(row->main_rwc, FF(1)); - validate_trace(std::move(trace), public_inputs, calldata); + std::vector const returndata = { 15, 315, 0 }; + validate_trace(std::move(trace), public_inputs, calldata, returndata); } // Test on division with zero numerator over finite field type. @@ -503,7 +509,8 @@ TEST_F(AvmArithmeticTestsFF, fDivisionNumeratorZero) EXPECT_EQ(row->main_sel_mem_op_c, FF(1)); EXPECT_EQ(row->main_rwc, FF(1)); - validate_trace(std::move(trace), public_inputs, calldata); + std::vector const returndata = { 0, 0, 0 }; + validate_trace(std::move(trace), public_inputs, calldata, returndata); } // Test on division by zero over finite field type. @@ -579,7 +586,7 @@ TEST_F(AvmArithmeticTestsFF, mixedOperationsWithError) trace_builder.halt(); auto trace = trace_builder.finalize(); - validate_trace(std::move(trace), public_inputs, calldata, true); + validate_trace(std::move(trace), public_inputs, calldata, {}, true); } // Test of equality on FF elements @@ -587,10 +594,10 @@ TEST_F(AvmArithmeticTestsFF, equality) { // Pick a field-sized number FF elem = FF::modulus - FF(1); - std::vector const calldata = { elem, elem, 1 }; + std::vector const calldata = { elem, elem }; gen_trace_builder(calldata); - trace_builder.op_calldata_copy(0, 0, 3, 0); - trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [q - 1, q -1, 1,0..] + trace_builder.op_calldata_copy(0, 0, 2, 0); + trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [q - 1, q - 1, 1, 0..] trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); @@ -599,17 +606,19 @@ TEST_F(AvmArithmeticTestsFF, equality) EXPECT_EQ(alu_row.alu_ff_tag, FF(1)); EXPECT_EQ(alu_row.alu_op_eq_diff_inv, FF(0)); // Expect 0 as inv of (q-1) - (q-1) - validate_trace(std::move(trace), public_inputs, calldata); + + std::vector const returndata = { elem, elem, 1 }; + validate_trace(std::move(trace), public_inputs, calldata, returndata); } // Test correct non-equality of FF elements TEST_F(AvmArithmeticTestsFF, nonEquality) { FF elem = FF::modulus - FF(1); - std::vector const calldata = { elem, elem + FF(1), 0 }; + std::vector const calldata = { elem, elem + FF(1) }; gen_trace_builder(calldata); - trace_builder.op_calldata_copy(0, 0, 3, 0); - trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [q - 1, q, 1,0..] + trace_builder.op_calldata_copy(0, 0, 2, 0); + trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [q - 1, q, 0, 0..] trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -618,7 +627,9 @@ TEST_F(AvmArithmeticTestsFF, nonEquality) EXPECT_EQ(alu_row.alu_ff_tag, FF(1)); EXPECT_EQ(alu_row.alu_op_eq_diff_inv, FF(-1).invert()); - validate_trace(std::move(trace), public_inputs, calldata); + + std::vector const returndata = { elem, 0, 0 }; + validate_trace(std::move(trace), public_inputs, calldata, returndata); } TEST_P(AvmArithmeticTestsDiv, division) diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp index e70b50106af9..55bafff7034b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp @@ -492,7 +492,7 @@ TEST_P(AvmBitwiseTestsAnd, AllAndTest) auto trace = trace_builder.finalize(); common_validate_bit_op(trace, 0, a, b, output, FF(0), FF(1), FF(2), mem_tag); - validate_trace(std::move(trace), public_inputs, {}, true); + validate_trace(std::move(trace), public_inputs, {}, { output }, true); } INSTANTIATE_TEST_SUITE_P(AvmBitwiseTests, AvmBitwiseTestsAnd, @@ -509,7 +509,7 @@ TEST_P(AvmBitwiseTestsOr, AllOrTest) auto trace = trace_builder.finalize(); common_validate_bit_op(trace, 1, a, b, output, FF(0), FF(1), FF(2), mem_tag); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, {}, { output }); } INSTANTIATE_TEST_SUITE_P(AvmBitwiseTests, AvmBitwiseTestsOr, @@ -526,7 +526,7 @@ TEST_P(AvmBitwiseTestsXor, AllXorTest) auto trace = trace_builder.finalize(); common_validate_bit_op(trace, 2, a, b, output, FF(0), FF(1), FF(2), mem_tag); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, {}, { output }); } INSTANTIATE_TEST_SUITE_P(AvmBitwiseTests, @@ -543,7 +543,7 @@ TEST_P(AvmBitwiseTestsShr, AllShrTest) trace_builder.op_return(0, 2, 1); auto trace = trace_builder.finalize(); common_validate_shift_op(trace, a, b, output, FF(0), FF(1), FF(2), mem_tag, true); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, {}, { output }); } INSTANTIATE_TEST_SUITE_P(AvmBitwiseTests, @@ -561,7 +561,7 @@ TEST_P(AvmBitwiseTestsShl, AllShlTest) auto trace = trace_builder.finalize(); common_validate_shift_op(trace, a, b, output, FF(0), FF(1), FF(2), mem_tag, false); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, {}, { output }); } INSTANTIATE_TEST_SUITE_P(AvmBitwiseTests, diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp index 11d9768300df..28055ca5f098 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp @@ -26,9 +26,9 @@ class AvmCastTests : public ::testing::Test { std::vector calldata; std::vector trace; - size_t main_addr; - size_t alu_addr; - size_t mem_addr_c; + size_t main_row_idx; + size_t alu_row_idx; + size_t mem_c_row_idx; void gen_trace( uint128_t const& a, uint32_t src_address, uint32_t dst_address, AvmMemoryTag src_tag, AvmMemoryTag dst_tag) @@ -44,20 +44,20 @@ class AvmCastTests : public ::testing::Test { { auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_cast == FF(1); }); ASSERT_TRUE(row != trace.end()); - main_addr = static_cast(row - trace.begin()); + main_row_idx = static_cast(row - trace.begin()); // Find the corresponding Alu trace row auto clk = row->main_clk; auto alu_row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.alu_clk == clk; }); ASSERT_TRUE(alu_row != trace.end()); - alu_addr = static_cast(alu_row - trace.begin()); + alu_row_idx = static_cast(alu_row - trace.begin()); // Mem entry output ic write operation auto mem_row_c = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.mem_tsp == FF(AvmMemTraceBuilder::NUM_SUB_CLK) * clk + AvmMemTraceBuilder::SUB_CLK_STORE_C; }); ASSERT_TRUE(mem_row_c != trace.end()); - mem_addr_c = static_cast(mem_row_c - trace.begin()); + mem_c_row_idx = static_cast(mem_row_c - trace.begin()); } void validate_cast_trace(FF const& a, @@ -70,7 +70,7 @@ class AvmCastTests : public ::testing::Test { ) { - auto const& row = trace.at(main_addr); + auto const& row = trace.at(main_row_idx); EXPECT_THAT(row, AllOf(MAIN_ROW_FIELD_EQ(sel_op_cast, 1), MAIN_ROW_FIELD_EQ(ia, a), @@ -90,7 +90,7 @@ class AvmCastTests : public ::testing::Test { MAIN_ROW_FIELD_EQ(sel_rng_8, 1), MAIN_ROW_FIELD_EQ(sel_rng_16, 1))); - auto const& alu_row = trace.at(alu_addr); + auto const& alu_row = trace.at(alu_row_idx); EXPECT_THAT(alu_row, AllOf(ALU_ROW_FIELD_EQ(op_cast, 1), ALU_ROW_FIELD_EQ(ia, a), @@ -108,13 +108,13 @@ class AvmCastTests : public ::testing::Test { ALU_ROW_FIELD_EQ(sel_alu, 1))); // Check that there is a second ALU row - auto alu_row_next = trace.at(alu_addr + 1); + auto alu_row_next = trace.at(alu_row_idx + 1); EXPECT_THAT(alu_row_next, AllOf(ALU_ROW_FIELD_EQ(op_cast, 0), ALU_ROW_FIELD_EQ(op_cast_prev, 1))); // We still want the ability to enable proving through the environment variable and therefore we do not pass // the boolean variable force_proof to validate_trace second argument. if (force_proof) { - validate_trace(std::move(trace), public_inputs, calldata, true); + validate_trace(std::move(trace), public_inputs, calldata, {}, true); } else { validate_trace(std::move(trace), public_inputs, calldata); } @@ -256,13 +256,13 @@ TEST_F(AvmCastTests, indirectAddrWrongResolutionU64ToU8) TEST_F(AvmCastNegativeTests, nonTruncatedOutputMainIc) { gen_trace(300, 0, 1, AvmMemoryTag::U16, AvmMemoryTag::U8); - ASSERT_EQ(trace.at(main_addr).main_ic, 44); + ASSERT_EQ(trace.at(main_row_idx).main_ic, 44); // Replace the output in main trace with the non-truncated value - trace.at(main_addr).main_ic = 300; + trace.at(main_row_idx).main_ic = 300; // Adapt the memory trace entry - trace.at(mem_addr_c).mem_val = 300; + trace.at(mem_c_row_idx).mem_val = 300; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_ALU"); } @@ -270,13 +270,13 @@ TEST_F(AvmCastNegativeTests, nonTruncatedOutputMainIc) TEST_F(AvmCastNegativeTests, wrongOutputMainIc) { gen_trace(151515, 0, 1, AvmMemoryTag::U32, AvmMemoryTag::FF); - ASSERT_EQ(trace.at(main_addr).main_ic, 151515); + ASSERT_EQ(trace.at(main_row_idx).main_ic, 151515); // Replace the output in main trace with a wrong value - trace.at(main_addr).main_ic = 151516; + trace.at(main_row_idx).main_ic = 151516; // Adapt the memory trace entry - trace.at(mem_addr_c).mem_val = 151516; + trace.at(mem_c_row_idx).mem_val = 151516; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_ALU"); } @@ -284,12 +284,12 @@ TEST_F(AvmCastNegativeTests, wrongOutputMainIc) TEST_F(AvmCastNegativeTests, wrongOutputAluIc) { gen_trace(6582736, 0, 1, AvmMemoryTag::U128, AvmMemoryTag::U16); - ASSERT_EQ(trace.at(alu_addr).alu_ic, 29136); + ASSERT_EQ(trace.at(alu_row_idx).alu_ic, 29136); // Replace output in ALU, MAIN, and MEM trace - trace.at(alu_addr).alu_ic = 33; - trace.at(main_addr).main_ic = 33; - trace.at(mem_addr_c).mem_val = 33; + trace.at(alu_row_idx).alu_ic = 33; + trace.at(main_row_idx).main_ic = 33; + trace.at(mem_c_row_idx).mem_val = 33; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_OP_CAST"); } @@ -304,7 +304,7 @@ TEST_F(AvmCastNegativeTests, wrongLimbDecompositionInput) trace = trace_builder.finalize(); gen_indices(); - trace.at(alu_addr).alu_a_lo -= 23; + trace.at(alu_row_idx).alu_a_lo -= 23; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "INPUT_DECOMP_1"); } @@ -312,9 +312,9 @@ TEST_F(AvmCastNegativeTests, wrongLimbDecompositionInput) TEST_F(AvmCastNegativeTests, wrongPSubALo) { gen_trace(12345, 0, 1, AvmMemoryTag::U32, AvmMemoryTag::U16); - ASSERT_EQ(trace.at(alu_addr).alu_ic, 12345); + ASSERT_EQ(trace.at(alu_row_idx).alu_ic, 12345); - trace.at(alu_addr).alu_p_sub_a_lo += 3; + trace.at(alu_row_idx).alu_p_sub_a_lo += 3; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUB_LO_1"); } @@ -329,7 +329,7 @@ TEST_F(AvmCastNegativeTests, wrongPSubAHi) trace = trace_builder.finalize(); gen_indices(); - trace.at(alu_addr).alu_p_sub_a_hi += 3; + trace.at(alu_row_idx).alu_p_sub_a_hi += 3; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUB_HI_1"); } @@ -338,7 +338,7 @@ TEST_F(AvmCastNegativeTests, disableRangecheck) { gen_trace(123, 23, 43, AvmMemoryTag::U8, AvmMemoryTag::U8); - trace.at(alu_addr).alu_sel_rng_chk_lookup = 0; + trace.at(alu_row_idx).alu_sel_rng_chk_lookup = 0; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "RNG_CHK_LOOKUP_SELECTOR"); } @@ -346,16 +346,16 @@ TEST_F(AvmCastNegativeTests, disableRangecheckSub) { gen_trace(123, 23, 43, AvmMemoryTag::U8, AvmMemoryTag::U8); - trace.at(alu_addr + 1).alu_sel_rng_chk_lookup = 0; + trace.at(alu_row_idx + 1).alu_sel_rng_chk_lookup = 0; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "RNG_CHK_LOOKUP_SELECTOR"); } TEST_F(AvmCastNegativeTests, wrongRangeCheckDecompositionLo) { gen_trace(987344323, 23, 43, AvmMemoryTag::FF, AvmMemoryTag::U128); - ASSERT_EQ(trace.at(alu_addr).alu_ic, 987344323); + ASSERT_EQ(trace.at(alu_row_idx).alu_ic, 987344323); - trace.at(alu_addr).alu_u16_r0 = 5555; + trace.at(alu_row_idx).alu_u16_r0 = 5555; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "LOWER_CMP_RNG_CHK"); } @@ -369,17 +369,17 @@ TEST_F(AvmCastNegativeTests, wrongRangeCheckDecompositionHi) trace = trace_builder.finalize(); gen_indices(); - trace.at(alu_addr).alu_u16_r9 = 5555; + trace.at(alu_row_idx).alu_u16_r9 = 5555; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "UPPER_CMP_RNG_CHK"); } TEST_F(AvmCastNegativeTests, outOfRangeU8Registers) { gen_trace(987344323, 23, 43, AvmMemoryTag::FF, AvmMemoryTag::U128); - ASSERT_EQ(trace.at(alu_addr).alu_ic, 987344323); + ASSERT_EQ(trace.at(alu_row_idx).alu_ic, 987344323); - trace.at(alu_addr).alu_u8_r0 += 256; - trace.at(alu_addr).alu_u8_r1 -= 1; // Adjust so that the decomposition is correct. + trace.at(alu_row_idx).alu_u8_r0 += 256; + trace.at(alu_row_idx).alu_u8_r1 -= 1; // Adjust so that the decomposition is correct. EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "Lookup LOOKUP_U8_0"); } @@ -387,10 +387,10 @@ TEST_F(AvmCastNegativeTests, outOfRangeU8Registers) TEST_F(AvmCastNegativeTests, outOfRangeU16Registers) { gen_trace(987344323, 23, 43, AvmMemoryTag::FF, AvmMemoryTag::U128); - ASSERT_EQ(trace.at(alu_addr).alu_ic, 987344323); + ASSERT_EQ(trace.at(alu_row_idx).alu_ic, 987344323); - trace.at(alu_addr).alu_u16_r0 += 65536; - trace.at(alu_addr).alu_u16_r1 -= 1; // Adjust so that the decomposition is correct. + trace.at(alu_row_idx).alu_u16_r0 += 65536; + trace.at(alu_row_idx).alu_u16_r1 -= 1; // Adjust so that the decomposition is correct. EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "Lookup LOOKUP_U16_0"); } @@ -398,10 +398,10 @@ TEST_F(AvmCastNegativeTests, outOfRangeU16Registers) TEST_F(AvmCastNegativeTests, wrongCopySubLoForRangeCheck) { gen_trace(987344323, 23, 43, AvmMemoryTag::U64, AvmMemoryTag::U128); - ASSERT_EQ(trace.at(alu_addr).alu_ic, 987344323); + ASSERT_EQ(trace.at(alu_row_idx).alu_ic, 987344323); - ASSERT_EQ(trace.at(alu_addr + 1).alu_a_lo, trace.at(alu_addr).alu_p_sub_a_lo); - trace.at(alu_addr + 1).alu_a_lo -= 1; + ASSERT_EQ(trace.at(alu_row_idx + 1).alu_a_lo, trace.at(alu_row_idx).alu_p_sub_a_lo); + trace.at(alu_row_idx + 1).alu_a_lo -= 1; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "OP_CAST_RNG_CHECK_P_SUB_A_LOW"); } @@ -415,33 +415,33 @@ TEST_F(AvmCastNegativeTests, wrongCopySubHiForRangeCheck) trace = trace_builder.finalize(); gen_indices(); - ASSERT_EQ(trace.at(alu_addr + 1).alu_a_hi, trace.at(alu_addr).alu_p_sub_a_hi); - trace.at(alu_addr + 1).alu_a_hi += 2; + ASSERT_EQ(trace.at(alu_row_idx + 1).alu_a_hi, trace.at(alu_row_idx).alu_p_sub_a_hi); + trace.at(alu_row_idx + 1).alu_a_hi += 2; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "OP_CAST_RNG_CHECK_P_SUB_A_HIGH"); } TEST_F(AvmCastNegativeTests, secondRowNoOp) { gen_trace(6583, 0, 1, AvmMemoryTag::U64, AvmMemoryTag::U8); - ASSERT_EQ(trace.at(alu_addr).alu_ic, 183); + ASSERT_EQ(trace.at(alu_row_idx).alu_ic, 183); // We have to enable alu_sel otherwise another relation will fail. - trace.at(alu_addr + 1).alu_sel_alu = 1; + trace.at(alu_row_idx + 1).alu_sel_alu = 1; // Add an LT selector in the next row (second part of the cast operation) auto trace_lt = trace; - trace_lt.at(alu_addr + 1).alu_op_lt = 1; + trace_lt.at(alu_row_idx + 1).alu_op_lt = 1; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace_lt)), "TWO_LINE_OP_NO_OVERLAP"); // Try with EQ selector auto trace_eq = trace; - trace_eq.at(alu_addr + 1).alu_op_eq = 1; + trace_eq.at(alu_row_idx + 1).alu_op_eq = 1; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace_eq)), "TWO_LINE_OP_NO_OVERLAP"); // Try with a second cast selector - trace.at(alu_addr + 1).alu_op_cast = 1; + trace.at(alu_row_idx + 1).alu_op_cast = 1; // Adjust to not violate #[RNG_CHK_LOOKUP_SELECTOR] - trace.at(alu_addr + 1).alu_sel_rng_chk_lookup = 2; + trace.at(alu_row_idx + 1).alu_sel_rng_chk_lookup = 2; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "TWO_LINE_OP_NO_OVERLAP"); } diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp index f961e542cb47..453d6443233c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp @@ -87,7 +87,7 @@ TEST_F(AvmControlFlowTests, simpleCall) EXPECT_EQ(halt_row->main_pc, FF(CALL_PC)); EXPECT_EQ(halt_row->main_internal_return_ptr, FF(1)); } - validate_trace(std::move(trace), public_inputs, {}, true); + validate_trace(std::move(trace), public_inputs, {}, {}, true); } TEST_F(AvmControlFlowTests, simpleJump) diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp index 24829d562f4c..98591c279454 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp @@ -100,7 +100,7 @@ TEST_F(AvmExecutionTests, basicAddReturn) ElementsAre(VariantWith(0), VariantWith(0), VariantWith(0))))); auto trace = gen_trace_from_instr(instructions); - validate_trace(std::move(trace), public_inputs, {}, true); + validate_trace(std::move(trace), public_inputs, {}, {}, true); } // Positive test for SET and SUB opcodes @@ -165,7 +165,7 @@ TEST_F(AvmExecutionTests, setAndSubOpcodes) // Find the first row enabling the subtraction selector auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_sub == 1; }); EXPECT_EQ(row->main_ic, 10000); // 47123 - 37123 = 10000 - validate_trace(std::move(trace), public_inputs, {}, true); + validate_trace(std::move(trace), public_inputs, {}, {}, true); } // Positive test for multiple MUL opcodes @@ -805,7 +805,7 @@ TEST_F(AvmExecutionTests, toRadixLeOpcode) } EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs, { FF::modulus - FF(1) }); + validate_trace(std::move(trace), public_inputs, { FF::modulus - FF(1) }, returndata); } // // Positive test with SHA256COMPRESSION. @@ -873,7 +873,7 @@ TEST_F(AvmExecutionTests, sha256CompressionOpcode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs, calldata); + validate_trace(std::move(trace), public_inputs, calldata, returndata); } // Positive test with SHA256 @@ -941,7 +941,7 @@ TEST_F(AvmExecutionTests, sha256Opcode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata, returndata); } // Positive test with POSEIDON2_PERM. @@ -992,7 +992,7 @@ TEST_F(AvmExecutionTests, poseidon2PermutationOpCode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs, calldata); + validate_trace(std::move(trace), public_inputs, calldata, returndata); } // Positive test with Keccakf1600. @@ -1066,7 +1066,7 @@ TEST_F(AvmExecutionTests, keccakf1600OpCode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata, returndata); } // Positive test with Keccak. @@ -1124,7 +1124,7 @@ TEST_F(AvmExecutionTests, keccakOpCode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata, returndata); } // Positive test with Pedersen. @@ -1177,7 +1177,7 @@ TEST_F(AvmExecutionTests, pedersenHashOpCode) EXPECT_EQ(returndata[0], expected_output); - validate_trace(std::move(trace), public_inputs, calldata); + validate_trace(std::move(trace), public_inputs, calldata, returndata); } // // Positive test with EmbeddedCurveAdd @@ -1239,7 +1239,7 @@ TEST_F(AvmExecutionTests, embeddedCurveAddOpCode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs, calldata); + validate_trace(std::move(trace), public_inputs, calldata, returndata); } // Positive test with MSM @@ -1316,7 +1316,7 @@ TEST_F(AvmExecutionTests, msmOpCode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs, calldata); + validate_trace(std::move(trace), public_inputs, calldata, returndata); } // Positive test for Kernel Input opcodes @@ -2229,7 +2229,7 @@ TEST_F(AvmExecutionTests, opCallOpcodes) auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints); EXPECT_EQ(returndata, std::vector({ 9, 8, 1 })); // The 1 represents the success - validate_trace(std::move(trace), public_inputs, calldata); + validate_trace(std::move(trace), public_inputs, calldata, returndata); } TEST_F(AvmExecutionTests, opGetContractInstanceOpcodes) @@ -2268,7 +2268,7 @@ TEST_F(AvmExecutionTests, opGetContractInstanceOpcodes) auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints); EXPECT_EQ(returndata, std::vector({ 1, 2, 3, 4, 5, 6 })); // The first one represents true - validate_trace(std::move(trace), public_inputs, calldata); + validate_trace(std::move(trace), public_inputs, calldata, returndata); } // Negative test detecting an invalid opcode byte. TEST_F(AvmExecutionTests, invalidOpcode) diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp index 47e82b751023..bf61c566d184 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp @@ -68,7 +68,7 @@ TEST_F(AvmIndirectMemTests, allIndirectAdd) EXPECT_EQ(row->main_sel_mem_op_b, FF(1)); EXPECT_EQ(row->main_sel_mem_op_c, FF(1)); - validate_trace(std::move(trace), public_inputs, {}, true); + validate_trace(std::move(trace), public_inputs, {}, {}, true); } // Testing a subtraction operation with direct input operands a, b, and an indirect diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_inter_table.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_inter_table.test.cpp index 400d0a480b4c..79855ca1de60 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_inter_table.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_inter_table.test.cpp @@ -44,9 +44,9 @@ class AvmInterTableTests : public ::testing::Test { class AvmPermMainAluNegativeTests : public AvmInterTableTests { protected: std::vector trace; - size_t main_addr; - size_t mem_addr; - size_t alu_addr; + size_t main_row_idx; + size_t mem_row_idx; + size_t alu_row_idx; void SetUp() override { @@ -78,9 +78,9 @@ class AvmPermMainAluNegativeTests : public AvmInterTableTests { }); ASSERT_TRUE(mem_row != trace.end()); - main_addr = static_cast(row - trace.begin()); - alu_addr = static_cast(alu_row - trace.begin()); - mem_addr = static_cast(mem_row - trace.begin()); + main_row_idx = static_cast(row - trace.begin()); + alu_row_idx = static_cast(alu_row - trace.begin()); + mem_row_idx = static_cast(mem_row - trace.begin()); } }; @@ -88,8 +88,8 @@ TEST_F(AvmPermMainAluNegativeTests, wrongAluOutputCopyInMain) { // Mutate the multiplication output. Note that the output alu counterpart is still valid // and pass the multiplication relation. - trace.at(main_addr).main_ic = 1008; - trace.at(mem_addr).mem_val = 1008; + trace.at(main_row_idx).main_ic = 1008; + trace.at(mem_row_idx).mem_val = 1008; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_ALU"); } @@ -97,10 +97,10 @@ TEST_F(AvmPermMainAluNegativeTests, wrongAluOutputCopyInMain) TEST_F(AvmPermMainAluNegativeTests, wrongCopyToAluIaInput) { // Mutate the input of alu_ia and adapt the output ic accordingly. - trace.at(alu_addr).alu_ia = 20; - trace.at(alu_addr).alu_ic = 1060; // 20 * 53; required to pass the alu mul relation - trace.at(alu_addr).alu_u8_r0 = 36; // 1060 % 256 = 36 - trace.at(alu_addr).alu_u8_r1 = 4; // 4 * 256 = 1024 + trace.at(alu_row_idx).alu_ia = 20; + trace.at(alu_row_idx).alu_ic = 1060; // 20 * 53; required to pass the alu mul relation + trace.at(alu_row_idx).alu_u8_r0 = 36; // 1060 % 256 = 36 + trace.at(alu_row_idx).alu_u8_r1 = 4; // 4 * 256 = 1024 EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_ALU"); } @@ -108,30 +108,30 @@ TEST_F(AvmPermMainAluNegativeTests, wrongCopyToAluIaInput) TEST_F(AvmPermMainAluNegativeTests, wrongCopyToAluIbInput) { // Mutate the input of alu_ia and adapt the output ic accordingly. - trace.at(alu_addr).alu_ib = 10; - trace.at(alu_addr).alu_ic = 190; // 19 * 10; required to pass the alu mul relation - trace.at(alu_addr).alu_u8_r0 = 190; - trace.at(alu_addr).alu_u8_r1 = 0; + trace.at(alu_row_idx).alu_ib = 10; + trace.at(alu_row_idx).alu_ic = 190; // 19 * 10; required to pass the alu mul relation + trace.at(alu_row_idx).alu_u8_r0 = 190; + trace.at(alu_row_idx).alu_u8_r1 = 0; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_ALU"); } TEST_F(AvmPermMainAluNegativeTests, wrongCopyToAluOpSelector) { - trace.at(alu_addr).alu_op_mul = 0; - trace.at(alu_addr).alu_op_add = 1; - trace.at(alu_addr).alu_ic = 72; // 19 + 53 - trace.at(alu_addr).alu_u8_r0 = 72; - trace.at(alu_addr).alu_u8_r1 = 0; + trace.at(alu_row_idx).alu_op_mul = 0; + trace.at(alu_row_idx).alu_op_add = 1; + trace.at(alu_row_idx).alu_ic = 72; // 19 + 53 + trace.at(alu_row_idx).alu_u8_r0 = 72; + trace.at(alu_row_idx).alu_u8_r1 = 0; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_ALU"); } TEST_F(AvmPermMainAluNegativeTests, removeAluSelector) { - trace.at(alu_addr).alu_sel_alu = 0; - trace.at(alu_addr).alu_op_mul = 0; - trace.at(alu_addr).alu_sel_rng_chk_lookup = 0; + trace.at(alu_row_idx).alu_sel_alu = 0; + trace.at(alu_row_idx).alu_op_mul = 0; + trace.at(alu_row_idx).alu_sel_rng_chk_lookup = 0; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_ALU"); } @@ -142,9 +142,9 @@ TEST_F(AvmPermMainAluNegativeTests, removeAluSelector) class AvmRangeCheckNegativeTests : public AvmInterTableTests { protected: std::vector trace; - size_t main_addr; - size_t mem_addr; - size_t alu_addr; + size_t main_row_idx; + size_t mem_row_idx; + size_t alu_row_idx; void genTraceAdd( uint128_t const& a, uint128_t const& b, uint128_t const& c, AvmMemoryTag tag, uint32_t min_trace_size = 0) @@ -174,9 +174,9 @@ class AvmRangeCheckNegativeTests : public AvmInterTableTests { }); ASSERT_TRUE(mem_row != trace.end()); - main_addr = static_cast(row - trace.begin()); - alu_addr = static_cast(alu_row - trace.begin()); - mem_addr = static_cast(mem_row - trace.begin()); + main_row_idx = static_cast(row - trace.begin()); + alu_row_idx = static_cast(alu_row - trace.begin()); + mem_row_idx = static_cast(mem_row - trace.begin()); }; }; @@ -191,9 +191,9 @@ TEST_F(AvmRangeCheckNegativeTests, additionU8Reg0) // All constraints except range checks on u8_r0, u8_r1 are satisfied. FF const fake_c = FF(15).add(-FF(2).pow(254)); - auto& row = trace.at(main_addr); - auto& mem_row = trace.at(mem_addr); - auto& alu_row = trace.at(alu_addr); + auto& row = trace.at(main_row_idx); + auto& mem_row = trace.at(mem_row_idx); + auto& alu_row = trace.at(alu_row_idx); row.main_ic = fake_c; mem_row.mem_val = fake_c; @@ -221,9 +221,9 @@ TEST_F(AvmRangeCheckNegativeTests, additionU8Reg0) TEST_F(AvmRangeCheckNegativeTests, additionU8Reg1) { genTraceAdd(19, 20, 39, AvmMemoryTag::U8); - auto& row = trace.at(main_addr); - auto& mem_row = trace.at(mem_addr); - auto& alu_row = trace.at(alu_addr); + auto& row = trace.at(main_row_idx); + auto& mem_row = trace.at(mem_row_idx); + auto& alu_row = trace.at(alu_row_idx); // a + b = u8_r0 + 2^8 * u8_r1 (mod p) // We recall that p-1 is a multiple of a large power of two. @@ -259,9 +259,9 @@ TEST_F(AvmRangeCheckNegativeTests, additionU8Reg1) TEST_F(AvmRangeCheckNegativeTests, additionU16Reg0) { genTraceAdd(1200, 2000, 3200, AvmMemoryTag::U16, 130); - auto& row = trace.at(main_addr); - auto& mem_row = trace.at(mem_addr); - auto& alu_row = trace.at(alu_addr); + auto& row = trace.at(main_row_idx); + auto& mem_row = trace.at(mem_row_idx); + auto& alu_row = trace.at(alu_row_idx); // a + b = u8_r0 + 2^8 * u8_r1 + 2^16 * u16_r0 (mod p) // We recall that p-1 is a multiple of a large power of two. @@ -306,7 +306,7 @@ TEST_F(AvmRangeCheckNegativeTests, additionU16Reg7) genTraceAdd(4500, 45, 4545, AvmMemoryTag::U16); auto trace_original = trace; - auto& alu_row = trace.at(alu_addr); + auto& alu_row = trace.at(alu_row_idx); alu_row.alu_u16_r7 = FF(235655); auto trace_same_cnt = trace; @@ -323,7 +323,7 @@ TEST_F(AvmRangeCheckNegativeTests, additionU16Reg7) TEST_F(AvmRangeCheckNegativeTests, additionU16Reg8) { genTraceAdd(4500, 45, 4545, AvmMemoryTag::U16); - trace.at(alu_addr).alu_u16_r8 = FF(235655); + trace.at(alu_row_idx).alu_u16_r8 = FF(235655); trace.at(1).lookup_u16_8_counts -= FF(1); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "LOOKUP_U16_8"); } @@ -332,7 +332,7 @@ TEST_F(AvmRangeCheckNegativeTests, additionU16Reg8) TEST_F(AvmRangeCheckNegativeTests, additionU16Reg9) { genTraceAdd(4500, 45, 4545, AvmMemoryTag::U16); - trace.at(alu_addr).alu_u16_r9 = FF(235655); + trace.at(alu_row_idx).alu_u16_r9 = FF(235655); trace.at(1).lookup_u16_9_counts -= FF(1); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "LOOKUP_U16_9"); } @@ -341,7 +341,7 @@ TEST_F(AvmRangeCheckNegativeTests, additionU16Reg9) TEST_F(AvmRangeCheckNegativeTests, additionU16Reg10) { genTraceAdd(4500, 45, 4545, AvmMemoryTag::U16); - trace.at(alu_addr).alu_u16_r10 = FF(235655); + trace.at(alu_row_idx).alu_u16_r10 = FF(235655); trace.at(1).lookup_u16_10_counts -= FF(1); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "LOOKUP_U16_10"); } @@ -350,7 +350,7 @@ TEST_F(AvmRangeCheckNegativeTests, additionU16Reg10) TEST_F(AvmRangeCheckNegativeTests, additionU16Reg11) { genTraceAdd(4500, 45, 4545, AvmMemoryTag::U16); - trace.at(alu_addr).alu_u16_r11 = FF(235655); + trace.at(alu_row_idx).alu_u16_r11 = FF(235655); trace.at(1).lookup_u16_11_counts -= FF(1); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "LOOKUP_U16_11"); } @@ -359,7 +359,7 @@ TEST_F(AvmRangeCheckNegativeTests, additionU16Reg11) TEST_F(AvmRangeCheckNegativeTests, additionU16Reg12) { genTraceAdd(4500, 45, 4545, AvmMemoryTag::U16); - trace.at(alu_addr).alu_u16_r12 = FF(235655); + trace.at(alu_row_idx).alu_u16_r12 = FF(235655); trace.at(1).lookup_u16_12_counts -= FF(1); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "LOOKUP_U16_12"); } @@ -368,7 +368,7 @@ TEST_F(AvmRangeCheckNegativeTests, additionU16Reg12) TEST_F(AvmRangeCheckNegativeTests, additionU16Reg13) { genTraceAdd(4500, 45, 4545, AvmMemoryTag::U16); - trace.at(alu_addr).alu_u16_r13 = FF(235655); + trace.at(alu_row_idx).alu_u16_r13 = FF(235655); trace.at(1).lookup_u16_13_counts -= FF(1); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "LOOKUP_U16_13"); } @@ -377,7 +377,7 @@ TEST_F(AvmRangeCheckNegativeTests, additionU16Reg13) TEST_F(AvmRangeCheckNegativeTests, additionU16Reg14) { genTraceAdd(4500, 45, 4545, AvmMemoryTag::U16); - trace.at(alu_addr).alu_u16_r14 = FF(235655); + trace.at(alu_row_idx).alu_u16_r14 = FF(235655); trace.at(1).lookup_u16_14_counts -= FF(1); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "LOOKUP_U16_14"); } @@ -388,11 +388,11 @@ TEST_F(AvmRangeCheckNegativeTests, additionU16Reg14) class AvmPermMainMemNegativeTests : public AvmInterTableTests { protected: std::vector trace; - size_t main_addr; - size_t mem_addr_a; - size_t mem_addr_b; - size_t mem_addr_c; - size_t alu_addr; + size_t main_row_idx; + size_t mem_a_row_idx; + size_t mem_b_row_idx; + size_t mem_c_row_idx; + size_t alu_row_idx; // Helper function to generate a trace with a subtraction // for c = a - b at arbitray chosen addresses 52 (a), 11 (b), 55 (c). @@ -433,11 +433,11 @@ class AvmPermMainMemNegativeTests : public AvmInterTableTests { }); ASSERT_TRUE(mem_row_b != trace.end()); - main_addr = static_cast(row - trace.begin()); - alu_addr = static_cast(alu_row - trace.begin()); - mem_addr_a = static_cast(mem_row_a - trace.begin()); - mem_addr_b = static_cast(mem_row_b - trace.begin()); - mem_addr_c = static_cast(mem_row_c - trace.begin()); + main_row_idx = static_cast(row - trace.begin()); + alu_row_idx = static_cast(alu_row - trace.begin()); + mem_a_row_idx = static_cast(mem_row_a - trace.begin()); + mem_b_row_idx = static_cast(mem_row_b - trace.begin()); + mem_c_row_idx = static_cast(mem_row_c - trace.begin()); } }; // Error tag propagation from memory trace back to the main trace. @@ -483,8 +483,8 @@ TEST_F(AvmPermMainMemNegativeTests, tagErrNotCopiedInMain) TEST_F(AvmPermMainMemNegativeTests, wrongValueIaInMem) { executeSub(21, 3); - trace.at(mem_addr_a).mem_val = 26; // Correct value: 21 - trace.at(mem_addr_a - 1).mem_val = 26; // We need to adjust the write operation beforehand (set opcode). + trace.at(mem_a_row_idx).mem_val = 26; // Correct value: 21 + trace.at(mem_a_row_idx - 1).mem_val = 26; // We need to adjust the write operation beforehand (set opcode). EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_A"); } @@ -492,8 +492,8 @@ TEST_F(AvmPermMainMemNegativeTests, wrongValueIaInMem) TEST_F(AvmPermMainMemNegativeTests, wrongValueIbInMem) { executeSub(21, 3); - trace.at(mem_addr_b).mem_val = 7; // Correct value: 3 - trace.at(mem_addr_b - 1).mem_val = 7; // We need to adjust the write operation beforehand (set opcode). + trace.at(mem_b_row_idx).mem_val = 7; // Correct value: 3 + trace.at(mem_b_row_idx - 1).mem_val = 7; // We need to adjust the write operation beforehand (set opcode). EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_B"); } @@ -501,7 +501,7 @@ TEST_F(AvmPermMainMemNegativeTests, wrongValueIbInMem) TEST_F(AvmPermMainMemNegativeTests, wrongValueIcInMem) { executeSub(21, 3); - trace.at(mem_addr_c).mem_val = 17; // Correct value: 18 = 21 - 3 + trace.at(mem_c_row_idx).mem_val = 17; // Correct value: 18 = 21 - 3 EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_C"); } @@ -509,7 +509,7 @@ TEST_F(AvmPermMainMemNegativeTests, wrongValueIcInMem) TEST_F(AvmPermMainMemNegativeTests, wrongAddressIaInMain) { executeSub(21, 3); - trace.at(main_addr).main_mem_addr_a = 28; // Correct address: 52 + trace.at(main_row_idx).main_mem_addr_a = 28; // Correct address: 52 EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_A"); } @@ -517,7 +517,7 @@ TEST_F(AvmPermMainMemNegativeTests, wrongAddressIaInMain) TEST_F(AvmPermMainMemNegativeTests, wrongAddressIbInMain) { executeSub(21, 3); - trace.at(main_addr).main_mem_addr_b = 2; // Correct address: 11 + trace.at(main_row_idx).main_mem_addr_b = 2; // Correct address: 11 EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_B"); } @@ -525,7 +525,7 @@ TEST_F(AvmPermMainMemNegativeTests, wrongAddressIbInMain) TEST_F(AvmPermMainMemNegativeTests, wrongAddressIcInMain) { executeSub(21, 3); - trace.at(main_addr).main_mem_addr_c = 75; // Correct address: 55 + trace.at(main_row_idx).main_mem_addr_c = 75; // Correct address: 55 EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_C"); } @@ -534,13 +534,13 @@ TEST_F(AvmPermMainMemNegativeTests, wrongInTagIaInMem) { executeSub(21, 3); auto wrong_in_tag = static_cast(AvmMemoryTag::U32); - trace.at(mem_addr_a).mem_r_in_tag = wrong_in_tag; // Correct value: AvmMemoryTag::U8 - trace.at(mem_addr_a).mem_tag = wrong_in_tag; + trace.at(mem_a_row_idx).mem_r_in_tag = wrong_in_tag; // Correct value: AvmMemoryTag::U8 + trace.at(mem_a_row_idx).mem_tag = wrong_in_tag; // We need to adjust the write operation beforehand (set opcode). - trace.at(mem_addr_a - 1).mem_r_in_tag = wrong_in_tag; - trace.at(mem_addr_a - 1).mem_w_in_tag = wrong_in_tag; - trace.at(mem_addr_a - 1).mem_tag = wrong_in_tag; + trace.at(mem_a_row_idx - 1).mem_r_in_tag = wrong_in_tag; + trace.at(mem_a_row_idx - 1).mem_w_in_tag = wrong_in_tag; + trace.at(mem_a_row_idx - 1).mem_tag = wrong_in_tag; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_A"); } @@ -549,13 +549,13 @@ TEST_F(AvmPermMainMemNegativeTests, wrongInTagIbInMem) { executeSub(21, 3); auto wrong_in_tag = static_cast(AvmMemoryTag::U16); - trace.at(mem_addr_b).mem_r_in_tag = wrong_in_tag; // Correct value: AvmMemoryTag::U8 - trace.at(mem_addr_b).mem_tag = wrong_in_tag; + trace.at(mem_b_row_idx).mem_r_in_tag = wrong_in_tag; // Correct value: AvmMemoryTag::U8 + trace.at(mem_b_row_idx).mem_tag = wrong_in_tag; // We need to adjust the write operation beforehand (set opcode). - trace.at(mem_addr_b - 1).mem_r_in_tag = wrong_in_tag; - trace.at(mem_addr_b - 1).mem_w_in_tag = wrong_in_tag; - trace.at(mem_addr_b - 1).mem_tag = wrong_in_tag; + trace.at(mem_b_row_idx - 1).mem_r_in_tag = wrong_in_tag; + trace.at(mem_b_row_idx - 1).mem_w_in_tag = wrong_in_tag; + trace.at(mem_b_row_idx - 1).mem_tag = wrong_in_tag; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_B"); } @@ -564,8 +564,8 @@ TEST_F(AvmPermMainMemNegativeTests, wrongInTagIcInMem) { executeSub(21, 3); auto wrong_in_tag = static_cast(AvmMemoryTag::U128); - trace.at(mem_addr_c).mem_w_in_tag = wrong_in_tag; // Correct value: AvmMemoryTag::U8 - trace.at(mem_addr_c).mem_tag = wrong_in_tag; + trace.at(mem_c_row_idx).mem_w_in_tag = wrong_in_tag; // Correct value: AvmMemoryTag::U8 + trace.at(mem_c_row_idx).mem_tag = wrong_in_tag; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_C"); } @@ -573,15 +573,15 @@ TEST_F(AvmPermMainMemNegativeTests, wrongInTagIcInMem) TEST_F(AvmPermMainMemNegativeTests, wrongRwIaInMem) { executeSub(21, 3); - trace.at(mem_addr_a).mem_rw = 1; // Write instead of read. + trace.at(mem_a_row_idx).mem_rw = 1; // Write instead of read. // Adjust timestamp value - trace.at(mem_addr_a).mem_tsp += FF(AvmMemTraceBuilder::SUB_CLK_STORE_A - AvmMemTraceBuilder::SUB_CLK_LOAD_A); + trace.at(mem_a_row_idx).mem_tsp += FF(AvmMemTraceBuilder::SUB_CLK_STORE_A - AvmMemTraceBuilder::SUB_CLK_LOAD_A); // Adjust diff value of previous row as well - FF diff = trace.at(mem_addr_a - 1).mem_diff_lo + trace.at(mem_addr_a - 1).mem_diff_mid * FF(1 << 16) + + FF diff = trace.at(mem_a_row_idx - 1).mem_diff_lo + trace.at(mem_a_row_idx - 1).mem_diff_mid * FF(1 << 16) + FF(AvmMemTraceBuilder::SUB_CLK_STORE_A - AvmMemTraceBuilder::SUB_CLK_LOAD_A); - trace.at(mem_addr_a - 1).mem_diff_mid = FF(uint32_t(diff) >> 16); - trace.at(mem_addr_a - 1).mem_diff_lo = FF(uint32_t(diff) & UINT16_MAX); + trace.at(mem_a_row_idx - 1).mem_diff_mid = FF(uint32_t(diff) >> 16); + trace.at(mem_a_row_idx - 1).mem_diff_lo = FF(uint32_t(diff) & UINT16_MAX); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_A"); } @@ -589,15 +589,15 @@ TEST_F(AvmPermMainMemNegativeTests, wrongRwIaInMem) TEST_F(AvmPermMainMemNegativeTests, wrongRwIbInMem) { executeSub(21, 3); - trace.at(mem_addr_b).mem_rw = 1; // Write instead of read. + trace.at(mem_b_row_idx).mem_rw = 1; // Write instead of read. // Adjust timestamp value - trace.at(mem_addr_b).mem_tsp += FF(AvmMemTraceBuilder::SUB_CLK_STORE_B - AvmMemTraceBuilder::SUB_CLK_LOAD_B); + trace.at(mem_b_row_idx).mem_tsp += FF(AvmMemTraceBuilder::SUB_CLK_STORE_B - AvmMemTraceBuilder::SUB_CLK_LOAD_B); // Adjust diff value of previous row as well - FF diff = trace.at(mem_addr_b - 1).mem_diff_lo + trace.at(mem_addr_b - 1).mem_diff_mid * FF(1 << 16) + + FF diff = trace.at(mem_b_row_idx - 1).mem_diff_lo + trace.at(mem_b_row_idx - 1).mem_diff_mid * FF(1 << 16) + FF(AvmMemTraceBuilder::SUB_CLK_STORE_B - AvmMemTraceBuilder::SUB_CLK_LOAD_B); - trace.at(mem_addr_b - 1).mem_diff_mid = FF(uint32_t(diff) >> 16); - trace.at(mem_addr_b - 1).mem_diff_lo = FF(uint32_t(diff) & UINT16_MAX); + trace.at(mem_b_row_idx - 1).mem_diff_mid = FF(uint32_t(diff) >> 16); + trace.at(mem_b_row_idx - 1).mem_diff_lo = FF(uint32_t(diff) & UINT16_MAX); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_B"); } @@ -608,10 +608,10 @@ TEST_F(AvmPermMainMemNegativeTests, wrongRwIcInMem) // a write for a read of Ic below leads to a violation that the memory // is initialized with zero values. executeSub(11, 11); - trace.at(mem_addr_c).mem_rw = 0; // Read instead of write. + trace.at(mem_c_row_idx).mem_rw = 0; // Read instead of write. // Adjust timestamp value. - trace.at(mem_addr_c).mem_tsp -= FF(AvmMemTraceBuilder::SUB_CLK_STORE_C - AvmMemTraceBuilder::SUB_CLK_LOAD_C); + trace.at(mem_c_row_idx).mem_tsp -= FF(AvmMemTraceBuilder::SUB_CLK_STORE_C - AvmMemTraceBuilder::SUB_CLK_LOAD_C); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_C"); } @@ -619,13 +619,13 @@ TEST_F(AvmPermMainMemNegativeTests, wrongRwIcInMem) TEST_F(AvmPermMainMemNegativeTests, wrongClkIaInMem) { executeSub(87, 23); - trace.at(mem_addr_a).mem_clk += 3; - trace.at(mem_addr_a).mem_tsp += AvmMemTraceBuilder::NUM_SUB_CLK * 3; + trace.at(mem_a_row_idx).mem_clk += 3; + trace.at(mem_a_row_idx).mem_tsp += AvmMemTraceBuilder::NUM_SUB_CLK * 3; // Adjust diff value of previous row as well - FF diff = trace.at(mem_addr_a - 1).mem_diff_lo + trace.at(mem_addr_a - 1).mem_diff_mid * FF(1 << 16) + + FF diff = trace.at(mem_a_row_idx - 1).mem_diff_lo + trace.at(mem_a_row_idx - 1).mem_diff_mid * FF(1 << 16) + FF(AvmMemTraceBuilder::NUM_SUB_CLK * 3); - trace.at(mem_addr_a - 1).mem_diff_mid = FF(uint32_t(diff) >> 16); - trace.at(mem_addr_a - 1).mem_diff_lo = FF(uint32_t(diff) & UINT16_MAX); + trace.at(mem_a_row_idx - 1).mem_diff_mid = FF(uint32_t(diff) >> 16); + trace.at(mem_a_row_idx - 1).mem_diff_lo = FF(uint32_t(diff) & UINT16_MAX); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_A"); } @@ -633,12 +633,12 @@ TEST_F(AvmPermMainMemNegativeTests, wrongClkIaInMem) TEST_F(AvmPermMainMemNegativeTests, wrongClkIbInMem) { executeSub(87, 23); - trace.at(mem_addr_b).mem_clk += 5; - trace.at(mem_addr_b).mem_tsp += AvmMemTraceBuilder::NUM_SUB_CLK * 5; - FF diff = trace.at(mem_addr_b - 1).mem_diff_lo + trace.at(mem_addr_b - 1).mem_diff_mid * FF(1 << 16) + + trace.at(mem_b_row_idx).mem_clk += 5; + trace.at(mem_b_row_idx).mem_tsp += AvmMemTraceBuilder::NUM_SUB_CLK * 5; + FF diff = trace.at(mem_b_row_idx - 1).mem_diff_lo + trace.at(mem_b_row_idx - 1).mem_diff_mid * FF(1 << 16) + FF(AvmMemTraceBuilder::NUM_SUB_CLK * 5); - trace.at(mem_addr_b - 1).mem_diff_mid = FF(uint32_t(diff) >> 16); - trace.at(mem_addr_b - 1).mem_diff_lo = FF(uint32_t(diff) & UINT16_MAX); + trace.at(mem_b_row_idx - 1).mem_diff_mid = FF(uint32_t(diff) >> 16); + trace.at(mem_b_row_idx - 1).mem_diff_lo = FF(uint32_t(diff) & UINT16_MAX); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_B"); } @@ -646,8 +646,8 @@ TEST_F(AvmPermMainMemNegativeTests, wrongClkIbInMem) TEST_F(AvmPermMainMemNegativeTests, wrongClkIcInMem) { executeSub(87, 23); - trace.at(mem_addr_c).mem_clk += 7; - trace.at(mem_addr_c).mem_tsp += AvmMemTraceBuilder::NUM_SUB_CLK * 7; + trace.at(mem_c_row_idx).mem_clk += 7; + trace.at(mem_c_row_idx).mem_tsp += AvmMemTraceBuilder::NUM_SUB_CLK * 7; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_C"); } diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp index 94157443a75f..1a6ca8a13803 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp @@ -7,8 +7,6 @@ #include #include -#define MEM_ROW_FIELD_EQ(field_name, expression) Field(#field_name, &Row::mem_##field_name, expression) - namespace tests_avm { using namespace bb; @@ -29,15 +27,15 @@ class AvmMemOpcodeTests : public ::testing::Test { protected: std::vector trace; - size_t main_addr; - size_t mem_a_addr; - size_t mem_b_addr; - size_t mem_c_addr; - size_t mem_d_addr; - size_t mem_ind_a_addr; - size_t mem_ind_b_addr; - size_t mem_ind_c_addr; - size_t mem_ind_d_addr; + size_t main_row_idx; + size_t mem_a_row_idx; + size_t mem_b_row_idx; + size_t mem_c_row_idx; + size_t mem_d_row_idx; + size_t mem_ind_a_row_idx; + size_t mem_ind_b_row_idx; + size_t mem_ind_c_row_idx; + size_t mem_ind_d_row_idx; void build_mov_trace(bool indirect, uint128_t const& val, @@ -84,14 +82,14 @@ class AvmMemOpcodeTests : public ::testing::Test { auto row = std::ranges::find_if(trace.begin(), trace.end(), gen_matcher(clk, AvmMemTraceBuilder::SUB_CLK_LOAD_A)); ASSERT_TRUE(row != trace.end()); - mem_a_addr = static_cast(row - trace.begin()); + mem_a_row_idx = static_cast(row - trace.begin()); // Find the memory trace position of the indirect load for register ia. if (indirect) { row = std::ranges::find_if( trace.begin(), trace.end(), gen_matcher(clk, AvmMemTraceBuilder::SUB_CLK_IND_LOAD_A)); ASSERT_TRUE(row != trace.end()); - mem_ind_a_addr = static_cast(row - trace.begin()); + mem_ind_a_row_idx = static_cast(row - trace.begin()); } } @@ -101,14 +99,14 @@ class AvmMemOpcodeTests : public ::testing::Test { auto row = std::ranges::find_if(trace.begin(), trace.end(), gen_matcher(clk, AvmMemTraceBuilder::SUB_CLK_STORE_C)); ASSERT_TRUE(row != trace.end()); - mem_c_addr = static_cast(row - trace.begin()); + mem_c_row_idx = static_cast(row - trace.begin()); // Find the memory trace position of the indirect load for register ic. if (indirect) { row = std::ranges::find_if( trace.begin(), trace.end(), gen_matcher(clk, AvmMemTraceBuilder::SUB_CLK_IND_LOAD_C)); ASSERT_TRUE(row != trace.end()); - mem_ind_c_addr = static_cast(row - trace.begin()); + mem_ind_c_row_idx = static_cast(row - trace.begin()); } } @@ -117,7 +115,7 @@ class AvmMemOpcodeTests : public ::testing::Test { // Find the first row enabling the MOV selector auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_mov == FF(1); }); ASSERT_TRUE(row != trace.end()); - main_addr = static_cast(row - trace.begin()); + main_row_idx = static_cast(row - trace.begin()); auto clk = row->main_clk; @@ -130,7 +128,7 @@ class AvmMemOpcodeTests : public ::testing::Test { // Find the first row enabling the CMOV selector auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_cmov == FF(1); }); ASSERT_TRUE(row != trace.end()); - main_addr = static_cast(row - trace.begin()); + main_row_idx = static_cast(row - trace.begin()); auto clk = row->main_clk; compute_index_a(clk, is_operand_indirect(indirect, 0)); @@ -139,27 +137,27 @@ class AvmMemOpcodeTests : public ::testing::Test { // Find the memory trace position corresponding to the load sub-operation of register ib. row = std::ranges::find_if(trace.begin(), trace.end(), gen_matcher(clk, AvmMemTraceBuilder::SUB_CLK_LOAD_B)); ASSERT_TRUE(row != trace.end()); - mem_b_addr = static_cast(row - trace.begin()); + mem_b_row_idx = static_cast(row - trace.begin()); // Find the memory trace position of the indirect load for register ib. if (is_operand_indirect(indirect, 1)) { row = std::ranges::find_if( trace.begin(), trace.end(), gen_matcher(clk, AvmMemTraceBuilder::SUB_CLK_IND_LOAD_B)); ASSERT_TRUE(row != trace.end()); - mem_ind_b_addr = static_cast(row - trace.begin()); + mem_ind_b_row_idx = static_cast(row - trace.begin()); } // Find the memory trace position corresponding to the load sub-operation of register id. row = std::ranges::find_if(trace.begin(), trace.end(), gen_matcher(clk, AvmMemTraceBuilder::SUB_CLK_LOAD_D)); ASSERT_TRUE(row != trace.end()); - mem_d_addr = static_cast(row - trace.begin()); + mem_d_row_idx = static_cast(row - trace.begin()); // Find the memory trace position of the indirect load for register id. if (is_operand_indirect(indirect, 3)) { row = std::ranges::find_if( trace.begin(), trace.end(), gen_matcher(clk, AvmMemTraceBuilder::SUB_CLK_IND_LOAD_D)); ASSERT_TRUE(row != trace.end()); - mem_ind_d_addr = static_cast(row - trace.begin()); + mem_ind_d_row_idx = static_cast(row - trace.begin()); } } @@ -174,7 +172,7 @@ class AvmMemOpcodeTests : public ::testing::Test { { compute_mov_indices(indirect); FF const val_ff = uint256_t::from_uint128(val); - auto const& main_row = trace.at(main_addr); + auto const& main_row = trace.at(main_row_idx); if (indirect) { EXPECT_THAT( @@ -190,7 +188,7 @@ class AvmMemOpcodeTests : public ::testing::Test { MAIN_ROW_FIELD_EQ(r_in_tag, static_cast(tag)), MAIN_ROW_FIELD_EQ(w_in_tag, static_cast(tag)))); - auto const& mem_a_row = trace.at(mem_a_addr); + auto const& mem_a_row = trace.at(mem_a_row_idx); EXPECT_THAT(mem_a_row, AllOf(MEM_ROW_FIELD_EQ(tag_err, 0), @@ -202,7 +200,7 @@ class AvmMemOpcodeTests : public ::testing::Test { MEM_ROW_FIELD_EQ(rw, 0), MEM_ROW_FIELD_EQ(sel_op_a, 1))); - auto const& mem_c_row = trace.at(mem_c_addr); + auto const& mem_c_row = trace.at(mem_c_row_idx); EXPECT_THAT(mem_c_row, AllOf(MEM_ROW_FIELD_EQ(tag_err, 0), @@ -213,7 +211,7 @@ class AvmMemOpcodeTests : public ::testing::Test { MEM_ROW_FIELD_EQ(sel_op_c, 1))); if (indirect) { - auto const& mem_ind_a_row = trace.at(mem_ind_a_addr); + auto const& mem_ind_a_row = trace.at(mem_ind_a_row_idx); EXPECT_THAT(mem_ind_a_row, AllOf(MEM_ROW_FIELD_EQ(tag_err, 0), MEM_ROW_FIELD_EQ(r_in_tag, static_cast(AvmMemoryTag::U32)), @@ -224,7 +222,7 @@ class AvmMemOpcodeTests : public ::testing::Test { MEM_ROW_FIELD_EQ(val, dir_src_offset), MEM_ROW_FIELD_EQ(sel_resolve_ind_addr_a, 1))); - auto const& mem_ind_c_row = trace.at(mem_ind_c_addr); + auto const& mem_ind_c_row = trace.at(mem_ind_c_row_idx); EXPECT_THAT(mem_ind_c_row, AllOf(MEM_ROW_FIELD_EQ(tag_err, 0), MEM_ROW_FIELD_EQ(r_in_tag, static_cast(AvmMemoryTag::U32)), @@ -254,7 +252,7 @@ class AvmMemOpcodeTests : public ::testing::Test { FF const& mov_val = mov_a ? a : b; FF const inv = mov_a ? d.invert() : 1; - EXPECT_THAT(trace.at(main_addr), + EXPECT_THAT(trace.at(main_row_idx), AllOf(MAIN_ROW_FIELD_EQ(ia, a), MAIN_ROW_FIELD_EQ(ib, b), MAIN_ROW_FIELD_EQ(ic, mov_val), @@ -282,7 +280,7 @@ class AvmMemOpcodeTests : public ::testing::Test { MAIN_ROW_FIELD_EQ(w_in_tag, static_cast(mov_tag)), MAIN_ROW_FIELD_EQ(inv, inv))); - EXPECT_THAT(trace.at(mem_a_addr), + EXPECT_THAT(trace.at(mem_a_row_idx), AllOf(MEM_ROW_FIELD_EQ(r_in_tag, static_cast(mov_tag)), MEM_ROW_FIELD_EQ(w_in_tag, static_cast(mov_tag)), MEM_ROW_FIELD_EQ(tag, static_cast(tag_a)), @@ -294,7 +292,7 @@ class AvmMemOpcodeTests : public ::testing::Test { MEM_ROW_FIELD_EQ(sel_op_a, 1), MEM_ROW_FIELD_EQ(sel_resolve_ind_addr_a, 0))); - EXPECT_THAT(trace.at(mem_b_addr), + EXPECT_THAT(trace.at(mem_b_row_idx), AllOf(MEM_ROW_FIELD_EQ(r_in_tag, static_cast(mov_tag)), MEM_ROW_FIELD_EQ(w_in_tag, static_cast(mov_tag)), MEM_ROW_FIELD_EQ(tag, static_cast(tag_b)), @@ -307,7 +305,7 @@ class AvmMemOpcodeTests : public ::testing::Test { MEM_ROW_FIELD_EQ(sel_op_b, 1), MEM_ROW_FIELD_EQ(sel_resolve_ind_addr_b, 0))); - EXPECT_THAT(trace.at(mem_c_addr), + EXPECT_THAT(trace.at(mem_c_row_idx), AllOf(MEM_ROW_FIELD_EQ(r_in_tag, static_cast(mov_tag)), MEM_ROW_FIELD_EQ(w_in_tag, static_cast(mov_tag)), MEM_ROW_FIELD_EQ(tag, static_cast(mov_tag)), @@ -319,7 +317,7 @@ class AvmMemOpcodeTests : public ::testing::Test { MEM_ROW_FIELD_EQ(sel_op_c, 1), MEM_ROW_FIELD_EQ(sel_resolve_ind_addr_c, 0))); - EXPECT_THAT(trace.at(mem_d_addr), + EXPECT_THAT(trace.at(mem_d_row_idx), AllOf(MEM_ROW_FIELD_EQ(r_in_tag, static_cast(mov_tag)), MEM_ROW_FIELD_EQ(w_in_tag, static_cast(mov_tag)), MEM_ROW_FIELD_EQ(tag, static_cast(tag_d)), @@ -395,14 +393,14 @@ TEST_F(AvmMemOpcodeTests, indirectMovInvalidAddressTag) compute_mov_indices(true); - EXPECT_EQ(trace.at(main_addr).main_tag_err, 1); - EXPECT_THAT(trace.at(mem_ind_c_addr), + EXPECT_EQ(trace.at(main_row_idx).main_tag_err, 1); + EXPECT_THAT(trace.at(mem_ind_c_row_idx), AllOf(MEM_ROW_FIELD_EQ(tag_err, 1), MEM_ROW_FIELD_EQ(tag, static_cast(AvmMemoryTag::U128)), MEM_ROW_FIELD_EQ(r_in_tag, static_cast(AvmMemoryTag::U32)), MEM_ROW_FIELD_EQ(sel_resolve_ind_addr_c, 1))); - validate_trace(std::move(trace), public_inputs, {}, true); + validate_trace(std::move(trace), public_inputs, {}, {}, true); } /****************************************************************************** @@ -535,7 +533,7 @@ TEST_F(AvmMemOpcodeTests, directSet) MAIN_ROW_FIELD_EQ(rwc, 1), MAIN_ROW_FIELD_EQ(sel_resolve_ind_addr_c, 0))); - EXPECT_THAT(trace.at(mem_c_addr), + EXPECT_THAT(trace.at(mem_c_row_idx), AllOf(MEM_ROW_FIELD_EQ(val, 5683), MEM_ROW_FIELD_EQ(addr, 99), MEM_ROW_FIELD_EQ(sel_op_c, 1), @@ -564,7 +562,7 @@ TEST_F(AvmMemOpcodeTests, indirectSet) MAIN_ROW_FIELD_EQ(sel_resolve_ind_addr_c, 1), MAIN_ROW_FIELD_EQ(ind_addr_c, 10))); - EXPECT_THAT(trace.at(mem_c_addr), + EXPECT_THAT(trace.at(mem_c_row_idx), AllOf(MEM_ROW_FIELD_EQ(val, 1979), MEM_ROW_FIELD_EQ(addr, 100), MEM_ROW_FIELD_EQ(sel_op_c, 1), @@ -573,7 +571,7 @@ TEST_F(AvmMemOpcodeTests, indirectSet) MEM_ROW_FIELD_EQ(w_in_tag, static_cast(AvmMemoryTag::U64)), MEM_ROW_FIELD_EQ(tag, static_cast(AvmMemoryTag::U64)))); - EXPECT_THAT(trace.at(mem_ind_c_addr), + EXPECT_THAT(trace.at(mem_ind_c_row_idx), AllOf(MEM_ROW_FIELD_EQ(val, 100), MEM_ROW_FIELD_EQ(addr, 10), MEM_ROW_FIELD_EQ(sel_op_c, 0), @@ -602,7 +600,7 @@ TEST_F(AvmMemOpcodeTests, indirectSetWrongTag) MAIN_ROW_FIELD_EQ(sel_resolve_ind_addr_c, 1), MAIN_ROW_FIELD_EQ(ind_addr_c, 10))); - EXPECT_THAT(trace.at(mem_ind_c_addr), + EXPECT_THAT(trace.at(mem_ind_c_row_idx), AllOf(MEM_ROW_FIELD_EQ(val, 100), MEM_ROW_FIELD_EQ(addr, 10), MEM_ROW_FIELD_EQ(sel_op_c, 0), @@ -629,7 +627,7 @@ TEST_F(AvmMemOpcodeNegativeTests, movWrongOutputErrorTag) { build_mov_trace(false, 234, 0, 1, AvmMemoryTag::U8); compute_mov_indices(false); - trace.at(main_addr).main_tag_err = 1; + trace.at(main_row_idx).main_tag_err = 1; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "INCL_MEM_TAG_ERR"); } @@ -638,7 +636,7 @@ TEST_F(AvmMemOpcodeNegativeTests, movWrongOutputValue) { build_mov_trace(false, 234, 0, 1, AvmMemoryTag::U8); compute_mov_indices(false); - trace.at(main_addr).main_ic = 233; + trace.at(main_row_idx).main_ic = 233; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "MOV_SAME_VALUE_A"); } @@ -647,7 +645,7 @@ TEST_F(AvmMemOpcodeNegativeTests, indMovWrongOutputValue) { build_mov_trace(true, 8732, 23, 24, AvmMemoryTag::U16, 432, 876); compute_mov_indices(true); - trace.at(main_addr).main_ic = 8733; + trace.at(main_row_idx).main_ic = 8733; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "MOV_SAME_VALUE_A"); } @@ -667,14 +665,14 @@ TEST_F(AvmMemOpcodeNegativeTests, movWrongOutputTagLoadIa) auto trace_tmp = trace; - trace.at(mem_a_addr).mem_r_in_tag = tag_u64; - trace.at(mem_a_addr).mem_tag_err = 1; - trace.at(mem_a_addr).mem_one_min_inv = one_min_inverse_diff; - trace.at(mem_c_addr).mem_tag = tag_u64; - trace.at(mem_c_addr).mem_w_in_tag = tag_u64; - trace.at(main_addr).main_r_in_tag = tag_u64; - trace.at(main_addr).main_w_in_tag = tag_u64; - trace.at(main_addr).main_tag_err = 1; + trace.at(mem_a_row_idx).mem_r_in_tag = tag_u64; + trace.at(mem_a_row_idx).mem_tag_err = 1; + trace.at(mem_a_row_idx).mem_one_min_inv = one_min_inverse_diff; + trace.at(mem_c_row_idx).mem_tag = tag_u64; + trace.at(mem_c_row_idx).mem_w_in_tag = tag_u64; + trace.at(main_row_idx).main_r_in_tag = tag_u64; + trace.at(main_row_idx).main_w_in_tag = tag_u64; + trace.at(main_row_idx).main_tag_err = 1; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "MOV_SAME_TAG"); } @@ -690,17 +688,17 @@ TEST_F(AvmMemOpcodeNegativeTests, movWrongOutputTagDisabledSelector) build_mov_trace(false, 234, 0, 1, AvmMemoryTag::U8); compute_mov_indices(false); - trace.at(mem_a_addr).mem_r_in_tag = tag_u64; - trace.at(mem_a_addr).mem_w_in_tag = tag_u64; - trace.at(mem_a_addr).mem_tag_err = 1; - trace.at(mem_a_addr).mem_one_min_inv = one_min_inverse_diff; - trace.at(mem_a_addr).mem_sel_mov_ia_to_ic = 0; - trace.at(mem_c_addr).mem_tag = tag_u64; - trace.at(mem_c_addr).mem_r_in_tag = tag_u64; - trace.at(mem_c_addr).mem_w_in_tag = tag_u64; - trace.at(main_addr).main_r_in_tag = tag_u64; - trace.at(main_addr).main_w_in_tag = tag_u64; - trace.at(main_addr).main_tag_err = 1; + trace.at(mem_a_row_idx).mem_r_in_tag = tag_u64; + trace.at(mem_a_row_idx).mem_w_in_tag = tag_u64; + trace.at(mem_a_row_idx).mem_tag_err = 1; + trace.at(mem_a_row_idx).mem_one_min_inv = one_min_inverse_diff; + trace.at(mem_a_row_idx).mem_sel_mov_ia_to_ic = 0; + trace.at(mem_c_row_idx).mem_tag = tag_u64; + trace.at(mem_c_row_idx).mem_r_in_tag = tag_u64; + trace.at(mem_c_row_idx).mem_w_in_tag = tag_u64; + trace.at(main_row_idx).main_r_in_tag = tag_u64; + trace.at(main_row_idx).main_w_in_tag = tag_u64; + trace.at(main_row_idx).main_tag_err = 1; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_A"); } @@ -714,10 +712,10 @@ TEST_F(AvmMemOpcodeNegativeTests, movWrongOutputTagInMainTrace) build_mov_trace(false, 234, 0, 1, AvmMemoryTag::U8); compute_mov_indices(false); - trace.at(mem_c_addr).mem_tag = tag_u64; - trace.at(mem_c_addr).mem_w_in_tag = tag_u64; - trace.at(main_addr).main_w_in_tag = tag_u64; - trace.at(main_addr).main_tag_err = 1; + trace.at(mem_c_row_idx).mem_tag = tag_u64; + trace.at(mem_c_row_idx).mem_w_in_tag = tag_u64; + trace.at(main_row_idx).main_w_in_tag = tag_u64; + trace.at(main_row_idx).main_tag_err = 1; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "MOV_MAIN_SAME_TAG"); } @@ -730,8 +728,8 @@ TEST_F(AvmMemOpcodeNegativeTests, movWrongOutputTagMainTraceRead) build_mov_trace(false, 234, 0, 1, AvmMemoryTag::U8); compute_mov_indices(false); - trace.at(mem_c_addr).mem_tag = tag_u64; - trace.at(mem_c_addr).mem_w_in_tag = tag_u64; + trace.at(mem_c_row_idx).mem_tag = tag_u64; + trace.at(mem_c_row_idx).mem_w_in_tag = tag_u64; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_C"); } @@ -743,7 +741,7 @@ TEST_F(AvmMemOpcodeNegativeTests, cmovBInsteadA) { build_cmov_trace_neg_test(true); - trace.at(main_addr).main_ic = 1980; + trace.at(main_row_idx).main_ic = 1980; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "MOV_SAME_VALUE_A"); } @@ -751,7 +749,7 @@ TEST_F(AvmMemOpcodeNegativeTests, cmovAInsteadB) { build_cmov_trace_neg_test(false); - trace.at(main_addr).main_ic = 1979; + trace.at(main_row_idx).main_ic = 1979; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "MOV_SAME_VALUE_B"); } @@ -759,9 +757,9 @@ TEST_F(AvmMemOpcodeNegativeTests, cmovAChangeTag) { build_cmov_trace_neg_test(true); - trace.at(mem_c_addr).mem_tag = static_cast(AvmMemoryTag::U32); - trace.at(mem_c_addr).mem_w_in_tag = static_cast(AvmMemoryTag::U32); - trace.at(main_addr).main_w_in_tag = static_cast(AvmMemoryTag::U32); + trace.at(mem_c_row_idx).mem_tag = static_cast(AvmMemoryTag::U32); + trace.at(mem_c_row_idx).mem_w_in_tag = static_cast(AvmMemoryTag::U32); + trace.at(main_row_idx).main_w_in_tag = static_cast(AvmMemoryTag::U32); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "MOV_MAIN_SAME_TAG"); } @@ -770,7 +768,7 @@ TEST_F(AvmMemOpcodeNegativeTests, cmovASkipCheckAbuse) { build_cmov_trace_neg_test(true); - trace.at(mem_a_addr).mem_skip_check_tag = 1; + trace.at(mem_a_row_idx).mem_skip_check_tag = 1; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SKIP_CHECK_TAG"); } @@ -779,8 +777,8 @@ TEST_F(AvmMemOpcodeNegativeTests, cmovASkipCheckAbuseDisableSelMovA) { build_cmov_trace_neg_test(true); - trace.at(mem_a_addr).mem_skip_check_tag = 1; - trace.at(mem_a_addr).mem_sel_mov_ia_to_ic = 0; + trace.at(mem_a_row_idx).mem_skip_check_tag = 1; + trace.at(mem_a_row_idx).mem_sel_mov_ia_to_ic = 0; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_A"); } @@ -789,8 +787,8 @@ TEST_F(AvmMemOpcodeNegativeTests, cmovBSkipCheckAbuseDisableSelMovB) { build_cmov_trace_neg_test(false); - trace.at(mem_b_addr).mem_skip_check_tag = 1; - trace.at(mem_b_addr).mem_sel_mov_ib_to_ic = 0; + trace.at(mem_b_row_idx).mem_skip_check_tag = 1; + trace.at(mem_b_row_idx).mem_sel_mov_ib_to_ic = 0; EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_MAIN_MEM_B"); } diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp index 05a02bb3862f..5708e65c00be 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp @@ -77,7 +77,7 @@ TEST_F(AvmMemoryTests, mismatchedTagAddOperation) EXPECT_EQ(row->mem_r_in_tag, FF(static_cast(AvmMemoryTag::U8))); EXPECT_EQ(row->mem_tag, FF(static_cast(AvmMemoryTag::FF))); - validate_trace(std::move(trace), public_inputs, calldata, true); + validate_trace(std::move(trace), public_inputs, calldata, {}, true); } // Testing an equality operation with a mismatched memory tag. diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_slice.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_slice.test.cpp new file mode 100644 index 000000000000..8f581c51a527 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_slice.test.cpp @@ -0,0 +1,337 @@ +#include "avm_common.test.hpp" +#include "barretenberg/vm/avm_trace/avm_common.hpp" +#include "barretenberg/vm/tests/helpers.test.hpp" +#include +#include + +#include + +#define SLICE_ROW_FIELD_EQ(field_name, expression) Field(#field_name, &Row::slice_##field_name, expression) + +namespace tests_avm { + +using namespace bb; +using namespace bb::avm_trace; +using namespace testing; + +class AvmSliceTests : public ::testing::Test { + public: + AvmSliceTests() + : public_inputs(generate_base_public_inputs()) + , trace_builder(AvmTraceBuilder(public_inputs)) + { + srs::init_crs_factory("../srs_db/ignition"); + } + + void gen_trace_builder(std::vector const& calldata) + { + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + this->calldata = calldata; + } + + void gen_single_calldata_copy( + bool indirect, uint32_t cd_size, uint32_t col_offset, uint32_t copy_size, uint32_t dst_offset) + { + ASSERT_LE(col_offset + copy_size, cd_size); + std::vector calldata; + for (size_t i = 0; i < cd_size; i++) { + calldata.emplace_back(i * i); + } + + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(static_cast(indirect), col_offset, copy_size, dst_offset); + trace_builder.op_return(0, 0, 0); + trace = trace_builder.finalize(); + } + + void validate_single_calldata_copy_trace(uint32_t col_offset, + uint32_t copy_size, + uint32_t dst_offset, + bool proof_verif = false) + { + // Find the first row enabling the calldata_copy selector + auto row = std::ranges::find_if( + trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_calldata_copy == FF(1); }); + + ASSERT_TRUE(row != trace.end()); + + // Memory trace view pertaining to the calldata_copy operation. + auto clk = row->main_clk; + auto mem_view = std::views::filter(trace, [clk](Row r) { + return r.mem_clk == clk && r.mem_rw == 1 && r.mem_sel_op_slice == 1 && + r.mem_tag == static_cast(AvmMemoryTag::FF); + }); + + // Check that the memory operations are as expected. + size_t count = 0; + for (auto const& mem_row : mem_view) { + EXPECT_THAT(mem_row, + AllOf(MEM_ROW_FIELD_EQ(val, (col_offset + count) * (col_offset + count)), + MEM_ROW_FIELD_EQ(addr, dst_offset + count), + MEM_ROW_FIELD_EQ(tag, static_cast(AvmMemoryTag::FF)), + MEM_ROW_FIELD_EQ(w_in_tag, static_cast(AvmMemoryTag::FF)), + MEM_ROW_FIELD_EQ(r_in_tag, static_cast(AvmMemoryTag::FF)), + MEM_ROW_FIELD_EQ(tag_err, 0))); + count++; + } + + EXPECT_EQ(count, copy_size); + + // Slice trace view pertaining to the calldata_copy operation. + auto slice_view = + std::views::filter(trace, [clk](Row r) { return r.slice_clk == clk && r.slice_sel_cd_cpy == 1; }); + + FF last_row_idx = 0; + + // Check that the slice trace is as expected. + count = 0; + for (auto const& slice_row : slice_view) { + EXPECT_THAT(slice_row, + AllOf(SLICE_ROW_FIELD_EQ(val, (col_offset + count) * (col_offset + count)), + SLICE_ROW_FIELD_EQ(addr, dst_offset + count), + SLICE_ROW_FIELD_EQ(col_offset, col_offset + count), + SLICE_ROW_FIELD_EQ(cnt, copy_size - count), + SLICE_ROW_FIELD_EQ(sel_start, static_cast(count == 0)))); + count++; + + if (count == copy_size) { + last_row_idx = slice_row.main_clk; + } + } + + // Check that the extra final row is well-formed. + EXPECT_THAT(trace.at(static_cast(last_row_idx + 1)), + AllOf(SLICE_ROW_FIELD_EQ(addr, FF(dst_offset) + FF(copy_size)), + SLICE_ROW_FIELD_EQ(col_offset, col_offset + copy_size), + SLICE_ROW_FIELD_EQ(cnt, 0), + SLICE_ROW_FIELD_EQ(clk, clk), + SLICE_ROW_FIELD_EQ(sel_cd_cpy, 0), + SLICE_ROW_FIELD_EQ(sel_start, 0))); + + if (proof_verif) { + validate_trace(std::move(trace), public_inputs, calldata, {}, true); + } else { + validate_trace(std::move(trace), public_inputs, calldata); + } + } + + VmPublicInputs public_inputs; + AvmTraceBuilder trace_builder; + std::vector calldata; + + std::vector trace; + size_t main_row_idx; + size_t alu_row_idx; + size_t mem_row_idx; +}; + +TEST_F(AvmSliceTests, simpleCopyAllCDValues) +{ + gen_single_calldata_copy(false, 12, 0, 12, 25); + validate_single_calldata_copy_trace(0, 12, 25, true); +} + +TEST_F(AvmSliceTests, singleCopyCDElement) +{ + gen_single_calldata_copy(false, 12, 5, 1, 25); + validate_single_calldata_copy_trace(5, 1, 25); +} + +TEST_F(AvmSliceTests, longCopyAllCDValues) +{ + gen_single_calldata_copy(false, 2000, 0, 2000, 873); + validate_single_calldata_copy_trace(0, 2000, 873); +} + +TEST_F(AvmSliceTests, copyFirstHalfCDValues) +{ + gen_single_calldata_copy(false, 12, 0, 6, 98127); + validate_single_calldata_copy_trace(0, 6, 98127); +} + +TEST_F(AvmSliceTests, copySecondHalfCDValues) +{ + gen_single_calldata_copy(false, 12, 6, 6, 0); + validate_single_calldata_copy_trace(6, 6, 0); +} + +TEST_F(AvmSliceTests, copyToHighestMemOffset) +{ + gen_single_calldata_copy(false, 8, 2, 6, UINT32_MAX - 5); + validate_single_calldata_copy_trace(2, 6, UINT32_MAX - 5); +} + +TEST_F(AvmSliceTests, twoCallsNoOverlap) +{ + calldata = { 2, 3, 4, 5, 6 }; + + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 2, 34); + trace_builder.op_calldata_copy(0, 3, 2, 2123); + trace_builder.op_return(0, 0, 0); + trace = trace_builder.finalize(); + + // Main trace views of rows enabling the calldata_copy selector + auto main_view = std::views::filter(trace, [](Row r) { return r.main_sel_op_calldata_copy == FF(1); }); + + std::vector main_rows; + for (auto const& row : main_view) { + main_rows.push_back(row); + } + + EXPECT_EQ(main_rows.size(), 2); + + EXPECT_THAT(main_rows.at(0), + AllOf(MAIN_ROW_FIELD_EQ(ia, 0), + MAIN_ROW_FIELD_EQ(ib, 2), + MAIN_ROW_FIELD_EQ(mem_addr_c, 34), + MAIN_ROW_FIELD_EQ(clk, 1))); + EXPECT_THAT(main_rows.at(1), + AllOf(MAIN_ROW_FIELD_EQ(ia, 3), + MAIN_ROW_FIELD_EQ(ib, 2), + MAIN_ROW_FIELD_EQ(mem_addr_c, 2123), + MAIN_ROW_FIELD_EQ(clk, 2))); + + validate_trace(std::move(trace), public_inputs, calldata); +} + +TEST_F(AvmSliceTests, indirectTwoCallsOverlap) +{ + calldata = { 2, 3, 4, 5, 6 }; + + gen_trace_builder(calldata); + trace_builder.op_set(0, 34, 100, AvmMemoryTag::U32); // indirect address 100 resolves to 34 + trace_builder.op_set(0, 2123, 101, AvmMemoryTag::U32); // indirect address 101 resolves to 2123 + trace_builder.op_calldata_copy(1, 1, 3, 100); + trace_builder.op_calldata_copy(1, 2, 3, 101); + trace_builder.op_return(0, 0, 0); + trace = trace_builder.finalize(); + + // Main trace views of rows enabling the calldata_copy selector + auto main_view = std::views::filter(trace, [](Row r) { return r.main_sel_op_calldata_copy == FF(1); }); + + std::vector main_rows; + for (auto const& row : main_view) { + main_rows.push_back(row); + } + + EXPECT_EQ(main_rows.size(), 2); + + EXPECT_THAT(main_rows.at(0), + AllOf(MAIN_ROW_FIELD_EQ(ia, 1), + MAIN_ROW_FIELD_EQ(ib, 3), + MAIN_ROW_FIELD_EQ(sel_resolve_ind_addr_c, 1), + MAIN_ROW_FIELD_EQ(ind_addr_c, 100), + MAIN_ROW_FIELD_EQ(mem_addr_c, 34), + MAIN_ROW_FIELD_EQ(clk, 3))); + EXPECT_THAT(main_rows.at(1), + AllOf(MAIN_ROW_FIELD_EQ(ia, 2), + MAIN_ROW_FIELD_EQ(ib, 3), + MAIN_ROW_FIELD_EQ(sel_resolve_ind_addr_c, 1), + MAIN_ROW_FIELD_EQ(ind_addr_c, 101), + MAIN_ROW_FIELD_EQ(mem_addr_c, 2123), + MAIN_ROW_FIELD_EQ(clk, 4))); + + validate_trace(std::move(trace), public_inputs, calldata); +} + +TEST_F(AvmSliceTests, indirectFailedResolution) +{ + calldata = { 2, 3, 4, 5, 6 }; + + gen_trace_builder(calldata); + trace_builder.op_set(0, 34, 100, AvmMemoryTag::U16); // indirect address 100 resolves to 34 + trace_builder.op_calldata_copy(1, 1, 3, 100); + trace_builder.halt(); + trace = trace_builder.finalize(); + + // Check that slice trace is empty + auto slice_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.slice_sel_cd_cpy == 1; }); + EXPECT_EQ(slice_row, trace.end()); + + auto count = std::ranges::count_if(trace.begin(), trace.end(), [](Row r) { return r.mem_sel_op_slice == 1; }); + // Check that MEM trace does not contain any entry related to calldata_copy write. + EXPECT_EQ(count, 0); + + // Find the first row enabling the calldata_copy selector + auto row = + std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_calldata_copy == FF(1); }); + + ASSERT_TRUE(row != trace.end()); + auto clk = row->main_clk; + auto mem_row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.mem_clk == clk; }); + + EXPECT_EQ(mem_row->mem_rw, 0); + EXPECT_EQ(mem_row->mem_sel_resolve_ind_addr_c, 1); + + validate_trace(std::move(trace), public_inputs, calldata); +} + +class AvmSliceNegativeTests : public AvmSliceTests {}; + +TEST_F(AvmSliceNegativeTests, wrongCDValueInSlice) +{ + gen_single_calldata_copy(false, 10, 0, 10, 0); + + trace.at(3).slice_val = 98; + + // Adapt corresponding MEM trace entry in a consistent way. + auto clk = trace.at(3).slice_clk; + auto addr = trace.at(3).slice_addr; + auto mem_row = std::ranges::find_if( + trace.begin(), trace.end(), [clk, addr](Row r) { return r.mem_clk == clk && r.mem_addr == addr; }); + mem_row->mem_val = 98; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "LOOKUP_CD_VALUE"); +} + +TEST_F(AvmSliceNegativeTests, wrongCDValueInMemory) +{ + gen_single_calldata_copy(false, 10, 0, 10, 0); + + auto clk = trace.at(5).slice_clk; + auto addr = trace.at(5).slice_addr; + auto mem_row = std::ranges::find_if( + trace.begin(), trace.end(), [clk, addr](Row r) { return r.mem_clk == clk && r.mem_addr == addr; }); + mem_row->mem_val = 98; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_SLICE_MEM"); +} + +TEST_F(AvmSliceNegativeTests, wrongCDValueInCalldataColumn) +{ + gen_single_calldata_copy(false, 10, 0, 10, 0); + + trace.at(2).main_calldata = 12; + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "LOOKUP_CD_VALUE"); +} + +TEST_F(AvmSliceNegativeTests, wrongCDValueInCalldataVerifier) +{ + calldata = { 2, 3, 4, 5, 6 }; + + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 1, 3, 100); + trace_builder.op_return(0, 0, 0); + trace = trace_builder.finalize(); + + validate_trace(std::move(trace), public_inputs, { 2, 3, 4, 5, 7 }, {}, true, true); +} + +TEST_F(AvmSliceNegativeTests, disableMemWriteEntry) +{ + gen_single_calldata_copy(false, 10, 0, 10, 0); + + // Multiple adjustements to get valid MEM trace. + trace.at(10).mem_sel_op_slice = 0; + trace.at(10).mem_skip_check_tag = 0; + trace.at(10).mem_sel_mem = 0; + trace.at(9).mem_last = 1; + trace.at(10).mem_last = 0; + trace.at(10).mem_tsp = 12; + trace.at(9).mem_sel_rng_chk = 0; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "PERM_SLICE_MEM"); +} + +} // namespace tests_avm diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp index d84f11226dec..283d08e7c3ef 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp @@ -25,19 +25,21 @@ std::vector gen_three_op_params(std::vector opera */ void validate_trace_check_circuit(std::vector&& trace) { - validate_trace(std::move(trace), {}, {}, false); + validate_trace(std::move(trace), {}, {}, {}, false); }; /** * @brief Helper routine which checks the circuit constraints and depending on - * the boolean with_proof value performs a proof generation and verification. + * the boolean with_proof value performs a proof generation and verification. * * @param trace The execution trace */ void validate_trace(std::vector&& trace, VmPublicInputs const& public_inputs, std::vector const& calldata, - bool with_proof) + std::vector const& returndata, + bool with_proof, + bool expect_proof_failure) { auto circuit_builder = AvmCircuitBuilder(); circuit_builder.set_trace(std::move(trace)); @@ -51,11 +53,15 @@ void validate_trace(std::vector&& trace, AvmVerifier verifier = composer.create_verifier(circuit_builder); std::vector> public_inputs_as_vec = - bb::avm_trace::copy_public_inputs_columns(public_inputs, calldata); + bb::avm_trace::copy_public_inputs_columns(public_inputs, calldata, returndata); bool verified = verifier.verify_proof(proof, { public_inputs_as_vec }); - EXPECT_TRUE(verified); + if (expect_proof_failure) { + EXPECT_FALSE(verified); + } else { + EXPECT_TRUE(verified); + } } }; diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp index e2c80155ada9..2a64252f9d86 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp @@ -15,6 +15,7 @@ } #define MAIN_ROW_FIELD_EQ(field_name, expression) Field(#field_name, &Row::main_##field_name, expression) +#define MEM_ROW_FIELD_EQ(field_name, expression) Field(#field_name, &Row::mem_##field_name, expression) namespace tests_avm { @@ -31,7 +32,9 @@ void validate_trace_check_circuit(std::vector&& trace); void validate_trace(std::vector&& trace, VmPublicInputs const& public_inputs = {}, std::vector const& calldata = {}, - bool with_proof = bb::avm_trace::ENABLE_PROVING); + std::vector const& returndata = {}, + bool with_proof = bb::avm_trace::ENABLE_PROVING, + bool expect_proof_failure = false); void mutate_ic_in_trace(std::vector& trace, std::function&& selectRow, FF const& newValue, From e7177ba0f96c1da3edbcdffdaaf88c128bbdd719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Rodr=C3=ADguez?= Date: Wed, 10 Jul 2024 18:44:40 +0200 Subject: [PATCH 10/32] fix: Memory init with no other ops gate counting (#7427) --- .../barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp index 7e887afea2f5..db5a32516934 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp @@ -643,7 +643,8 @@ AcirFormat circuit_serde_to_acir_format(Program::Circuit const& circuit, bool ho } else if constexpr (std::is_same_v) { auto block = handle_memory_init(arg); uint32_t block_id = arg.block_id.value; - block_id_to_block_constraint[block_id] = std::make_pair(block, std::vector()); + std::vector opcode_indices = { i }; + block_id_to_block_constraint[block_id] = std::make_pair(block, opcode_indices); } else if constexpr (std::is_same_v) { auto block = block_id_to_block_constraint.find(arg.block_id.value); if (block == block_id_to_block_constraint.end()) { From 7b8c2ba14600f4e51896bec15c6e7f3286885050 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Wed, 10 Jul 2024 14:04:56 -0300 Subject: [PATCH 11/32] chore: Disable flaky cheat code test --- yarn-project/end-to-end/src/guides/dapp_testing.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/guides/dapp_testing.test.ts b/yarn-project/end-to-end/src/guides/dapp_testing.test.ts index eca88b76dc1f..81f12ef8a8cc 100644 --- a/yarn-project/end-to-end/src/guides/dapp_testing.test.ts +++ b/yarn-project/end-to-end/src/guides/dapp_testing.test.ts @@ -124,7 +124,8 @@ describe('guides/dapp/testing', () => { cheats = CheatCodes.create(ETHEREUM_HOST, pxe); }); - it('warps time to 1h into the future', async () => { + // TODO(@spalladino) Disabled due to flakiness after #7347. Note that warp is already tested in e2e_cheat_codes. + it.skip('warps time to 1h into the future', async () => { // docs:start:warp const newTimestamp = Math.floor(Date.now() / 1000) + 60 * 60 * 24; await cheats.aztec.warp(newTimestamp); From 7870a5815dc759aed7097dc9eb5ab8e10b3a1865 Mon Sep 17 00:00:00 2001 From: Facundo Date: Wed, 10 Jul 2024 18:13:33 +0100 Subject: [PATCH 12/32] chore(bb): fix double increment (#7428) That I just introduced. --- barretenberg/cpp/src/barretenberg/common/ref_array.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/common/ref_array.hpp b/barretenberg/cpp/src/barretenberg/common/ref_array.hpp index 4939b571686e..3de5cd9bb668 100644 --- a/barretenberg/cpp/src/barretenberg/common/ref_array.hpp +++ b/barretenberg/cpp/src/barretenberg/common/ref_array.hpp @@ -25,7 +25,7 @@ template class RefArray { RefArray(const std::array& ptr_array) { for (std::size_t i = 0; i < N; ++i) { - storage[i++] = ptr_array[i]; + storage[i] = ptr_array[i]; } } template RefArray(T& ref, Ts&... rest) From f1778876eac8ef65edd06c49d1ddf2429d6583e5 Mon Sep 17 00:00:00 2001 From: ledwards2225 <98505400+ledwards2225@users.noreply.github.com> Date: Wed, 10 Jul 2024 12:38:16 -0700 Subject: [PATCH 13/32] chore: minimize usage of get_row in inverse computation (#7431) Using get_row in hot loops is known to be a bad plan since it amounts to a copy. When I implemented log derivative table lookups, I carelessly used the method in logderiv_library.hpp which computes the inverses needed in the log deriv relation. That method uses get_row in a loop over the entire execution trace which amounts to copying the entire set of prover polynomials one row at a time. A half-measure fix is to still use get_row, but only where we really need to use it (i.e. where the gate in question is active). this is what I did for the databus log-deriv lookup relation. This is still less efficient than it could be because we're copying an entire row when we only need a small subset of the data. This too could be avoided but at the cost of some icky duplication so for now I'm leaving it as is with reference to a bberg issue. Results in a ~0.5s reduction in ClientIvc bench, essentially entirely in the PG prep round (where the lookup inverses are computed): Before: `ClientIVCBench/Full/6 15131 ms 10319 ms` `ProtoGalaxyProver_::preparation_round(t) 3569 52.15%` After: `ClientIVCBench/Full/6 14582 ms 9853 ms` `ProtoGalaxyProver_::preparation_round(t) 3055 48.72%` --- .../relations/databus_lookup_relation.hpp | 1 + .../relations/logderiv_lookup_relation.hpp | 28 +++++++++++++++++++ .../stdlib_circuit_builders/mega_flavor.hpp | 2 +- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp index c0ec529cdd72..42dfd002c62a 100644 --- a/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp @@ -208,6 +208,7 @@ template class DatabusLookupRelationImpl { } // We only compute the inverse if this row contains a read gate or data that has been read if (is_read || nonzero_read_count) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/940): avoid get_row if possible. auto row = polynomials.get_row(i); // Note: this is a copy. use sparingly! inverse_polynomial[i] = compute_read_term(row, relation_parameters) * compute_write_term(row, relation_parameters); diff --git a/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp index 92078db8e856..d2cb576b575a 100644 --- a/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp @@ -134,6 +134,34 @@ template class LogDerivLookupRelationImpl { table_index * eta_three; } + /** + * @brief Construct the polynomial I whose components are the inverse of the product of the read and write terms + * @details If the denominators of log derivative lookup relation are read_term and write_term, then I_i = + * (read_term_i*write_term_i)^{-1}. + * @note Importantly, I_i = 0 for rows i at which there is no read or write, so the cost of this method is + * proportional to the actual number of lookups. + * + */ + template + static void compute_logderivative_inverse(Polynomials& polynomials, + auto& relation_parameters, + const size_t circuit_size) + { + auto& inverse_polynomial = get_inverse_polynomial(polynomials); + + for (size_t i = 0; i < circuit_size; ++i) { + // We only compute the inverse if this row contains a lookup gate or data that has been looked up + if (polynomials.q_lookup[i] == 1 || polynomials.lookup_read_tags[i] == 1) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/940): avoid get_row if possible. + auto row = polynomials.get_row(i); // Note: this is a copy. use sparingly! + inverse_polynomial[i] = compute_read_term(row, relation_parameters) * + compute_write_term(row, relation_parameters); + } + } + // Compute inverse polynomial I in place by inverting the product at each row + FF::batch_invert(inverse_polynomial); + }; + /** * @brief Log-derivative style lookup argument for conventional lookups form tables with 3 or fewer columns * @details The identity to be checked is of the form diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp index 37680a5c543d..bcaf075835ab 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp @@ -391,7 +391,7 @@ class MegaFlavor { void compute_logderivative_inverses(const RelationParameters& relation_parameters) { // Compute inverses for conventional lookups - compute_logderivative_inverse>( + LogDerivLookupRelation::compute_logderivative_inverse( this->polynomials, relation_parameters, this->circuit_size); // Compute inverses for calldata reads From 59b92ca0f72ca3705dd6933b304897c91edc81c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Wed, 10 Jul 2024 22:23:59 +0200 Subject: [PATCH 14/32] fix: using different generators in private refund (#7414) Fixes #7320 --- .../aztec-nr/aztec/src/generators.nr | 20 ++++ noir-projects/aztec-nr/aztec/src/lib.nr | 1 + .../src/types/token_note.nr | 100 +++++++++--------- 3 files changed, 73 insertions(+), 48 deletions(-) create mode 100644 noir-projects/aztec-nr/aztec/src/generators.nr diff --git a/noir-projects/aztec-nr/aztec/src/generators.nr b/noir-projects/aztec-nr/aztec/src/generators.nr new file mode 100644 index 000000000000..02eae3307fb2 --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/generators.nr @@ -0,0 +1,20 @@ +use dep::protocol_types::point::Point; + +// A set of generators generated with `derive_generators(...)` function from noir::std +global Ga1 = Point { x: 0x30426e64aee30e998c13c8ceecda3a77807dbead52bc2f3bf0eae851b4b710c1, y: 0x113156a068f603023240c96b4da5474667db3b8711c521c748212a15bc034ea6, is_infinite: false }; +global Ga2 = Point { x: 0x2825c79cc6a5cbbeef7d6a8f1b6a12b312aa338440aefeb4396148c89147c049, y: 0x129bfd1da54b7062d6b544e7e36b90736350f6fba01228c41c72099509f5701e, is_infinite: false }; +global Ga3 = Point { x: 0x0edb1e293c3ce91bfc04e3ceaa50d2c541fa9d091c72eb403efb1cfa2cb3357f, y: 0x1341d675fa030ece3113ad53ca34fd13b19b6e9762046734f414824c4d6ade35, is_infinite: false }; + +mod test { + use crate::generators::{Ga1, Ga2, Ga3}; + use dep::protocol_types::point::Point; + use std::hash::derive_generators; + + #[test] +fn test_generators() { + let generators: [Point; 3] = derive_generators("aztec_nr_generators".as_bytes(), 0); + assert_eq(generators[0], Ga1); + assert_eq(generators[1], Ga2); + assert_eq(generators[2], Ga3); + } +} diff --git a/noir-projects/aztec-nr/aztec/src/lib.nr b/noir-projects/aztec-nr/aztec/src/lib.nr index d4b1abf35e71..af7f03c1f516 100644 --- a/noir-projects/aztec-nr/aztec/src/lib.nr +++ b/noir-projects/aztec-nr/aztec/src/lib.nr @@ -1,5 +1,6 @@ mod context; mod deploy; +mod generators; mod hash; mod history; mod initializer; diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr index 30ef7add279a..99c61356e142 100644 --- a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr @@ -2,7 +2,8 @@ use dep::aztec::{ prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, point::Point, scalar::Scalar, hash::poseidon2_hash}, note::utils::compute_note_hash_for_consumption, oracle::unsafe_rand::unsafe_rand, - keys::getters::get_nsk_app, note::note_getter_options::PropertySelector + keys::getters::get_nsk_app, note::note_getter_options::PropertySelector, + generators::{Ga1 as G_amt, Ga2 as G_npk, Ga3 as G_rnd} }; use dep::std::field::bn254::decompose; use dep::std::embedded_curve_ops::multi_scalar_mul; @@ -32,8 +33,6 @@ trait PrivatelyRefundable { global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. global TOKEN_NOTE_BYTES_LEN: Field = 3 * 32 + 64; -// Grumpkin generator point. -global G1 = Point { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; #[aztec(note)] struct TokenNote { @@ -75,11 +74,11 @@ impl NoteInterface for TokenNote { fn compute_note_content_hash(self) -> Field { let (npk_lo, npk_hi) = decompose(self.npk_m_hash); let (random_lo, random_hi) = decompose(self.randomness); - // We compute the note content hash as an x-coordinate of `G ^ (amount + npk_m_hash + randomness)` instead + // We compute the note content hash as an x-coordinate of `G_amt * amount + G_npk * npk_m_hash + G_rnd * randomness` instead // of using pedersen or poseidon2 because it allows us to privately add and subtract from amount in public // by leveraging homomorphism. multi_scalar_mul( - [G1, G1, G1], + [G_amt, G_npk, G_rnd], [Scalar { lo: self.amount.to_integer(), hi: 0 @@ -126,56 +125,58 @@ impl OwnedNote for TokenNote { * these are going to be eventually turned into notes: * one for the user, and one for the fee payer. * - * So you can think of these (x,y) points as "partial notes": they encode part of the internals of the notes. + * So you can think of these (x, y) points as "partial notes": they encode part of the internals of the notes. * * This is because the compute_note_content_hash function above defines the content hash to be * the x-coordinate of a point defined as: * - * amount * G + npk * G + randomness * G - * = (amount + npk + randomness) * G + * G_amt * amount + G_npk * npk_m_hash + G_rnd * randomness * - * where G is a generator point. Interesting point here is that we actually need to convert + * where G_amt, G_npk and G_rnd are generator points. Interesting point here is that we actually need to convert * - amount - * - npk + * - npk_m_hash * - randomness * from grumpkin Field elements * (which have a modulus of 21888242871839275222246405745257275088548364400416034343698204186575808495617) * into a grumpkin scalar * (which have a modulus of 21888242871839275222246405745257275088696311157297823662689037894645226208583) * - * The intuition for this is that the Field elements define the domain of the x,y coordinates for points on the curves, - * but the number of points on the curve is actually greater than the size of that domain. + * The intuition for this is that the Field elements define the domain of the x, y coordinates for points on + * the curves, but the number of points on the curve is actually greater than the size of that domain. * - * (Consider, e.g. if the curve were defined over a field of 10 elements, and each x coord had two corresponding y for +/-) + * (Consider, e.g. if the curve were defined over a field of 10 elements, and each x coord had two corresponding + * y for +/-) * * For a bit more info, see * https://hackmd.io/@aztec-network/ByzgNxBfd#2-Grumpkin---A-curve-on-top-of-BN-254-for-SNARK-efficient-group-operations * * - * Anyway, if we have a secret scalar n := amount + npk + randomness, and then we reveal a point n * G, there is no efficient way to - * deduce what n is. This is the discrete log problem. + * Anyway, if we have a secret scalar s, and then we reveal a point s * G (G being a generator), there is no efficient + * way to deduce what s is. This is the discrete log problem. * * However we can still perform addition/subtraction on points! That is why we generate those two points, which are: - * incomplete_fee_payer_point := (fee_payer_npk + fee_payer_randomness) * G - * incomplete_user_point := (user_npk + funded_amount + user_randomness) * G + * incomplete_fee_payer_point := G_npk * fee_payer_npk + G_amt * fee_payer_randomness + * incomplete_user_point := G_npk * user_npk + G_amt * funded_amount + G_rnd * user_randomness * - * where `funded_amount` is the total amount in tokens that the sponsored user initially supplied, from which the transaction fee will be subtracted. + * where `funded_amount` is the total amount in tokens that the sponsored user initially supplied, from which + * the transaction fee will be subtracted. * - * So we pass those points into the teardown function (here) and compute a third point corresponding to the transaction fee as just + * So we pass those points into the teardown function (here) and compute a third point corresponding to the transaction + * fee as just: * - * fee_point := transaction_fee * G + * fee_point := G_amt * transaction_fee * * Then we arrive at the final points via addition/subtraction of that transaction fee point: * - * fee_payer_point := incomplete_fee_payer_point + fee_point - * = (fee_payer_npk + fee_payer_randomness) * G + transaction_fee * G - * = (fee_payer_npk + fee_payer_randomness + transaction_fee) * G + * fee_payer_point := incomplete_fee_payer_point + fee_point = + * = (G_npk * fee_payer_npk + G_rnd * fee_payer_randomness) + G_amt * transaction_fee = + * = G_amt * transaction_fee + G_npk * fee_payer_npk + G_rnd * fee_payer_randomness * - * user_point := incomplete_user_point - fee_point - * = (user_npk + funded_amount + user_randomness) * G - transaction_fee * G - * = (user_npk + user_randomness + (funded_amount - transaction_fee)) * G + * user_point := incomplete_user_point - fee_point = + * = (G_amt * funded_amount + G_npk * user_npk + G_rnd + user_randomness) - G_amt * transaction_fee = + * = G_amt * (funded_amount - transaction_fee) + G_npk * user_npk + G_rnd + user_randomness * - * When we return the x-coordinate of those points, it identically matches the note_content_hash of (and therefore *is*) notes like: + * The x-coordinate of points above identically matches the note_content_hash of (and therefore *is*) notes like: * { * amount: (funded_amount - transaction_fee), * npk_m_hash: user_npk, @@ -184,26 +185,29 @@ impl OwnedNote for TokenNote { * * Why do we need different randomness for the user and the fee payer notes? * --> This is because if the randomness values were the same we could fingerprint the user by doing the following: - * 1) randomness_influence = incomplete_fee_payer_point - G * fee_payer_npk = - * = (fee_payer_npk + randomness) * G - G * fee_payer_npk = randomness * G - * 2) user_fingerprint = incomplete_user_point - G * funded_amount - randomness_influence = - * = (user_npk + funded_amount + randomness) * G - funded_amount * G - randomness * G = - * = user_npk * G + * 1) randomness_influence = incomplete_fee_payer_point - G_npk * fee_payer_npk = + * = (G_npk * fee_payer_npk + G_rnd * randomness) - G_npk * fee_payer_npk = + * = G_rnd * randomness + * 2) user_fingerprint = incomplete_user_point - G_amt * funded_amount - randomness_influence = + * = (G_npk * user_npk + G_amt * funded_amount + G_rnd * randomness) - G_amt * funded_amount + * - G_rnd * randomness = + * = G_npk * user_npk * 3) Then the second time the user would use this fee paying contract we would recover the same fingerprint and * link that the 2 transactions were made by the same user. Given that it's expected that only a limited set - * of fee paying contracts will be used and they will be known searching for fingerprints by trying different + * of fee paying contracts will be used and they will be known, searching for fingerprints by trying different * fee payer npk values of these known contracts is a feasible attack. */ impl PrivatelyRefundable for TokenNote { fn generate_refund_points(fee_payer_npk_m_hash: Field, user_npk_m_hash: Field, funded_amount: Field, user_randomness: Field, fee_payer_randomness: Field) -> (Point, Point) { - // 1. To be able to multiply generators with randomness and npk_m_hash using barretneberg's (BB) blackbox function we - // first need to convert the fields to high and low limbs. + // 1. To be able to multiply generators with randomness and npk_m_hash using barretneberg's (BB) blackbox + // function we first need to convert the fields to high and low limbs. let (fee_payer_randomness_lo, fee_payer_randomness_hi) = decompose(fee_payer_randomness); let (fee_payer_npk_m_hash_lo, fee_payer_npk_m_hash_hi) = decompose(fee_payer_npk_m_hash); - // 2. Now that we have correct representationsn of fee payer and randomness we can compute `G ^ (fee_payer_npk + randomness)` + // 2. Now that we have correct representationsn of fee payer and randomness we can compute + // `G_npk * fee_payer_npk + G_rnd * randomness`. let incomplete_fee_payer_point = multi_scalar_mul( - [G1, G1], + [G_npk, G_rnd], [Scalar { lo: fee_payer_npk_m_hash_lo, hi: fee_payer_npk_m_hash_hi @@ -216,28 +220,28 @@ impl PrivatelyRefundable for TokenNote { // 3. We do the necessary conversion for values relevant for the sponsored user point. let (user_randomness_lo, user_randomness_hi) = decompose(user_randomness); - // TODO(#7324): representing user with their npk_m_hash here does not work with key rotation - let (user_lo, user_hi) = decompose(user_npk_m_hash); + // TODO(#7324), TODO(#7323): using npk_m_hash here is vulnerable in 2 ways described in the linked issues. + let (user_npk_lo, user_npk_hi) = decompose(user_npk_m_hash); let (funded_amount_lo, funded_amount_hi) = decompose(funded_amount); - // 4. We compute `G ^ (user_npk_m_hash + funded_amount + randomness)` + // 4. We compute `G_amt * funded_amount + G_npk * user_npk_m_hash + G_rnd * randomness`. let incomplete_user_point = multi_scalar_mul( - [G1, G1, G1], + [G_amt, G_npk, G_rnd], [Scalar { - lo: user_lo, - hi: user_hi - }, - Scalar { lo: funded_amount_lo, hi: funded_amount_hi }, + Scalar { + lo: user_npk_lo, + hi: user_npk_hi + }, Scalar { lo: user_randomness_lo, hi: user_randomness_hi }] ); - // 5. At last we represent the points as Points and return them. + // 5. At last we return the points. (incomplete_fee_payer_point, incomplete_user_point) } @@ -245,9 +249,9 @@ impl PrivatelyRefundable for TokenNote { // 1. We convert the transaction fee to high and low limbs to be able to use BB API. let (transaction_fee_lo, transaction_fee_hi) = decompose(transaction_fee); - // 2. We compute the fee point as `G ^ transaction_fee` + // 2. We compute the fee point as `G_amt * transaction_fee` let fee_point = multi_scalar_mul( - [G1], + [G_amt], [Scalar { lo: transaction_fee_lo, hi: transaction_fee_hi, From a6a605d3cd83b2f4b8e47722ff262382a7a2ea1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Thu, 11 Jul 2024 00:01:00 +0200 Subject: [PATCH 15/32] chore(boxes): adding an init command for an empty project (#7398) Quick PR to add a `npx aztec-app init` command that provides a `nargo new`-like feature. This will be used in tutorials and specially in the EthCC workshop. --------- Co-authored-by: josh crites --- .devcontainer/sandbox_only/devcontainer.json | 18 ++ .devcontainer/scripts/onCreateCommand.sh | 21 ++- .devcontainer/scripts/postAttachCommand.sh | 3 +- boxes/README.md | 22 ++- boxes/bin.js | 169 +++++++++---------- boxes/init/.yarnrc.yml | 1 + boxes/init/Nargo.toml | 6 + boxes/init/package.json | 9 + boxes/init/src/main.nr | 6 + boxes/package.json | 4 +- boxes/scripts/init.js | 19 +++ boxes/scripts/steps/sandbox/run.js | 13 +- boxes/scripts/utils.js | 3 +- boxes/yarn.lock | 60 +++---- docs/docs/getting_started.md | 67 +++++++- docs/docs/getting_started/manual_install.md | 77 --------- 16 files changed, 269 insertions(+), 229 deletions(-) create mode 100644 .devcontainer/sandbox_only/devcontainer.json create mode 100644 boxes/init/.yarnrc.yml create mode 100644 boxes/init/Nargo.toml create mode 100644 boxes/init/package.json create mode 100644 boxes/init/src/main.nr create mode 100644 boxes/scripts/init.js delete mode 100644 docs/docs/getting_started/manual_install.md diff --git a/.devcontainer/sandbox_only/devcontainer.json b/.devcontainer/sandbox_only/devcontainer.json new file mode 100644 index 000000000000..eafead0351d9 --- /dev/null +++ b/.devcontainer/sandbox_only/devcontainer.json @@ -0,0 +1,18 @@ +{ + "name": "Sandbox Only", + "image": "node:lts-bookworm", + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": {} + }, + "onCreateCommand": "cp -R /root/workspace /root/scripts && rm -rf /root/workspace/* && sh /root/scripts/onCreateCommand.sh sandbox_only", + "postAttachCommand": "sh /root/scripts/postAttachCommand.sh", + "customizations": { + "vscode": { + "settings": {}, + "extensions": ["noir-lang.vscode-noir"] + } + }, + "workspaceMount": "source=${localWorkspaceFolder}/.devcontainer/scripts,target=/root/workspace,type=bind", + "workspaceFolder": "/root/workspace", + "forwardPorts": [8080] +} diff --git a/.devcontainer/scripts/onCreateCommand.sh b/.devcontainer/scripts/onCreateCommand.sh index c0970999305b..f90491c9bd08 100755 --- a/.devcontainer/scripts/onCreateCommand.sh +++ b/.devcontainer/scripts/onCreateCommand.sh @@ -13,14 +13,17 @@ fi if ! grep -q "alias sandbox" ~/.bashrc; then echo "alias sandbox=\"npx aztec-app sandbox\"" >> ~/.bashrc fi +corepack enable -source ~/.bashrc -yes | npx aztec-app -t $TYPE -n $NAME -s -mv $NAME/* $NAME/.* . -rm -rf $NAME +if [ "$TYPE" != "sandbox_only" ]; then + source ~/.bashrc + yes | npx create-aztec-app -t $TYPE -n $NAME -s + mv $NAME/* $NAME/.* . + rm -rf $NAME + + yarn -yarn - -npx -y playwright install --with-deps -yarn add @aztec/builder -yarn prep + npx -y playwright install --with-deps + yarn add @aztec/builder + yarn prep +fi diff --git a/.devcontainer/scripts/postAttachCommand.sh b/.devcontainer/scripts/postAttachCommand.sh index 9eeff69f3502..06eb743d1064 100755 --- a/.devcontainer/scripts/postAttachCommand.sh +++ b/.devcontainer/scripts/postAttachCommand.sh @@ -1,7 +1,6 @@ #!/usr/bin/env bash -TYPE=$1 -NAME=$2 +apt update apt install gh gh codespace ports visibility 8080:public -c $CODESPACE_NAME diff --git a/boxes/README.md b/boxes/README.md index f7adc35ecb10..f75bbb5c08ac 100644 --- a/boxes/README.md +++ b/boxes/README.md @@ -1,4 +1,24 @@ -# Aztec Boxes +# Aztec-App + +Aztec-App is a set of tools to ease development on Aztec. It consists of two main components: +1. `npx` script +2. boxes (starter kits) +## npx script + +NPX is a tool bundled with `npm` and other package managers. It allows you to run a binary from a cache without installing it globally. + +To ease the development process, Aztec has developed this binary. To run it, install Node and run: + +```bash +npx aztec-app +``` + +This will prompt you with some options to clone `Aztec Boxes` and install the sandbox. As the `npx` script evolves, other commands will be added or removed. You can run it with the `-h` flag to know what other commands and flags you can pass to it. + +> [!NOTE] +> As a tool that doesn't (yet) have automated testing, it versioning and release process is decoupled from `aztec`, and its deployment is entirely manual by running `yarn npm publish --access public`. + +## Aztec Boxes Aztec Boxes are the one-stop-shop for developing on Aztec. They often include a combination of: diff --git a/boxes/bin.js b/boxes/bin.js index 75a26d2b3565..cd160479d055 100755 --- a/boxes/bin.js +++ b/boxes/bin.js @@ -1,23 +1,15 @@ #!/usr/bin/env node -import { Command, Option } from "commander"; +import { Command } from "commander"; const program = new Command(); import { chooseProject } from "./scripts/steps/chooseBox.js"; -import { - install, - update, - sandboxInstallOrUpdate, -} from "./scripts/steps/sandbox/install.js"; +import { sandboxInstallOrUpdate } from "./scripts/steps/sandbox/install.js"; import axios from "axios"; import pino from "pino"; import pretty from "pino-pretty"; import ora from "ora"; import { AZTEC_REPO } from "./scripts/config.js"; -import { - start, - stop, - log, - sandboxRunStep, -} from "./scripts/steps/sandbox/run.js"; +import { sandboxRunStep } from "./scripts/steps/sandbox/run.js"; +import { init } from "./scripts/init.js"; const getLatestStable = async () => { const { data } = await axios.get( @@ -26,86 +18,88 @@ const getLatestStable = async () => { return data[0].tag_name.split("-v")[1]; }; -const init = async ({ debug, github_token, version }) => { - const axiosOpts = { - timeout: 5000, - headers: github_token ? { Authorization: `token ${github_token}` } : {}, - }; - - const prettyOpts = { - sync: true, - colorize: true, - include: debug ? "time" : "", - customLevels: "success:80", - customColors: "success:bgGreen", - }; - - const prettyStream = pretty(prettyOpts); - const logger = pino( - { - customLevels: { - success: 80, +program + .option("-v, --version ", "a version number or master tag") + .option("-d, --debug", "output extra debugging") + .option("-gh, --github_token ", "a github token") + .hook("preSubcommand", async (thisCommand) => { + const { debug, github_token, version } = thisCommand.opts(); + const axiosOpts = { + timeout: 5000, + headers: github_token ? { Authorization: `token ${github_token}` } : {}, + }; + + const prettyOpts = { + sync: true, + colorize: true, + include: debug ? "time" : "", + customLevels: "success:80", + customColors: "success:bgGreen", + }; + + const prettyStream = pretty(prettyOpts); + const logger = pino( + { + customLevels: { + success: 80, + }, + level: debug ? "debug" : "info", }, - level: debug ? "debug" : "info", - }, - prettyStream, - ); - - global.debug = (msg) => logger.debug(msg); - global.info = (msg) => logger.info(msg); - global.success = (msg) => logger.success(msg); - - global.warn = (msg) => logger.warn(msg); - global.error = (msg) => logger.error(msg); - - global.github = async ({ path, raw = false }) => { - try { - const url = raw - ? `https://raw.githubusercontent.com/${AZTEC_REPO}/${path}` - : `https://api.github.com/repos/${AZTEC_REPO}/contents/${path}`; - const { data } = await axios.get(url, axiosOpts); - global.debug(data); - return data; - } catch (e) { - global.error(e); - } - }; - - // versioning is confusing here because "latest" and "master" point to the same thing at times - // so let's clarify a bit: - // - // if the user has set a version (ex. "master" or "0.23.0"), use that - // otherwise use the stable release (ex. 0.24.0) - global.latestStable = await getLatestStable(); - global.version = version || global.latestStable; - - // if the user has set a semver version (matches the regex), fetch that tag (i.e. aztec-packages-v0.23.0) - // otherwise use the version as the tag - global.tag = global.version.match(/^\d+\.\d+\.\d+$/) - ? `aztec-packages-v${global.version}` - : global.version; - - global.debug(`Version: ${global.version}`); - global.debug(`Tag: ${global.tag}`); - global.debug(`LatestStable: ${global.latestStable}`); - - global.spinner = ora({ color: "blue" }); -}; + prettyStream, + ); + + global.debug = (msg) => logger.debug(msg); + global.info = (msg) => logger.info(msg); + global.success = (msg) => logger.success(msg); + + global.warn = (msg) => logger.warn(msg); + global.error = (msg) => logger.error(msg); + + global.github = async ({ path, raw = false }) => { + try { + const url = raw + ? `https://raw.githubusercontent.com/${AZTEC_REPO}/${path}` + : `https://api.github.com/repos/${AZTEC_REPO}/contents/${path}`; + const { data } = await axios.get(url, axiosOpts); + global.debug(data); + return data; + } catch (e) { + global.error(e); + } + }; + + // versioning is confusing here because "latest" and "master" point to the same thing at times + // so let's clarify a bit: + // + // if the user has set a version (ex. "master" or "0.23.0"), use that + // otherwise use the stable release (ex. 0.24.0) + global.latestStable = await getLatestStable(); + global.version = version || global.latestStable; + + // if the user has set a semver version (matches the regex), fetch that tag (i.e. aztec-packages-v0.23.0) + // otherwise use the version as the tag + global.tag = global.version.match(/^\d+\.\d+\.\d+$/) + ? `aztec-packages-v${global.version}` + : global.version; + + global.debug(`Version: ${global.version}`); + global.debug(`Tag: ${global.tag}`); + global.debug(`LatestStable: ${global.latestStable}`); + + global.spinner = ora({ color: "blue" }); + }); -const sandbox = program.command("sandbox"); -sandbox.description("Manage the Aztec Sandbox"); -sandbox.command("start").action(start); -sandbox.command("logs").action(log); -sandbox.command("stop").action(stop); -sandbox.command("install").action(install); -sandbox.command("update").action(update); +program + .command("init") + .description("Bootstrap an empty Aztec contract") + .argument("[folder]", "optional folder to init your project into", ".") + .action(async (folder) => { + await init(folder); + }); program .command("new", { isDefault: true }) .description("An Aztec project with a built-in development network") - .option("-d, --debug", "output extra debugging") - .option("-gh, --github_token ", "a github token") - .option("-v, --version ", "a version number or master tag") .option( "-s, --skip-sandbox", "skip sandbox installation and run after cloning", @@ -128,8 +122,7 @@ program } const { projectType, projectName, skipSandbox } = options; - // SETUP: Initialize global variables - await init(options); + // // STEP 1: Choose the boilerplate await chooseProject({ projectType, projectName }); diff --git a/boxes/init/.yarnrc.yml b/boxes/init/.yarnrc.yml new file mode 100644 index 000000000000..3186f3f0795a --- /dev/null +++ b/boxes/init/.yarnrc.yml @@ -0,0 +1 @@ +nodeLinker: node-modules diff --git a/boxes/init/Nargo.toml b/boxes/init/Nargo.toml new file mode 100644 index 000000000000..14bcaec85ac4 --- /dev/null +++ b/boxes/init/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "init" +type = "contract" + +[dependencies] +aztec = { path = "../../noir-projects/aztec-nr/aztec" } diff --git a/boxes/init/package.json b/boxes/init/package.json new file mode 100644 index 000000000000..12bd80ead441 --- /dev/null +++ b/boxes/init/package.json @@ -0,0 +1,9 @@ +{ + "packageManager": "yarn@4.2.2", + "type": "module", + "dependencies": { + "@aztec/accounts": "latest", + "@aztec/aztec.js": "latest", + "@aztec/builder": "latest" + } +} diff --git a/boxes/init/src/main.nr b/boxes/init/src/main.nr new file mode 100644 index 000000000000..8e06a99f11ce --- /dev/null +++ b/boxes/init/src/main.nr @@ -0,0 +1,6 @@ + +contract Main { + #[aztec(private)] + #[aztec(initializer)] + fn constructor() { } +} diff --git a/boxes/package.json b/boxes/package.json index ad941bc6c07d..726903809070 100644 --- a/boxes/package.json +++ b/boxes/package.json @@ -1,7 +1,7 @@ { - "name": "create-aztec-app", + "name": "aztec-app", "packageManager": "yarn@4.0.2", - "version": "0.4.4", + "version": "0.4.9", "type": "module", "scripts": { "compile": "yarn workspaces foreach -A -v run compile", diff --git a/boxes/scripts/init.js b/boxes/scripts/init.js new file mode 100644 index 000000000000..ad122b90a272 --- /dev/null +++ b/boxes/scripts/init.js @@ -0,0 +1,19 @@ +import { replacePaths } from "./utils.js"; +import { AZTEC_REPO } from "./config.js"; +import tiged from "tiged"; + +export async function init(folder) { + const emitter = tiged(`${AZTEC_REPO}/boxes/init${tag && `#${tag}`}`, { + verbose: true, + }); + emitter.on("info", ({ message }) => debug(message)); + emitter.on("warn", ({ message }) => error(message)); + await emitter.clone(`${folder}`); + + await replacePaths({ + rootDir: `${folder}`, + tag, + version, + prefix: "", + }); +} diff --git a/boxes/scripts/steps/sandbox/run.js b/boxes/scripts/steps/sandbox/run.js index 65206dd785a9..eb6d00bf7c2e 100644 --- a/boxes/scripts/steps/sandbox/run.js +++ b/boxes/scripts/steps/sandbox/run.js @@ -1,17 +1,6 @@ import confirm from "@inquirer/confirm"; -import { execSync } from "child_process"; import axios from "axios"; -const sandbox = (command) => - execSync( - `docker compose -f $HOME/.aztec/docker-compose.yml -p sandbox ${command}`, - { stdio: "inherit" } - ); - -export const start = () => sandbox("up -d"); -export const stop = () => sandbox("down"); -export const log = () => sandbox("logs -f"); - export async function sandboxRunStep() { spinner.text = "Trying to reach the sandbox..."; @@ -29,7 +18,7 @@ export async function sandboxRunStep() { Accept: "*/*", "Content-Type": "application/json", }, - } + }, ); spinner.succeed(); success("The Sandbox is already running!"); diff --git a/boxes/scripts/utils.js b/boxes/scripts/utils.js index e29511266b04..e5aa33f7a714 100644 --- a/boxes/scripts/utils.js +++ b/boxes/scripts/utils.js @@ -199,7 +199,7 @@ export async function replacePaths({ rootDir, prefix = "" }) { replaces.push( new Promise(async (resolve, reject) => { let content = parse(await fs.readFile(filePath, "utf8")); - + if (!content.dependencies) return; Object.keys(content.dependencies).forEach((dep) => { const directory = content.dependencies[dep].path.replace( /^(..\/)+/, @@ -224,6 +224,7 @@ export async function replacePaths({ rootDir, prefix = "" }) { replaces.push( new Promise(async (resolve, reject) => { let content = JSON.parse(await fs.readFile(filePath, "utf8")); + if (!content.dependencies) return; Object.keys(content.dependencies) .filter((deps) => deps.match("@aztec")) // "master" actually means "latest" for the npm release diff --git a/boxes/yarn.lock b/boxes/yarn.lock index 526dda9a34fe..5a2e5e285d1b 100644 --- a/boxes/yarn.lock +++ b/boxes/yarn.lock @@ -15,15 +15,15 @@ __metadata: languageName: node linkType: hard -"@aztec/accounts@link:../yarn-project/accounts::locator=create-aztec-app%40workspace%3A.": +"@aztec/accounts@link:../yarn-project/accounts::locator=aztec-app%40workspace%3A.": version: 0.0.0-use.local - resolution: "@aztec/accounts@link:../yarn-project/accounts::locator=create-aztec-app%40workspace%3A." + resolution: "@aztec/accounts@link:../yarn-project/accounts::locator=aztec-app%40workspace%3A." languageName: node linkType: soft -"@aztec/aztec.js@link:../yarn-project/aztec.js::locator=create-aztec-app%40workspace%3A.": +"@aztec/aztec.js@link:../yarn-project/aztec.js::locator=aztec-app%40workspace%3A.": version: 0.0.0-use.local - resolution: "@aztec/aztec.js@link:../yarn-project/aztec.js::locator=create-aztec-app%40workspace%3A." + resolution: "@aztec/aztec.js@link:../yarn-project/aztec.js::locator=aztec-app%40workspace%3A." languageName: node linkType: soft @@ -51,15 +51,15 @@ __metadata: languageName: node linkType: hard -"@aztec/circuits.js@link:../yarn-project/circuits.js::locator=create-aztec-app%40workspace%3A.": +"@aztec/circuits.js@link:../yarn-project/circuits.js::locator=aztec-app%40workspace%3A.": version: 0.0.0-use.local - resolution: "@aztec/circuits.js@link:../yarn-project/circuits.js::locator=create-aztec-app%40workspace%3A." + resolution: "@aztec/circuits.js@link:../yarn-project/circuits.js::locator=aztec-app%40workspace%3A." languageName: node linkType: soft -"@aztec/foundation@link:../yarn-project/foundation::locator=create-aztec-app%40workspace%3A.": +"@aztec/foundation@link:../yarn-project/foundation::locator=aztec-app%40workspace%3A.": version: 0.0.0-use.local - resolution: "@aztec/foundation@link:../yarn-project/foundation::locator=create-aztec-app%40workspace%3A." + resolution: "@aztec/foundation@link:../yarn-project/foundation::locator=aztec-app%40workspace%3A." languageName: node linkType: soft @@ -113,9 +113,9 @@ __metadata: languageName: unknown linkType: soft -"@aztec/types@link:../yarn-project/types::locator=create-aztec-app%40workspace%3A.": +"@aztec/types@link:../yarn-project/types::locator=aztec-app%40workspace%3A.": version: 0.0.0-use.local - resolution: "@aztec/types@link:../yarn-project/types::locator=create-aztec-app%40workspace%3A." + resolution: "@aztec/types@link:../yarn-project/types::locator=aztec-app%40workspace%3A." languageName: node linkType: soft @@ -2353,6 +2353,26 @@ __metadata: languageName: node linkType: hard +"aztec-app@workspace:.": + version: 0.0.0-use.local + resolution: "aztec-app@workspace:." + dependencies: + "@iarna/toml": "npm:^2.2.5" + "@inquirer/confirm": "npm:^3.0.0" + "@inquirer/input": "npm:^2.0.0" + "@inquirer/select": "npm:^2.0.0" + "@playwright/test": "npm:1.42.0" + axios: "npm:^1.6.7" + commander: "npm:^12.0.0" + ora: "npm:^8.0.1" + pino: "npm:^8.19.0" + pino-pretty: "npm:^10.3.1" + tiged: "npm:^2.12.6" + bin: + aztec-app: bin.js + languageName: unknown + linkType: soft + "babel-jest@npm:^29.7.0": version: 29.7.0 resolution: "babel-jest@npm:29.7.0" @@ -3096,26 +3116,6 @@ __metadata: languageName: node linkType: hard -"create-aztec-app@workspace:.": - version: 0.0.0-use.local - resolution: "create-aztec-app@workspace:." - dependencies: - "@iarna/toml": "npm:^2.2.5" - "@inquirer/confirm": "npm:^3.0.0" - "@inquirer/input": "npm:^2.0.0" - "@inquirer/select": "npm:^2.0.0" - "@playwright/test": "npm:1.42.0" - axios: "npm:^1.6.7" - commander: "npm:^12.0.0" - ora: "npm:^8.0.1" - pino: "npm:^8.19.0" - pino-pretty: "npm:^10.3.1" - tiged: "npm:^2.12.6" - bin: - create-aztec-app: bin.js - languageName: unknown - linkType: soft - "create-jest@npm:^29.7.0": version: 29.7.0 resolution: "create-jest@npm:29.7.0" diff --git a/docs/docs/getting_started.md b/docs/docs/getting_started.md index 9b78a80b8e17..1d1fa22519e1 100644 --- a/docs/docs/getting_started.md +++ b/docs/docs/getting_started.md @@ -2,24 +2,77 @@ title: Quickstart --- -The easiest way to start developing on Aztec locally is through `npx aztec-app`. This is a convenient way of installing the development environment (A.K.A. Sandbox) and starting new projects from a boilerplate. +You can get started with an Aztec development environment (A.K.A. Sandbox) in less than 5 minutes. -To locally install the Sandbox without other tools, see [here](./getting_started/manual_install.md). +The Sandbox is an Aztec network running fully on your machine, and interacting with a development Ethereum node. You can develop and deploy on it just like on a testnet or mainnet. -## Prerequisites +### Prerequisites + +You need two global dependencies in your machine: - Node.js >= v18 (recommend installing with [nvm](https://github.com/nvm-sh/nvm)) - Docker (visit [this page of the Docker docs](https://docs.docker.com/get-docker/) on how to install it) -### Run the `npx` script +### Install the sandbox + +Run: + +```bash +bash -i <(curl -s install.aztec.network) +``` + +This will install the following tools: + +- **aztec** - launches various infrastructure subsystems (sequencer, prover, pxe, etc). +- **aztec-nargo** - aztec's build of nargo, the noir compiler toolchain. +- **aztec-sandbox** - a wrapper around docker-compose that launches services needed for sandbox testing. +- **aztec-up** - a tool to upgrade the aztec toolchain to the latest, or specific versions. +- **aztec-builder** - A useful tool for projects to generate ABIs and update their dependencies. + +Once these have been installed, to start the sandbox, run: + +```bash +aztec-sandbox +``` + +### Have fun + +**Congratulations, you have just installed and run the Aztec Sandbox!** + +```bash + /\ | | + / \ ___| |_ ___ ___ + / /\ \ |_ / __/ _ \/ __| + / ____ \ / /| || __/ (__ + /_/___ \_\/___|\__\___|\___| + +``` + +In the terminal, you will see some logs: + +1. Sandbox version +2. Contract addresses of rollup contracts +3. PXE (private execution environment) setup logs +4. Initial accounts that are shipped with the sandbox and can be used in tests + +## Running Aztec PXE / Node / P2P-Bootstrap node + +If you wish to run components of the Aztec network stack separately, you can use the `aztec start` command with various options for enabling components. + +```bash +aztec start --node [nodeOptions] --pxe [pxeOptions] --archiver [archiverOptions] --sequencer [sequencerOptions] --prover [proverOptions] ----p2p-bootstrap [p2pOptions] +``` + +Starting the aztec node alongside a PXE, sequencer or archiver, will attach the components to the node.Eg if you want to run a PXE separately to a node, you can [read this guide](./aztec/concepts/pxe/index.md)/ + +## Update the sandbox -Thanks to Node, you can run the recommended `npx script`: +To update the sandbox, you can just run: ```bash -npx aztec-app +aztec-up ``` -This script gives you some options to bootstrap a new project, start/stop the sandbox, or see the logs. Run `npx aztec-app -h` for a list of options. ## Install Noir LSP (recommended) diff --git a/docs/docs/getting_started/manual_install.md b/docs/docs/getting_started/manual_install.md deleted file mode 100644 index a5e3f3ad93b2..000000000000 --- a/docs/docs/getting_started/manual_install.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: Manual install -sidebar_position: 1 ---- - -You can have some more control over the sandbox by installing it manually through the underlying script used by [`npx aztec-app`](../getting_started.md). - -This involves some knowledge on Docker if you want to stop, restart, or detach from logs. But it also gives you better control over things such as environment variables. - -### Prerequisites - -- Node.js >= v18 (recommend installing with [nvm](https://github.com/nvm-sh/nvm)) -- Docker (visit [this page of the Docker docs](https://docs.docker.com/get-docker/) on how to install it) - -### Install the sandbox - -To install the latest Sandbox version, run: - -```bash -bash -i <(curl -s install.aztec.network) -``` - -This will install the following tools: - -- **aztec** - launches various infrastructure subsystems (sequencer, prover, pxe, etc). -- **aztec-nargo** - aztec's build of nargo, the noir compiler toolchain. -- **aztec-sandbox** - a wrapper around docker-compose that launches services needed for sandbox testing. -- **aztec-up** - a tool to upgrade the aztec toolchain to the latest, or specific versions. -- **aztec-builder** - A useful tool for projects to generate ABIs and update their dependencies. - -Once these have been installed, to start the sandbox, run: - -```bash -aztec-sandbox -``` - -### Have fun - -**Congratulations, you have just installed and run the Aztec Sandbox!** - -```bash - /\ | | - / \ ___| |_ ___ ___ - / /\ \ |_ / __/ _ \/ __| - / ____ \ / /| || __/ (__ - /_/___ \_\/___|\__\___|\___| - -``` - -In the terminal, you will see some logs: - -1. Sandbox version -2. Contract addresses of rollup contracts -3. PXE (private execution environment) setup logs -4. Initial accounts that are shipped with the sandbox and can be used in tests - -## Running Aztec PXE / Node / P2P-Bootstrap node - -If you wish to run components of the Aztec network stack separately, you can use the `aztec start` command with various options for enabling components. - -```bash -aztec start --node [nodeOptions] --pxe [pxeOptions] --archiver [archiverOptions] --sequencer [sequencerOptions] --prover [proverOptions] ----p2p-bootstrap [p2pOptions] -``` - -Starting the aztec node alongside a PXE, sequencer or archiver, will attach the components to the node.Eg if you want to run a PXE separately to a node, you can [read this guide](../aztec/concepts/pxe/index.md)/ - -## Update the sandbox - -To update the sandbox, you can just run: - -```bash -aztec-up -``` - -## Next steps - -Visit the [sandbox reference](../reference/sandbox_reference/index.md) for more info on which environment variables you can set, which cheat codes you can use, and learn about what exactly is the Aztec Sandbox. From 723a0c10c9010f3869f103c77f71950efbf7106c Mon Sep 17 00:00:00 2001 From: ludamad Date: Wed, 10 Jul 2024 20:01:46 -0400 Subject: [PATCH 16/32] feat: Integrate new proving systems in e2e (#6971) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **THE AWESOME:** PXE uses ClientIVC. Public kernels, rollup, and parity circuits use vanilla recursion-based IVC using UltraHonk. 🎉 Linear time proofs without FFTs, better constraint counts for poseidon (eventually) and no recursion in the private kernel circuits **THE CAVEATS:** This merges with many TODOs to reinstate functionality, improve security and performance. - If you are lead to believe honk proofs are constant-sized, you have been fed lies We are rounding up to a proof size that allows 2**28 gates. Please take effort to NOT rely on this assumption, as it is just a stop-gap. It is OK to temporarily rely on this to simplify kernel development in particular, but we should not hard-code this assumption into e.g. typescript in the future - Things are a bit slower now, not faster We prioritized correctness and any slowdowns will be investigated soon. Some of it comes from the larger constant size proof. As well, we will soon be able to drop constraint count in poisedon with UH - Transcript hashing is not yet in place - #7410 Alvaro's recent work with the VK tree had to be partially undone (aka the parts that made it really validate in kernels, so most of it for now) because our tube VK currently cannot be written ahead of time. What's more, correctly handling log-sized proofs will mean many tube and kernel VKs in the future. This will need a pass. - #7374 This test used a lot of mocking and was stubbed out in the interest of time. It's not necessarily hard to bring back. - #7373 We need one soon. The relevant deploying functionality has been commented out for now with this issue linked. - #7372 This needs to be double-checked for current kernel proof, but we will do this post-merge with a pass on observability - #7371 We need to figure out how to get this program stack bincode-encoded in the future - #7370 Right now redundant VKs are serialized with the client ivc proofs - #7369 Related to #7410, currently tube proving is too unlike the rest of the pattern - #7368 It's currently a bit of a mess of grabbing bytecode artifacts with ad-hoc logic - https://github.com/AztecProtocol/barretenberg/issues/1048 Inputs should be passed to the tube circuit correctly, but they are NOT currently used. Fixing this should be contained within bb --------- Co-authored-by: codygunton Co-authored-by: ledwards2225 Co-authored-by: lucasxia01 Co-authored-by: maramihali --- .github/workflows/ci.yml | 12 +- .vscode/launch.json | 9 +- .vscode/settings.json | 2 +- barretenberg/.vscode/launch.json | 20 ++ barretenberg/acir_tests/reset_acir_tests.sh | 2 +- barretenberg/cpp/CMakeLists.txt | 10 + barretenberg/cpp/cmake/libdeflate.cmake | 10 + barretenberg/cpp/scripts/flamegraph.pl | 4 +- .../cpp/src/barretenberg/bb/CMakeLists.txt | 4 +- barretenberg/cpp/src/barretenberg/bb/main.cpp | 215 ++++++++++++++-- .../barretenberg/client_ivc/client_ivc.cpp | 4 + .../barretenberg/client_ivc/client_ivc.hpp | 49 ++++ .../cpp/src/barretenberg/constants.hpp | 3 +- .../cpp/src/barretenberg/dsl/CMakeLists.txt | 16 +- .../dsl/acir_format/acir_format.cpp | 109 ++++---- .../dsl/acir_format/acir_format.hpp | 2 +- .../acir_format/acir_to_constraint_buf.cpp | 8 +- .../acir_format/honk_recursion_constraint.cpp | 60 +++-- .../honk_recursion_constraint.test.cpp | 19 +- .../dsl/acir_format/recursion_constraint.cpp | 4 +- .../dsl/acir_format/recursion_constraint.hpp | 4 +- .../arithmetization/arithmetization.hpp | 29 ++- .../src/core/libraries/ConstantsGen.sol | 7 +- noir-projects/gates_report.sh | 14 +- .../parity-lib/src/root/root_parity_inputs.nr | 3 +- .../src/private_kernel_init.nr | 4 - .../src/private_kernel_inner.nr | 23 +- .../src/private_kernel_reset.nr | 21 +- .../src/private_kernel_tail.nr | 21 +- .../src/private_kernel_tail_to_public.nr | 20 +- .../src/public_kernel_app_logic.nr | 27 +- .../src/public_kernel_setup.nr | 25 +- .../src/public_kernel_tail.nr | 21 +- .../src/public_kernel_teardown.nr | 18 +- .../rollup-lib/src/base/base_rollup_inputs.nr | 23 +- .../src/merge/merge_rollup_inputs.nr | 29 ++- .../rollup-lib/src/root/root_rollup_inputs.nr | 11 +- .../abis/private_kernel/private_call_data.nr | 15 +- .../types/src/abis/private_kernel_data.nr | 22 -- .../crates/types/src/constants.nr | 12 +- .../crates/types/src/hash.nr | 6 +- .../crates/types/src/tests/fixture_builder.nr | 7 +- .../scripts/generate_vk_json.js | 5 +- .../verify_honk_proof/Prover.toml | 4 +- .../verify_honk_proof/src/main.nr | 2 +- noir/noir-repo/test_programs/rebuild.sh | 2 +- noir/verify_honk_proof/src/main.nr | 2 +- scripts/earthly-ci | 2 +- .../src/contract/base_contract_interaction.ts | 6 +- yarn-project/bb-prover/package.json | 1 + yarn-project/bb-prover/src/bb/cli.ts | 32 +++ yarn-project/bb-prover/src/bb/execute.ts | 234 +++++++++++++++++- ...creator.ts => bb_private_kernel_prover.ts} | 228 ++++++++--------- .../bb-prover/src/prover/bb_prover.ts | 184 ++++++++++++-- yarn-project/bb-prover/src/prover/index.ts | 2 +- .../bb-prover/src/test/test_circuit_prover.ts | 42 ++++ .../verification_key/verification_key_data.ts | 6 +- .../bb-prover/src/verifier/bb_verifier.ts | 13 +- .../circuit-types/src/interfaces/index.ts | 2 +- ...of_creator.ts => private_kernel_prover.ts} | 57 ++--- .../src/interfaces/proving-job.ts | 16 ++ .../src/interfaces/server_circuit_prover.ts | 20 +- yarn-project/circuit-types/src/mocks.ts | 4 +- .../circuit-types/src/tx/processed_tx.ts | 45 +++- yarn-project/circuit-types/src/tx/tx.ts | 24 +- yarn-project/circuits.js/src/constants.gen.ts | 7 +- .../src/structs/client_ivc_proof.ts | 95 +++++++ yarn-project/circuits.js/src/structs/index.ts | 1 + .../src/structs/kernel/kernel_data.ts | 11 +- .../src/structs/kernel/private_call_data.ts | 13 +- .../src/structs/kernel/private_kernel_data.ts | 13 +- .../public_kernel_circuit_private_inputs.ts | 8 +- .../src/structs/kernel/public_kernel_data.ts | 10 +- .../src/structs/rollup/base_rollup.ts | 55 ++++ .../src/structs/verification_key.ts | 7 +- .../circuits.js/src/tests/factories.ts | 12 +- yarn-project/end-to-end/package.json | 1 + .../src/benchmarks/bench_prover.test.ts | 5 +- .../composed/integration_l1_publisher.test.ts | 4 +- .../end-to-end/src/e2e_2_pxes.test.ts | 4 + .../src/e2e_prover/e2e_prover_test.ts | 110 ++++---- yarn-project/end-to-end/src/fixtures/utils.ts | 4 +- .../src/type_conversion.ts | 2 - .../noir-protocol-circuits-types/src/vks.ts | 6 +- .../p2p/src/service/tx_messages.test.ts | 6 +- yarn-project/p2p/src/service/tx_messages.ts | 10 +- .../prover-client/src/mocks/fixtures.ts | 4 +- .../orchestrator/block-building-helpers.ts | 19 +- .../src/orchestrator/orchestrator.ts | 27 +- .../src/orchestrator/tx-proving-state.ts | 10 +- .../src/prover-agent/memory-proving-queue.ts | 21 +- .../src/prover-agent/prover-agent.ts | 12 +- .../src/test/bb_prover_base_rollup.test.ts | 8 +- yarn-project/pxe/package.json | 2 + .../src/kernel_prover/kernel_prover.test.ts | 42 ++-- .../pxe/src/kernel_prover/kernel_prover.ts | 128 ++++++---- .../kernel_prover/test/test_circuit_prover.ts | 62 +++-- .../pxe/src/pxe_service/create_pxe_service.ts | 14 +- .../pxe/src/pxe_service/pxe_service.ts | 17 +- .../src/pxe_service/test/pxe_service.test.ts | 6 +- .../src/sequencer/sequencer.test.ts | 3 +- .../src/sequencer/sequencer.ts | 2 +- .../src/public/abstract_phase_manager.ts | 3 +- .../src/public/public_processor.test.ts | 48 ++-- .../simulator/src/public/public_processor.ts | 4 +- yarn-project/yarn.lock | 10 + 106 files changed, 1856 insertions(+), 827 deletions(-) create mode 100644 barretenberg/.vscode/launch.json create mode 100644 barretenberg/cpp/cmake/libdeflate.cmake rename yarn-project/bb-prover/src/prover/{bb_native_proof_creator.ts => bb_private_kernel_prover.ts} (66%) rename yarn-project/circuit-types/src/interfaces/{proof_creator.ts => private_kernel_prover.ts} (73%) create mode 100644 yarn-project/circuits.js/src/structs/client_ivc_proof.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2692fde7e2ec..fb797f3c0506 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -157,7 +157,7 @@ jobs: - uses: ./.github/ci-setup-action - name: Setup and Test uses: ./.github/ensure-tester-with-images - timeout-minutes: 40 + timeout-minutes: 45 with: runner_type: ${{ contains(matrix.test, 'prover') && '64core-tester-x86' || '16core-tester-x86' }} builder_type: builder-x86 @@ -166,6 +166,7 @@ jobs: builder_images_to_copy: aztecprotocol/aztec:${{ env.GIT_COMMIT }} aztecprotocol/end-to-end:${{ env.GIT_COMMIT }} # command to produce the images in case they don't exist builder_command: cd yarn-project/end-to-end/ && ../../scripts/earthly-ci +${{ matrix.test }} + tester_ttl: 40 run: | set -eux cd ./yarn-project/end-to-end/ @@ -381,7 +382,7 @@ jobs: - name: "Format noir-projects" working-directory: ./noir-projects/ timeout-minutes: 40 - run: | + run: | earthly-ci --no-output \ --secret AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} \ --secret AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} \ @@ -465,7 +466,6 @@ jobs: steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } - # Only allow one memory-hunger prover test to use this runner - uses: ./.github/ci-setup-action with: concurrency_key: yarn-project-formatting-x86 @@ -474,13 +474,11 @@ jobs: run: earthly-ci --no-output ./yarn-project/+format-check yarn-project-test: - # quiet machine needs: build runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } - # Only allow one memory-hunger prover test to use this runner - uses: ./.github/ci-setup-action with: concurrency_key: yarn-project-test-x86 @@ -527,7 +525,7 @@ jobs: - name: "Docs Preview" if: github.event.number timeout-minutes: 40 - run: | + run: | earthly-ci --no-output \ --secret AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} \ --secret AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} \ @@ -639,7 +637,7 @@ jobs: earthly-ci \ --secret AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} \ --secret AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} \ - --artifact +gates-report/gates_report.json + --artifact +gates-report/gates_report.json mv gates_report.json ../protocol_circuits_report.json - name: Compare gates reports diff --git a/.vscode/launch.json b/.vscode/launch.json index fa4b77b4ad03..1c9a6801e9c4 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,8 +5,7 @@ "version": "0.2.0", "configurations": [ { - "address": "${config:mainframeAddress}", - "port": 9221, + "port": 9229, "type": "node", "request": "attach", "name": "Attach to Remote", @@ -14,5 +13,11 @@ "localRoot": "${workspaceFolder}", "sourceMaps": true }, + { + "type": "node", + "request": "attach", + "name": "Attach", + "port": 9229 + } ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 6bde2bae40ae..1df0f7fc2e0a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -120,7 +120,7 @@ "editor.defaultFormatter": "hashicorp.terraform" }, "[typescript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "vscode.typescript-language-features" }, "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" diff --git a/barretenberg/.vscode/launch.json b/barretenberg/.vscode/launch.json new file mode 100644 index 000000000000..5ea1dbb12277 --- /dev/null +++ b/barretenberg/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "LLDB: Prove Ultra Honk Output All", + "type": "lldb", + "request": "launch", + "program": "/mnt/user-data/adam/aztec-packages/barretenberg/cpp/build-debug/bin/bb", + "args": [ + "prove_ultra_honk_output_all", + "-o", "/tmp/bb-095XQV/tmp-PPXk0y", + "-b", "/tmp/bb-095XQV/tmp-PPXk0y/PrivateKernelInitArtifact-bytecode", + "-w", "/tmp/bb-095XQV/tmp-PPXk0y/witness.gz", + "-v" + ], + "cwd": "${workspaceFolder}", + "stopOnEntry": false + } + ] +} \ No newline at end of file diff --git a/barretenberg/acir_tests/reset_acir_tests.sh b/barretenberg/acir_tests/reset_acir_tests.sh index dffb4d438375..c89731cd79cb 100755 --- a/barretenberg/acir_tests/reset_acir_tests.sh +++ b/barretenberg/acir_tests/reset_acir_tests.sh @@ -1,4 +1,4 @@ -# Run from barretenberg/acir_tests +# Run from within barretenberg/acir_tests cd ../../noir/noir-repo cargo clean noirup -p . diff --git a/barretenberg/cpp/CMakeLists.txt b/barretenberg/cpp/CMakeLists.txt index 23c621aa2d8a..780eb8ed5e2a 100644 --- a/barretenberg/cpp/CMakeLists.txt +++ b/barretenberg/cpp/CMakeLists.txt @@ -143,6 +143,16 @@ include(cmake/gtest.cmake) include(cmake/benchmark.cmake) include(cmake/module.cmake) include(cmake/msgpack.cmake) + +# We do not need to bloat barretenberg.wasm with gzip functionality in a browser context as the browser can do this +if (NOT WASM) + include(cmake/libdeflate.cmake) +else() + set(DISABLE_AZTEC_VM ON) +endif() +if(DISABLE_AZTEC_VM) + add_definitions(-DDISABLE_AZTEC_VM=1) +endif() include(cmake/backward-cpp.cmake) if (WASM) diff --git a/barretenberg/cpp/cmake/libdeflate.cmake b/barretenberg/cpp/cmake/libdeflate.cmake new file mode 100644 index 000000000000..fd151996e069 --- /dev/null +++ b/barretenberg/cpp/cmake/libdeflate.cmake @@ -0,0 +1,10 @@ +include(FetchContent) + +FetchContent_Declare( + libdeflate + GIT_REPOSITORY https://github.com/ebiggers/libdeflate.git + GIT_TAG b03254d978d7af21a7512dee8fdc3367bc15c656 +) + +# Download and populate libdeflate +FetchContent_MakeAvailable(libdeflate) \ No newline at end of file diff --git a/barretenberg/cpp/scripts/flamegraph.pl b/barretenberg/cpp/scripts/flamegraph.pl index d2172b616640..b3adc1c32367 100755 --- a/barretenberg/cpp/scripts/flamegraph.pl +++ b/barretenberg/cpp/scripts/flamegraph.pl @@ -410,7 +410,7 @@ sub color { } elsif ($name =~ m:^L?(java|javax|jdk|net|org|com|io|sun)/:) { # Java $type = "green"; } elsif ($name =~ /:::/) { # Java, typical perf-map-agent method separator - $type = "green"; + $type = "green"; } elsif ($name =~ /::/) { # C++ $type = "yellow"; } elsif ($name =~ m:_\[k\]$:) { # kernel annotation @@ -818,7 +818,7 @@ sub flow { // ctrl-F for search // ctrl-I to toggle case-sensitive search window.addEventListener("keydown",function (e) { - if (e.keyCode === 114 || (e.ctrlKey && e.keyCode === 70)) { + if (e.keyCode === 103 || (e.ctrlKey && e.keyCode === 70)) { e.preventDefault(); search_prompt(); } diff --git a/barretenberg/cpp/src/barretenberg/bb/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/bb/CMakeLists.txt index 031861aa4c22..f0812aea948d 100644 --- a/barretenberg/cpp/src/barretenberg/bb/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/bb/CMakeLists.txt @@ -1,4 +1,4 @@ -if (NOT(FUZZING)) +if (NOT(FUZZING) AND NOT(WASM)) add_executable( bb main.cpp @@ -11,6 +11,8 @@ if (NOT(FUZZING)) PRIVATE barretenberg env + circuit_checker + libdeflate::libdeflate_static ) if(CHECK_CIRCUIT_STACKTRACES) target_link_libraries( diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index d5cd3e11d825..3c1fa44785a6 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -5,7 +5,9 @@ #include "barretenberg/dsl/acir_format/acir_format.hpp" #include "barretenberg/honk/proof_system/types/proof.hpp" #include "barretenberg/plonk/proof_system/proving_key/serialize.hpp" +#include "barretenberg/serialize/cbind.hpp" #include "barretenberg/stdlib/honk_recursion/verifier/client_ivc_recursive_verifier.hpp" +#include #ifndef DISABLE_AZTEC_VM #include "barretenberg/vm/avm_trace/avm_common.hpp" #include "barretenberg/vm/avm_trace/avm_execution.hpp" @@ -15,6 +17,7 @@ #include "get_bn254_crs.hpp" #include "get_bytecode.hpp" #include "get_grumpkin_crs.hpp" +#include "libdeflate.h" #include "log.hpp" #include #include @@ -24,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -241,14 +245,155 @@ bool proveAndVerifyHonkProgram(const std::string& bytecodePath, const std::strin return true; } -bool foldAndVerifyProgram(const std::string& bytecodePath, const std::string& witnessPath) +struct VectorOfAcirAndWitnesses { + std::vector> acirGzippedBincoes; + std::vector> witnessMaps; +}; + +// TODO(#7371): this could probably be more idiomatic +template T unpack_from_file(const std::string& filename) +{ + std::ifstream fin; + fin.open(filename, std::ios::ate | std::ios::binary); + if (!fin.is_open()) { + throw std::invalid_argument("file not found"); + } + if (fin.tellg() == -1) { + throw std::invalid_argument("something went wrong"); + } + + uint64_t fsize = static_cast(fin.tellg()); + fin.seekg(0, std::ios_base::beg); + + T result; + char* encoded_data = new char[fsize]; + fin.read(encoded_data, static_cast(fsize)); + msgpack::unpack(encoded_data, fsize).get().convert(result); + return result; +} + +// TODO(#7371) find a home for this +acir_format::WitnessVector witness_map_to_witness_vector(std::map const& witness_map) +{ + acir_format::WitnessVector wv; + size_t index = 0; + for (auto& e : witness_map) { + uint64_t value = std::stoull(e.first); + // ACIR uses a sparse format for WitnessMap where unused witness indices may be left unassigned. + // To ensure that witnesses sit at the correct indices in the `WitnessVector`, we fill any indices + // which do not exist within the `WitnessMap` with the dummy value of zero. + while (index < value) { + wv.push_back(fr(0)); + index++; + } + wv.push_back(fr(uint256_t(e.second))); + index++; + } + return wv; +} + +std::vector decompressedBuffer(uint8_t* bytes, size_t size) +{ + std::vector content; + // initial size guess + content.resize(1024ULL * 128ULL); + for (;;) { + auto decompressor = std::unique_ptr{ + libdeflate_alloc_decompressor(), libdeflate_free_decompressor + }; + size_t actual_size = 0; + libdeflate_result decompress_result = libdeflate_gzip_decompress( + decompressor.get(), bytes, size, std::data(content), std::size(content), &actual_size); + if (decompress_result == LIBDEFLATE_INSUFFICIENT_SPACE) { + // need a bigger buffer + content.resize(content.size() * 2); + continue; + } + if (decompress_result == LIBDEFLATE_BAD_DATA) { + throw std::invalid_argument("bad gzip data in bb main"); + } + content.resize(actual_size); + break; + } + return content; +} + +void client_ivc_prove_output_all_msgpack(const std::string& bytecodePath, + const std::string& witnessPath, + const std::string& outputPath) { using Flavor = MegaFlavor; // This is the only option using Builder = Flavor::CircuitBuilder; + using Program = acir_format::AcirProgram; + using ECCVMVK = ECCVMFlavor::VerificationKey; + using TranslatorVK = TranslatorFlavor::VerificationKey; - init_bn254_crs(1 << 18); + init_bn254_crs(1 << 24); init_grumpkin_crs(1 << 14); + auto gzippedBincodes = unpack_from_file>(bytecodePath); + auto witnessMaps = unpack_from_file>(witnessPath); + std::vector folding_stack; + for (size_t i = 0; i < gzippedBincodes.size(); i++) { + // TODO(#7371) there is a lot of copying going on in bincode, we should make sure this writes as a buffer in + // the future + std::vector buffer = + decompressedBuffer(reinterpret_cast(&gzippedBincodes[i][0]), gzippedBincodes[i].size()); // NOLINT + + std::vector constraint_systems = acir_format::program_buf_to_acir_format( + buffer, + false); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): + // this assumes that folding is never done with ultrahonk. + std::vector witnessBuffer = + decompressedBuffer(reinterpret_cast(&witnessMaps[i][0]), witnessMaps[i].size()); // NOLINT + acir_format::WitnessVectorStack witness_stack = acir_format::witness_buf_to_witness_stack(witnessBuffer); + acir_format::AcirProgramStack program_stack{ constraint_systems, witness_stack }; + folding_stack.push_back(program_stack.back()); + } + // TODO(#7371) dedupe this with the rest of the similar code + ClientIVC ivc; + ivc.structured_flag = true; + // Accumulate the entire program stack into the IVC + for (Program& program : folding_stack) { + // auto& stack_item = program_stack.witness_stack[i]; + + // Construct a bberg circuit from the acir representation + auto circuit = + acir_format::create_circuit(program.constraints, 0, program.witness, false, ivc.goblin.op_queue); + ivc.accumulate(circuit); + } + + // Write the proof and verification keys into the working directory in 'binary' format (in practice it seems this + // directory is passed by bb.js) + std::string vkPath = outputPath + "/inst_vk"; // the vk of the last instance + std::string accPath = outputPath + "/pg_acc"; + std::string proofPath = outputPath + "/client_ivc_proof"; + std::string translatorVkPath = outputPath + "/translator_vk"; + std::string eccVkPath = outputPath + "/ecc_vk"; + + auto proof = ivc.prove(); + auto eccvm_vk = std::make_shared(ivc.goblin.get_eccvm_proving_key()); + auto translator_vk = std::make_shared(ivc.goblin.get_translator_proving_key()); + + auto last_instance = std::make_shared(ivc.instance_vk); + vinfo("ensure valid proof: ", ivc.verify(proof, { ivc.verifier_accumulator, last_instance })); + + vinfo("write proof and vk data to files.."); + write_file(proofPath, to_buffer(proof)); + write_file(vkPath, to_buffer(ivc.instance_vk)); + write_file(accPath, to_buffer(ivc.verifier_accumulator)); + write_file(translatorVkPath, to_buffer(translator_vk)); + write_file(eccVkPath, to_buffer(eccvm_vk)); +} + +bool foldAndVerifyProgram(const std::string& bytecodePath, const std::string& witnessPath) +{ + using Flavor = MegaFlavor; // This is the only option + using Builder = Flavor::CircuitBuilder; + + init_bn254_crs(1 << 22); + init_grumpkin_crs(1 << 16); + ClientIVC ivc; ivc.structured_flag = true; @@ -288,8 +433,8 @@ void client_ivc_prove_output_all(const std::string& bytecodePath, using ECCVMVK = ECCVMFlavor::VerificationKey; using TranslatorVK = TranslatorFlavor::VerificationKey; - init_bn254_crs(1 << 18); - init_grumpkin_crs(1 << 14); + init_bn254_crs(1 << 22); + init_grumpkin_crs(1 << 16); ClientIVC ivc; ivc.structured_flag = true; @@ -337,9 +482,10 @@ void client_ivc_prove_output_all(const std::string& bytecodePath, /** * @brief Creates a Honk Proof for the Tube circuit responsible for recursively verifying a ClientIVC proof. * - * @param outputPath the working directory from which the proof and verification data are read + * @param output_path the working directory from which the proof and verification data are read + * @param num_unused_public_inputs */ -void prove_tube(const std::string& outputPath) +void prove_tube(const std::string& output_path) { using ClientIVC = stdlib::recursion::honk::ClientIVCRecursiveVerifier; using NativeInstance = ClientIVC::FoldVerifierInput::Instance; @@ -352,11 +498,11 @@ void prove_tube(const std::string& outputPath) using Builder = UltraCircuitBuilder; using GrumpkinVk = bb::VerifierCommitmentKey; - std::string vkPath = outputPath + "/inst_vk"; // the vk of the last instance - std::string accPath = outputPath + "/pg_acc"; - std::string proofPath = outputPath + "/client_ivc_proof"; - std::string translatorVkPath = outputPath + "/translator_vk"; - std::string eccVkPath = outputPath + "/ecc_vk"; + std::string vkPath = output_path + "/inst_vk"; // the vk of the last instance + std::string accPath = output_path + "/pg_acc"; + std::string proofPath = output_path + "/client_ivc_proof"; + std::string translatorVkPath = output_path + "/translator_vk"; + std::string eccVkPath = output_path + "/ecc_vk"; // Note: this could be decreased once we optimise the size of the ClientIVC recursiveve rifier init_bn254_crs(1 << 25); @@ -380,23 +526,46 @@ void prove_tube(const std::string& outputPath) GoblinVerifierInput goblin_verifier_input{ eccvm_vk, translator_vk }; VerifierInput input{ fold_verifier_input, goblin_verifier_input }; auto builder = std::make_shared(); + // Padding needed for sending the right number of public inputs + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1048): INSECURE - make this tube proof actually use + // these public inputs by turning proof into witnesses and call + // set_public on each witness + auto num_public_inputs = (size_t)proof.folding_proof[1]; + for (size_t i = 0; i < num_public_inputs; i++) { + // We offset 3 + builder->add_public_variable(proof.folding_proof[i + 3]); + } ClientIVC verifier{ builder, input }; verifier.verify(proof); info("num gates: ", builder->get_num_gates()); info("generating proof"); using Prover = UltraProver_; - + using Verifier = UltraVerifier_; Prover tube_prover{ *builder }; auto tube_proof = tube_prover.construct_proof(); - - std::string tubeProofPath = outputPath + "/proof"; + std::string tubeProofPath = output_path + "/proof"; write_file(tubeProofPath, to_buffer(tube_proof)); - std::string tubeVkPath = outputPath + "/vk"; + std::string tubeProofAsFieldsPath = output_path + "/proof_fields.json"; + auto proof_data = to_json(tube_proof); + write_file(tubeProofAsFieldsPath, { proof_data.begin(), proof_data.end() }); + + std::string tubeVkPath = output_path + "/vk"; auto tube_verification_key = std::make_shared(tube_prover.instance->proving_key); write_file(tubeVkPath, to_buffer(tube_verification_key)); + + std::string tubeAsFieldsVkPath = output_path + "/vk_fields.json"; + auto field_els = tube_verification_key->to_field_elements(); + info("verificaton key length in fields:", field_els.size()); + auto data = to_json(field_els); + write_file(tubeAsFieldsVkPath, { data.begin(), data.end() }); + + info("Native verification of the tube_proof"); + Verifier tube_verifier(tube_verification_key); + bool verified = tube_verifier.verify_proof(tube_proof); + info("Tube proof verification: ", verified); } /** @@ -432,10 +601,10 @@ void prove(const std::string& bytecodePath, const std::string& witnessPath, cons } /** - * @brief Computes the number of Barretenberg specific gates needed to create a proof for the specific ACIR circuit + * @brief Computes the number of Barretenberg specific gates needed to create a proof for the specific ACIR circuit. * * Communication: - * - stdout: A JSON string of the number of ACIR opcodes and final backend circuit size + * - stdout: A JSON string of the number of ACIR opcodes and final backend circuit size. * * @param bytecodePath Path to the file containing the serialized circuit */ @@ -522,7 +691,7 @@ bool verify(const std::string& proof_path, const std::string& vk_path) */ void write_vk(const std::string& bytecodePath, const std::string& outputPath) { - auto constraint_system = get_constraint_system(bytecodePath, /*honk_recursion=*/false); + auto constraint_system = get_constraint_system(bytecodePath, false); acir_proofs::AcirComposer acir_composer{ 0, verbose_logging }; acir_composer.create_circuit(constraint_system); init_bn254_crs(acir_composer.get_dyadic_circuit_size()); @@ -902,7 +1071,7 @@ void proof_as_fields_honk(const std::string& proof_path, const std::string& outp } /** - * @brief Converts a verification key from a byte array into a list of field elements + * @brief Converts a verification key from a byte array into a list of field elements. * * Why is this needed? * This follows the same rationale as `proofAsFields`. @@ -1073,7 +1242,6 @@ int main(int argc, char* argv[]) } std::string command = args[0]; - std::string bytecode_path = get_option(args, "-b", "./target/program.json"); std::string witness_path = get_option(args, "-w", "./target/witness.gz"); std::string proof_path = get_option(args, "-p", "./proofs/proof"); @@ -1102,6 +1270,13 @@ int main(int argc, char* argv[]) if (command == "prove_and_verify_mega_honk_program") { return proveAndVerifyHonkProgram(bytecode_path, witness_path) ? 0 : 1; } + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1050) we need a verify_client_ivc bb cli command + // TODO(#7371): remove this + if (command == "client_ivc_prove_output_all_msgpack") { + std::string output_path = get_option(args, "-o", "./proofs/proof"); + client_ivc_prove_output_all_msgpack(bytecode_path, witness_path, output_path); + return 0; + } if (command == "fold_and_verify_program") { return foldAndVerifyProgram(bytecode_path, witness_path) ? 0 : 1; } diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index d351ea09b5ce..204470263423 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -28,6 +28,9 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr(circuit, structured_flag); + // Track the maximum size of each block for all circuits porcessed (for debugging purposes only) + max_block_sizes.update(circuit); + // Set the instance verification key from precomputed if available, else compute it if (precomputed_vk) { instance_vk = precomputed_vk; @@ -53,6 +56,7 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr namespace bb { @@ -46,9 +47,55 @@ class ClientIVC { HonkProof decider_proof; GoblinProof goblin_proof; + size_t size() const { return folding_proof.size() + decider_proof.size() + goblin_proof.size(); } + MSGPACK_FIELDS(folding_proof, decider_proof, goblin_proof); }; + // A debugging utility for tracking the max size of each block over all circuits in the IVC + struct MaxBlockSizes { + size_t ecc_op{ 0 }; + size_t pub_inputs{ 0 }; + size_t arithmetic{ 0 }; + size_t delta_range{ 0 }; + size_t elliptic{ 0 }; + size_t aux{ 0 }; + size_t lookup{ 0 }; + size_t busread{ 0 }; + size_t poseidon_external{ 0 }; + size_t poseidon_internal{ 0 }; + + void update(ClientCircuit& circuit) + { + ecc_op = std::max(circuit.blocks.ecc_op.size(), ecc_op); + pub_inputs = std::max(circuit.public_inputs.size(), pub_inputs); + arithmetic = std::max(circuit.blocks.arithmetic.size(), arithmetic); + delta_range = std::max(circuit.blocks.delta_range.size(), delta_range); + elliptic = std::max(circuit.blocks.elliptic.size(), elliptic); + aux = std::max(circuit.blocks.aux.size(), aux); + lookup = std::max(circuit.blocks.lookup.size(), lookup); + busread = std::max(circuit.blocks.busread.size(), busread); + poseidon_external = std::max(circuit.blocks.poseidon_external.size(), poseidon_external); + poseidon_internal = std::max(circuit.blocks.poseidon_internal.size(), poseidon_internal); + } + + void print() + { + info("Minimum required block sizes for structured trace: "); + info("goblin ecc op :\t", ecc_op); + info("pub inputs :\t", pub_inputs); + info("arithmetic :\t", arithmetic); + info("delta range :\t", delta_range); + info("elliptic :\t", elliptic); + info("auxiliary :\t", aux); + info("lookups :\t", lookup); + info("busread :\t", busread); + info("poseidon ext :\t", poseidon_external); + info("poseidon int :\t", poseidon_internal); + info(""); + } + }; + private: using ProverFoldOutput = FoldingResult; // Note: We need to save the last instance that was folded in order to compute its verification key, this will not @@ -81,5 +128,7 @@ class ClientIVC { HonkProof decider_prove() const; std::vector> precompute_folding_verification_keys(std::vector); + + MaxBlockSizes max_block_sizes; // for tracking minimum block size requirements across an IVC }; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp index 4adf2c4a6b18..72e8f9fcd3ea 100644 --- a/barretenberg/cpp/src/barretenberg/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -2,6 +2,7 @@ #include namespace bb { -// The log of the max circuit size assumed in order to achieve constant sized proofs +// The log of the max circuit size assumed in order to achieve constant sized Honk proofs +// TODO(https://github.com/AztecProtocol/barretenberg/issues/1046): Remove the need for const sized proofs static constexpr uint32_t CONST_PROOF_SIZE_LOG_N = 28; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt index 0d504b53b658..2bd424e4ecf4 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt @@ -1,5 +1,7 @@ -barretenberg_module( - dsl + +# We do not need to bloat barretenberg.wasm with gzip functionality in a browser context as the browser can do this + +set(DSL_DEPENDENCIES plonk ultra_honk client_ivc @@ -10,5 +12,13 @@ barretenberg_module( crypto_merkle_tree stdlib_schnorr ultra_honk - stdlib_honk_recursion + stdlib_honk_recursion) + +if (NOT WASM) + list(APPEND DSL_DEPENDENCIES libdeflate::libdeflate_static) +endif() + +barretenberg_module( + dsl + ${DSL_DEPENDENCIES} ) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 528fd947ed31..cef13ea1e7a4 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -347,19 +347,21 @@ void build_constraints(Builder& builder, // proof aggregation state are a circuit constant. The user tells us they how they want these // constants set by keeping the nested aggregation object attached to the proof as public inputs. std::array nested_aggregation_object = {}; - for (size_t i = 0; i < HonkRecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { - // Set the nested aggregation object indices to witness indices from the proof - nested_aggregation_object[i] = - static_cast(constraint.proof[HonkRecursionConstraint::inner_public_input_offset + i]); - // Adding the nested aggregation object to the constraint's public inputs - constraint.public_inputs.emplace_back(nested_aggregation_object[i]); - } + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + // for (size_t i = 0; i < HonkRecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { + // // Set the nested aggregation object indices to witness indices from the proof + // nested_aggregation_object[i] = + // static_cast(constraint.proof[HonkRecursionConstraint::inner_public_input_offset + i]); + // // Adding the nested aggregation object to the constraint's public inputs + // constraint.public_inputs.emplace_back(nested_aggregation_object[i]); + // } // Remove the aggregation object so that they can be handled as normal public inputs // in they way that the recursion constraint expects - constraint.proof.erase(constraint.proof.begin() + HonkRecursionConstraint::inner_public_input_offset, - constraint.proof.begin() + - static_cast(HonkRecursionConstraint::inner_public_input_offset + - HonkRecursionConstraint::AGGREGATION_OBJECT_SIZE)); + // constraint.proof.erase(constraint.proof.begin() + HonkRecursionConstraint::inner_public_input_offset, + // constraint.proof.begin() + + // static_cast(HonkRecursionConstraint::inner_public_input_offset + // + + // HonkRecursionConstraint::AGGREGATION_OBJECT_SIZE)); current_aggregation_object = create_honk_recursion_constraints(builder, constraint, current_aggregation_object, @@ -376,47 +378,52 @@ void build_constraints(Builder& builder, // First add the output aggregation object as public inputs // Set the indices as public inputs because they are no longer being // created in ACIR - for (const auto& idx : current_aggregation_object) { - builder.set_public_input(idx); - } - - // Make sure the verification key records the public input indices of the - // final recursion output. - std::vector proof_output_witness_indices(current_aggregation_object.begin(), - current_aggregation_object.end()); - builder.set_recursive_proof(proof_output_witness_indices); - } else if (honk_recursion && - builder.is_recursive_circuit) { // Set a default aggregation object if we don't have one. - // TODO(https://github.com/AztecProtocol/barretenberg/issues/911): These are pairing points extracted from - // a valid proof. This is a workaround because we can't represent the point at infinity in biggroup yet. - fq x0("0x031e97a575e9d05a107acb64952ecab75c020998797da7842ab5d6d1986846cf"); - fq y0("0x178cbf4206471d722669117f9758a4c410db10a01750aebb5666547acf8bd5a4"); - - fq x1("0x0f94656a2ca489889939f81e9c74027fd51009034b3357f0e91b8a11e7842c38"); - fq y1("0x1b52c2020d7464a0c80c0da527a08193fe27776f50224bd6fb128b46c1ddb67f"); - std::vector aggregation_object_fq_values = { x0, y0, x1, y1 }; - size_t agg_obj_indices_idx = 0; - for (fq val : aggregation_object_fq_values) { - const uint256_t x = val; - std::array val_limbs = { - x.slice(0, fq_ct::NUM_LIMB_BITS), - x.slice(fq_ct::NUM_LIMB_BITS, fq_ct::NUM_LIMB_BITS * 2), - x.slice(fq_ct::NUM_LIMB_BITS * 2, fq_ct::NUM_LIMB_BITS * 3), - x.slice(fq_ct::NUM_LIMB_BITS * 3, stdlib::field_conversion::TOTAL_BITS) - }; - for (size_t i = 0; i < fq_ct::NUM_LIMBS; ++i) { - uint32_t idx = builder.add_variable(val_limbs[i]); - builder.set_public_input(idx); - current_aggregation_object[agg_obj_indices_idx] = idx; - agg_obj_indices_idx++; - } - } - // Make sure the verification key records the public input indices of the - // final recursion output. - std::vector proof_output_witness_indices(current_aggregation_object.begin(), - current_aggregation_object.end()); - builder.set_recursive_proof(proof_output_witness_indices); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + // for (const auto& idx : current_aggregation_object) { + // builder.set_public_input(idx); + // } + + // // Make sure the verification key records the public input indices of the + // // final recursion output. + // std::vector proof_output_witness_indices(current_aggregation_object.begin(), + // current_aggregation_object.end()); + // builder.set_recursive_proof(proof_output_witness_indices); } + static_cast(honk_recursion); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + // else if (honk_recursion && + // builder.is_recursive_circuit) { // Set a default aggregation object if we don't have one. + // // TODO(https://github.com/AztecProtocol/barretenberg/issues/911): These are pairing points extracted + // from + // // a valid proof. This is a workaround because we can't represent the point at infinity in biggroup + // yet. fq x0("0x031e97a575e9d05a107acb64952ecab75c020998797da7842ab5d6d1986846cf"); fq + // y0("0x178cbf4206471d722669117f9758a4c410db10a01750aebb5666547acf8bd5a4"); + + // fq x1("0x0f94656a2ca489889939f81e9c74027fd51009034b3357f0e91b8a11e7842c38"); + // fq y1("0x1b52c2020d7464a0c80c0da527a08193fe27776f50224bd6fb128b46c1ddb67f"); + // std::vector aggregation_object_fq_values = { x0, y0, x1, y1 }; + // size_t agg_obj_indices_idx = 0; + // for (fq val : aggregation_object_fq_values) { + // const uint256_t x = val; + // std::array val_limbs = { + // x.slice(0, fq_ct::NUM_LIMB_BITS), + // x.slice(fq_ct::NUM_LIMB_BITS, fq_ct::NUM_LIMB_BITS * 2), + // x.slice(fq_ct::NUM_LIMB_BITS * 2, fq_ct::NUM_LIMB_BITS * 3), + // x.slice(fq_ct::NUM_LIMB_BITS * 3, stdlib::field_conversion::TOTAL_BITS) + // }; + // for (size_t i = 0; i < fq_ct::NUM_LIMBS; ++i) { + // uint32_t idx = builder.add_variable(val_limbs[i]); + // builder.set_public_input(idx); + // current_aggregation_object[agg_obj_indices_idx] = idx; + // agg_obj_indices_idx++; + // } + // } + // // Make sure the verification key records the public input indices of the + // // final recursion output. + // std::vector proof_output_witness_indices(current_aggregation_object.begin(), + // current_aggregation_object.end()); + // builder.set_recursive_proof(proof_output_witness_indices); + // } } } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp index 80edf92270ba..1b0e8b5057b8 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -166,7 +166,7 @@ struct AcirProgramStack { std::vector constraint_systems; WitnessVectorStack witness_stack; - AcirProgramStack(std::vector& constraint_systems_in, WitnessVectorStack& witness_stack_in) + AcirProgramStack(const std::vector& constraint_systems_in, const WitnessVectorStack& witness_stack_in) : constraint_systems(constraint_systems_in) , witness_stack(witness_stack_in) {} diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp index db5a32516934..2a7882a2080b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp @@ -751,14 +751,14 @@ AcirProgramStack get_acir_program_stack(std::string const& bytecode_path, std::string const& witness_path, bool honk_recursion) { - auto bytecode = get_bytecode(bytecode_path); - auto constraint_systems = + std::vector bytecode = get_bytecode(bytecode_path); + std::vector constraint_systems = program_buf_to_acir_format(bytecode, honk_recursion); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): // Remove honk recursion flag - auto witness_data = get_bytecode(witness_path); - auto witness_stack = witness_buf_to_witness_stack(witness_data); + std::vector witness_data = get_bytecode(witness_path); + WitnessVectorStack witness_stack = witness_buf_to_witness_stack(witness_data); return { constraint_systems, witness_stack }; } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp index fb7789298458..37ff4c41062f 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp @@ -55,42 +55,46 @@ std::array create_ho using RecursiveVerificationKey = Flavor::VerificationKey; using RecursiveVerifier = bb::stdlib::recursion::honk::UltraRecursiveVerifier_; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044) reinstate aggregation + static_cast(input_aggregation_object); + static_cast(nested_aggregation_object); // Construct aggregation points from the nested aggregation witness indices - std::array nested_aggregation_points = - agg_points_from_witness_indicies(builder, nested_aggregation_object); + // std::array nested_aggregation_points = + // agg_points_from_witness_indicies(builder, nested_aggregation_object); // Construct an in-circuit representation of the verification key. // For now, the v-key is a circuit constant and is fixed for the circuit. // (We may need a separate recursion opcode for this to vary, or add more config witnesses to this opcode) - const auto& aggregation_input = input_aggregation_object; - aggregation_state_ct cur_aggregation_object; - cur_aggregation_object.P0 = nested_aggregation_points[0]; - cur_aggregation_object.P1 = nested_aggregation_points[1]; - cur_aggregation_object.has_data = true; // the nested aggregation object always exists + // const auto& aggregation_input = input_aggregation_object; + // aggregation_state_ct cur_aggregation_object; + // cur_aggregation_object.P0 = nested_aggregation_points[0]; + // cur_aggregation_object.P1 = nested_aggregation_points[1]; + // cur_aggregation_object.has_data = true; // the nested aggregation object always exists // TODO(https://github.com/AztecProtocol/barretenberg/issues/995): generate this challenge properly. - field_ct recursion_separator = bb::stdlib::witness_t(&builder, 2); + // field_ct recursion_separator = bb::stdlib::witness_t(&builder, 2); // If we have previously recursively verified proofs, `previous_aggregation_object_nonzero = true` // For now this is a complile-time constant i.e. whether this is true/false is fixed for the circuit! - bool previous_aggregation_indices_all_zero = true; - for (const auto& idx : aggregation_input) { - previous_aggregation_indices_all_zero &= (idx == 0); - } + // bool previous_aggregation_indices_all_zero = true; + // for (const auto& idx : aggregation_input) { + // previous_aggregation_indices_all_zero &= (idx == 0); + // } - // Aggregate the aggregation object if it exists. It exists if we have previously verified proofs, i.e. if this is - // not the first recursion constraint. - if (!previous_aggregation_indices_all_zero) { - std::array inner_agg_points = agg_points_from_witness_indicies(builder, aggregation_input); - // If we have a previous aggregation object, aggregate it into the current aggregation object. - // TODO(https://github.com/AztecProtocol/barretenberg/issues/995): Verify that using challenge and challenge - // squared is safe. - cur_aggregation_object.P0 += inner_agg_points[0] * recursion_separator; - cur_aggregation_object.P1 += inner_agg_points[1] * recursion_separator; - recursion_separator = - recursion_separator * - recursion_separator; // update the challenge to be challenge squared for the next aggregation - } + // // Aggregate the aggregation object if it exists. It exists if we have previously verified proofs, i.e. if this + // is + // // not the first recursion constraint. + // if (!previous_aggregation_indices_all_zero) { + // std::array inner_agg_points = agg_points_from_witness_indicies(builder, aggregation_input); + // // If we have a previous aggregation object, aggregate it into the current aggregation object. + // // TODO(https://github.com/AztecProtocol/barretenberg/issues/995): Verify that using challenge and challenge + // // squared is safe. + // cur_aggregation_object.P0 += inner_agg_points[0] * recursion_separator; + // cur_aggregation_object.P1 += inner_agg_points[1] * recursion_separator; + // recursion_separator = + // recursion_separator * + // recursion_separator; // update the challenge to be challenge squared for the next aggregation + // } std::vector key_fields; key_fields.reserve(input.key.size()); @@ -210,8 +214,10 @@ std::array create_ho std::array pairing_points = verifier.verify_proof(proof_fields); // Aggregate the current aggregation object with these pairing points from verify_proof - cur_aggregation_object.P0 += pairing_points[0] * recursion_separator; - cur_aggregation_object.P1 += pairing_points[1] * recursion_separator; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + aggregation_state_ct cur_aggregation_object; + cur_aggregation_object.P0 = pairing_points[0]; // * recursion_separator; + cur_aggregation_object.P1 = pairing_points[1]; // * recursion_separator; std::vector proof_witness_indices = { cur_aggregation_object.P0.x.binary_basis_limbs[0].element.normalize().witness_index, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp index 612599108288..43b9505b13bb 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp @@ -158,17 +158,17 @@ class AcirHonkRecursionConstraint : public ::testing::Test { const size_t inner_public_input_offset = 3; // - Save the public inputs so that we can set their values. // - Then truncate them from the proof because the ACIR API expects proofs without public inputs + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation std::vector inner_public_input_values( proof_witnesses.begin() + static_cast(inner_public_input_offset), proof_witnesses.begin() + - static_cast(inner_public_input_offset + num_inner_public_inputs - - RecursionConstraint::AGGREGATION_OBJECT_SIZE)); + static_cast(inner_public_input_offset + num_inner_public_inputs)); // We want to make sure that we do not remove the nested aggregation object. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation proof_witnesses.erase(proof_witnesses.begin() + static_cast(inner_public_input_offset), proof_witnesses.begin() + - static_cast(inner_public_input_offset + num_inner_public_inputs - - RecursionConstraint::AGGREGATION_OBJECT_SIZE)); + static_cast(inner_public_input_offset + num_inner_public_inputs)); std::vector key_witnesses = verification_key->to_field_elements(); @@ -179,8 +179,9 @@ class AcirHonkRecursionConstraint : public ::testing::Test { const uint32_t public_input_start_idx = static_cast(inner_public_input_offset + witness_offset); // points to public_input_0 const uint32_t proof_indices_start_idx = - static_cast(public_input_start_idx + num_inner_public_inputs - - RecursionConstraint::AGGREGATION_OBJECT_SIZE); // points to agg_obj_0 + static_cast(public_input_start_idx + num_inner_public_inputs); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + // - RecursionConstraint::AGGREGATION_OBJECT_SIZE); // points to agg_obj_0 const uint32_t key_indices_start_idx = static_cast(proof_indices_start_idx + proof_witnesses.size() - inner_public_input_offset); // would point to vkey_3 without the - @@ -203,7 +204,8 @@ class AcirHonkRecursionConstraint : public ::testing::Test { // We keep the nested aggregation object attached to the proof, // thus we do not explicitly have to keep the public inputs while setting up the initial recursion // constraint. They will later be attached as public inputs when creating the circuit. - for (size_t i = 0; i < num_inner_public_inputs - RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + for (size_t i = 0; i < num_inner_public_inputs; ++i) { inner_public_inputs.push_back(static_cast(i + public_input_start_idx)); } @@ -242,7 +244,8 @@ class AcirHonkRecursionConstraint : public ::testing::Test { // // We once again have to check whether we have a nested proof, because if we do have one // then we could get a segmentation fault as `inner_public_inputs` was never filled with values. - for (size_t i = 0; i < num_inner_public_inputs - RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + for (size_t i = 0; i < num_inner_public_inputs; ++i) { witness[inner_public_inputs[i]] = inner_public_input_values[i]; } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp index 1a2fc9e502c3..ac3b4dc2c885 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp @@ -44,8 +44,8 @@ void generate_dummy_proof() {} std::array create_recursion_constraints( Builder& builder, const RecursionConstraint& input, - std::array input_aggregation_object, - std::array nested_aggregation_object, + const std::array& input_aggregation_object, + const std::array& nested_aggregation_object, bool has_valid_witness_assignments) { const auto& nested_aggregation_indices = nested_aggregation_object; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp index 6e17c6e88ffe..fa0fafd0c127 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp @@ -62,8 +62,8 @@ struct RecursionConstraint { std::array create_recursion_constraints( Builder& builder, const RecursionConstraint& input, - std::array input_aggregation_object, - std::array nested_aggregation_object, + const std::array& input_aggregation_object, + const std::array& nested_aggregation_object, bool has_valid_witness_assignments = false); std::vector export_key_in_recursion_format(std::shared_ptr const& vkey); diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp index 4d3514f20cfc..be21ac1c4305 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp @@ -348,22 +348,20 @@ template class UltraHonkArith { UltraHonkTraceBlock poseidon_external; UltraHonkTraceBlock poseidon_internal; - // This is a set of fixed block sizes that accomodates the circuits currently processed in the ClientIvc bench. - // Note 1: The individual block sizes do NOT need to be powers of 2, this is just for conciseness. - // Note 2: Current sizes result in a full trace size of 2^18. It's not possible to define a fixed structure - // that accomdates both the kernel and the function circuit while remaining under 2^17. This is because the - // circuits differ in structure but are also both designed to be "full" within the 2^17 size. + // The set of fixed block sizes used when the structured trace is turned on. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1047): For development and practical purposes this + // needs to be more dynamic. Sizes currently set to accommodate the full e2e test. std::array fixed_block_sizes{ 1 << 10, // ecc_op; - 1 << 7, // pub_inputs; - 1 << 16, // arithmetic; - 1 << 15, // delta_range; - 1 << 14, // elliptic; - 1 << 16, // aux; - 1 << 15, // lookup; + 30000, // pub_inputs; + 755000, // arithmetic; + 140000, // delta_range; + 600000, // elliptic; + 1400000, // aux; + 460000, // lookup; 1 << 7, // busread; - 1 << 11, // poseidon_external; - 1 << 14 // poseidon_internal; + 15000, // poseidon_external; + 85000 // poseidon_internal; }; TraceBlocks() @@ -409,12 +407,17 @@ template class UltraHonkArith { void check_within_fixed_sizes() { + int i = 0; for (auto block : this->get()) { if (block.size() > block.get_fixed_size()) { info("WARNING: Num gates in circuit block exceeds the specified fixed size - execution trace will " "not be constructed correctly!"); + info("Block index: ", i); + info("Actual size: ", block.size()); + info("Fixed size: ", block.get_fixed_size()); ASSERT(false); } + i++; } } diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 5db8fda12967..41ee122490fa 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -204,9 +204,10 @@ library Constants { uint256 internal constant LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 64; uint256 internal constant NUM_MSGS_PER_BASE_PARITY = 4; uint256 internal constant NUM_BASE_PARITY_PER_ROOT_PARITY = 4; - uint256 internal constant RECURSIVE_PROOF_LENGTH = 93; - uint256 internal constant NESTED_RECURSIVE_PROOF_LENGTH = 109; - uint256 internal constant VERIFICATION_KEY_LENGTH_IN_FIELDS = 114; + uint256 internal constant RECURSIVE_PROOF_LENGTH = 393; + uint256 internal constant NESTED_RECURSIVE_PROOF_LENGTH = 393; + uint256 internal constant TUBE_PROOF_LENGTH = 393; + uint256 internal constant VERIFICATION_KEY_LENGTH_IN_FIELDS = 103; uint256 internal constant SENDER_SELECTOR = 0; uint256 internal constant ADDRESS_SELECTOR = 1; uint256 internal constant STORAGE_ADDRESS_SELECTOR = 1; diff --git a/noir-projects/gates_report.sh b/noir-projects/gates_report.sh index d7968406f25b..ff638e59ac62 100755 --- a/noir-projects/gates_report.sh +++ b/noir-projects/gates_report.sh @@ -1,9 +1,9 @@ #!/usr/bin/env bash set -eu -# TODO(https://github.com/noir-lang/noir/issues/4962): This script is still yet to be integrated with noir-lang/noir-gates-diff +# TODO(https://github.com/noir-lang/noir/issues/4962): This script is still yet to be integrated with noir-lang/noir-gates-diff # The script needs some slight updating as `nargo info` expects a complete JSON object, while this script expects a single object field -# representing a list of circuit reports for a program. +# representing a list of circuit reports for a program. # The ACIR tests in barretenberg also expect every target bytecode to have the name `acir.gz` while this script expects the same name of the package cd noir-protocol-circuits PROTOCOL_CIRCUITS_DIR=$PWD @@ -12,24 +12,24 @@ BB_BIN=${BB_BIN:-../../barretenberg/cpp/build/bin/bb} echo "{\"programs\": [" > gates_report.json -# Bound for checking where to place last parentheses +# Bound for checking where to place last parentheses NUM_ARTIFACTS=$(ls -1q "$PROTOCOL_CIRCUITS_DIR/target"/*.json | wc -l) ITER="1" -for pathname in "$PROTOCOL_CIRCUITS_DIR/target"/*.json; do +for pathname in "$PROTOCOL_CIRCUITS_DIR/target"/*.json; do ARTIFACT_NAME=$(basename -s .json "$pathname") - GATES_INFO=$($BB_BIN gates -b "./target/$ARTIFACT_NAME.json") + GATES_INFO=$($BB_BIN gates -h -b "./target/$ARTIFACT_NAME.json") MAIN_FUNCTION_INFO=$(echo $GATES_INFO | jq -r '.functions[0] | .name = "main"') echo "{\"package_name\": \"$ARTIFACT_NAME\", \"functions\": [$MAIN_FUNCTION_INFO]" >> gates_report.json if (($ITER == $NUM_ARTIFACTS)); then echo "}" >> gates_report.json - else + else echo "}, " >> gates_report.json fi ITER=$(( $ITER + 1 )) done -echo "]}" >> gates_report.json \ No newline at end of file +echo "]}" >> gates_report.json \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr index 134421e483f0..cb9aebbbb13e 100644 --- a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr @@ -48,7 +48,8 @@ impl RootParityInputs { //TODO: Do we need to validate this following hash //assert(hash(self.children[i].verification_key) == self.children[i].verification_key.hash); self.children[i].verify(); - self.children[i].validate_in_vk_tree(); + // TODO(#7410) we need the tube vk to reinstate this + // self.children[i].validate_in_vk_tree(); } } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr index f016a8ada883..35608b4c28d4 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr @@ -40,10 +40,6 @@ impl PrivateKernelInitCircuitPrivateInputs { private_call_data_validator.validate_as_first_call(); private_call_data_validator.validate_against_tx_request(self.tx_request); private_call_data_validator.validate(output.end.note_hashes); - if !std::runtime::is_unconstrained() { - // verify/aggregate the private call proof - self.private_call.verify(); - } // Validate output. if !std::runtime::is_unconstrained() { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr index a98a4a5c6b67..2f34b4de60b0 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -53,11 +53,8 @@ impl PrivateKernelInnerCircuitPrivateInputs { private_call_data_validator.validate_against_previous_kernel(self.previous_kernel.public_inputs); private_call_data_validator.validate(output.end.note_hashes); if !std::runtime::is_unconstrained() { - // verify/aggregate the private call proof - self.private_call.verify(); - // verify/aggregate the previous kernel - self.previous_kernel.verify(); - self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) currently stubbed out until tube vk handled + // self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } // Validate output. @@ -150,13 +147,11 @@ mod tests { let _res = builder.execute(); } } - - #[test(should_fail_with="Invalid vk index")] - fn invalid_previous_kernel() { - let mut builder = PrivateKernelInnerInputsBuilder::new(); - - builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); - - let _res = builder.execute(); - } + // TODO(#7410) we need the tube vk to reinstate this + // #[test(should_fail_with="Invalid vk index")] + // fn invalid_previous_kernel() { + // let mut builder = PrivateKernelInnerInputsBuilder::new(); + // builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); + // let _res = builder.execute(); + // } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr index bd442c0eaf40..8d8ef785f207 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr @@ -42,9 +42,8 @@ impl PublicKernelCircuitPublicInputs { if !dep::std::runtime::is_unconstrained() { - // verify the previous kernel proof - self.previous_kernel.verify(); - self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) currently stubbed out until tube vk handled + // self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } // construct the circuit outputs let mut public_inputs = PublicKernelCircuitPublicInputsBuilder::empty(); @@ -85,7 +84,7 @@ impl PublicKernelAppLogicCircuitPrivateInputs { let mut remaining_calls = array_to_bounded_vec(self.previous_kernel.public_inputs.end.public_call_stack); let reverted_call_request = remaining_calls.pop(); // even though we reverted, we still need to make sure the correct call was made - // but don't do the full `validate_call_against_request` because + // but don't do the full `validate_call_against_request` because // that makes a bunch of assertions that we don't want to make // e.g. that msg_sender is self in the case of internal. // We don't want to make those checks because we already know we reverted, @@ -210,7 +209,7 @@ mod tests { // the key difference in this test versus those that use builder.execute() // is that we do not add a public call request to the previous kernel. - // this means that when we call `to_public_kernel_data` below, + // this means that when we call `to_public_kernel_data` below, // it will say needs_app_logic is false let previous_kernel = builder.previous_kernel.to_public_kernel_data(true); @@ -304,7 +303,7 @@ mod tests { builder.public_call.public_inputs.nullifiers.extend_from_array(current); let siloed = current.map( - |current: Nullifier| + |current: Nullifier| Nullifier { value: compute_siloed_nullifier(contract_address, current.value), note_hash: current.note_hash, counter: current.counter } ); @@ -636,13 +635,11 @@ mod tests { let _res = builder.execute(); } } - - #[test(should_fail_with="Invalid vk index")] - fn invalid_previous_kernel() { - let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new(); - - builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); - - let _res = builder.execute(); - } + // TODO(#7410) we need the tube vk to reinstate this + // #[test(should_fail_with="Invalid vk index")] + // fn invalid_previous_kernel() { + // let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new(); + // builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); + // let _res = builder.execute(); + // } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr index 46f0d711000c..bb7f785607ef 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr @@ -18,8 +18,8 @@ struct PublicKernelSetupCircuitPrivateInputs { // And we just initialize the missing values to zero in TS before passing it to the circuit, // except for the constants.global_variables which we populate with the current block values. // This is a bit of a hack, but it allows us to reuse the setup circuit until - // the setup phase of the public kernel is complete. Maybe in a perfect world we would - // have a SetupInit, SetupInner, etc, but this will change anyway once the public VM is able to + // the setup phase of the public kernel is complete. Maybe in a perfect world we would + // have a SetupInit, SetupInner, etc, but this will change anyway once the public VM is able to // consume entire enqueued public calls. previous_kernel: PublicKernelData, public_call: PublicCallData, @@ -46,9 +46,10 @@ impl PublicKernelSetupCircuitPrivateInputs { fn public_kernel_setup(self) -> PublicKernelCircuitPublicInputs { if !dep::std::runtime::is_unconstrained() { - // verify the previous kernel proof + // Recursively verify the tube proof or a previous public kernel proof self.previous_kernel.verify(); - self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) currently stubbed out until tube vk handled + // self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } // construct the circuit outputs let mut public_inputs = PublicKernelCircuitPublicInputsBuilder::empty(); @@ -626,13 +627,11 @@ mod tests { let _res = builder.execute(); } } - - #[test(should_fail_with="Invalid vk index")] - fn invalid_previous_kernel() { - let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); - - builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); - - let _res = builder.execute(); - } + // TODO(#7410) we need the tube vk to reinstate this + // #[test(should_fail_with="Invalid vk index")] + // fn invalid_previous_kernel() { + // let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); + // builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); + // let _res = builder.execute(); + // } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr index 72061159abbe..30e065b30413 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr @@ -67,9 +67,10 @@ impl PublicKernelTailCircuitPrivateInputs { pub fn public_kernel_tail(self) -> KernelCircuitPublicInputs { if !dep::std::runtime::is_unconstrained() { - // verify the previous kernel proof + // Recursively verify the tube proof or a previous public kernel proof self.previous_kernel.verify(); - self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) currently stubbed out until tube vk handled + // self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } self.validate_inputs(); @@ -629,13 +630,11 @@ mod tests { let _res = builder.execute(); } - - #[test(should_fail_with="Invalid vk index")] - fn invalid_previous_kernel() { - let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); - - builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); - - let _res = builder.execute(); - } + // TODO(#7410) we need the tube vk to reinstate this + // #[test(should_fail_with="Invalid vk index")] + // fn invalid_previous_kernel() { + // let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); + // builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); + // let _res = builder.execute(); + // } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr index 8069c45fc435..b92619c190d7 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr @@ -108,7 +108,8 @@ impl PublicKernelTeardownCircuitPrivateInputs { if !dep::std::runtime::is_unconstrained() { // verify the previous kernel proof self.previous_kernel.verify(); - self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) currently stubbed out until tube vk handled + // self.previous_kernel.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } // construct the circuit outputs @@ -606,13 +607,10 @@ mod tests { let _res = builder.execute(); } } - - #[test(should_fail_with="Invalid vk index")] - fn invalid_previous_kernel() { - let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); - - builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); - - let _res = builder.execute(); - } + // #[test(should_fail_with="Invalid vk index")] + // fn invalid_previous_kernel() { + // let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); + // builder.previous_kernel = builder.previous_kernel.in_vk_tree(BASE_ROLLUP_INDEX); + // let _res = builder.execute(); + // } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr index 52a87dda50ca..9a5a20b7937f 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr @@ -65,9 +65,10 @@ struct BaseRollupInputs { impl BaseRollupInputs { pub fn base_rollup_circuit(self) -> BaseOrMergeRollupPublicInputs { if !dep::std::runtime::is_unconstrained() { - // Verify the kernel circuit proof + // Recursively verify the tube proof if straight from private, or the public kernel tail self.kernel_data.verify(); - self.kernel_data.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) we need the tube vk to reinstate this + // self.kernel_data.validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } // Verify the kernel chain_id and versions assert( @@ -259,7 +260,7 @@ impl BaseRollupInputs { } // Deducts the tx_fee from the GasToken balance of the fee_payer. If there is already a PublicDataUpdateRequest - // in this tx for their balance (because they issued a 'claim' to increase their balance by bridging from L1), + // in this tx for their balance (because they issued a 'claim' to increase their balance by bridging from L1), // update it by subtracting the tx_fee. Otherwise, build a new PublicDataUpdateRequest to subtract the tx_fee // from the balance of the fee_payer, using the fee_payer_gas_token_balance_read_hint to read the current balance. // Returns the data update request that subtracts the tx_fee from the fee_payer's balance, and the index where it @@ -1447,13 +1448,11 @@ mod tests { let _res = builder.execute(); } - - #[test(should_fail_with="Invalid vk index")] - fn invalid_previous_kernel() { - let mut builder = BaseRollupInputsBuilder::new(); - - builder.kernel_data = builder.kernel_data.in_vk_tree(BASE_ROLLUP_INDEX); - - let _res = builder.execute(); - } + // TODO(#7410) we need the tube vk to reinstate this + // #[test(should_fail_with="Invalid vk index")] + // fn invalid_previous_kernel() { + // let mut builder = BaseRollupInputsBuilder::new(); + // builder.kernel_data = builder.kernel_data.in_vk_tree(BASE_ROLLUP_INDEX); + // let _res = builder.execute(); + // } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr index cd04084aec0b..792e62acd32f 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr @@ -29,10 +29,12 @@ impl MergeRollupInputs { // Verify the previous rollup proofs if !dep::std::runtime::is_unconstrained() { self.previous_rollup_data[0].verify(); - self.previous_rollup_data[0].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) we need the tube vk to reinstate this + // self.previous_rollup_data[0].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); self.previous_rollup_data[1].verify(); - self.previous_rollup_data[1].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) we need the tube vk to reinstate this + // self.previous_rollup_data[1].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } let left = self.previous_rollup_data[0].base_or_merge_rollup_public_inputs; @@ -212,17 +214,14 @@ mod tests { let _outputs = inputs.merge_rollup_circuit(); } - - #[test(should_fail_with="Invalid vk index")] - fn invalid_previous_circuit() { - let mut inputs = default_merge_rollup_inputs(); - - let vk_tree = dep::types::tests::fixtures::vk_tree::get_vk_merkle_tree(); - - inputs.previous_rollup_data[0].vk.hash = vk_tree.leaves[ROOT_PARITY_INDEX]; - inputs.previous_rollup_data[0].vk_witness.leaf_index = ROOT_PARITY_INDEX as Field; - inputs.previous_rollup_data[0].vk_witness.sibling_path = vk_tree.get_sibling_path(ROOT_PARITY_INDEX); - - let _outputs = inputs.merge_rollup_circuit(); - } + // TODO(#7410) we need the tube vk to reinstate this + // #[test(should_fail_with="Invalid vk index")] + // fn invalid_previous_circuit() { + // let mut inputs = default_merge_rollup_inputs(); + // let vk_tree = dep::types::tests::fixtures::vk_tree::get_vk_merkle_tree(); + // inputs.previous_rollup_data[0].vk.hash = vk_tree.leaves[ROOT_PARITY_INDEX]; + // inputs.previous_rollup_data[0].vk_witness.leaf_index = ROOT_PARITY_INDEX as Field; + // inputs.previous_rollup_data[0].vk_witness.sibling_path = vk_tree.get_sibling_path(ROOT_PARITY_INDEX); + // let _outputs = inputs.merge_rollup_circuit(); + // } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr index 68c62d126c7f..863a8074f9d8 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr @@ -41,14 +41,17 @@ impl RootRollupInputs { // Verify the previous rollup proofs if !dep::std::runtime::is_unconstrained() { self.previous_rollup_data[0].verify(); - self.previous_rollup_data[0].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) we need the tube vk to reinstate this + // self.previous_rollup_data[0].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); self.previous_rollup_data[1].verify(); - self.previous_rollup_data[1].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); + // TODO(#7410) we need the tube vk to reinstate this + // self.previous_rollup_data[1].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); // verify the root parity self.l1_to_l2_roots.verify(); - self.l1_to_l2_roots.validate_in_vk_tree(); + // TODO(#7410) we need the tube vk to reinstate this + // self.l1_to_l2_roots.validate_in_vk_tree(); } let left = self.previous_rollup_data[0].base_or_merge_rollup_public_inputs; @@ -65,7 +68,7 @@ impl RootRollupInputs { self.l1_to_l2_message_subtree_sibling_path, empty_l1_to_l2_subtree_root, self.l1_to_l2_roots.public_inputs.converted_root, - // TODO(Kev): For now we can add a test that this fits inside of + // TODO(Kev): For now we can add a test that this fits inside of // a u8. L1_TO_L2_MSG_SUBTREE_HEIGHT as u8 ); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr index bf3868946025..6afa3fed807d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr @@ -14,7 +14,6 @@ struct PrivateCallData { public_call_stack: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], public_teardown_call_request: CallRequest, - proof: RecursiveProof, vk: VerificationKey, salted_initialization_hash: SaltedInitializationHash, @@ -22,18 +21,6 @@ struct PrivateCallData { contract_class_artifact_hash: Field, contract_class_public_bytecode_commitment: Field, function_leaf_membership_witness: MembershipWitness, - - acir_hash: Field, -} -impl Verifiable for PrivateCallData { - fn verify(self) { - let inputs = PrivateCircuitPublicInputs::serialize(self.call_stack_item.public_inputs); - std::verify_proof( - self.vk.key.as_slice(), - self.proof.fields.as_slice(), - inputs.as_slice(), - self.vk.hash - ); - } + acir_hash: Field, } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr index 0439e09afc51..781be7d481c3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr @@ -5,18 +5,8 @@ use crate::merkle_tree::membership::assert_check_membership; use crate::utils::arrays::find_index_hint; struct PrivateKernelData { - // TODO(David): Left a note asking if we need this due to it - // already being in the proof. public_inputs: PrivateKernelCircuitPublicInputs, - // TODO(David): Mentions the dichotomy between a proof created for the - // circuit, which is a sequence of field elements, versus a proof - // created for solidity/native verification which is a collection of bytes. - // Kev: I've been questioning if we _need_ the sequence of field elements. - // It makes verification cheaper, though I have not tested how much cheaper. - // Removing it would also reduce complexity on the Noir side, as we have - // special methods to convert "inner proofs" into sequence of field elements. - proof: NestedRecursiveProof, vk: VerificationKey, // This index and path are meant to be those of a leaf within the tree of protocol circuits vks; not the tree @@ -25,18 +15,6 @@ struct PrivateKernelData { vk_path: [Field; VK_TREE_HEIGHT], } -impl Verifiable for PrivateKernelData { - fn verify(self) { - let inputs = PrivateKernelCircuitPublicInputs::serialize(self.public_inputs); - std::verify_proof( - self.vk.key.as_slice(), - self.proof.fields.as_slice(), - inputs.as_slice(), - self.vk.hash - ); - } -} - impl PrivateKernelData { fn validate_in_vk_tree(self, allowed_indices: [u32; N]) { let index_hint = find_index_hint(allowed_indices, self.vk_index); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index dd8e58736303..49f67780fccd 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -170,10 +170,10 @@ global FIXED_L2_GAS: u32 = 512; global FIXED_AVM_STARTUP_L2_GAS = 1024; // pays for hashing/validating logs global L2_GAS_PER_LOG_BYTE = 4; -// pays for tree insertions. +// pays for tree insertions. global L2_GAS_PER_NOTE_HASH = 32; // nullifiers are more expensive to insert/validate: -// they are inserted into an indexed tree and must be checked for duplicates +// they are inserted into an indexed tree and must be checked for duplicates global L2_GAS_PER_NULLIFIER = 64; // CANONICAL CONTRACT ADDRESSES @@ -270,11 +270,13 @@ global NUM_MSGS_PER_BASE_PARITY: u32 = 4; // FIX: Sadly, writing this as above causes a type error in type_conversion.ts. global NUM_BASE_PARITY_PER_ROOT_PARITY: u32 = 4; +// TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation // Lengths of the different types of proofs in fields -global RECURSIVE_PROOF_LENGTH = 93; -global NESTED_RECURSIVE_PROOF_LENGTH = 109; +global RECURSIVE_PROOF_LENGTH = 393; +global NESTED_RECURSIVE_PROOF_LENGTH = 393; +global TUBE_PROOF_LENGTH = RECURSIVE_PROOF_LENGTH; // in the future these can differ -global VERIFICATION_KEY_LENGTH_IN_FIELDS = 114; +global VERIFICATION_KEY_LENGTH_IN_FIELDS = 103; /** * Enumerate the hash_indices which are used for pedersen hashing. diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr index bf2afcf5da84..de1d41b7fd11 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -183,9 +183,9 @@ pub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, pub fn accumulate_sha256(input: [Field; 2]) -> Field { // This is a note about the cpp code, since it takes an array of Fields // instead of a U128. - // 4 Field elements when converted to bytes will usually + // 4 Field elements when converted to bytes will usually // occupy 4 * 32 = 128 bytes. - // However, this function is making the assumption that each Field + // However, this function is making the assumption that each Field // only occupies 128 bits. // // TODO(David): This does not seem to be getting guaranteed anywhere in the code? @@ -205,7 +205,7 @@ pub fn accumulate_sha256(input: [Field; 2]) -> Field { // Computes the final logs hash for a tx. // NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX -// to avoid doubling code, since we can't define the byte len to be 32*N directly. +// to avoid doubling code, since we can't define the byte len to be 32*N directly. pub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field { // Convert each field element into a byte array and append the bytes to `hash_input_flattened` let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32]; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index db5ce46d15e4..13f3a1850f98 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -80,7 +80,7 @@ struct FixtureBuilder { historical_header: Header, tx_context: TxContext, global_variables: GlobalVariables, - + // Accumulated data. note_hashes: BoundedVec, nullifiers: BoundedVec, @@ -128,7 +128,7 @@ struct FixtureBuilder { vk_index: u32, vk_path: [Field; VK_TREE_HEIGHT], vk_tree_root: Field, - + // Counters. min_revertible_side_effect_counter: u32, counter_start: u32, @@ -294,7 +294,6 @@ impl FixtureBuilder { call_stack_item: self.to_private_call_stack_item(), public_call_stack: subarray(self.public_call_requests.storage), public_teardown_call_request: self.public_teardown_call_stack.storage[0], - proof: RecursiveProof::empty(), vk: self.vk, function_leaf_membership_witness: self.function_leaf_membership_witness, salted_initialization_hash: self.salted_initialization_hash, @@ -421,7 +420,7 @@ impl FixtureBuilder { pub fn to_private_kernel_data(self) -> PrivateKernelData { let public_inputs = self.to_private_kernel_circuit_public_inputs(); - PrivateKernelData { public_inputs, proof: self.proof, vk: self.vk, vk_index: self.vk_index, vk_path: self.vk_path } + PrivateKernelData { public_inputs, vk: self.vk, vk_index: self.vk_index, vk_path: self.vk_path } } pub fn to_public_kernel_circuit_public_inputs(self, revertible: bool) -> PublicKernelCircuitPublicInputs { diff --git a/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js b/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js index 68a60491bfcc..8071d782d5ba 100644 --- a/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js +++ b/noir-projects/noir-protocol-circuits/scripts/generate_vk_json.js @@ -119,9 +119,8 @@ async function generateVKData( ); const jsonVkPath = vkJsonFileNameForArtifactName(outputFolder, artifactName); - const writeVkCommand = `${BB_BIN_PATH} write_vk -b "${artifactPath}" -o "${binaryVkPath}"`; - - const vkAsFieldsCommand = `${BB_BIN_PATH} vk_as_fields -k "${binaryVkPath}" -o "${jsonVkPath}"`; + const writeVkCommand = `${BB_BIN_PATH} write_vk_ultra_honk -h -b "${artifactPath}" -o "${binaryVkPath}"`; + const vkAsFieldsCommand = `${BB_BIN_PATH} vk_as_fields_ultra_honk -k "${binaryVkPath}" -o "${jsonVkPath}"`; await new Promise((resolve, reject) => { child_process.exec(`${writeVkCommand} && ${vkAsFieldsCommand}`, (err) => { diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml index 921b69e100ac..fc5e6002dbfd 100644 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml +++ b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml @@ -1,4 +1,4 @@ key_hash = "0x096129b1c6e108252fc5c829c4cc9b7e8f0d1fd9f29c2532b563d6396645e08f" -proof = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf","0x00000000000000000000000000000000000000000000000b75c020998797da78","0x0000000000000000000000000000000000000000000000005a107acb64952eca","0x000000000000000000000000000000000000000000000000000031e97a575e9d","0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4","0x00000000000000000000000000000000000000000000000c410db10a01750aeb","0x00000000000000000000000000000000000000000000000d722669117f9758a4","0x000000000000000000000000000000000000000000000000000178cbf4206471","0x000000000000000000000000000000000000000000000000e91b8a11e7842c38","0x000000000000000000000000000000000000000000000007fd51009034b3357f","0x000000000000000000000000000000000000000000000009889939f81e9c7402","0x0000000000000000000000000000000000000000000000000000f94656a2ca48","0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f","0x0000000000000000000000000000000000000000000000093fe27776f50224bd","0x000000000000000000000000000000000000000000000004a0c80c0da527a081","0x0000000000000000000000000000000000000000000000000001b52c2020d746","0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632","0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc","0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62","0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c","0x000000000000000000000000000000b0804efd6573805f991458295f510a2004","0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e","0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47","0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15","0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd","0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383","0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4","0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x000000000000000000000000000000f968b227a358a305607f3efc933823d288","0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08","0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f","0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1","0x0000000000000000000000000000005b739ed2075f2b046062b8fc6a2d1e9863","0x00000000000000000000000000000000001285cd1030d338c0e1603b4da2c838","0x00000000000000000000000000000027447d6c281eb38b2b937af4a516d60c04","0x000000000000000000000000000000000019bc3d980465fbb4a656a74296fc58","0x000000000000000000000000000000b484788ace8f7df86dd5e325d2e9b12599","0x00000000000000000000000000000000000a2ca0d10eb7b767114ae230b728d3","0x000000000000000000000000000000c6dfc7092f16f95795e437664498b88d53","0x0000000000000000000000000000000000131067b4e4d95a4f6f8cf5c9b5450a","0x0f413f22eec51f2a02800e0cafaeec1d92d744fbbaef213c687b9edabd6985f5","0x21230f4ff26c80ffb5d037a9d1d26c3f955ca34cbeca4f54db6656b932967a0c","0x0521f877fe35535767f99597cc50effbd283dcae6812ee0a7620d796ccbfd642","0x202b01350a9cc5c20ec0f3eaada338c0a3b793811bd539418ffa3cc4302615e2","0x2d1214d9b0d41058ad4a172d9c0aecc5bdabe95e687c3465050c6b5396509be4","0x1113b344a151b0af091cb28d728b752ebb4865da6cd7ee68471b961ca5cf69b9","0x2aa66d0954bb83e17bd5c9928d3aa7a7df75d741d409f7c15ba596804ba643fb","0x2e26bc7a530771ef7a95d5360d537e41cf94d8a0942764ff09881c107f91a106","0x0f14f32b921bb63ad1df00adab7c82af58ea8aa7f353f14b281208d8c5fab504","0x13429515c0c53b6502bbcdf545defb3cb69a986c9263e070fcbb397391aae1a3","0x1f21cac5e2f262afc1006a21454cc6bcb018c44e53ad8ab61cebbac99e539176","0x2a9886a6ddc8a61b097c668cd362fc8acdee8dde74f7b1af192c3e060bb2948f","0x2d718181e408ead2e9bcd30a84ad1fccbaf8d48ab6d1820bad4933d284b503c4","0x2634c1aafc902f14508f34d3d7e9d485f42d1a4c95b5a1ef73711ed0d3c68d77","0x092ede9777e6472ce5ffd8c963d466006189e960e2c591d338dc8d4af1a057fb","0x1cba45b17fd24f1cb1b4ab7b83eee741f6c77ba70a497dc4de259eceb7d5ea26","0x246e887c7bf2e17f919b2393b6e9b00b33e8822d862544a775aac05cb7bff710","0x04c3f539fe8689971948afcb437f1ecbd444a5bddaca1c8a450348dcd8480047","0x20c6a423ae4fd58e8951aa378d02d77baf90508ceb48856db2319d70938b186e","0x1bcf8786b554b3316d8ebdbc9d006a4e5d4865aad512ffd404b7f83550d3d030","0x09ab038260518f0970564afcd6bf22e2abf6b1fa5e12a327bbf195b6ca5edd78","0x1024e32554746f89c195286ba6ccfc9765e5d14bbe8064bc6fdf22d16ec6b495","0x17706656f8dbd7e47bb257a6428f0cb7278ea02fa9e6ce431d7bcc9133fba9c7","0x25a3e8a33c15ef2a4dd16313a6049bf1d468b4cdc141f238f2d51a1e8e1c22b3","0x1198863f08006edb27aee23164fb117a4ddec1bf1ed89807aa907e5cd24bf068","0x1862b4856b5b4d4a064f873e221703e4e2cd1ebfca1337dedca56485c38ed5a0","0x062214af1ea6dd6bf8895b92d394571c43970b6f967e1c794624d96071b25ad3","0x1e5be9428ddcf1f9b0cbafc28101e792ec5cf73852b0cd0b84fbff71b4490e09","0x2d4189bea5b1e30f63c64bd26df82f18bcaf885ec8887b54634b2557869ce87f","0x0f2e5d9a908850e9d44925e17d8b12d1adb1ed029799c9b5858598504242bbc0","0x3050dc85746a57931d99f3f35e77c2ba561fba0baa018b79ff1fd544026833ae","0x2a591a32437e5e0b875a137fd868bd1b6dbc003ff1b661f26e00627cc7c5cf47","0x27946841e1670ad9c65717016d0cedf524724217236e81b9fd0a264a36ebfb0e","0x0fc396e9d19d6e68e289602e292ee345542d0d28bf6de34fa62cc577cbdfb1df","0x08e7433a07a44c0c9c4dd4b273a2685bbd1a91fd5cf2b43409458fab42a23e1b","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x12bd9bfb029c3503a5c6deea87b0a0f11bb9f7ea584af2d48f3e48d7e09247ae","0x2ccc4810748c0a82dfc0f063d0b8c7999ffe9474653080e6ef92b3cb7a428784","0x08eb574d7fecadadb508c8bd35fdad06b99110609d679763c2e3645229b1b95a","0x0f1a65e747c8021ed7c454a4be1e89b1bce66ead9ed980fa98a7a050eafe98a1","0x1c8ff9e36684ec71614dee4c17859b06c742089f6029d3694a16e00dac9b57f1","0x0303101a8ba712aeca4da85b767ab8d3ecf489ec7d746f8ee20041717cc000e9","0x0aaf64c65e7088e5596108c9601467911fea809ca6540d79af77e6e66e36cd99","0x17caf164ce74ea7edfb1390e07763d2197797ec26661b92cde18a98d61d2fddc","0x18cb055c7ad6d01437725bb457681d81f3ecadc4f35d838a3c13daf25a44456a","0x2d78602b8bbcd32b36a99a6e2d248e7fe044ef1b50813133370412f9ef5299f0","0x2b139276ea86d426a115479e4154f72a6bd83a6253bf13e9670dc6b4664378f0","0x127c7837b384902c39a104036c09546728571c46c8166b1b9b13b3a615ebb781","0x05faa4816f83cf0189a482ad943c94b9ec6474002f2b327f8698763ad0ea0985","0x2f90359cc30ee693fb3aced96523cf7aebd152c22329eee56a398d9a4ac0628e","0x0a71beaf17a59c5a238f04c1f203848d87502c5057a78c13f0cfb0f9876e7714","0x2696c1e6d089556adaeb95c8a5e3065b00a393a38c2d69e9bd6ce8cdc49d87da","0x1f3d165a7dc6564a036e451eb9cb7f1e1cb1e6d29daa75e3f135ea3e58a79ccd","0x1473a660819bdd838d56122b72b32b267211e9f1103239480ec50fa85c9e1035","0x0a8ccaeb22451f391b3fc3467c8e6e900270a7afb7b510e8acf5a4f06f1c0888","0x03b3080afc0658cc87e307758cebc171921f43eca159b9dedf7f72aa8dd926bd","0x2dd7d6663fa0e1755dfafac352c361fcd64c7f4d53627e3646870ac169cc4a07","0x1ec54b883f5f35ccad0e75695af20790d9860104095bab34c9bf01628dd40cb9","0x193dff50f83c241f7a9e087a29ce72ecf3f6d8563593f786dcd04c32bcfd4ced","0x135122c0dae26cda8ca1c09de8225064ad86d10423ab0aaa53b481aa4626e1d6","0x08d5a56cbfab5aeed56d3cdd7fb6b30fc26b0c1a5b63fccd7fa44c53ba6fd35a","0x0d12f126dfa2daad3726d00ca339284cc22e36c6d81bb7a4b95c6f9598b60e7c","0x2e8b24bbdf2fd839d3c7cae1f0eeb96bfcfaeef30b27476f2fafcb17da78cd5e","0x2364acfe0cea39b7f749c5f303b99504977357925f810f684c60f35d16315211","0x06ca062eb70b8c51cfac35345e7b6b51f33a8ec9ebe204fb9b4911200bf508b7","0x266c0aa1ccb97186815bf69084f600d06ddd934e59a38dfe602ee5d6b9487f22","0x1d817537a49c6d0e3b4b65c6665334b91d7593142e60065048be9e55ceb5e7ab","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x25b77026673a1e613e50df0e88fb510973739d5f9064bd364079a9f884209632","0x25c9bc7a3f6aae3d43ff68b5614b34b5eaceff37157b37347995d231784ac1fd","0x085f69baef22680ae15f4801ef4361ebe9c7fc24a94b5bc2527dce8fb705439e","0x0d7c6b9ce31bfc32238a205455baf5ffe99cd30eb0f7bb5b504e1d4501e01382","0x1001a8cc4bc1221c814fba0eddcf3c40619b133373640c600de5bed0a0a05b10","0x20f5894be90e52977cb70f4f4cbd5101693db0360848939750db7e91109d54b6","0x22c09cb26db43f0599408b4daed0f4f496c66424e6affa41c14387d8e0af851b","0x24e5f41357798432426a9549d71e8cc681eaebacbe87f6e3bf38e85de5aa2f3d","0x06eb90100c736fbf2b87432d7821ecdc0b365024739bc36363d48b905973f5b9","0x000000000000000000000000000000ece6d09ed58e9f5661c01140b10558a8c2","0x000000000000000000000000000000000012b6e4f37adcb34b8e88ff8b6eebce","0x000000000000000000000000000000b226a2bb93593fa1fab19a44767828a3f5","0x00000000000000000000000000000000002b5b518342030543092e1428a7e33c","0x00000000000000000000000000000022ba33857034a0574c216eb3c1ddff3025","0x00000000000000000000000000000000001918e58df857985a7cf9eae7802165","0x00000000000000000000000000000045c2d840b96fb6106cc14dcad89dd5f675","0x00000000000000000000000000000000000afdfac1e3a1febdd0208867d44f98","0x00000000000000000000000000000042ebed6c5ec45d794f119aef24c192af0f","0x00000000000000000000000000000000002d05ef250900bbcc5751bbeb210d6a","0x00000000000000000000000000000060d604bdda48eecc90ed065bd9770e1323","0x00000000000000000000000000000000001fed91c63d0041660c1cbc84c2ffbb","0x00000000000000000000000000000054196b549cde36092e8184c7f4f7d878de","0x00000000000000000000000000000000000153f26a01294329922b492485cc31","0x00000000000000000000000000000056ebea579d10dbb440f0222931df2c0059","0x00000000000000000000000000000000000d2cbc61ce5b7cdd7fce398da4637b","0x000000000000000000000000000000e2b9512360b9797d96675d8a2fd2f7aa5d","0x000000000000000000000000000000000025742905f105ff895f74e7c3daa34a","0x000000000000000000000000000000a2dd7df55db59bd41b83518d4403fbc382","0x00000000000000000000000000000000002c1d9c3cbb9371d4cc4e9f900b9a46","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000bcf12ae40c9425c3e67654b84181f90502","0x00000000000000000000000000000000000b6d3faa8a71ff6ef1aa887b7307cf","0x0000000000000000000000000000001f6f719acc23b8f84808c0275d61cfb456","0x0000000000000000000000000000000000296030933ed0c134457ae71c393dfe","0x000000000000000000000000000000ebe1a57cdd7d3d763289b40ef5ed9a7ae0","0x000000000000000000000000000000000010f30483e7df51fca2316d3367603c","0x0000000000000000000000000000000149b7b283ab18060618c8e051864c03cd","0x00000000000000000000000000000000001ef7763235a3a25e241a5f06704dc3"] +proof = ["0x0000000000000000000000000000000000000000000000000000000000000010","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000001","0x00000000000000000000000000000079ea57b3d7247e1b84fc1ab449de746345","0x000000000000000000000000000000000023fb17d477c91e0fb057233a66ef2a","0x000000000000000000000000000000146353d3faf24455819947aa0a25868174","0x00000000000000000000000000000000000093b1c637419c9f016bb0261cdfc6","0x000000000000000000000000000000325b128a84544d31fa1c577232c742b574","0x00000000000000000000000000000000002b3db93a2fca4c31308471d4f55fa2","0x00000000000000000000000000000054d9d87932eee6280c37d802ec8d47ca02","0x000000000000000000000000000000000000397167bb1e36d061487e93e4d97e","0x000000000000000000000000000000143b0960a1b9f19a44ad1cf2b7059832d6","0x0000000000000000000000000000000000158446576b2d43f78b48799ff7e760","0x000000000000000000000000000000cf640bad8ccc1890d738ab917d6caa957e","0x00000000000000000000000000000000001d6fd185d8771b864545438c6a1d68","0x000000000000000000000000000000a33cd928d0d4c7f244824b63b15f4c5423","0x00000000000000000000000000000000000433ccd872d2a302104048474e0bea","0x000000000000000000000000000000eaf7d13e5e9706e1b8a9343bd493a060af","0x00000000000000000000000000000000001a062842ba351b311ae52693f5114e","0x000000000000000000000000000000a33cd928d0d4c7f244824b63b15f4c5423","0x00000000000000000000000000000000000433ccd872d2a302104048474e0bea","0x000000000000000000000000000000eaf7d13e5e9706e1b8a9343bd493a060af","0x00000000000000000000000000000000001a062842ba351b311ae52693f5114e","0x000000000000000000000000000000160d90f214f524875c01cb9cf0f2d272b9","0x000000000000000000000000000000000015d5f906c4fe06017b0f9824434d09","0x0000000000000000000000000000007fc2db3cfe49b7666aeafd8cf6973c9fed","0x00000000000000000000000000000000000c7fc1e545a8ee19a7bc6ad6f2ea47","0x000000000000000000000000000000fc3c9df244afbba117cd897a4c929edb84","0x0000000000000000000000000000000000216f0c3a2e5e8683d9717ad40eadde","0x000000000000000000000000000000c381b45048aa5163e0129e4031e29058cb","0x00000000000000000000000000000000002f11022de88492201c28f87582684d","0x000000000000000000000000000000c98462e08c423124d92a41110c378db160","0x00000000000000000000000000000000000106dafb059575ec9b926aa90edfef","0x0000000000000000000000000000007d0cc0465628f6b0f3918aa9d7cf33ff38","0x00000000000000000000000000000000002cff01344fc7c6f81399b7ae660ad4","0x07eff01a06f356d255515e5f27cb51e8873277beb3f986c215181b475df4dd8e","0x28745e58da3e495762fee75759b60674a1017089c5bfe9cf2ec9da4c920b2273","0x1d5b7b751e509ac70caa253595be4523d1963cf7bd6751d2c146e2fc10d00196","0x26fe27f73b55be7d49b4c1c11f085f47f6a241ba5ea0d48b47964e7adf5e8e5a","0x239206c519de2576a554a70f387cdf5d525a599541be2ecd9260e52d572ae07c","0x04e35b29a57c31c89c72a6387bf89613b64c2827e0c2402b8dfb2c1cfea0c878","0x1e8398c5dd85d15154110c2480f2249030aecd7595242ae86bbdf7b2730ca070","0x2ba9986a038e85a4dd96badffb6a44950c37360fd6e8ec6c4b9647377bcb45f5","0x27ca7a06ceea23d329c52dac8c0715440238d37362ab0fb1e26544b18bb79a3b","0x23b768d51fa7922f8292309455adc5730b8964818c328a42dff60a57add32f50","0x24e8634d5381475abe5821450299d9d8d725a472610fe265e44c8360c4708c95","0x0cdbb73fe5c035427113e66a15b8c41e963ae215e491d855a3ce8c3ab200fb3b","0x0e8acd2ed6af85e4f71b96c51d2a57bceea5c50fb405b7888359f0635b415da7","0x2914cc0244acf5ac6d674d3c96d543ee2f3e95d0248ee66daf0cf2932107e300","0x00ff0384250d2c2e59cd1cf58cebd1d3b1ebab7989eb2eaa6b6bbce69f9e8ba0","0x253f7a5007d47d3d858fc0e172c971cb54f97cea5c63ca60efe61589913b2499","0x2d34704fc711dabe0f716dbebc5dfd0eaa5667006847d333dadc86e15bf672c0","0x0bdd67ff40c61242e46a234c0d438663a9ccae833d1e0b22833ffe41e2828bb4","0x04c7ba2edccfb340eba0c94a7a5d5d53b010939621053c7c0fd27f2ba4b08273","0x0c3f68e6de8042a10098596e80ea79882b37d22c6a6adaa64f5c668739932fa5","0x14bcb10845b45cb8fdcac13e41ad755f6d966756ee2f3d4ed8a5791d4b345ea8","0x0dd68c1e3d122d4d4b28a8ac7e6a592146afe70e3852906c27ccc7e345f745e2","0x06816aff04192007cb2b3ed2cee4b22e044ced0199b136942348ced61990c1a7","0x3013f13664687bc3cbe26314f17cf309486ef71ffb55ce2589075554fc31ee69","0x1941a602d47af0e52f06a272998b6a59313f316508c0778714a36d7bb4f5669b","0x268750f15f2ac995d1d59859b7d636ae814e751b84318218ac1ce75a14b00e18","0x2aaff14fd98aa13ffdf34e3f689e16b2e8cb7695db9a014dd270b021968e3bb2","0x090087ad0d688396823bbd90a8770c1101e5907efd1c4fbafff8a1e9f2f84d89","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x152deae3a77021b0201a74d98b30d842baea62c0d2531d69d5e866e59f48e052","0x084acb08dc53880864266b6dea02ec7a85ffab2ab590ba9a4adb32ad2c8ffe53","0x1b8ab1a2e47a839fdbf19d2cbea2abe79c57722270123cf96289a11e233cd175","0x03493f800f9abbe4e405f0f637f41f22dcc10e44e836a09115ed5821cd5856e6","0x24c358e686e47c512bbec4a1b9ac562c251e004ea142df44ea3b18cf214baa47","0x18296076ac89be1c4c24a04553be7bd07bba5a41d1c33de2bec14cfd1262ab9f","0x0e30341606dc2577a451251241394b3871e9db0e1758d250d36348bcbb8b6fdb","0x15f846978484540ac3c35eee38ccd980f01e8bda6050a645c4abca6f22b24619","0x2735dd2b603cde2937bf842002e8704ef1e3883d2d0a6e999dd7015496c10302","0x23c47d9891d04bdb88ca239119e423afdc6d2bd45fb92f5f19b8b0a9583fc863","0x1ce47f9088eecc7268d4558aa02a4902282bccaacbe882917cc57969af2236d0","0x2b5a6f937fcc921cced568de248e19fd3801e688505ee44af6499e14885c9879","0x2ae2f654890e7018bae8308b5a97230cdcd3b63b24334a05dc4fdc4107cff73d","0x06a87313997c2a5318a8ce0f75e26b9c4a2a83bd9c3578f10d1c1f3bfded8f29","0x0afe95fddb76f390d58e15b7e647e9ed083a66aa7829a18963125d865b64ef7f","0x1ff7ecaf04f4e8a9d57f79c85dd963099f6005f542df7c20505af69061473114","0x26ca489f39024294da78a601feda0a17c40d46e2c7d0787b47dc0afaf027a8c8","0x2da37034033c950b2f85c32be2b0f1102dae5ec01e13681ffc9a9a3033469a8d","0x22c35dc92f5bf1cb569ad756b45208ffa8a85d825ebacf8e7354e9162651d1fa","0x0e443f72c90fec92786098f7ec90cea01f6202db6998b34dbb1e7b0293f4bebd","0x049684508bb0af0f27bcaaf96aa53eac25a425e159eb33e031db157d63c22fb9","0x20d990716bfec57f52f603d50d0d81c4c851bfc231894eb573fa54f2ac70c9dd","0x1fd19e900621d01488be88d4a6d95c2583c19c6d1d49e8cd139bce76051b71bc","0x1679a31a104b20b301737b9214f12a0707727bd4510d5a53e5bec1321816cdfa","0x27b3d8000581372f35039477c28a268065b3717dbd9337c06a82162781e0d131","0x23b79b53bdb698ef8c7c01afaf3350deb78b5e841e09b13b6ef86fc68f97bcab","0x1d4abc42698589c40b05e187c12af268fffe64010756a8d08ea817105305a770","0x0f744ca06905efa1f604f387284979be483c00ee9298134e7337bd8bb4a88933","0x0be6790122704c6ed4c37fef0b524b413e63b88c2dadbe67a5ba039cf11cc628","0x19fa34479d41d734a17619048627633807d706b2b1035a326efada8f3e8eb183","0x1b208f5cc663a9560e8685c351cb17b8e5862eb16f1407cf654e8ffae331aa9b","0x1b140725b61fe2e1057d72525aecf1d319ecb509a392f68e4058d13cea209993","0x1b140725b61fe2e1057d72525aecf1d319ecb509a392f68e4058d13cea209993","0x0d1703eac9b276094d72a50322dd82033960a6f1f6176aa2b029e39a1375bb51","0x09ba2a48cfdcc27f6b6db2ca277c5016d4f5a177e65eec6f68e30a67d4b06c1b","0x0e243bf8b2d6b8e46ed75902fe60781b2b41cf45287f367df850ce50de7f86af","0x1be244289270e4c0dc8517edfe335954fa7b56c3bf6fe06bc2d268f7db7a68ee","0x116ef1bfcfbca0612c92872aa3d07d32cb0b9716b1ba735846888a56e03c6207","0x0de8a7471ceb058680d2e0afa73e3dd843b527db1c16ebfaf8612447ffbee858","0x16911fee4120f72d81b0dfb0eeeb7380611119ee990daec5669b711cb35e2756","0x1c278b26a16e1ee7e21a71b67a31cb0b9907dae80776aa1dc7094ea5b4e2c34e","0x0f5c67db668b1f1880c51f805ec3d40aa27d34b4c8833f755d4466c285264399","0x000000000000000000000000000000dc2546d68fbe5a4913dde8ed73f673bc5f","0x00000000000000000000000000000000001310657525d78319e5b15c92398dcf","0x0000000000000000000000000000000fde9a035776897ed560b4d9ae338b5f85","0x00000000000000000000000000000000000f84fecfb3ea28426f114d9de93cb3","0x000000000000000000000000000000d3ea685110f3ff69bf91cc32cc5170b62e","0x0000000000000000000000000000000000179205f5ebaf3eaf5d50be462f830d","0x00000000000000000000000000000024a7284c15d725d62b8f5c1090b08b58b7","0x00000000000000000000000000000000002b6fdb2139f7b9443cbd82e6423486","0x00000000000000000000000000000006489f49eed3370ee31c80590eed2d0c3a","0x000000000000000000000000000000000010c11c3a122e00a12e0cf7a58d81ae","0x000000000000000000000000000000eb2d1eef7e7c7c0c054859600d264176e9","0x000000000000000000000000000000000028ac3239a0917c7c3761e11fbf9541","0x0000000000000000000000000000006ecbe6a2ccf0c9e1b743a84e1540796b81","0x0000000000000000000000000000000000098a99a81cbc111660301a03f77d96","0x000000000000000000000000000000c4f256019891f39b00b1b00428b3a154a5","0x00000000000000000000000000000000001bc2f83790ff1d3086273e4560135c","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000868795ebcbf38bffa96f455a314c7b9310","0x00000000000000000000000000000000002e43e0a550d7cce874e869ed0ef545","0x0000000000000000000000000000001e5a780edfd01526758b69bfaf25803f67","0x00000000000000000000000000000000000f0991f4b5dc348354f019ecc66502","0x000000000000000000000000000000cb917b7819afd60fc86ea477594ffca008","0x000000000000000000000000000000000002beaa7c144fc6620870e72ee8064c","0x000000000000000000000000000000b7f4dfed23506dadd1726a896e226d7a34","0x00000000000000000000000000000000001bb28f2fcfb40843aa5f5e38d689e1"] public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] -verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84","0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae","0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16","0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1","0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c","0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7","0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8","0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c","0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5","0x00000000000000000000000000000000002002681bb417184b2df070a16a3858","0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511","0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223","0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7","0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c","0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130","0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f","0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3","0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592","0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3","0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1","0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0","0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c","0x0000000000000000000000000000009f825dde88092070747180d581c342444a","0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01","0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff","0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9","0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1","0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b","0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2","0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f","0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0","0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349","0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8","0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2","0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556","0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d","0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb","0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d","0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8","0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862","0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e","0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830","0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f","0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe","0x000000000000000000000000000000231147211b3c75e1f47d150e4bbd2fb22e","0x00000000000000000000000000000000000d19ee104a10d3c701cfd87473cbbe","0x0000000000000000000000000000006705f3f382637d00f698e2c5c94ed05ae9","0x00000000000000000000000000000000000b9c792da28bb60601dd7ce4b74e68","0x000000000000000000000000000000ac5acc8cc21e4ddb225c510670f80c80b3","0x00000000000000000000000000000000002da9d3fa57343e6998aba19429b9fa","0x0000000000000000000000000000004bacbf54b7c17a560df0af18b6d0d527be","0x00000000000000000000000000000000000faea33aeca2025b22c288964b21eb","0x000000000000000000000000000000492e756298d68d6e95de096055cc0336c3","0x00000000000000000000000000000000001a12a12f004859e5a3675c7315121b","0x000000000000000000000000000000893d521d512f30e6d32afbbc0cecd8ee00","0x00000000000000000000000000000000001674b3c1ef12c6da690631e0d86c04","0x000000000000000000000000000000aa6cb02a52e7a613873d4ac9b411349945","0x00000000000000000000000000000000001ecb1fe9c493add46751f9940f73e1","0x00000000000000000000000000000045b3d362ca82cba69fb2b9c733a5b8c351","0x000000000000000000000000000000000019a683586af466e331945b732d2f8c","0x000000000000000000000000000000fc79b052dfdfe67c0ecfc06b4267ffd694","0x00000000000000000000000000000000001336a70c396393038d5e9913744ac2","0x0000000000000000000000000000005450d29af1e9438e91cd33ddeb2548226e","0x000000000000000000000000000000000000993a602891cfd0e6f6ecf7404933","0x000000000000000000000000000000498efddab90a32e9b2db729ed6e9b40192","0x00000000000000000000000000000000002425efebe9628c63ca6fc28bdb5901","0x000000000000000000000000000000d8488157f875a21ab5f93f1c2b641f3de9","0x0000000000000000000000000000000000290f95ada3936604dc4b14df7504e3","0x0000000000000000000000000000005d6902187f3ed60dcce06fca211b40329a","0x00000000000000000000000000000000002b5870a6ba0b20aaa0178e5adfbc36","0x000000000000000000000000000000e5c2519171fa0e548fc3c4966ffc1ce570","0x00000000000000000000000000000000001cb8d8f4793b7debbdc429389dbf2d","0x000000000000000000000000000000a3ee22dd60456277b86c32a18982dcb185","0x00000000000000000000000000000000002493c99a3d068b03f8f2b8d28b57ce","0x000000000000000000000000000000f6c3731486320082c20ec71bbdc92196c1","0x00000000000000000000000000000000001ded39c4c8366469843cd63f09ecac","0x000000000000000000000000000000494997477ab161763e46601d95844837ef","0x00000000000000000000000000000000002e0cddbc5712d79b59cb3b41ebbcdd","0x000000000000000000000000000000426db4c64531d350750df62dbbc41a1bd9","0x0000000000000000000000000000000000303126892f664d8d505964d14315ec","0x00000000000000000000000000000076a6b2c6040c0c62bd59acfe3e3e125672","0x000000000000000000000000000000000000874a5ad262eecc6b565e0b085074","0x000000000000000000000000000000ef082fb517183c9c6841c2b8ef2ca1df04","0x0000000000000000000000000000000000127b2a745a1b74968c3edc18982b9b","0x000000000000000000000000000000c9efd4f8c3d56e1eb23d789a8f710d5be6","0x000000000000000000000000000000000015a18748490ff4c2b1871081954e86","0x000000000000000000000000000000a0011ef987dc016ab110eacd554a1d8bbf","0x00000000000000000000000000000000002097c84955059442a95df075833071","0x000000000000000000000000000000d38e9426ad3085b68b00a93c17897c2877","0x00000000000000000000000000000000002aecd48089890ea0798eb952c66824","0x00000000000000000000000000000078d8a9ce405ce559f441f2e71477ff3ddb","0x00000000000000000000000000000000001216bdb2f0d961bb8a7a23331d2150","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb","0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56","0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc","0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4"] +verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000010","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000008c068dccb0e55d4b56c7c32ebfafeb5b02","0x0000000000000000000000000000000000266c985199590a284abf77ba01c36e","0x00000000000000000000000000000044fb25551548bb4059099673aed8646b35","0x000000000000000000000000000000000023ab8c745db114ee56b97a8aa27934","0x000000000000000000000000000000a56563b42599f0e4ad5455a8fd988b9ff3","0x00000000000000000000000000000000000a94e3640063f3f4758fcfe457d298","0x0000000000000000000000000000008a51861ca043ceae044d6ab4f136331514","0x00000000000000000000000000000000001812e50744ac8ed3cc4a9594a701cc","0x000000000000000000000000000000b911c8cf179747b410c1cb9fd8a8bde095","0x00000000000000000000000000000000001826edb9faf624498fe82f5a61008d","0x000000000000000000000000000000ed158ea534a9c72ec9e614906fd7adff9a","0x000000000000000000000000000000000017cb9637e464dc2647b9b8688c5fa0","0x0000000000000000000000000000004b5064dd55e5ec8cd9bdd01c0e22eb7122","0x00000000000000000000000000000000002c7cff0caa8ba3fec7523dcbc934a8","0x000000000000000000000000000000f268df76bf0d78739ded43daba9c339499","0x00000000000000000000000000000000002e11974b75c78b276ae16219b99dc9","0x000000000000000000000000000000cfc293980c0ecf813f4f1436ff140740c3","0x000000000000000000000000000000000016ff2972a7eedf8ff27f494904fa47","0x00000000000000000000000000000085a92cc2b6efec726ea10710b20776ee70","0x0000000000000000000000000000000000278709e98b64a3553dc3e6e514e7ff","0x0000000000000000000000000000004391d81714b7d7ad40642b9308d02258b4","0x0000000000000000000000000000000000207710f769c857fbe624a2333097b2","0x0000000000000000000000000000002f767ee4790206ca5c193b742aa672d6d8","0x00000000000000000000000000000000001044cdbbd63806d10426ca4cb77cbc","0x000000000000000000000000000000314be7aecd2a710b8966befe7c0b08f574","0x00000000000000000000000000000000000558190b4fa7d726895b6d7d9c0bef","0x000000000000000000000000000000d64f3a11faf61b8776b0e778ab7a16c09c","0x00000000000000000000000000000000000d1c3d5e8fe0193b17834424ce605d","0x000000000000000000000000000000d8019ded441b9e454eb4045069cefee487","0x00000000000000000000000000000000002c066d46d386975a57df073e19403b","0x0000000000000000000000000000006bf779063abc501d4102fbfc99d4227c16","0x00000000000000000000000000000000001bbf8b9e8c4b2184984b994c744d21","0x0000000000000000000000000000003896ea793e6b3f6a14218d476534109610","0x00000000000000000000000000000000000e84090add56f2500ab518c655cae6","0x00000000000000000000000000000065df446fdddba972f3c4414ad3c901f4f9","0x00000000000000000000000000000000002b78a584bd6ae88cf4ec7c65c90e0b","0x00000000000000000000000000000094e611b5d59a27773f744710b476fbd30f","0x00000000000000000000000000000000001bd6129f9646aa21af0d77e7b1cc97","0x000000000000000000000000000000139a9d1593d56e65e710b2f344756b721e","0x00000000000000000000000000000000002f8d492d76a22b6834f0b88e2d4096","0x00000000000000000000000000000026c814cd7c5e1ba2094969bb1d74f1c66b","0x000000000000000000000000000000000013129f0714c3307644809495e01504","0x0000000000000000000000000000007d4549a4df958fe4825e7cb590563154ab","0x00000000000000000000000000000000000e7d5873232b1bdd0ce181513b47d1","0x000000000000000000000000000000a54541a8f32c0d9f8645edf17aac8fa230","0x00000000000000000000000000000000001e0677756494ded8010e8ef02518b2","0x0000000000000000000000000000008b101700e2d4f9116b01bfaaf3c458a423","0x0000000000000000000000000000000000021e43a3c385eba62bcc47aad7b9ea","0x00000000000000000000000000000099559d1c1ed6758494d18b9890bb5e3f97","0x00000000000000000000000000000000002e68b3c679543d2933bf9f7f77d422","0x000000000000000000000000000000c842dceb89f5cf4c130810f4802014a67f","0x00000000000000000000000000000000000d647daa6d2a8ac14f2da194b3a27e","0x000000000000000000000000000000af641be24f11d735581ad2e14787470194","0x00000000000000000000000000000000001e90f381ece8401026212fdbb26199","0x000000000000000000000000000000f601a4b716e755b0cf516d07e403265e27","0x00000000000000000000000000000000002d49d628876caa6993afe9fc30a764","0x0000000000000000000000000000008e9de4c6ce2e85105ec90ab63303b61502","0x00000000000000000000000000000000001b063563a7858b064132573e0aca86","0x00000000000000000000000000000021c200c8468139aa32fcf13fd1d8570828","0x0000000000000000000000000000000000023a4e744c62548c3b32986b3bc73a","0x0000000000000000000000000000000af941f79a4d93c6e9aad19c6049e1fa53","0x000000000000000000000000000000000003db2201f4b1b9a4d3646331e1f8e1","0x00000000000000000000000000000005d91fe16bd2b8dd3ce8b7d70ce6222b4f","0x0000000000000000000000000000000000102db0f3fd668e06f49d133d1bf994","0x0000000000000000000000000000009459915944c39a12b978a433efb6517d0f","0x00000000000000000000000000000000000b1c9fa9f4ce17e53f3acd13be4078","0x0000000000000000000000000000007c8d45be92476f8867dca4078fb7b6b2f8","0x00000000000000000000000000000000001f21afb9b7ccd5c404f0115253d2a6","0x0000000000000000000000000000004d78a34b40208c31be4fb8b39d23f1d1de","0x00000000000000000000000000000000000f3090488b19df76c4358537728d9a","0x00000000000000000000000000000060b0272756debcae50a25a3ee7d7095ea9","0x00000000000000000000000000000000002e84bca0d93b098853cca06147ec94","0x000000000000000000000000000000a0875603e0a017ce12ff79764af43e7421","0x0000000000000000000000000000000000245798a7b19502ba14b46eb68dc771","0x00000000000000000000000000000089b25e854077925674d0645ed1e784c929","0x000000000000000000000000000000000008b8347d14433adba1d9e9406eb1db","0x000000000000000000000000000000d0d3258758dfa9bae9e415f6d48d990e16","0x0000000000000000000000000000000000224948ddbcddb1e360efa2ac511aac","0x000000000000000000000000000000f6a101330e9f928dc80a3d3b9afefb373a","0x00000000000000000000000000000000001011627c159ab9f3ff0a0416a01df6","0x0000000000000000000000000000002ec420ad50087360c152c131400547bcc6","0x000000000000000000000000000000000018dab63316305864682bfe7b586e91","0x0000000000000000000000000000004bd9f352c132c7ae6bed5ea997693e6300","0x00000000000000000000000000000000001edb4d30542aa0ac4fe8eb31fc2ce0","0x0000000000000000000000000000008bcf42c24591e90cf41fc687829fe0b0aa","0x000000000000000000000000000000000027a49cd522a4fbbdfc8846331514de","0x000000000000000000000000000000bdfbf1d964fcfb887c3631ef202797fc2f","0x00000000000000000000000000000000001432caafa62e791082fd900fcb34a1","0x0000000000000000000000000000006f99a40f79f14ed78a291d53d0425ddc9d","0x000000000000000000000000000000000007ea92c2de0345ded1d25b237f0845","0x000000000000000000000000000000bc1328fa2c343da93cb98486d414f0a40a","0x0000000000000000000000000000000000255aeaa6894472e3cb6b0a790cf290","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000008775499e69e8bd2c39af33bd5fa0b4079a","0x0000000000000000000000000000000000024236bda126650fb5228cf424a087","0x000000000000000000000000000000b0eb1a867b06854066589b967455259b32","0x0000000000000000000000000000000000233cda9292be02cfa2da9d0fc7b0ea"] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr index ecfd18f38374..a18403eba718 100644 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr @@ -1,6 +1,6 @@ // This circuit aggregates a single Honk proof from `assert_statement_recursive`. -global SIZE_OF_PROOF_IF_LOGN_IS_28 : u32 = 409; +global SIZE_OF_PROOF_IF_LOGN_IS_28 : u32 = 393; fn main( verification_key: [Field; 103], // This is the proof without public inputs attached. diff --git a/noir/noir-repo/test_programs/rebuild.sh b/noir/noir-repo/test_programs/rebuild.sh index 13479f58b4b8..a70f69d531d9 100755 --- a/noir/noir-repo/test_programs/rebuild.sh +++ b/noir/noir-repo/test_programs/rebuild.sh @@ -45,7 +45,7 @@ rm -rf $current_dir/acir_artifacts mkdir -p $current_dir/acir_artifacts # Gather directories to process. -dirs_to_process=() +# dirs_to_process=() for dir in $base_path/*; do if [[ ! -d $dir ]] || [[ " ${excluded_dirs[@]} " =~ " $(basename "$dir") " ]]; then continue diff --git a/noir/verify_honk_proof/src/main.nr b/noir/verify_honk_proof/src/main.nr index ecfd18f38374..a18403eba718 100644 --- a/noir/verify_honk_proof/src/main.nr +++ b/noir/verify_honk_proof/src/main.nr @@ -1,6 +1,6 @@ // This circuit aggregates a single Honk proof from `assert_statement_recursive`. -global SIZE_OF_PROOF_IF_LOGN_IS_28 : u32 = 409; +global SIZE_OF_PROOF_IF_LOGN_IS_28 : u32 = 393; fn main( verification_key: [Field; 103], // This is the proof without public inputs attached. diff --git a/scripts/earthly-ci b/scripts/earthly-ci index c2ae10b529ad..49cc4db605a3 100755 --- a/scripts/earthly-ci +++ b/scripts/earthly-ci @@ -65,7 +65,7 @@ while [ $ATTEMPT_COUNT -lt $MAX_ATTEMPTS ]; do wipe_non_cache_docker_state fi sleep 20 - elif grep 'status 125: docker: Error response from daemon: layer does not exist.' $OUTPUT_FILE >/dev/null || grep 'could not determine buildkit address - is Docker or Podman running?' $OUTPUT_FILE >/dev/null ; then + elif grep 'status 125: docker: Error response from daemon: layer does not exist.' $OUTPUT_FILE >/dev/null || grep 'could not determine buildkit address - is Docker or Podman running?' $OUTPUT_FILE >/dev/null || grep 'please make sure the URL is valid, and Docker 18.09 or later is installed on the remote host' $OUTPUT_FILE >/dev/null ; then wipe_non_cache_docker_state # wait for other docker restarts sleep 20 diff --git a/yarn-project/aztec.js/src/contract/base_contract_interaction.ts b/yarn-project/aztec.js/src/contract/base_contract_interaction.ts index 1cdbaa00b4d1..af130fe08c5a 100644 --- a/yarn-project/aztec.js/src/contract/base_contract_interaction.ts +++ b/yarn-project/aztec.js/src/contract/base_contract_interaction.ts @@ -25,7 +25,11 @@ export type SendMethodOptions = { * Implements the sequence create/simulate/send. */ export abstract class BaseContractInteraction { - protected tx?: Tx; + /** + * The transaction execution result. Set by prove(). + * Made public for simple mocking. + */ + public tx?: Tx; protected txRequest?: TxExecutionRequest; protected log = createDebugLogger('aztec:js:contract_interaction'); diff --git a/yarn-project/bb-prover/package.json b/yarn-project/bb-prover/package.json index 89ad0498089c..909ffa5251a5 100644 --- a/yarn-project/bb-prover/package.json +++ b/yarn-project/bb-prover/package.json @@ -65,6 +65,7 @@ "@aztec/noir-protocol-circuits-types": "workspace:^", "@aztec/simulator": "workspace:^", "@aztec/telemetry-client": "workspace:^", + "@msgpack/msgpack": "^3.0.0-beta2", "@noir-lang/noirc_abi": "portal:../../noir/packages/noirc_abi", "@noir-lang/types": "portal:../../noir/packages/types", "commander": "^9.0.0", diff --git a/yarn-project/bb-prover/src/bb/cli.ts b/yarn-project/bb-prover/src/bb/cli.ts index ce2e02eb8323..ae585b37797b 100644 --- a/yarn-project/bb-prover/src/bb/cli.ts +++ b/yarn-project/bb-prover/src/bb/cli.ts @@ -89,6 +89,38 @@ export function getProgram(log: LogFn): Command { ); }); + program + .command('write-vk') + .description('Generates the verification key for the specified circuit') + .requiredOption( + '-w, --working-directory ', + 'A directory to use for storing input/output files', + BB_WORKING_DIRECTORY, + ) + .requiredOption('-b, --bb-path ', 'The path to the BB binary', BB_BINARY_PATH) + .requiredOption('-c, --circuit ', 'The name of a protocol circuit') + .action(async options => { + const compiledCircuit = ProtocolCircuitArtifacts[options.circuit as ProtocolArtifact]; + if (!compiledCircuit) { + log(`Failed to find circuit ${options.circuit}`); + return; + } + try { + await fs.access(options.workingDirectory, fs.constants.W_OK); + } catch (error) { + log(`Working directory does not exist`); + return; + } + await generateKeyForNoirCircuit( + options.bbPath, + options.workingDirectory, + options.circuit, + compiledCircuit, + 'vk', + log, + ); + }); + program .command('write-contract') .description('Generates the verification contract for the specified circuit') diff --git a/yarn-project/bb-prover/src/bb/execute.ts b/yarn-project/bb-prover/src/bb/execute.ts index 7c97fcede72c..d682e563fc59 100644 --- a/yarn-project/bb-prover/src/bb/execute.ts +++ b/yarn-project/bb-prover/src/bb/execute.ts @@ -148,11 +148,11 @@ export async function generateKeyForNoirCircuit( // args are the output path and the input bytecode path const args = ['-o', `${outputPath}/${VK_FILENAME}`, '-b', bytecodePath]; const timer = new Timer(); - let result = await executeBB(pathToBB, `write_${key}`, args, log); + let result = await executeBB(pathToBB, `write_${key}_ultra_honk`, args, log); // If we succeeded and the type of key if verification, have bb write the 'fields' version too if (result.status == BB_RESULT.SUCCESS && key === 'vk') { const asFieldsArgs = ['-k', `${outputPath}/${VK_FILENAME}`, '-o', `${outputPath}/${VK_FIELDS_FILENAME}`, '-v']; - result = await executeBB(pathToBB, `vk_as_fields`, asFieldsArgs, log); + result = await executeBB(pathToBB, `vk_as_fields_ultra_honk`, asFieldsArgs, log); } const duration = timer.ms(); @@ -187,6 +187,145 @@ export async function generateKeyForNoirCircuit( return res; } +// TODO(#7369) comment this etc (really just take inspiration from this and rewrite it all O:)) +export async function executeBbClientIvcProof( + pathToBB: string, + workingDirectory: string, + bytecodeStackPath: string, + witnessStackPath: string, + log: LogFn, +): Promise { + // Check that the working directory exists + try { + await fs.access(workingDirectory); + } catch (error) { + return { status: BB_RESULT.FAILURE, reason: `Working directory ${workingDirectory} does not exist` }; + } + + // The proof is written to e.g. /workingDirectory/proof + const outputPath = `${workingDirectory}`; + + const binaryPresent = await fs + .access(pathToBB, fs.constants.R_OK) + .then(_ => true) + .catch(_ => false); + if (!binaryPresent) { + return { status: BB_RESULT.FAILURE, reason: `Failed to find bb binary at ${pathToBB}` }; + } + + try { + // Write the bytecode to the working directory + log(`bytecodePath ${bytecodeStackPath}`); + log(`outputPath ${outputPath}`); + const args = ['-o', outputPath, '-b', bytecodeStackPath, '-w', witnessStackPath, '-v']; + const timer = new Timer(); + const logFunction = (message: string) => { + log(`client ivc proof BB out - ${message}`); + }; + + const result = await executeBB(pathToBB, 'client_ivc_prove_output_all_msgpack', args, logFunction); + const durationMs = timer.ms(); + + if (result.status == BB_RESULT.SUCCESS) { + return { + status: BB_RESULT.SUCCESS, + durationMs, + proofPath: `${outputPath}`, + pkPath: undefined, + vkPath: `${outputPath}`, + }; + } + // Not a great error message here but it is difficult to decipher what comes from bb + return { + status: BB_RESULT.FAILURE, + reason: `Failed to generate proof. Exit code ${result.exitCode}. Signal ${result.signal}.`, + }; + } catch (error) { + return { status: BB_RESULT.FAILURE, reason: `${error}` }; + } +} + +/** + * Used for generating verification keys of noir circuits. + * It is assumed that the working directory is a temporary and/or random directory used solely for generating this VK. + * @param pathToBB - The full path to the bb binary + * @param workingDirectory - A working directory for use by bb + * @param circuitName - An identifier for the circuit + * @param bytecode - The compiled circuit bytecode + * @param inputWitnessFile - The circuit input witness + * @param log - A logging function + * @returns An object containing a result indication, the location of the VK and the duration taken + */ +export async function computeVerificationKey( + pathToBB: string, + workingDirectory: string, + circuitName: string, + bytecode: Buffer, + log: LogFn, +): Promise { + // Check that the working directory exists + try { + await fs.access(workingDirectory); + } catch (error) { + return { status: BB_RESULT.FAILURE, reason: `Working directory ${workingDirectory} does not exist` }; + } + + // The bytecode is written to e.g. /workingDirectory/BaseParityArtifact-bytecode + const bytecodePath = `${workingDirectory}/${circuitName}-bytecode`; + + // The verification key is written to this path + const outputPath = `${workingDirectory}/vk`; + + const binaryPresent = await fs + .access(pathToBB, fs.constants.R_OK) + .then(_ => true) + .catch(_ => false); + if (!binaryPresent) { + return { status: BB_RESULT.FAILURE, reason: `Failed to find bb binary at ${pathToBB}` }; + } + + try { + // Write the bytecode to the working directory + await fs.writeFile(bytecodePath, bytecode); + const timer = new Timer(); + const logFunction = (message: string) => { + log(`computeVerificationKey(${circuitName}) BB out - ${message}`); + }; + let result = await executeBB( + pathToBB, + 'write_vk_ultra_honk', + ['-o', outputPath, '-b', bytecodePath, '-v'], + logFunction, + ); + if (result.status == BB_RESULT.FAILURE) { + return { status: BB_RESULT.FAILURE, reason: 'Failed writing VK.' }; + } + result = await executeBB( + pathToBB, + 'vk_as_fields_ultra_honk', + ['-o', outputPath + '_fields.json', '-k', outputPath, '-v'], + logFunction, + ); + const duration = timer.ms(); + + if (result.status == BB_RESULT.SUCCESS) { + return { + status: BB_RESULT.SUCCESS, + durationMs: duration, + pkPath: undefined, + vkPath: `${outputPath}`, + }; + } + // Not a great error message here but it is difficult to decipher what comes from bb + return { + status: BB_RESULT.FAILURE, + reason: `Failed to write VK. Exit code ${result.exitCode}. Signal ${result.signal}.`, + }; + } catch (error) { + return { status: BB_RESULT.FAILURE, reason: `${error}` }; + } +} + /** * Used for generating proofs of noir circuits. * It is assumed that the working directory is a temporary and/or random directory used solely for generating this proof. @@ -235,7 +374,7 @@ export async function generateProof( const logFunction = (message: string) => { log(`${circuitName} BB out - ${message}`); }; - const result = await executeBB(pathToBB, 'prove_output_all', args, logFunction); + const result = await executeBB(pathToBB, 'prove_ultra_honk_output_all', args, logFunction); const duration = timer.ms(); if (result.status == BB_RESULT.SUCCESS) { @@ -257,6 +396,87 @@ export async function generateProof( } } +/** + * Used for generating proofs of the tube circuit + * It is assumed that the working directory is a temporary and/or random directory used solely for generating this proof. + * @param pathToBB - The full path to the bb binary + * @param workingDirectory - A working directory for use by bb + * @param circuitName - An identifier for the circuit + * @param bytecode - The compiled circuit bytecode + * @param inputWitnessFile - The circuit input witness + * @param log - A logging function + * @returns An object containing a result indication, the location of the proof and the duration taken + */ +export async function generateTubeProof( + pathToBB: string, + workingDirectory: string, + log: LogFn, +): Promise { + // Check that the working directory exists + try { + await fs.access(workingDirectory); + } catch (error) { + return { status: BB_RESULT.FAILURE, reason: `Working directory ${workingDirectory} does not exist` }; + } + + // // Paths for the inputs + const vkPath = join(workingDirectory, 'inst_vk.bin'); // the vk of the last instance + const accPath = join(workingDirectory, 'pg_acc.bin'); + const proofPath = join(workingDirectory, 'client_ivc_proof.bin'); + const translatorVkPath = join(workingDirectory, 'translator_vk.bin'); + const eccVkPath = join(workingDirectory, 'ecc_vk.bin'); + + // The proof is written to e.g. /workingDirectory/proof + const outputPath = workingDirectory; + const filePresent = async (file: string) => + await fs + .access(file, fs.constants.R_OK) + .then(_ => true) + .catch(_ => false); + + const binaryPresent = await filePresent(pathToBB); + if (!binaryPresent) { + return { status: BB_RESULT.FAILURE, reason: `Failed to find bb binary at ${pathToBB}` }; + } + + try { + if ( + !filePresent(vkPath) || + !filePresent(accPath) || + !filePresent(proofPath) || + !filePresent(translatorVkPath) || + !filePresent(eccVkPath) + ) { + return { status: BB_RESULT.FAILURE, reason: `Client IVC input files not present in ${workingDirectory}` }; + } + const args = ['-o', outputPath, '-v']; + + const timer = new Timer(); + const logFunction = (message: string) => { + log(`TubeCircuit (prove) BB out - ${message}`); + }; + const result = await executeBB(pathToBB, 'prove_tube', args, logFunction); + const durationMs = timer.ms(); + + if (result.status == BB_RESULT.SUCCESS) { + return { + status: BB_RESULT.SUCCESS, + durationMs, + proofPath: outputPath, + pkPath: undefined, + vkPath: outputPath, + }; + } + // Not a great error message here but it is difficult to decipher what comes from bb + return { + status: BB_RESULT.FAILURE, + reason: `Failed to generate proof. Exit code ${result.exitCode}. Signal ${result.signal}.`, + }; + } catch (error) { + return { status: BB_RESULT.FAILURE, reason: `${error}` }; + } +} + /** * Used for generating AVM proofs. * It is assumed that the working directory is a temporary and/or random directory used solely for generating this proof. @@ -381,7 +601,7 @@ export async function verifyProof( verificationKeyPath: string, log: LogFn, ): Promise { - return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'verify', log); + return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'verify_ultra_honk', log); } /** @@ -414,7 +634,7 @@ async function verifyProofInternal( pathToBB: string, proofFullPath: string, verificationKeyPath: string, - command: 'verify' | 'avm_verify', + command: 'verify_ultra_honk' | 'avm_verify', log: LogFn, ): Promise { const binaryPresent = await fs @@ -468,7 +688,7 @@ export async function writeVkAsFields( try { const args = ['-k', `${verificationKeyPath}/${verificationKeyFilename}`, '-v']; const timer = new Timer(); - const result = await executeBB(pathToBB, 'vk_as_fields', args, log); + const result = await executeBB(pathToBB, 'vk_as_fields_ultra_honk', args, log); const duration = timer.ms(); if (result.status == BB_RESULT.SUCCESS) { return { status: BB_RESULT.SUCCESS, durationMs: duration, vkPath: verificationKeyPath }; @@ -510,7 +730,7 @@ export async function writeProofAsFields( try { const args = ['-p', `${proofPath}/${proofFileName}`, '-k', vkFilePath, '-v']; const timer = new Timer(); - const result = await executeBB(pathToBB, 'proof_as_fields', args, log); + const result = await executeBB(pathToBB, 'proof_as_fields_honk', args, log); const duration = timer.ms(); if (result.status == BB_RESULT.SUCCESS) { return { status: BB_RESULT.SUCCESS, durationMs: duration, proofPath: proofPath }; diff --git a/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts b/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts similarity index 66% rename from yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts rename to yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts index 31686b6f2a64..e15f4e995079 100644 --- a/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts +++ b/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts @@ -1,9 +1,12 @@ -import { type AppCircuitProofOutput, type KernelProofOutput, type ProofCreator } from '@aztec/circuit-types'; -import { type CircuitProvingStats, type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats'; import { - AGGREGATION_OBJECT_LENGTH, + type AppCircuitSimulateOutput, + type PrivateKernelProver, + type PrivateKernelSimulateOutput, +} from '@aztec/circuit-types'; +import { type CircuitSimulationStats, type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats'; +import { + ClientIvcProof, Fr, - NESTED_RECURSIVE_PROOF_LENGTH, type PrivateCircuitPublicInputs, type PrivateKernelCircuitPublicInputs, type PrivateKernelInitCircuitPrivateInputs, @@ -12,7 +15,6 @@ import { type PrivateKernelTailCircuitPrivateInputs, type PrivateKernelTailCircuitPublicInputs, Proof, - RECURSIVE_PROOF_LENGTH, RecursiveProof, type VerificationKeyAsFields, type VerificationKeyData, @@ -40,20 +42,29 @@ import { import { WASMSimulator } from '@aztec/simulator'; import { type NoirCompiledCircuit } from '@aztec/types/noir'; +import { encode } from '@msgpack/msgpack'; import { serializeWitness } from '@noir-lang/noirc_abi'; import { type WitnessMap } from '@noir-lang/types'; import * as fs from 'fs/promises'; -import { join } from 'path'; +import path from 'path'; -import { BB_RESULT, PROOF_FIELDS_FILENAME, PROOF_FILENAME, generateProof, verifyProof } from '../bb/execute.js'; +import { + BB_RESULT, + PROOF_FIELDS_FILENAME, + PROOF_FILENAME, + computeVerificationKey, + executeBbClientIvcProof, + verifyProof, +} from '../bb/execute.js'; import { mapProtocolArtifactNameToCircuitName } from '../stats.js'; import { extractVkData } from '../verification_key/verification_key_data.js'; /** * This proof creator implementation uses the native bb binary. * This is a temporary implementation until we make the WASM version work. + * TODO(#7368): this class grew 'organically' aka it could use a look at its resposibilities */ -export class BBNativeProofCreator implements ProofCreator { +export class BBNativePrivateKernelProver implements PrivateKernelProver { private simulator = new WASMSimulator(); private verificationKeys: Map> = new Map< @@ -67,16 +78,59 @@ export class BBNativeProofCreator implements ProofCreator { private log = createDebugLogger('aztec:bb-native-prover'), ) {} + private async _createClientIvcProof( + directory: string, + acirs: Buffer[], + witnessStack: WitnessMap[], + ): Promise { + // TODO(#7371): Longer term we won't use this hacked together msgpack format + // and instead properly create the bincode serialization from rust + await fs.writeFile(path.join(directory, 'acir.msgpack'), encode(acirs)); + await fs.writeFile( + path.join(directory, 'witnesses.msgpack'), + encode(witnessStack.map(map => serializeWitness(map))), + ); + const provingResult = await executeBbClientIvcProof( + this.bbBinaryPath, + directory, + path.join(directory, 'acir.msgpack'), + path.join(directory, 'witnesses.msgpack'), + this.log.info, + ); + + if (provingResult.status === BB_RESULT.FAILURE) { + this.log.error(`Failed to generate client ivc proof`); + throw new Error(provingResult.reason); + } + + const proof = await ClientIvcProof.readFromOutputDirectory(directory); + + this.log.info(`Generated IVC proof`, { + duration: provingResult.durationMs, + eventName: 'circuit-proving', + }); + + return proof; + } + + async createClientIvcProof(acirs: Buffer[], witnessStack: WitnessMap[]): Promise { + this.log.info(`Generating Client IVC proof`); + const operation = async (directory: string) => { + return await this._createClientIvcProof(directory, acirs, witnessStack); + }; + return await runInDirectory(this.bbWorkingDirectory, operation); + } + public getSiloedCommitments(publicInputs: PrivateCircuitPublicInputs) { const contractAddress = publicInputs.callContext.storageContractAddress; return Promise.resolve(publicInputs.noteHashes.map(commitment => siloNoteHash(contractAddress, commitment.value))); } - public async createProofInit( + public async simulateProofInit( inputs: PrivateKernelInitCircuitPrivateInputs, - ): Promise> { - return await this.createSafeProof( + ): Promise> { + return await this.simulate( inputs, 'PrivateKernelInitArtifact', convertPrivateKernelInitInputsToWitnessMap, @@ -84,10 +138,10 @@ export class BBNativeProofCreator implements ProofCreator { ); } - public async createProofInner( + public async simulateProofInner( inputs: PrivateKernelInnerCircuitPrivateInputs, - ): Promise> { - return await this.createSafeProof( + ): Promise> { + return await this.simulate( inputs, 'PrivateKernelInnerArtifact', convertPrivateKernelInnerInputsToWitnessMap, @@ -95,10 +149,10 @@ export class BBNativeProofCreator implements ProofCreator { ); } - public async createProofReset( + public async simulateProofReset( inputs: PrivateKernelResetCircuitPrivateInputsVariants, - ): Promise> { - return await this.createSafeProof( + ): Promise> { + return await this.simulate( inputs, PrivateResetTagToArtifactName[inputs.sizeTag], convertPrivateKernelResetInputsToWitnessMap, @@ -106,18 +160,18 @@ export class BBNativeProofCreator implements ProofCreator { ); } - public async createProofTail( + public async simulateProofTail( inputs: PrivateKernelTailCircuitPrivateInputs, - ): Promise> { + ): Promise> { if (!inputs.isForPublic()) { - return await this.createSafeProof( + return await this.simulate( inputs, 'PrivateKernelTailArtifact', convertPrivateKernelTailInputsToWitnessMap, convertPrivateKernelTailOutputsFromWitnessMap, ); } - return await this.createSafeProof( + return await this.simulate( inputs, 'PrivateKernelTailToPublicArtifact', convertPrivateKernelTailToPublicInputsToWitnessMap, @@ -125,23 +179,13 @@ export class BBNativeProofCreator implements ProofCreator { ); } - public async createAppCircuitProof( - partialWitness: WitnessMap, + public async computeAppCircuitVerificationKey( bytecode: Buffer, appCircuitName?: string, - ): Promise { + ): Promise { const operation = async (directory: string) => { this.log.debug(`Proving app circuit`); - const proofOutput = await this.createProof(directory, partialWitness, bytecode, 'App', appCircuitName); - if (proofOutput.proof.proof.length != RECURSIVE_PROOF_LENGTH) { - throw new Error(`Incorrect proof length`); - } - const proof = proofOutput.proof as RecursiveProof; - const output: AppCircuitProofOutput = { - proof, - verificationKey: proofOutput.verificationKey, - }; - return output; + return await this.computeVerificationKey(directory, bytecode, 'App', appCircuitName); }; return await runInDirectory(this.bbWorkingDirectory, operation); @@ -192,7 +236,7 @@ export class BBNativeProofCreator implements ProofCreator { * @param filePath - The directory containing the verification key data files * @param circuitType - The type of circuit to which the verification key corresponds */ - private async updateVerificationKeyAfterProof(filePath: string, circuitType: ClientProtocolArtifact) { + private async updateVerificationKeyAfterSimulation(filePath: string, circuitType: ClientProtocolArtifact) { let promise = this.verificationKeys.get(circuitType); if (!promise) { promise = extractVkData(filePath); @@ -202,28 +246,12 @@ export class BBNativeProofCreator implements ProofCreator { return await promise; } - private async createSafeProof Buffer }, O extends { toBuffer: () => Buffer }>( - inputs: I, - circuitType: ClientProtocolArtifact, - convertInputs: (inputs: I) => WitnessMap, - convertOutputs: (outputs: WitnessMap) => O, - ): Promise> { - const operation = async (directory: string) => { - return await this.generateWitnessAndCreateProof(inputs, circuitType, directory, convertInputs, convertOutputs); - }; - return await runInDirectory(this.bbWorkingDirectory, operation); - } - - private async generateWitnessAndCreateProof< - I extends { toBuffer: () => Buffer }, - O extends { toBuffer: () => Buffer }, - >( + private async simulate Buffer }, O extends { toBuffer: () => Buffer }>( inputs: I, circuitType: ClientProtocolArtifact, - directory: string, convertInputs: (inputs: I) => WitnessMap, convertOutputs: (outputs: WitnessMap) => O, - ): Promise> { + ): Promise> { this.log.debug(`Generating witness for ${circuitType}`); const compiledCircuit: NoirCompiledCircuit = ClientCircuitArtifacts[circuitType]; @@ -240,99 +268,69 @@ export class BBNativeProofCreator implements ProofCreator { outputSize: output.toBuffer().length, } satisfies CircuitWitnessGenerationStats); - const proofOutput = await this.createProof( - directory, - outputWitness, - Buffer.from(compiledCircuit.bytecode, 'base64'), - circuitType, + // TODO(#7410) we dont need to generate vk's for these circuits, they are in the vk tree + const { verificationKey } = await runInDirectory(this.bbWorkingDirectory, dir => + this.computeVerificationKey(dir, Buffer.from(compiledCircuit.bytecode, 'base64'), circuitType), ); - if (proofOutput.proof.proof.length != NESTED_RECURSIVE_PROOF_LENGTH) { - throw new Error(`Incorrect proof length`); - } - const nestedProof = proofOutput.proof as RecursiveProof; - - const kernelOutput: KernelProofOutput = { + const kernelOutput: PrivateKernelSimulateOutput = { publicInputs: output, - proof: nestedProof, - verificationKey: proofOutput.verificationKey, + verificationKey, + outputWitness, }; return kernelOutput; } - private async createProof( + private async computeVerificationKey( directory: string, - partialWitness: WitnessMap, bytecode: Buffer, circuitType: ClientProtocolArtifact | 'App', appCircuitName?: string, ): Promise<{ - proof: RecursiveProof | RecursiveProof; verificationKey: VerificationKeyAsFields; }> { - const compressedBincodedWitness = serializeWitness(partialWitness); - - const inputsWitnessFile = join(directory, 'witness.gz'); - - await fs.writeFile(inputsWitnessFile, compressedBincodedWitness); - - this.log.debug(`Written ${inputsWitnessFile}`); - const dbgCircuitName = appCircuitName ? `(${appCircuitName})` : ''; - this.log.info(`Proving ${circuitType}${dbgCircuitName} circuit...`); + this.log.info(`Computing VK of ${circuitType}${dbgCircuitName} circuit...`); const timer = new Timer(); - const provingResult = await generateProof( - this.bbBinaryPath, - directory, - circuitType, - bytecode, - inputsWitnessFile, - this.log.debug, - ); + const vkResult = await computeVerificationKey(this.bbBinaryPath, directory, circuitType, bytecode, this.log.debug); - if (provingResult.status === BB_RESULT.FAILURE) { - this.log.error(`Failed to generate proof for ${circuitType}${dbgCircuitName}: ${provingResult.reason}`); - throw new Error(provingResult.reason); + if (vkResult.status === BB_RESULT.FAILURE) { + this.log.error(`Failed to generate proof for ${circuitType}${dbgCircuitName}: ${vkResult.reason}`); + throw new Error(vkResult.reason); } - this.log.info(`Generated ${circuitType}${dbgCircuitName} circuit proof in ${Math.ceil(timer.ms())} ms`); + this.log.info(`Generated ${circuitType}${dbgCircuitName} VK in ${Math.ceil(timer.ms())} ms`); if (circuitType === 'App') { const vkData = await extractVkData(directory); - const proof = await this.readProofAsFields(directory, circuitType, vkData); - this.log.debug(`Generated proof`, { - eventName: 'circuit-proving', + this.log.debug(`Computed verification key`, { circuitName: 'app-circuit', - duration: provingResult.durationMs, - inputSize: compressedBincodedWitness.length, - proofSize: proof.binaryProof.buffer.length, - appCircuitName, + duration: vkResult.durationMs, + eventName: 'circuit-simulation', + inputSize: bytecode.length, + outputSize: vkData.keyAsBytes.length, circuitSize: vkData.circuitSize, numPublicInputs: vkData.numPublicInputs, - } as CircuitProvingStats); + } as CircuitSimulationStats); - return { proof, verificationKey: vkData.keyAsFields }; + return { verificationKey: vkData.keyAsFields }; } - const vkData = await this.updateVerificationKeyAfterProof(directory, circuitType); - - const proof = await this.readProofAsFields(directory, circuitType, vkData); + const vkData = await this.updateVerificationKeyAfterSimulation(directory, circuitType); - await this.verifyProofForProtocolCircuit(circuitType, proof.binaryProof); - - this.log.debug(`Generated proof`, { + this.log.debug(`Computed verification key`, { circuitName: mapProtocolArtifactNameToCircuitName(circuitType), - duration: provingResult.durationMs, - eventName: 'circuit-proving', - inputSize: compressedBincodedWitness.length, - proofSize: proof.binaryProof.buffer.length, + duration: vkResult.durationMs, + eventName: 'circuit-simulation', + inputSize: bytecode.length, + outputSize: vkData.keyAsBytes.length, circuitSize: vkData.circuitSize, numPublicInputs: vkData.numPublicInputs, - } as CircuitProvingStats); + } as CircuitSimulationStats); - return { proof, verificationKey: vkData.keyAsFields }; + return { verificationKey: vkData.keyAsFields }; } /** @@ -352,10 +350,12 @@ export class BBNativeProofCreator implements ProofCreator { ]); const json = JSON.parse(proofString); const fields = json.map(Fr.fromString); - const numPublicInputs = - circuitType === 'App' ? vkData.numPublicInputs : vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH; + const numPublicInputs = vkData.numPublicInputs; + // const numPublicInputs = + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + // circuitType === 'App' ? vkData.numPublicInputs : vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH; const fieldsWithoutPublicInputs = fields.slice(numPublicInputs); - this.log.debug( + this.log.info( `Circuit type: ${circuitType}, complete proof length: ${fields.length}, without public inputs: ${fieldsWithoutPublicInputs.length}, num public inputs: ${numPublicInputs}, circuit size: ${vkData.circuitSize}, is recursive: ${vkData.isRecursive}, raw length: ${binaryProof.length}`, ); const proof = new RecursiveProof( diff --git a/yarn-project/bb-prover/src/prover/bb_prover.ts b/yarn-project/bb-prover/src/prover/bb_prover.ts index 419469cf2f6e..625c8a59fc9d 100644 --- a/yarn-project/bb-prover/src/prover/bb_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_prover.ts @@ -9,7 +9,6 @@ import { } from '@aztec/circuit-types'; import { type CircuitProvingStats, type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats'; import { - AGGREGATION_OBJECT_LENGTH, type AvmCircuitInputs, type BaseOrMergeRollupPublicInputs, type BaseParityInputs, @@ -30,6 +29,8 @@ import { type RootParityInputs, type RootRollupInputs, type RootRollupPublicInputs, + TUBE_PROOF_LENGTH, + TubeInputs, type VerificationKeyAsFields, type VerificationKeyData, makeRecursiveProofFromBinary, @@ -62,6 +63,7 @@ import { Attributes, type TelemetryClient, trackSpan } from '@aztec/telemetry-cl import { abiEncode } from '@noir-lang/noirc_abi'; import { type Abi, type WitnessMap } from '@noir-lang/types'; +import crypto from 'crypto'; import * as fs from 'fs/promises'; import * as path from 'path'; @@ -75,6 +77,7 @@ import { generateAvmProof, generateKeyForNoirCircuit, generateProof, + generateTubeProof, verifyAvmProof, verifyProof, writeProofAsFields, @@ -222,6 +225,16 @@ export class BBNativeRollupProver implements ServerCircuitProver { kernelRequest.inputs.previousKernel.vk, ); + // PUBLIC KERNEL: kernel request should be nonempty at start of public kernel proving but it is not + // TODO(#7369): We should properly enqueue the tube in the public kernel lifetime + if (!kernelRequest.inputs.previousKernel.clientIvcProof.isEmpty()) { + const { tubeVK, tubeProof } = await this.getTubeProof( + new TubeInputs(kernelRequest.inputs.previousKernel.clientIvcProof), + ); + kernelRequest.inputs.previousKernel.vk = tubeVK; + kernelRequest.inputs.previousKernel.proof = tubeProof; + } + await this.verifyWithKey( kernelRequest.inputs.previousKernel.vk, kernelRequest.inputs.previousKernel.proof.binaryProof, @@ -267,23 +280,27 @@ export class BBNativeRollupProver implements ServerCircuitProver { /** * Simulates the base rollup circuit from its inputs. - * @param input - Inputs to the circuit. + * @param baseRollupInput - Inputs to the circuit. * @returns The public inputs as outputs of the simulation. */ public async getBaseRollupProof( - input: BaseRollupInputs, + baseRollupInput: BaseRollupInputs, // TODO: remove tail proof from here ): Promise> { // We may need to convert the recursive proof into fields format - input.kernelData.proof = await this.ensureValidProof( - input.kernelData.proof, + logger.debug(`kernel Data proof: ${baseRollupInput.kernelData.proof}`); + logger.info(`in getBaseRollupProof`); + logger.info(`Number of public inputs in baseRollupInput: ${baseRollupInput.kernelData.vk.numPublicInputs}`); + logger.info(`Number of public inputs ${baseRollupInput.kernelData.publicInputs}`); + baseRollupInput.kernelData.proof = await this.ensureValidProof( + baseRollupInput.kernelData.proof, 'BaseRollupArtifact', - input.kernelData.vk, + baseRollupInput.kernelData.vk, ); const { circuitOutput, proof } = await this.createRecursiveProof( - input, + baseRollupInput, // BaseRollupInputs 'BaseRollupArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, + NESTED_RECURSIVE_PROOF_LENGTH, // WORKTODO: this should be BASE_ROLLUP_PROOF_LENGTH or something like this convertBaseRollupInputsToWitnessMap, convertBaseRollupOutputsFromWitnessMap, ); @@ -356,6 +373,20 @@ export class BBNativeRollupProver implements ServerCircuitProver { return emptyPrivateKernelProof; } + public async getEmptyTubeProof( + inputs: PrivateKernelEmptyInputData, + ): Promise> { + const emptyNested = await this.getEmptyNestedProof(); + const emptyPrivateKernelProof = await this.getEmptyTubeProofFromEmptyNested( + PrivateKernelEmptyInputs.from({ + ...inputs, + emptyNested, + }), + ); + + return emptyPrivateKernelProof; + } + private async getEmptyNestedProof(): Promise { const inputs = new EmptyNestedCircuitInputs(); const { proof } = await this.createRecursiveProof( @@ -368,11 +399,15 @@ export class BBNativeRollupProver implements ServerCircuitProver { const verificationKey = await this.getVerificationKeyDataForCircuit('EmptyNestedArtifact'); await this.verifyProof('EmptyNestedArtifact', proof.binaryProof); + // logger.debug(`EmptyNestedData proof size: ${proof.proof.length}`); + // logger.debug(`EmptyNestedData proof: ${proof.proof}`); + // logger.debug(`EmptyNestedData vk size: ${verificationKey.keyAsFields.key.length}`); + // logger.debug(`EmptyNestedData vk: ${verificationKey.keyAsFields.key}`); return new EmptyNestedData(proof, verificationKey.keyAsFields); } - private async getEmptyPrivateKernelProofFromEmptyNested( + private async getEmptyTubeProofFromEmptyNested( inputs: PrivateKernelEmptyInputs, ): Promise> { const { circuitOutput, proof } = await this.createRecursiveProof( @@ -382,7 +417,24 @@ export class BBNativeRollupProver implements ServerCircuitProver { convertPrivateKernelEmptyInputsToWitnessMap, convertPrivateKernelEmptyOutputsFromWitnessMap, ); + // info(`proof: ${proof.proof}`); + const verificationKey = await this.getVerificationKeyDataForCircuit('PrivateKernelEmptyArtifact'); + await this.verifyProof('PrivateKernelEmptyArtifact', proof.binaryProof); + return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey); + } + + private async getEmptyPrivateKernelProofFromEmptyNested( + inputs: PrivateKernelEmptyInputs, + ): Promise> { + const { circuitOutput, proof } = await this.createRecursiveProof( + inputs, + 'PrivateKernelEmptyArtifact', + NESTED_RECURSIVE_PROOF_LENGTH, + convertPrivateKernelEmptyInputsToWitnessMap, + convertPrivateKernelEmptyOutputsFromWitnessMap, + ); + //info(`proof: ${proof.proof}`); const verificationKey = await this.getVerificationKeyDataForCircuit('PrivateKernelEmptyArtifact'); await this.verifyProof('PrivateKernelEmptyArtifact', proof.binaryProof); @@ -513,6 +565,22 @@ export class BBNativeRollupProver implements ServerCircuitProver { return provingResult; } + private async generateTubeProofWithBB(bbWorkingDirectory: string, input: TubeInputs): Promise { + logger.debug(`Proving tube...`); + + const hasher = crypto.createHash('sha256'); + hasher.update(input.toBuffer()); + + await input.clientIVCData.writeToOutputDirectory(bbWorkingDirectory); + const provingResult = await generateTubeProof(this.config.bbBinaryPath, bbWorkingDirectory, logger.verbose); + + if (provingResult.status === BB_RESULT.FAILURE) { + logger.error(`Failed to generate proof for tube proof: ${provingResult.reason}`); + throw new Error(provingResult.reason); + } + return provingResult; + } + private async createAvmProof(input: AvmCircuitInputs): Promise { const cleanupDir: boolean = !process.env.AVM_PROVING_PRESERVE_WORKING_DIR; const operation = async (bbWorkingDirectory: string): Promise => { @@ -554,8 +622,34 @@ export class BBNativeRollupProver implements ServerCircuitProver { return await runInDirectory(this.config.bbWorkingDirectory, operation, cleanupDir); } + public async getTubeProof( + input: TubeInputs, + ): Promise<{ tubeVK: VerificationKeyData; tubeProof: RecursiveProof }> { + // this probably is gonna need to call client ivc + const operation = async (bbWorkingDirectory: string) => { + logger.debug(`createTubeProof: ${bbWorkingDirectory}`); + const provingResult = await this.generateTubeProofWithBB(bbWorkingDirectory, input); + + // Read the proof as fields + const tubeVK = await extractVkData(provingResult.vkPath!); + const tubeProof = await this.readTubeProofAsFields(provingResult.proofPath!, tubeVK, TUBE_PROOF_LENGTH); + // Sanity check the tube proof (can be removed later) + await this.verifyWithKey(tubeVK, tubeProof.binaryProof); + + // TODO(#7369): properly time tube construction + logger.info( + `Generated proof for tubeCircuit in ${Math.ceil(provingResult.durationMs)} ms, size: ${ + tubeProof.proof.length + } fields`, + ); + + return { tubeVK, tubeProof }; + }; + return await runInDirectory(this.config.bbWorkingDirectory, operation); + } + /** - * Executes a circuit and returns it's outputs and corresponding proof with embedded aggregation object + * Executes a circuit and returns its outputs and corresponding proof with embedded aggregation object * @param witnessMap - The input witness * @param circuitType - The type of circuit to be executed * @param proofLength - The length of the proof to be generated. This is a dummy parameter to aid in type checking @@ -574,6 +668,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { convertInput: (input: CircuitInputType) => WitnessMap, convertOutput: (outputWitness: WitnessMap) => CircuitOutputType, ): Promise<{ circuitOutput: CircuitOutputType; proof: RecursiveProof }> { + // this probably is gonna need to call client ivc const operation = async (bbWorkingDirectory: string) => { const { provingResult, @@ -619,6 +714,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { */ public async verifyProof(circuitType: ServerProtocolArtifact, proof: Proof) { const verificationKey = await this.getVerificationKeyDataForCircuit(circuitType); + // info(`vkey in: ${verificationKey.keyAsFields.key}`); return await this.verifyWithKey(verificationKey, proof); } @@ -691,7 +787,8 @@ export class BBNativeRollupProver implements ServerCircuitProver { } const operation = async (bbWorkingDirectory: string) => { - const numPublicInputs = vk.numPublicInputs - AGGREGATION_OBJECT_LENGTH; + // const numPublicInputs = vk.numPublicInputs; + const numPublicInputs = vk.numPublicInputs; // - AGGREGATION_OBJECT_LENGTH; const proofFullFilename = path.join(bbWorkingDirectory, PROOF_FILENAME); const vkFullFilename = path.join(bbWorkingDirectory, VK_FILENAME); @@ -723,7 +820,10 @@ export class BBNativeRollupProver implements ServerCircuitProver { encoding: 'utf-8', }); const json = JSON.parse(proofString); - const fields = json.slice(numPublicInputs).map(Fr.fromString); + const fields = json + .slice(0, 3) + .map(Fr.fromString) + .concat(json.slice(3 + numPublicInputs).map(Fr.fromString)); return new RecursiveProof( fields, new Proof(proof.binaryProof.buffer, vk.numPublicInputs), @@ -800,13 +900,21 @@ export class BBNativeRollupProver implements ServerCircuitProver { if (!vkData) { throw new Error(`Invalid verification key for ${circuitType}`); } - const numPublicInputs = CIRCUITS_WITHOUT_AGGREGATION.has(circuitType) - ? vkData.numPublicInputs - : vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH; - const fieldsWithoutPublicInputs = json.slice(numPublicInputs).map(Fr.fromString); + const numPublicInputs = vkData.numPublicInputs; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1044): Reinstate aggregation + // const numPublicInputs = CIRCUITS_WITHOUT_AGGREGATION.has(circuitType) + // ? vkData.numPublicInputs + // : vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH; + const fieldsWithoutPublicInputs = json + .slice(0, 3) + .map(Fr.fromString) + .concat(json.slice(3 + numPublicInputs).map(Fr.fromString)); logger.debug( - `Circuit type: ${circuitType}, complete proof length: ${json.length}, without public inputs: ${fieldsWithoutPublicInputs.length}, num public inputs: ${numPublicInputs}, circuit size: ${vkData.circuitSize}, is recursive: ${vkData.isRecursive}, raw length: ${binaryProof.length}`, + `num pub inputs ${vkData.numPublicInputs} and without aggregation ${CIRCUITS_WITHOUT_AGGREGATION.has( + circuitType, + )}`, ); + const proof = new RecursiveProof( fieldsWithoutPublicInputs, new Proof(binaryProof, numPublicInputs), @@ -818,4 +926,46 @@ export class BBNativeRollupProver implements ServerCircuitProver { return proof; } + + /** + * Parses and returns a tube proof stored in the specified directory. TODO merge wih above + * @param filePath - The directory containing the proof data + * @param circuitType - The type of circuit proven + * @returns The proof + * TODO(#7369) This is entirely redundant now with the above method, deduplicate + */ + private async readTubeProofAsFields( + filePath: string, + vkData: VerificationKeyData, + proofLength: PROOF_LENGTH, + ): Promise> { + const proofFilename = path.join(filePath, PROOF_FILENAME); + const proofFieldsFilename = path.join(filePath, PROOF_FIELDS_FILENAME); + + const [binaryProof, proofString] = await Promise.all([ + fs.readFile(proofFilename), + fs.readFile(proofFieldsFilename, { encoding: 'utf-8' }), + ]); + + const json = JSON.parse(proofString); + + const numPublicInputs = vkData.numPublicInputs; + if (numPublicInputs === 0) { + throw new Error(`Tube proof should have public inputs (e.g. the number of public inputs from PrivateKernelTail)`); + } + + const proofFields = json + .slice(0, 3) + .map(Fr.fromString) + .concat(json.slice(3 + numPublicInputs).map(Fr.fromString)); + logger.debug( + `Circuit type: tube circuit, complete proof length: ${json.length}, num public inputs: ${numPublicInputs}, circuit size: ${vkData.circuitSize}, is recursive: ${vkData.isRecursive}, raw length: ${binaryProof.length}`, + ); + const proof = new RecursiveProof(proofFields, new Proof(binaryProof, numPublicInputs), true); + if (proof.proof.length !== proofLength) { + throw new Error(`Proof length doesn't match expected length (${proof.proof.length} != ${proofLength})`); + } + + return proof; + } } diff --git a/yarn-project/bb-prover/src/prover/index.ts b/yarn-project/bb-prover/src/prover/index.ts index e3f2298b127d..614534850895 100644 --- a/yarn-project/bb-prover/src/prover/index.ts +++ b/yarn-project/bb-prover/src/prover/index.ts @@ -1,2 +1,2 @@ export * from './bb_prover.js'; -export * from './bb_native_proof_creator.js'; +export * from './bb_private_kernel_prover.js'; diff --git a/yarn-project/bb-prover/src/test/test_circuit_prover.ts b/yarn-project/bb-prover/src/test/test_circuit_prover.ts index be9c0be794c0..814bdd2e9119 100644 --- a/yarn-project/bb-prover/src/test/test_circuit_prover.ts +++ b/yarn-project/bb-prover/src/test/test_circuit_prover.ts @@ -20,10 +20,13 @@ import { type Proof, type PublicKernelCircuitPublicInputs, RECURSIVE_PROOF_LENGTH, + type RecursiveProof, RootParityInput, type RootParityInputs, type RootRollupInputs, type RootRollupPublicInputs, + TUBE_PROOF_LENGTH, + type TubeInputs, VerificationKeyData, makeEmptyProof, makeEmptyRecursiveProof, @@ -41,6 +44,7 @@ import { convertMergeRollupInputsToWitnessMap, convertMergeRollupOutputsFromWitnessMap, convertPrivateKernelEmptyInputsToWitnessMap, + convertPrivateKernelEmptyOutputsFromWitnessMap, convertRootParityInputsToWitnessMap, convertRootParityOutputsFromWitnessMap, convertRootRollupInputsToWitnessMap, @@ -107,6 +111,34 @@ export class TestCircuitProver implements ServerCircuitProver { ); } + public async getEmptyTubeProof( + inputs: PrivateKernelEmptyInputData, + ): Promise> { + const emptyNested = new EmptyNestedData( + makeRecursiveProof(RECURSIVE_PROOF_LENGTH), + ProtocolCircuitVks['EmptyNestedArtifact'].keyAsFields, + ); + const kernelInputs = new PrivateKernelEmptyInputs( + emptyNested, + inputs.header, + inputs.chainId, + inputs.version, + inputs.vkTreeRoot, + ); + const witnessMap = convertPrivateKernelEmptyInputsToWitnessMap(kernelInputs); + const witness = await this.wasmSimulator.simulateCircuit( + witnessMap, + SimulatedServerCircuitArtifacts.PrivateKernelEmptyArtifact, + ); + const result = convertPrivateKernelEmptyOutputsFromWitnessMap(witness); + + return makePublicInputsAndRecursiveProof( + result, + makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), + VerificationKeyData.makeFake(), + ); + } + /** * Simulates the base parity circuit from its inputs. * @param inputs - Inputs to the circuit. @@ -217,6 +249,16 @@ export class TestCircuitProver implements ServerCircuitProver { ProtocolCircuitVks['BaseRollupArtifact'], ); } + + public getTubeProof( + _tubeInput: TubeInputs, + ): Promise<{ tubeVK: VerificationKeyData; tubeProof: RecursiveProof }> { + return Promise.resolve({ + tubeVK: VerificationKeyData.makeFake(), + tubeProof: makeEmptyRecursiveProof(TUBE_PROOF_LENGTH), + }); + } + /** * Simulates the merge rollup circuit from its inputs. * @param input - Inputs to the circuit. diff --git a/yarn-project/bb-prover/src/verification_key/verification_key_data.ts b/yarn-project/bb-prover/src/verification_key/verification_key_data.ts index 8f773859052c..b2fe18cc5e18 100644 --- a/yarn-project/bb-prover/src/verification_key/verification_key_data.ts +++ b/yarn-project/bb-prover/src/verification_key/verification_key_data.ts @@ -25,11 +25,7 @@ export async function extractVkData(vkDirectoryPath: string): Promise, - vkHash, - ); + const vkAsFields = new VerificationKeyAsFields(fields as Tuple, vkHash); const vk = new VerificationKeyData(vkAsFields, rawBinary); return vk; } diff --git a/yarn-project/bb-prover/src/verifier/bb_verifier.ts b/yarn-project/bb-prover/src/verifier/bb_verifier.ts index 0c34e7bccec7..3c13a6999488 100644 --- a/yarn-project/bb-prover/src/verifier/bb_verifier.ts +++ b/yarn-project/bb-prover/src/verifier/bb_verifier.ts @@ -128,18 +128,19 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier { return fs.readFile(result.contractPath!, 'utf-8'); } - async verifyProof(tx: Tx): Promise { - const { proof, data } = tx; - const expectedCircuit: ClientProtocolArtifact = data.forPublic + verifyProof(tx: Tx): Promise { + const expectedCircuit: ClientProtocolArtifact = tx.data.forPublic ? 'PrivateKernelTailToPublicArtifact' : 'PrivateKernelTailArtifact'; try { - await this.verifyProofForCircuit(expectedCircuit, proof); - return true; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1050) we need a proper verify flow for clientIvcProof + // For now we handle only the trivial blank data case + // await this.verifyProofForCircuit(expectedCircuit, proof); + return Promise.resolve(!tx.clientIvcProof.isEmpty()); } catch (err) { this.logger.warn(`Failed to verify ${expectedCircuit} proof for tx ${Tx.getHash(tx)}: ${String(err)}`); - return false; + return Promise.resolve(false); } } } diff --git a/yarn-project/circuit-types/src/interfaces/index.ts b/yarn-project/circuit-types/src/interfaces/index.ts index 33a88a846c52..34c08cca3162 100644 --- a/yarn-project/circuit-types/src/interfaces/index.ts +++ b/yarn-project/circuit-types/src/interfaces/index.ts @@ -8,4 +8,4 @@ export * from './prover-client.js'; export * from './proving-job.js'; export * from './block-prover.js'; export * from './server_circuit_prover.js'; -export * from './proof_creator.js'; +export * from './private_kernel_prover.js'; diff --git a/yarn-project/circuit-types/src/interfaces/proof_creator.ts b/yarn-project/circuit-types/src/interfaces/private_kernel_prover.ts similarity index 73% rename from yarn-project/circuit-types/src/interfaces/proof_creator.ts rename to yarn-project/circuit-types/src/interfaces/private_kernel_prover.ts index 82c57b993c25..282984690d77 100644 --- a/yarn-project/circuit-types/src/interfaces/proof_creator.ts +++ b/yarn-project/circuit-types/src/interfaces/private_kernel_prover.ts @@ -1,5 +1,5 @@ import { - type NESTED_RECURSIVE_PROOF_LENGTH, + type ClientIvcProof, type PrivateCircuitPublicInputs, type PrivateKernelCircuitPublicInputs, type PrivateKernelInitCircuitPrivateInputs, @@ -7,8 +7,6 @@ import { type PrivateKernelResetCircuitPrivateInputsVariants, type PrivateKernelTailCircuitPrivateInputs, type PrivateKernelTailCircuitPublicInputs, - type RECURSIVE_PROOF_LENGTH, - type RecursiveProof, type VerificationKeyAsFields, } from '@aztec/circuits.js'; import { type Fr } from '@aztec/foundation/fields'; @@ -19,37 +17,31 @@ import { type WitnessMap } from '@noir-lang/acvm_js'; * Represents the output of the proof creation process for init and inner private kernel circuit. * Contains the public inputs required for the init and inner private kernel circuit and the generated proof. */ -export type KernelProofOutput = { +export type PrivateKernelSimulateOutput = { /** * The public inputs required for the proof generation process. */ publicInputs: PublicInputsType; - /** - * The zk-SNARK proof for the kernel execution. - */ - proof: RecursiveProof; + + clientIvcProof?: ClientIvcProof; verificationKey: VerificationKeyAsFields; + + outputWitness: WitnessMap; }; /** - * Represents the output of the proof creation process for init and inner private kernel circuit. - * Contains the public inputs required for the init and inner private kernel circuit and the generated proof. + * Represents the output of the circuit simulation process for init and inner private kernel circuit. */ -export type AppCircuitProofOutput = { - /** - * The zk-SNARK proof for the kernel execution. - */ - proof: RecursiveProof; - +export type AppCircuitSimulateOutput = { verificationKey: VerificationKeyAsFields; }; /** - * ProofCreator provides functionality to create and validate proofs, and retrieve + * PrivateKernelProver provides functionality to simulate and validate circuits, and retrieve * siloed commitments necessary for maintaining transaction privacy and security on the network. */ -export interface ProofCreator { +export interface PrivateKernelProver { /** * Computes the siloed commitments for a given set of public inputs. * @@ -64,9 +56,9 @@ export interface ProofCreator { * @param privateKernelInputsInit - The private data structure for the initial iteration. * @returns A Promise resolving to a ProofOutput object containing public inputs and the kernel proof. */ - createProofInit( + simulateProofInit( privateKernelInputsInit: PrivateKernelInitCircuitPrivateInputs, - ): Promise>; + ): Promise>; /** * Creates a proof output for a given previous kernel data and private call data for an inner iteration. @@ -74,9 +66,9 @@ export interface ProofCreator { * @param privateKernelInputsInner - The private input data structure for the inner iteration. * @returns A Promise resolving to a ProofOutput object containing public inputs and the kernel proof. */ - createProofInner( + simulateProofInner( privateKernelInputsInner: PrivateKernelInnerCircuitPrivateInputs, - ): Promise>; + ): Promise>; /** * Creates a proof output by resetting the arrays using the reset circuit. @@ -84,9 +76,9 @@ export interface ProofCreator { * @param privateKernelInputsTail - The private input data structure for the reset circuit. * @returns A Promise resolving to a ProofOutput object containing public inputs and the kernel proof. */ - createProofReset( + simulateProofReset( privateKernelInputsReset: PrivateKernelResetCircuitPrivateInputsVariants, - ): Promise>; + ): Promise>; /** * Creates a proof output based on the last inner kernel iteration kernel data for the final ordering iteration. @@ -94,9 +86,16 @@ export interface ProofCreator { * @param privateKernelInputsTail - The private input data structure for the final ordering iteration. * @returns A Promise resolving to a ProofOutput object containing public inputs and the kernel proof. */ - createProofTail( + simulateProofTail( privateKernelInputsTail: PrivateKernelTailCircuitPrivateInputs, - ): Promise>; + ): Promise>; + + /** + * Based of a program stack, create a folding proof. + * @param acirs The program bytecode. + * @param witnessStack The witnessses for each program bytecode. + */ + createClientIvcProof(acirs: Buffer[], witnessStack: WitnessMap[]): Promise; /** * Creates a proof for an app circuit. @@ -106,9 +105,5 @@ export interface ProofCreator { * @param appCircuitName - Optionally specify the name of the app circuit * @returns A Promise resolving to a Proof object */ - createAppCircuitProof( - partialWitness: WitnessMap, - bytecode: Buffer, - appCircuitName?: string, - ): Promise; + computeAppCircuitVerificationKey(bytecode: Buffer, appCircuitName?: string): Promise; } diff --git a/yarn-project/circuit-types/src/interfaces/proving-job.ts b/yarn-project/circuit-types/src/interfaces/proving-job.ts index e68eff265ace..bed8fdf78312 100644 --- a/yarn-project/circuit-types/src/interfaces/proving-job.ts +++ b/yarn-project/circuit-types/src/interfaces/proving-job.ts @@ -15,6 +15,8 @@ import { type RootParityInputs, type RootRollupInputs, type RootRollupPublicInputs, + type TUBE_PROOF_LENGTH, + type TubeInputs, type VerificationKeyData, } from '@aztec/circuits.js'; @@ -31,6 +33,12 @@ export type PublicInputsAndRecursiveProof = { verificationKey: VerificationKeyData; }; +export type PublicInputsAndTubeProof = { + inputs: T; + proof: RecursiveProof; + verificationKey: VerificationKeyData; +}; + export function makePublicInputsAndRecursiveProof( inputs: T, proof: RecursiveProof, @@ -62,6 +70,8 @@ export enum ProvingRequestType { BASE_PARITY, ROOT_PARITY, + // Recursive Client IVC verification to connect private -> public or rollup + TUBE_PROOF, } export type ProvingRequest = @@ -102,6 +112,10 @@ export type ProvingRequest = | { type: ProvingRequestType.PRIVATE_KERNEL_EMPTY; inputs: PrivateKernelEmptyInputData; + } + | { + type: ProvingRequestType.TUBE_PROOF; + inputs: TubeInputs; }; export type ProvingRequestPublicInputs = { @@ -117,6 +131,8 @@ export type ProvingRequestPublicInputs = { [ProvingRequestType.BASE_PARITY]: RootParityInput; [ProvingRequestType.ROOT_PARITY]: RootParityInput; + // TODO(#7369) properly structure tube proof flow + [ProvingRequestType.TUBE_PROOF]: { tubeVK: VerificationKeyData; tubeProof: RecursiveProof<393> }; }; export type ProvingRequestResult = ProvingRequestPublicInputs[T]; diff --git a/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts b/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts index 0bf3e3a79325..69c096cca47f 100644 --- a/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts +++ b/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts @@ -1,6 +1,7 @@ import { type ProofAndVerificationKey, type PublicInputsAndRecursiveProof, + type PublicInputsAndTubeProof, type PublicKernelNonTailRequest, type PublicKernelTailRequest, type Tx, @@ -16,10 +17,13 @@ import { type PrivateKernelEmptyInputData, type PublicKernelCircuitPublicInputs, type RECURSIVE_PROOF_LENGTH, + type RecursiveProof, type RootParityInput, type RootParityInputs, type RootRollupInputs, type RootRollupPublicInputs, + type TubeInputs, + type VerificationKeyData, } from '@aztec/circuits.js'; /** @@ -49,10 +53,19 @@ export interface ServerCircuitProver { * @param input - Input to the circuit. */ getBaseRollupProof( - input: BaseRollupInputs, + baseRollupInput: BaseRollupInputs, signal?: AbortSignal, ): Promise>; + /** + * Get a recursively verified client IVC proof (making it a compatible honk proof for the rest of the rollup). + * @param input - Input to the circuit. + */ + getTubeProof( + tubeInput: TubeInputs, + signal?: AbortSignal, + ): Promise<{ tubeVK: VerificationKeyData; tubeProof: RecursiveProof }>; + /** * Creates a proof for the given input. * @param input - Input to the circuit. @@ -94,6 +107,11 @@ export interface ServerCircuitProver { signal?: AbortSignal, ): Promise>; + getEmptyTubeProof( + inputs: PrivateKernelEmptyInputData, + signal?: AbortSignal, + ): Promise>; + /** * Create a proof for the AVM circuit. * @param inputs - Inputs to the AVM circuit. diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index 48f60ba5567d..5059012ffb57 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -1,6 +1,7 @@ import { AztecAddress, CallRequest, + ClientIvcProof, GasSettings, LogHash, MAX_NULLIFIERS_PER_TX, @@ -12,7 +13,6 @@ import { PublicCallRequest, computeContractClassId, getContractClassFromArtifact, - makeEmptyProof, } from '@aztec/circuits.js'; import { makeCombinedAccumulatedData, @@ -162,7 +162,7 @@ export const mockTx = ( const tx = new Tx( data, - makeEmptyProof(), + ClientIvcProof.empty(), noteEncryptedLogs, encryptedLogs, unencryptedLogs, diff --git a/yarn-project/circuit-types/src/tx/processed_tx.ts b/yarn-project/circuit-types/src/tx/processed_tx.ts index edf5228603c6..2f89ec1434bb 100644 --- a/yarn-project/circuit-types/src/tx/processed_tx.ts +++ b/yarn-project/circuit-types/src/tx/processed_tx.ts @@ -3,6 +3,7 @@ import { EncryptedTxL2Logs, PublicDataWrite, type PublicInputsAndRecursiveProof, + type PublicInputsAndTubeProof, type SimulationError, type Tx, TxEffect, @@ -11,20 +12,20 @@ import { } from '@aztec/circuit-types'; import { type AvmExecutionHints, + ClientIvcProof, Fr, type Gas, type GasFees, type Header, KernelCircuitPublicInputs, type NESTED_RECURSIVE_PROOF_LENGTH, - type Proof, type PublicDataUpdateRequest, type PublicKernelCircuitPrivateInputs, type PublicKernelCircuitPublicInputs, type PublicKernelTailCircuitPrivateInputs, type RecursiveProof, + type TUBE_PROOF_LENGTH, type VerificationKeyData, - makeEmptyProof, } from '@aztec/circuits.js'; import { type CircuitName } from '../stats/stats.js'; @@ -69,7 +70,7 @@ export type PublicProvingRequest = AvmProvingRequest | PublicKernelRequest; * Represents a tx that has been processed by the sequencer public processor, * so its kernel circuit public inputs are filled in. */ -export type ProcessedTx = Pick & { +export type ProcessedTx = Pick & { /** * Output of the private tail or public tail kernel circuit for this tx. */ @@ -151,7 +152,6 @@ export type FailedTx = { export function makeProcessedTx( tx: Tx, kernelOutput: KernelCircuitPublicInputs, - proof: Proof, publicProvingRequests: PublicProvingRequest[], revertReason?: SimulationError, gasUsed: ProcessedTx['gasUsed'] = {}, @@ -160,7 +160,7 @@ export function makeProcessedTx( return { hash: tx.getTxHash(), data: kernelOutput, - proof, + clientIvcProof: tx.clientIvcProof, // TODO(4712): deal with non-revertible logs here noteEncryptedLogs: tx.noteEncryptedLogs, encryptedLogs: tx.encryptedLogs, @@ -178,6 +178,11 @@ export type PaddingProcessedTx = ProcessedTx & { recursiveProof: RecursiveProof; }; +export type PaddingProcessedTxFromTube = ProcessedTx & { + verificationKey: VerificationKeyData; + recursiveProof: RecursiveProof; +}; + /** * Makes a padding empty tx with a valid proof. * @returns A valid padding processed tx. @@ -192,7 +197,32 @@ export function makePaddingProcessedTx( encryptedLogs: EncryptedTxL2Logs.empty(), unencryptedLogs: UnencryptedTxL2Logs.empty(), data: kernelOutput.inputs, - proof: kernelOutput.proof.binaryProof, + clientIvcProof: ClientIvcProof.empty(), + isEmpty: true, + revertReason: undefined, + publicProvingRequests: [], + gasUsed: {}, + finalPublicDataUpdateRequests: [], + verificationKey: kernelOutput.verificationKey, + recursiveProof: kernelOutput.proof, + }; +} + +/** + * Makes a padding empty tx with a valid proof. + * @returns A valid padding processed tx. + */ +export function makePaddingProcessedTxFromTubeProof( + kernelOutput: PublicInputsAndTubeProof, +): PaddingProcessedTxFromTube { + const hash = new TxHash(Fr.ZERO.toBuffer()); + return { + hash, + noteEncryptedLogs: EncryptedNoteTxL2Logs.empty(), + encryptedLogs: EncryptedTxL2Logs.empty(), + unencryptedLogs: UnencryptedTxL2Logs.empty(), + data: kernelOutput.inputs, + clientIvcProof: ClientIvcProof.empty(), isEmpty: true, revertReason: undefined, publicProvingRequests: [], @@ -213,7 +243,6 @@ export function makeEmptyProcessedTx(header: Header, chainId: Fr, version: Fr, v emptyKernelOutput.constants.txContext.chainId = chainId; emptyKernelOutput.constants.txContext.version = version; emptyKernelOutput.constants.vkTreeRoot = vkTreeRoot; - const emptyProof = makeEmptyProof(); const hash = new TxHash(Fr.ZERO.toBuffer()); return { @@ -222,7 +251,7 @@ export function makeEmptyProcessedTx(header: Header, chainId: Fr, version: Fr, v encryptedLogs: EncryptedTxL2Logs.empty(), unencryptedLogs: UnencryptedTxL2Logs.empty(), data: emptyKernelOutput, - proof: emptyProof, + clientIvcProof: ClientIvcProof.empty(), isEmpty: true, revertReason: undefined, publicProvingRequests: [], diff --git a/yarn-project/circuit-types/src/tx/tx.ts b/yarn-project/circuit-types/src/tx/tx.ts index b71e99074d51..39e0184f659f 100644 --- a/yarn-project/circuit-types/src/tx/tx.ts +++ b/yarn-project/circuit-types/src/tx/tx.ts @@ -1,7 +1,7 @@ import { + ClientIvcProof, ContractClassRegisteredEvent, PrivateKernelTailCircuitPublicInputs, - Proof, PublicCallRequest, type PublicKernelCircuitPublicInputs, } from '@aztec/circuits.js'; @@ -25,8 +25,10 @@ export class Tx { public readonly data: PrivateKernelTailCircuitPublicInputs, /** * Proof from the private kernel circuit. + * TODO(#7368): This client IVC object currently contains various VKs that will eventually be more like static data. + * */ - public readonly proof: Proof, + public readonly clientIvcProof: ClientIvcProof, /** * Encrypted note logs generated by the tx. */ @@ -72,7 +74,7 @@ export class Tx { const reader = BufferReader.asReader(buffer); return new Tx( reader.readObject(PrivateKernelTailCircuitPublicInputs), - reader.readObject(Proof), + reader.readObject(ClientIvcProof), reader.readObject(EncryptedNoteTxL2Logs), reader.readObject(EncryptedTxL2Logs), reader.readObject(UnencryptedTxL2Logs), @@ -88,7 +90,7 @@ export class Tx { toBuffer() { return serializeToBuffer([ this.data, - this.proof, + this.clientIvcProof, this.noteEncryptedLogs, this.encryptedLogs, this.unencryptedLogs, @@ -108,7 +110,7 @@ export class Tx { noteEncryptedLogs: this.noteEncryptedLogs.toBuffer().toString('hex'), encryptedLogs: this.encryptedLogs.toBuffer().toString('hex'), unencryptedLogs: this.unencryptedLogs.toBuffer().toString('hex'), - proof: this.proof.toBuffer().toString('hex'), + clientIvcProof: this.clientIvcProof.toBuffer().toString('hex'), enqueuedPublicFunctions: this.enqueuedPublicFunctionCalls.map(f => f.toBuffer().toString('hex')) ?? [], publicTeardownFunctionCall: this.publicTeardownFunctionCall.toBuffer().toString('hex'), }; @@ -133,14 +135,14 @@ export class Tx { const noteEncryptedLogs = EncryptedNoteTxL2Logs.fromBuffer(Buffer.from(obj.noteEncryptedLogs, 'hex')); const encryptedLogs = EncryptedTxL2Logs.fromBuffer(Buffer.from(obj.encryptedLogs, 'hex')); const unencryptedLogs = UnencryptedTxL2Logs.fromBuffer(Buffer.from(obj.unencryptedLogs, 'hex')); - const proof = Buffer.from(obj.proof, 'hex'); + const clientIvcProof = ClientIvcProof.fromBuffer(Buffer.from(obj.clientIvcProof, 'hex')); const enqueuedPublicFunctions = obj.enqueuedPublicFunctions ? obj.enqueuedPublicFunctions.map((x: string) => PublicCallRequest.fromBuffer(Buffer.from(x, 'hex'))) : []; const publicTeardownFunctionCall = PublicCallRequest.fromBuffer(Buffer.from(obj.publicTeardownFunctionCall, 'hex')); return new Tx( publicInputs, - Proof.fromBuffer(proof), + clientIvcProof, noteEncryptedLogs, encryptedLogs, unencryptedLogs, @@ -176,7 +178,7 @@ export class Tx { newCommitmentCount: this.data.getNonEmptyNoteHashes().length, newNullifierCount: this.data.getNonEmptyNullifiers().length, - proofSize: this.proof.buffer.length, + proofSize: this.clientIvcProof.clientIvcProofBuffer.length, size: this.toBuffer().length, feePaymentMethod: @@ -199,7 +201,7 @@ export class Tx { getSize() { return ( this.data.getSize() + - this.proof.buffer.length + + this.clientIvcProof.clientIvcProofBuffer.length + this.noteEncryptedLogs.getSerializedLength() + this.encryptedLogs.getSerializedLength() + this.unencryptedLogs.getSerializedLength() + @@ -233,7 +235,7 @@ export class Tx { */ static clone(tx: Tx): Tx { const publicInputs = PrivateKernelTailCircuitPublicInputs.fromBuffer(tx.data.toBuffer()); - const proof = Proof.fromBuffer(tx.proof.toBuffer()); + const clientIvcProof = ClientIvcProof.fromBuffer(tx.clientIvcProof.toBuffer()); const noteEncryptedLogs = EncryptedNoteTxL2Logs.fromBuffer(Buffer.from(tx.noteEncryptedLogs.toBuffer())); const encryptedLogs = EncryptedTxL2Logs.fromBuffer(tx.encryptedLogs.toBuffer()); const unencryptedLogs = UnencryptedTxL2Logs.fromBuffer(tx.unencryptedLogs.toBuffer()); @@ -243,7 +245,7 @@ export class Tx { const publicTeardownFunctionCall = PublicCallRequest.fromBuffer(tx.publicTeardownFunctionCall.toBuffer()); return new Tx( publicInputs, - proof, + clientIvcProof, noteEncryptedLogs, encryptedLogs, unencryptedLogs, diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 38eb09c6f9ff..308495143d7d 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -188,9 +188,10 @@ export const L2_TO_L1_MSGS_NUM_BYTES_PER_BASE_ROLLUP = 256; export const LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 64; export const NUM_MSGS_PER_BASE_PARITY = 4; export const NUM_BASE_PARITY_PER_ROOT_PARITY = 4; -export const RECURSIVE_PROOF_LENGTH = 93; -export const NESTED_RECURSIVE_PROOF_LENGTH = 109; -export const VERIFICATION_KEY_LENGTH_IN_FIELDS = 114; +export const RECURSIVE_PROOF_LENGTH = 393; +export const NESTED_RECURSIVE_PROOF_LENGTH = 393; +export const TUBE_PROOF_LENGTH = 393; +export const VERIFICATION_KEY_LENGTH_IN_FIELDS = 103; export const SENDER_SELECTOR = 0; export const ADDRESS_SELECTOR = 1; export const STORAGE_ADDRESS_SELECTOR = 1; diff --git a/yarn-project/circuits.js/src/structs/client_ivc_proof.ts b/yarn-project/circuits.js/src/structs/client_ivc_proof.ts new file mode 100644 index 000000000000..313a49b5f81f --- /dev/null +++ b/yarn-project/circuits.js/src/structs/client_ivc_proof.ts @@ -0,0 +1,95 @@ +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +import * as fs from 'fs/promises'; +import path from 'path'; + +/** + * TODO(https://github.com/AztecProtocol/aztec-packages/issues/7370) refactory this to + * eventually we read all these VKs from the data tree instead of passing them + */ +export class ClientIvcProof { + constructor( + // produced by the sequencer when making the tube proof + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7370): Need to precompute private kernel tail VK so we can verify this immediately in the tx pool + // which parts of these are needed to quickly verify that we have a correct IVC proof + public instVkBuffer: Buffer, + public pgAccBuffer: Buffer, + public clientIvcProofBuffer: Buffer, + public translatorVkBuffer: Buffer, + public eccVkBuffer: Buffer, + ) {} + + public isEmpty() { + return this.clientIvcProofBuffer.length === 0; + } + + static empty() { + return new ClientIvcProof(Buffer.from(''), Buffer.from(''), Buffer.from(''), Buffer.from(''), Buffer.from('')); + } + + /** + * TODO(#7371): eventually remove client_ivc_prove_output_all_msgpack and properly handle these accumulators and VKs + * Create a ClientIvcProof from the result of client_ivc_prove_output_all or client_ivc_prove_output_all_msgpack + * @param directory the directory of results + * @returns the encapsulated client ivc proof + */ + static async readFromOutputDirectory(directory: string) { + const [instVkBuffer, pgAccBuffer, clientIvcProofBuffer, translatorVkBuffer, eccVkBuffer] = await Promise.all( + ['inst_vk', 'pg_acc', 'client_ivc_proof', 'translator_vk', 'ecc_vk'].map(fileName => + fs.readFile(path.join(directory, fileName)), + ), + ); + return new ClientIvcProof(instVkBuffer, pgAccBuffer, clientIvcProofBuffer, translatorVkBuffer, eccVkBuffer); + } + + /** + * TODO(#7371): eventually remove client_ivc_prove_output_all_msgpack and properly handle these accumulators and VKs + * Serialize a ClientIvcProof to the files expected by prove_tube + * + * Example usage: + * await runInDirectory(bbWorkingDirectory, async (dir: string) => { + * await privateTx.clientIvcProof!.writeToOutputDirectory(bbWorkingDirectory); + * const result = await generateTubeProof(bbPath, dir, logger.info) + * expect(result.status).toBe(BB_RESULT.SUCCESS) + * }); + * @param proof the ClientIvcProof from readFromOutputDirectory + * @param directory the directory of results + */ + async writeToOutputDirectory(directory: string) { + const { instVkBuffer, pgAccBuffer, clientIvcProofBuffer, translatorVkBuffer, eccVkBuffer } = this; + const fileData = [ + ['inst_vk', instVkBuffer], + ['pg_acc', pgAccBuffer], + ['client_ivc_proof', clientIvcProofBuffer], + ['translator_vk', translatorVkBuffer], + ['ecc_vk', eccVkBuffer], + ] as const; + await Promise.all(fileData.map(([fileName, buffer]) => fs.writeFile(path.join(directory, fileName), buffer))); + } + + static fromBuffer(buffer: Buffer | BufferReader): ClientIvcProof { + const reader = BufferReader.asReader(buffer); + return new ClientIvcProof( + reader.readBuffer(), + reader.readBuffer(), + reader.readBuffer(), + reader.readBuffer(), + reader.readBuffer(), + ); + } + + public toBuffer() { + return serializeToBuffer( + this.instVkBuffer.length, + this.instVkBuffer, + this.pgAccBuffer.length, + this.pgAccBuffer, + this.clientIvcProofBuffer.length, + this.clientIvcProofBuffer, + this.translatorVkBuffer.length, + this.translatorVkBuffer, + this.eccVkBuffer.length, + this.eccVkBuffer, + ); + } +} diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index d90356a074a2..15dff650a62e 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -3,6 +3,7 @@ export * from './avm/avm.js'; export * from './call_context.js'; export * from './call_request.js'; export * from './caller_context.js'; +export * from './client_ivc_proof.js'; export * from './complete_address.js'; export * from './content_commitment.js'; export * from './context/private_context_inputs.js'; diff --git a/yarn-project/circuits.js/src/structs/kernel/kernel_data.ts b/yarn-project/circuits.js/src/structs/kernel/kernel_data.ts index 2bcf52b74533..855ad7f8866a 100644 --- a/yarn-project/circuits.js/src/structs/kernel/kernel_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/kernel_data.ts @@ -2,12 +2,13 @@ import { makeTuple } from '@aztec/foundation/array'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; -import { NESTED_RECURSIVE_PROOF_LENGTH, VK_TREE_HEIGHT } from '../../constants.gen.js'; +import { RECURSIVE_PROOF_LENGTH, VK_TREE_HEIGHT } from '../../constants.gen.js'; import { RecursiveProof, makeEmptyRecursiveProof } from '../recursive_proof.js'; import { type UInt32 } from '../shared.js'; import { VerificationKeyData } from '../verification_key.js'; import { KernelCircuitPublicInputs } from './kernel_circuit_public_inputs.js'; +// TODO: less ambiguous name export class KernelData { constructor( /** @@ -15,9 +16,9 @@ export class KernelData { */ public publicInputs: KernelCircuitPublicInputs, /** - * Proof of the previous kernel. + * The previous kernel's proof (may be a tube proof or public kernel proof). */ - public proof: RecursiveProof, + public proof: RecursiveProof, /** * Verification key of the previous kernel. */ @@ -35,7 +36,7 @@ export class KernelData { static empty(): KernelData { return new this( KernelCircuitPublicInputs.empty(), - makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), + makeEmptyRecursiveProof(RECURSIVE_PROOF_LENGTH), VerificationKeyData.makeFake(), 0, makeTuple(VK_TREE_HEIGHT, Fr.zero), @@ -46,7 +47,7 @@ export class KernelData { const reader = BufferReader.asReader(buffer); return new this( reader.readObject(KernelCircuitPublicInputs), - RecursiveProof.fromBuffer(reader, NESTED_RECURSIVE_PROOF_LENGTH), + RecursiveProof.fromBuffer(reader, RECURSIVE_PROOF_LENGTH), reader.readObject(VerificationKeyData), reader.readNumber(), reader.readArray(VK_TREE_HEIGHT, Fr), diff --git a/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts b/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts index c00d927fb5bd..d01fefe28ab7 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts @@ -2,15 +2,10 @@ import { Fr } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; -import { - FUNCTION_TREE_HEIGHT, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - RECURSIVE_PROOF_LENGTH, -} from '../../constants.gen.js'; +import { FUNCTION_TREE_HEIGHT, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL } from '../../constants.gen.js'; import { CallRequest } from '../call_request.js'; import { MembershipWitness } from '../membership_witness.js'; import { PrivateCallStackItem } from '../private_call_stack_item.js'; -import { RecursiveProof } from '../recursive_proof.js'; import { VerificationKeyAsFields } from '../verification_key.js'; /** @@ -30,10 +25,6 @@ export class PrivateCallData { * The public call request for the teardown function. */ public publicTeardownCallRequest: CallRequest, - /** - * The proof of the execution of this private call. - */ - public proof: RecursiveProof, /** * The verification key for the function being invoked. */ @@ -74,7 +65,6 @@ export class PrivateCallData { fields.callStackItem, fields.publicCallStack, fields.publicTeardownCallRequest, - fields.proof, fields.vk, fields.contractClassArtifactHash, fields.contractClassPublicBytecodeCommitment, @@ -108,7 +98,6 @@ export class PrivateCallData { reader.readObject(PrivateCallStackItem), reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, CallRequest), reader.readObject(CallRequest), - RecursiveProof.fromBuffer(reader, RECURSIVE_PROOF_LENGTH), reader.readObject(VerificationKeyAsFields), reader.readObject(Fr), reader.readObject(Fr), diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_data.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_data.ts index bb4081c6b94d..33bced5e4d54 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_data.ts @@ -2,8 +2,7 @@ import { makeTuple } from '@aztec/foundation/array'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; -import { NESTED_RECURSIVE_PROOF_LENGTH, VK_TREE_HEIGHT } from '../../constants.gen.js'; -import { RecursiveProof, makeEmptyRecursiveProof } from '../recursive_proof.js'; +import { VK_TREE_HEIGHT } from '../../constants.gen.js'; import { type UInt32 } from '../shared.js'; import { VerificationKeyAsFields } from '../verification_key.js'; import { PrivateKernelCircuitPublicInputs } from './private_kernel_circuit_public_inputs.js'; @@ -12,15 +11,13 @@ import { PrivateKernelCircuitPublicInputs } from './private_kernel_circuit_publi * Data of the previous kernel iteration in the chain of kernels. */ export class PrivateKernelData { + // NOTE: as of move to honk and client IVC, previous private kernels no longer come with their proof + // as we do client IVC not recursive verification. We need to ensure the public inputs here is properly constrained, TODO(https://github.com/AztecProtocol/barretenberg/issues/1048) constructor( /** * Public inputs of the previous kernel. */ public publicInputs: PrivateKernelCircuitPublicInputs, - /** - * Proof of the previous kernel. - */ - public proof: RecursiveProof, /** * Verification key of the previous kernel. */ @@ -40,14 +37,13 @@ export class PrivateKernelData { * @returns The buffer. */ toBuffer() { - return serializeToBuffer(this.publicInputs, this.proof, this.vk, this.vkIndex, this.vkPath); + return serializeToBuffer(this.publicInputs, this.vk, this.vkIndex, this.vkPath); } static fromBuffer(buffer: Buffer | BufferReader): PrivateKernelData { const reader = BufferReader.asReader(buffer); return new this( reader.readObject(PrivateKernelCircuitPublicInputs), - RecursiveProof.fromBuffer(reader, NESTED_RECURSIVE_PROOF_LENGTH), reader.readObject(VerificationKeyAsFields), reader.readNumber(), reader.readArray(VK_TREE_HEIGHT, Fr), @@ -57,7 +53,6 @@ export class PrivateKernelData { static empty(): PrivateKernelData { return new PrivateKernelData( PrivateKernelCircuitPublicInputs.empty(), - makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), VerificationKeyAsFields.makeFake(), 0, makeTuple(VK_TREE_HEIGHT, Fr.zero), diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.ts index 190593832db6..b55aec38f247 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.ts @@ -1,5 +1,6 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { ClientIvcProof } from '../client_ivc_proof.js'; import { PublicCallData } from './public_call_data.js'; import { PublicKernelData } from './public_kernel_data.js'; @@ -12,6 +13,8 @@ export class PublicKernelCircuitPrivateInputs { * Kernels are recursive and this is the data from the previous kernel. */ public readonly previousKernel: PublicKernelData, + + public readonly clientIvcProof: ClientIvcProof, /** * Public calldata assembled from the execution result and proof. */ @@ -23,7 +26,7 @@ export class PublicKernelCircuitPrivateInputs { * @returns - Buffer representation of the object. */ toBuffer() { - return serializeToBuffer(this.previousKernel, this.publicCall); + return serializeToBuffer(this.previousKernel, this.clientIvcProof, this.publicCall); } /** @@ -42,8 +45,9 @@ export class PublicKernelCircuitPrivateInputs { static fromBuffer(buffer: BufferReader | Buffer) { const reader = BufferReader.asReader(buffer); const previousKernel = reader.readObject(PublicKernelData); + const clientIvcProof = reader.readObject(ClientIvcProof); const publicCall = reader.readObject(PublicCallData); - return new PublicKernelCircuitPrivateInputs(previousKernel, publicCall); + return new PublicKernelCircuitPrivateInputs(previousKernel, clientIvcProof, publicCall); } /** diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_data.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_data.ts index 50e2c5101dd2..7a1608f9a8e2 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_data.ts @@ -3,6 +3,7 @@ import { Fr } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; import { NESTED_RECURSIVE_PROOF_LENGTH, VK_TREE_HEIGHT } from '../../constants.gen.js'; +import { ClientIvcProof } from '../client_ivc_proof.js'; import { RecursiveProof, makeEmptyRecursiveProof } from '../recursive_proof.js'; import { type UInt32 } from '../shared.js'; import { VerificationKeyData } from '../verification_key.js'; @@ -33,6 +34,11 @@ export class PublicKernelData { * Sibling path of the previous kernel's vk in a tree of vks. */ public vkPath: Tuple, + + /** + * TODO(https://github.com/AztecProtocol/aztec-packages/issues/7369) this should be tube-proved for the first iteration and replace proof above + */ + public clientIvcProof: ClientIvcProof = ClientIvcProof.empty(), ) {} static fromBuffer(buffer: Buffer | BufferReader): PublicKernelData { @@ -43,6 +49,7 @@ export class PublicKernelData { reader.readObject(VerificationKeyData), reader.readNumber(), reader.readArray(VK_TREE_HEIGHT, Fr), + reader.readObject(ClientIvcProof), ); } @@ -53,6 +60,7 @@ export class PublicKernelData { VerificationKeyData.makeFake(), 0, makeTuple(VK_TREE_HEIGHT, Fr.zero), + ClientIvcProof.empty(), ); } @@ -61,6 +69,6 @@ export class PublicKernelData { * @returns The buffer. */ toBuffer() { - return serializeToBuffer(this.publicInputs, this.proof, this.vk, this.vkIndex, this.vkPath); + return serializeToBuffer(this.publicInputs, this.proof, this.vk, this.vkIndex, this.vkPath, this.clientIvcProof); } } diff --git a/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts index fbe008cc0361..4e7ef406af39 100644 --- a/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts @@ -8,6 +8,7 @@ import { MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_DATA_TREE_HEIGHT, } from '../../constants.gen.js'; +import { ClientIvcProof } from '../client_ivc_proof.js'; import { GlobalVariables } from '../global_variables.js'; import { KernelData } from '../kernel/kernel_data.js'; import { MembershipWitness } from '../membership_witness.js'; @@ -194,3 +195,57 @@ export class BaseRollupInputs { ); } } + +export class TubeInputs { + constructor(public clientIVCData: ClientIvcProof) {} + + static from(fields: FieldsOf): TubeInputs { + return new TubeInputs(...TubeInputs.getFields(fields)); + } + + static getFields(fields: FieldsOf) { + return [fields.clientIVCData] as const; + } + + /** + * Serializes the inputs to a buffer. + * @returns The inputs serialized to a buffer. + */ + toBuffer() { + return serializeToBuffer(...TubeInputs.getFields(this)); + } + + /** + * Serializes the inputs to a hex string. + * @returns The instance serialized to a hex string. + */ + toString() { + return this.toBuffer().toString('hex'); + } + + /** + * Deserializes the inputs from a buffer. + * @param buffer - The buffer to deserialize from. + * @returns A new TubeInputs instance. + */ + static fromBuffer(buffer: Buffer | BufferReader): TubeInputs { + const reader = BufferReader.asReader(buffer); + return new TubeInputs(reader.readObject(ClientIvcProof)); + } + + isEmpty(): boolean { + return this.clientIVCData.isEmpty(); + } + /** + * Deserializes the inputs from a hex string. + * @param str - A hex string to deserialize from. + * @returns A new TubeInputs instance. + */ + static fromString(str: string) { + return TubeInputs.fromBuffer(Buffer.from(str, 'hex')); + } + + static empty() { + return new TubeInputs(ClientIvcProof.empty()); + } +} diff --git a/yarn-project/circuits.js/src/structs/verification_key.ts b/yarn-project/circuits.js/src/structs/verification_key.ts index 4e66c1e5a826..2baffbf8039d 100644 --- a/yarn-project/circuits.js/src/structs/verification_key.ts +++ b/yarn-project/circuits.js/src/structs/verification_key.ts @@ -74,9 +74,10 @@ export class CommitmentMap { } } -export const CIRCUIT_SIZE_INDEX = 3; -export const CIRCUIT_PUBLIC_INPUTS_INDEX = 4; -export const CIRCUIT_RECURSIVE_INDEX = 5; +// TODO: find better home for these constants +export const CIRCUIT_SIZE_INDEX = 0; +export const CIRCUIT_PUBLIC_INPUTS_INDEX = 1; +export const CIRCUIT_RECURSIVE_INDEX = 0; /** * Provides a 'fields' representation of a circuit's verification key diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 9e7154f93931..9df75d8d6ad6 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -27,6 +27,7 @@ import { CallContext, CallRequest, CallerContext, + ClientIvcProof, CombineHints, CombinedAccumulatedData, CombinedConstantData, @@ -129,6 +130,7 @@ import { ScopedReadRequest, StateDiffHints, StateReference, + TUBE_PROOF_LENGTH, TxContext, TxRequest, VK_TREE_HEIGHT, @@ -608,7 +610,7 @@ export function makePublicKernelData(seed = 1, kernelPublicInputs?: PublicKernel export function makeRollupKernelData(seed = 1, kernelPublicInputs?: KernelCircuitPublicInputs): KernelData { return new KernelData( kernelPublicInputs ?? makeKernelCircuitPublicInputs(seed, true), - makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH, seed + 0x80), + makeRecursiveProof(TUBE_PROOF_LENGTH, seed + 0x80), VerificationKeyData.makeFake(), 0x42, makeTuple(VK_TREE_HEIGHT, fr, 0x1000), @@ -694,7 +696,11 @@ export function makePublicCallData(seed = 1, full = false): PublicCallData { * @returns Public kernel inputs. */ export function makePublicKernelCircuitPrivateInputs(seed = 1): PublicKernelCircuitPrivateInputs { - return new PublicKernelCircuitPrivateInputs(makePublicKernelData(seed), makePublicCallData(seed + 0x1000)); + return new PublicKernelCircuitPrivateInputs( + makePublicKernelData(seed), + ClientIvcProof.empty(), + makePublicCallData(seed + 0x1000), + ); } export function makeCombineHints(seed = 1): CombineHints { @@ -748,7 +754,7 @@ export function makePublicKernelInputsWithTweak( const kernelCircuitPublicInputs = makePublicKernelCircuitPublicInputs(seed, false); const previousKernel = makePublicKernelData(seed, kernelCircuitPublicInputs); const publicCall = makePublicCallData(seed + 0x1000); - const publicKernelInputs = new PublicKernelCircuitPrivateInputs(previousKernel, publicCall); + const publicKernelInputs = new PublicKernelCircuitPrivateInputs(previousKernel, ClientIvcProof.empty(), publicCall); if (tweak) { tweak(publicKernelInputs); } diff --git a/yarn-project/end-to-end/package.json b/yarn-project/end-to-end/package.json index fe4762ed479a..c60db38d6f99 100644 --- a/yarn-project/end-to-end/package.json +++ b/yarn-project/end-to-end/package.json @@ -16,6 +16,7 @@ "formatting": "run -T prettier --check ./src \"!src/web/main.js\" && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "test": "LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", + "test:debug": "LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --inspect --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", "test:integration": "concurrently -k -s first -c reset,dim -n test,anvil \"yarn test:integration:run\" \"anvil\"", "test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --no-cache --runInBand --config jest.integration.config.json" }, diff --git a/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts index 7dde1b74f29d..7a714d1a3438 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts @@ -1,5 +1,5 @@ import { getSchnorrAccount, getSchnorrWallet } from '@aztec/accounts/schnorr'; -import { PublicFeePaymentMethod, TxStatus } from '@aztec/aztec.js'; +import { PublicFeePaymentMethod, TxStatus, sleep } from '@aztec/aztec.js'; import { type AccountWallet } from '@aztec/aztec.js/wallet'; import { CompleteAddress, Fq, Fr, GasSettings } from '@aztec/circuits.js'; import { FPCContract, GasTokenContract, TestContract, TokenContract } from '@aztec/noir-contracts.js'; @@ -144,6 +144,9 @@ describe('benchmarks/proving', () => { provingPxes.push(pxe); } + /*TODO(post-honk): We wait 5 seconds for a race condition in setting up 4 nodes. + What is a more robust solution? */ + await sleep(5000); }); afterAll(async () => { diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 9c0ee2dfaa42..59656c44182c 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -29,7 +29,7 @@ import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, PublicDataUpdateRequest, } from '@aztec/circuits.js'; -import { fr, makeProof } from '@aztec/circuits.js/testing'; +import { fr } from '@aztec/circuits.js/testing'; import { type L1ContractAddresses, createEthereumChain } from '@aztec/ethereum'; import { makeTuple, range } from '@aztec/foundation/array'; import { openTmpStore } from '@aztec/kv-store/utils'; @@ -183,7 +183,7 @@ describe('L1Publisher integration', () => { seed + 0x500, ); - const processedTx = makeProcessedTx(tx, kernelOutput, makeProof(), []); + const processedTx = makeProcessedTx(tx, kernelOutput, []); processedTx.data.end.noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, fr, seed + 0x100); processedTx.data.end.nullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, fr, seed + 0x200); diff --git a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts index 3bb9d05de911..9fd48ad46079 100644 --- a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts +++ b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts @@ -11,6 +11,7 @@ import { type Wallet, computeSecretHash, retryUntil, + sleep, } from '@aztec/aztec.js'; import { ChildContract, TestContract, TokenContract } from '@aztec/noir-contracts.js'; @@ -44,6 +45,9 @@ describe('e2e_2_pxes', () => { ({ pxe: pxeB, teardown: teardownB } = await setupPXEService(aztecNode!, {}, undefined, true)); [walletB] = await createAccounts(pxeB, 1); + /*TODO(post-honk): We wait 5 seconds for a race condition in setting up two nodes. + What is a more robust solution? */ + await sleep(5000); }); afterEach(async () => { diff --git a/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts b/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts index 4f65251ed013..b98823ebe956 100644 --- a/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts +++ b/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts @@ -11,18 +11,18 @@ import { type PXE, type TxHash, computeSecretHash, - createDebugLogger, - deployL1Contract, + createDebugLogger, // TODO(#7373): Deploy honk solidity verifier + // deployL1Contract, } from '@aztec/aztec.js'; import { BBCircuitVerifier } from '@aztec/bb-prover'; -import { RollupAbi } from '@aztec/l1-artifacts'; +// import { RollupAbi } from '@aztec/l1-artifacts'; import { TokenContract } from '@aztec/noir-contracts.js'; import { type PXEService } from '@aztec/pxe'; -// @ts-expect-error solc-js doesn't publish its types https://github.com/ethereum/solc-js/issues/689 -import solc from 'solc'; -import { getContract } from 'viem'; - +// TODO(#7373): Deploy honk solidity verifier +// // @ts-expect-error solc-js doesn't publish its types https://github.com/ethereum/solc-js/issues/689 +// import solc from 'solc'; +// import { getContract } from 'viem'; import { waitRegisteredAccountSynced } from '../benchmarks/utils.js'; import { getACVMConfig } from '../fixtures/get_acvm_config.js'; import { getBBConfig } from '../fixtures/get_bb_config.js'; @@ -287,56 +287,58 @@ export class FullProverTest { ); } - async deployVerifier() { + deployVerifier() { if (!this.circuitProofVerifier) { throw new Error('No verifier'); } - const { walletClient, publicClient, l1ContractAddresses } = this.context.deployL1ContractsValues; - - const contract = await this.circuitProofVerifier.generateSolidityContract( - 'RootRollupArtifact', - 'UltraVerifier.sol', - ); - - const input = { - language: 'Solidity', - sources: { - 'UltraVerifier.sol': { - content: contract, - }, - }, - settings: { - // we require the optimizer - optimizer: { - enabled: true, - runs: 200, - }, - evmVersion: 'paris', - outputSelection: { - '*': { - '*': ['evm.bytecode.object', 'abi'], - }, - }, - }, - }; - - const output = JSON.parse(solc.compile(JSON.stringify(input))); - - const abi = output.contracts['UltraVerifier.sol']['UltraVerifier'].abi; - const bytecode: string = output.contracts['UltraVerifier.sol']['UltraVerifier'].evm.bytecode.object; - - const verifierAddress = await deployL1Contract(walletClient, publicClient, abi, `0x${bytecode}`); - - this.logger.info(`Deployed Real verifier at ${verifierAddress}`); - - const rollup = getContract({ - abi: RollupAbi, - address: l1ContractAddresses.rollupAddress.toString(), - client: walletClient, - }); - - await rollup.write.setVerifier([verifierAddress.toString()]); - this.logger.info('Rollup only accepts valid proofs now'); + // TODO(#7373): Deploy honk solidity verifier + return Promise.resolve(); + // const { walletClient, publicClient, l1ContractAddresses } = this.context.deployL1ContractsValues; + + // const contract = await this.circuitProofVerifier.generateSolidityContract( + // 'RootRollupArtifact', + // 'UltraVerifier.sol', + // ); + + // const input = { + // language: 'Solidity', + // sources: { + // 'UltraVerifier.sol': { + // content: contract, + // }, + // }, + // settings: { + // // we require the optimizer + // optimizer: { + // enabled: true, + // runs: 200, + // }, + // evmVersion: 'paris', + // outputSelection: { + // '*': { + // '*': ['evm.bytecode.object', 'abi'], + // }, + // }, + // }, + // }; + + // const output = JSON.parse(solc.compile(JSON.stringify(input))); + + // const abi = output.contracts['UltraVerifier.sol']['UltraVerifier'].abi; + // const bytecode: string = output.contracts['UltraVerifier.sol']['UltraVerifier'].evm.bytecode.object; + + // const verifierAddress = await deployL1Contract(walletClient, publicClient, abi, `0x${bytecode}`); + + // this.logger.info(`Deployed Real verifier at ${verifierAddress}`); + + // const rollup = getContract({ + // abi: RollupAbi, + // address: l1ContractAddresses.rollupAddress.toString(), + // client: walletClient, + // }); + + // await rollup.write.setVerifier([verifierAddress.toString()]); + // this.logger.info('Rollup only accepts valid proofs now'); } } diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index 93d3e0bd3be3..9c086c800449 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -28,7 +28,7 @@ import { } from '@aztec/aztec.js'; import { deployInstance, registerContractClass } from '@aztec/aztec.js/deployment'; import { DefaultMultiCallEntrypoint } from '@aztec/aztec.js/entrypoint'; -import { type BBNativeProofCreator } from '@aztec/bb-prover'; +import { type BBNativePrivateKernelProver } from '@aztec/bb-prover'; import { CANONICAL_AUTH_REGISTRY_ADDRESS, CANONICAL_KEY_REGISTRY_ADDRESS, @@ -161,7 +161,7 @@ export async function setupPXEService( opts: Partial = {}, logger = getLogger(), useLogSuffix = false, - proofCreator?: BBNativeProofCreator, + proofCreator?: BBNativePrivateKernelProver, ): Promise<{ /** * The PXE instance. diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index 210acd1a56e4..45ad64d3e7a9 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -976,7 +976,6 @@ export function mapPrivateCallDataToNoir(privateCallData: PrivateCallData): Priv call_stack_item: mapPrivateCallStackItemToNoir(privateCallData.callStackItem), public_call_stack: mapTuple(privateCallData.publicCallStack, mapCallRequestToNoir), public_teardown_call_request: mapCallRequestToNoir(privateCallData.publicTeardownCallRequest), - proof: mapRecursiveProofToNoir(privateCallData.proof), vk: mapVerificationKeyToNoir(privateCallData.vk), function_leaf_membership_witness: mapMembershipWitnessToNoir(privateCallData.functionLeafMembershipWitness), contract_class_artifact_hash: mapFieldToNoir(privateCallData.contractClassArtifactHash), @@ -1552,7 +1551,6 @@ export function mapPrivateKernelCircuitPublicInputsToNoir( export function mapPrivateKernelDataToNoir(privateKernelInnerData: PrivateKernelData): PrivateKernelDataNoir { return { public_inputs: mapPrivateKernelCircuitPublicInputsToNoir(privateKernelInnerData.publicInputs), - proof: mapRecursiveProofToNoir(privateKernelInnerData.proof), vk: mapVerificationKeyToNoir(privateKernelInnerData.vk), vk_index: mapFieldToNoir(new Fr(privateKernelInnerData.vkIndex)), vk_path: mapTuple(privateKernelInnerData.vkPath, mapFieldToNoir), diff --git a/yarn-project/noir-protocol-circuits-types/src/vks.ts b/yarn-project/noir-protocol-circuits-types/src/vks.ts index 2d56ff679a9e..9cd86bc3fa6a 100644 --- a/yarn-project/noir-protocol-circuits-types/src/vks.ts +++ b/yarn-project/noir-protocol-circuits-types/src/vks.ts @@ -59,9 +59,10 @@ function keyJsonToVKData(json: VkJson): VerificationKeyData { return new VerificationKeyData( new VerificationKeyAsFields( assertLength( - keyAsFields.slice(1).map((str: string) => new Fr(Buffer.from(str.slice(2), 'hex'))), + keyAsFields.map((str: string) => new Fr(Buffer.from(str.slice(2), 'hex'))), VERIFICATION_KEY_LENGTH_IN_FIELDS, ), + // TODO(#7410) what should be the vk hash here? new Fr(Buffer.from(keyAsFields[0].slice(2), 'hex')), ), Buffer.from(keyAsBytes, 'hex'), @@ -157,7 +158,8 @@ export function getVKIndex(vk: VerificationKeyData | VerificationKeyAsFields | F const index = getVKTree().getIndex(hash.toBuffer()); if (index < 0) { - throw new Error(`VK index for ${hash.toString()} not found in VK tree`); + //throw new Error(`VK index for ${hash.toString()} not found in VK tree`); + return 0; // faked for now } return index; } diff --git a/yarn-project/p2p/src/service/tx_messages.test.ts b/yarn-project/p2p/src/service/tx_messages.test.ts index 108fb1484161..007cfe739afc 100644 --- a/yarn-project/p2p/src/service/tx_messages.test.ts +++ b/yarn-project/p2p/src/service/tx_messages.test.ts @@ -5,9 +5,9 @@ import { expect } from '@jest/globals'; import { fromTxMessage, toTxMessage } from './tx_messages.js'; const verifyTx = (actual: Tx, expected: Tx) => { - expect(actual.data!.toBuffer()).toEqual(expected.data?.toBuffer()); - expect(actual.proof!.toBuffer()).toEqual(expected.proof!.toBuffer()); - expect(actual.encryptedLogs!.toBuffer()).toEqual(expected.encryptedLogs?.toBuffer()); + expect(actual.data.toBuffer()).toEqual(expected.data.toBuffer()); + expect(actual.clientIvcProof.toBuffer()).toEqual(expected.clientIvcProof.toBuffer()); + expect(actual.encryptedLogs.toBuffer()).toEqual(expected.encryptedLogs.toBuffer()); }; describe('Messages', () => { diff --git a/yarn-project/p2p/src/service/tx_messages.ts b/yarn-project/p2p/src/service/tx_messages.ts index 53fa7442faf3..cec7a59f5a4d 100644 --- a/yarn-project/p2p/src/service/tx_messages.ts +++ b/yarn-project/p2p/src/service/tx_messages.ts @@ -1,5 +1,5 @@ import { EncryptedNoteTxL2Logs, EncryptedTxL2Logs, Tx, UnencryptedTxL2Logs } from '@aztec/circuit-types'; -import { PrivateKernelTailCircuitPublicInputs, Proof, PublicCallRequest } from '@aztec/circuits.js'; +import { ClientIvcProof, PrivateKernelTailCircuitPublicInputs, PublicCallRequest } from '@aztec/circuits.js'; import { numToUInt32BE } from '@aztec/foundation/serialize'; import { type SemVer } from 'semver'; @@ -67,7 +67,7 @@ export function toTxMessage(tx: Tx): Buffer { }; const messageBuffer = Buffer.concat([ createMessageComponent(tx.data), - createMessageComponent(tx.proof), + createMessageComponent(tx.clientIvcProof), createMessageComponent(tx.noteEncryptedLogs), createMessageComponent(tx.encryptedLogs), createMessageComponent(tx.unencryptedLogs), @@ -113,9 +113,9 @@ export function fromTxMessage(buffer: Buffer): Tx { // this is the opposite of the 'toMessage' function // so the first 4 bytes is the complete length, skip it const publicInputs = toObject(buffer.subarray(4), PrivateKernelTailCircuitPublicInputs); - const proof = toObject(publicInputs.remainingData, Proof); + const clientIvcProof = toObject(publicInputs.remainingData, ClientIvcProof); - const noteEncryptedLogs = toObject(proof.remainingData, EncryptedNoteTxL2Logs); + const noteEncryptedLogs = toObject(clientIvcProof.remainingData, EncryptedNoteTxL2Logs); if (!noteEncryptedLogs.obj) { noteEncryptedLogs.obj = new EncryptedNoteTxL2Logs([]); } @@ -133,7 +133,7 @@ export function fromTxMessage(buffer: Buffer): Tx { const publicTeardownCall = toObject(publicCalls.remainingData, PublicCallRequest); return new Tx( publicInputs.obj!, - proof.obj!, + clientIvcProof.obj!, noteEncryptedLogs.obj, encryptedLogs.obj, unencryptedLogs.obj, diff --git a/yarn-project/prover-client/src/mocks/fixtures.ts b/yarn-project/prover-client/src/mocks/fixtures.ts index c10f9d42140f..e960506c43f5 100644 --- a/yarn-project/prover-client/src/mocks/fixtures.ts +++ b/yarn-project/prover-client/src/mocks/fixtures.ts @@ -21,7 +21,7 @@ import { PublicDataTreeLeaf, PublicDataUpdateRequest, } from '@aztec/circuits.js'; -import { fr, makeProof } from '@aztec/circuits.js/testing'; +import { fr } from '@aztec/circuits.js/testing'; import { makeTuple } from '@aztec/foundation/array'; import { padArrayEnd } from '@aztec/foundation/collection'; import { randomBytes } from '@aztec/foundation/crypto'; @@ -113,7 +113,7 @@ export const makeBloatedProcessedTx = async (builderDb: MerkleTreeOperations, se seed + 0x600, ); - const processedTx = makeProcessedTx(tx, kernelOutput, makeProof(), []); + const processedTx = makeProcessedTx(tx, kernelOutput, []); processedTx.data.end.noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, fr, seed + 0x100); processedTx.data.end.nullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, fr, seed + 0x100000); diff --git a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts index fd1c2e827463..c0aaba59c464 100644 --- a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts +++ b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts @@ -13,7 +13,7 @@ import { MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MembershipWitness, MergeRollupInputs, - NESTED_RECURSIVE_PROOF_LENGTH, + type NESTED_RECURSIVE_PROOF_LENGTH, NOTE_HASH_SUBTREE_HEIGHT, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_HEIGHT, @@ -30,16 +30,17 @@ import { PublicDataTreeLeaf, type PublicDataTreeLeafPreimage, PublicDataUpdateRequest, + type RECURSIVE_PROOF_LENGTH, type RecursiveProof, type RootParityInput, RootRollupInputs, type RootRollupPublicInputs, StateDiffHints, type StateReference, + type TUBE_PROOF_LENGTH, VK_TREE_HEIGHT, type VerificationKeyAsFields, type VerificationKeyData, - makeRecursiveProofFromBinary, } from '@aztec/circuits.js'; import { assertPermutation, makeTuple } from '@aztec/foundation/array'; import { padArrayEnd } from '@aztec/foundation/collection'; @@ -60,6 +61,7 @@ export type TreeNames = BaseTreeNames | 'L1ToL2MessageTree' | 'Archive'; // Builds the base rollup inputs, updating the contract, nullifier, and data trees in the process export async function buildBaseRollupInput( tx: ProcessedTx, + proof: RecursiveProof, globalVariables: GlobalVariables, db: MerkleTreeOperations, kernelVk: VerificationKeyData, @@ -158,7 +160,7 @@ export async function buildBaseRollupInput( ); return BaseRollupInputs.from({ - kernelData: getKernelDataFor(tx, kernelVk), + kernelData: getKernelDataFor(tx, kernelVk, proof), start, stateDiffHints, feePayerGasTokenBalanceReadHint, @@ -286,17 +288,18 @@ export async function getTreeSnapshot(id: MerkleTreeId, db: MerkleTreeOperations return new AppendOnlyTreeSnapshot(Fr.fromBuffer(treeInfo.root), Number(treeInfo.size)); } -export function getKernelDataFor(tx: ProcessedTx, vk: VerificationKeyData): KernelData { - const recursiveProof = makeRecursiveProofFromBinary(tx.proof, NESTED_RECURSIVE_PROOF_LENGTH); +export function getKernelDataFor( + tx: ProcessedTx, + vk: VerificationKeyData, + proof: RecursiveProof, +): KernelData { const leafIndex = getVKIndex(vk); return new KernelData( tx.data, - recursiveProof, - + proof, // VK for the kernel circuit vk, - leafIndex, getVKSiblingPath(leafIndex), ); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index 5673297f60a8..d8ffb6655ebc 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -43,6 +43,7 @@ import { type RecursiveProof, type RootParityInput, RootParityInputs, + TubeInputs, type VerificationKeyAsFields, VerificationKeyData, makeEmptyProof, @@ -449,11 +450,7 @@ export class ProvingOrchestrator { * @param provingState - The proving state being worked on */ private async prepareTransaction(tx: ProcessedTx, provingState: ProvingState) { - // Pass the private kernel tail vk here as the previous one. - // If there are public functions then this key will be overwritten once the public tail has been proven - const previousKernelVerificationKey = ProtocolCircuitVks.PrivateKernelTailArtifact; - - const txInputs = await this.prepareBaseRollupInputs(provingState, tx, previousKernelVerificationKey); + const txInputs = await this.prepareBaseRollupInputs(provingState, tx); if (!txInputs) { // This should not be possible throw new Error(`Unable to add padding transaction, preparing base inputs failed`); @@ -558,13 +555,28 @@ export class ProvingOrchestrator { private async prepareBaseRollupInputs( provingState: ProvingState | undefined, tx: ProcessedTx, - kernelVk: VerificationKeyData, ): Promise<[BaseRollupInputs, TreeSnapshots] | undefined> { if (!provingState?.verifyState()) { logger.debug('Not preparing base rollup inputs, state invalid'); return; } - const inputs = await buildBaseRollupInput(tx, provingState.globalVariables, this.db, kernelVk); + + const getBaseInputsEmptyTx = async () => { + const inputs = { + header: await this.db.buildInitialHeader(), + chainId: tx.data.constants.globalVariables.chainId, + version: tx.data.constants.globalVariables.version, + vkTreeRoot: tx.data.constants.vkTreeRoot, + }; + + const proof = await this.prover.getEmptyTubeProof(inputs); + return await buildBaseRollupInput(tx, proof.proof, provingState.globalVariables, this.db, proof.verificationKey); + }; + const getBaseInputsNonEmptyTx = async () => { + const proof = await this.prover.getTubeProof(new TubeInputs(tx.clientIvcProof)); + return await buildBaseRollupInput(tx, proof.tubeProof, provingState.globalVariables, this.db, proof.tubeVK); + }; + const inputs = tx.isEmpty ? await getBaseInputsEmptyTx() : await getBaseInputsNonEmptyTx(); const promises = [MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.PUBLIC_DATA_TREE].map( async (id: MerkleTreeId) => { return { key: id, value: await getTreeSnapshot(id, this.db) }; @@ -970,6 +982,7 @@ export class ProvingOrchestrator { result => { const nextKernelRequest = txProvingState.getNextPublicKernelFromKernelProof( functionIndex, + // PUBLIC KERNEL: I want to pass a client ivc proof into here? result.proof, result.verificationKey, ); diff --git a/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts b/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts index 6fcfdd9140d1..4ef6bd68d02b 100644 --- a/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts +++ b/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts @@ -9,11 +9,10 @@ import { import { type AppendOnlyTreeSnapshot, type BaseRollupInputs, - NESTED_RECURSIVE_PROOF_LENGTH, + type NESTED_RECURSIVE_PROOF_LENGTH, type Proof, type RecursiveProof, type VerificationKeyData, - makeRecursiveProofFromBinary, } from '@aztec/circuits.js'; export enum TX_PROVING_CODE { @@ -51,16 +50,14 @@ export class TxProvingState { public readonly treeSnapshots: Map, privateKernelVk: VerificationKeyData, ) { - let previousKernelProof: RecursiveProof | undefined = - makeRecursiveProofFromBinary(processedTx.proof, NESTED_RECURSIVE_PROOF_LENGTH); let previousProofType = PublicKernelType.NON_PUBLIC; for (let i = 0; i < processedTx.publicProvingRequests.length; i++) { const provingRequest = processedTx.publicProvingRequests[i]; const kernelRequest = provingRequest.type === AVM_REQUEST ? provingRequest.kernelRequest : provingRequest; // the first circuit has a valid previous proof, it came from private - if (previousKernelProof) { - kernelRequest.inputs.previousKernel.proof = previousKernelProof; + if (i === 0) { kernelRequest.inputs.previousKernel.vk = privateKernelVk; + kernelRequest.inputs.previousKernel.clientIvcProof = processedTx.clientIvcProof; } const vmRequest = provingRequest.type === AVM_REQUEST ? provingRequest : undefined; const publicFunction: PublicFunction = { @@ -71,7 +68,6 @@ export class TxProvingState { publicKernelRequest: kernelRequest, }; this.publicFunctions.push(publicFunction); - previousKernelProof = undefined; previousProofType = kernelRequest.type; } } diff --git a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts index ba9935faca97..dcba5452acd3 100644 --- a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts +++ b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts @@ -21,10 +21,13 @@ import type { PrivateKernelEmptyInputData, PublicKernelCircuitPublicInputs, RECURSIVE_PROOF_LENGTH, + RecursiveProof, RootParityInput, RootParityInputs, RootRollupInputs, RootRollupPublicInputs, + TubeInputs, + VerificationKeyData, } from '@aztec/circuits.js'; import { randomBytes } from '@aztec/foundation/crypto'; import { AbortError, TimeoutError } from '@aztec/foundation/error'; @@ -246,6 +249,20 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource return this.enqueue({ type: ProvingRequestType.PRIVATE_KERNEL_EMPTY, inputs }, signal); } + getTubeProof( + inputs: TubeInputs, + signal?: AbortSignal | undefined, + ): Promise<{ tubeVK: VerificationKeyData; tubeProof: RecursiveProof }> { + return this.enqueue({ type: ProvingRequestType.TUBE_PROOF, inputs }, signal); + } + + getEmptyTubeProof( + inputs: PrivateKernelEmptyInputData, + signal?: AbortSignal, + ): Promise> { + return this.enqueue({ type: ProvingRequestType.PRIVATE_KERNEL_EMPTY, inputs }, signal); + } + /** * Creates a proof for the given input. * @param input - Input to the circuit. @@ -285,13 +302,13 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource * @param input - Input to the circuit. */ getBaseRollupProof( - input: BaseRollupInputs, + baseRollupInput: BaseRollupInputs, signal?: AbortSignal, ): Promise> { return this.enqueue( { type: ProvingRequestType.BASE_ROLLUP, - inputs: input, + inputs: baseRollupInput, }, signal, ); diff --git a/yarn-project/prover-client/src/prover-agent/prover-agent.ts b/yarn-project/prover-client/src/prover-agent/prover-agent.ts index 14cb93aa74bb..37e4f51e32de 100644 --- a/yarn-project/prover-client/src/prover-agent/prover-agent.ts +++ b/yarn-project/prover-client/src/prover-agent/prover-agent.ts @@ -104,12 +104,16 @@ export class ProverAgent { } catch (err) { if (this.isRunning()) { this.log.error( - `Error processing proving job id=${job.id} type=${ProvingRequestType[job.request.type]}: ${err}`, + `Error processing proving job id=${job.id} type=${ProvingRequestType[job.request.type]}: ${ + (err as any).stack || err + }`, ); await jobSource.rejectProvingJob(job.id, new ProvingError((err as any)?.message ?? String(err))); } else { this.log.debug( - `Dropping proving job id=${job.id} type=${ProvingRequestType[job.request.type]}: agent stopped: ${err}`, + `Dropping proving job id=${job.id} type=${ProvingRequestType[job.request.type]}: agent stopped: ${ + (err as any).stack || err + }`, ); } } @@ -160,6 +164,10 @@ export class ProverAgent { return this.circuitProver.getEmptyPrivateKernelProof(inputs); } + case ProvingRequestType.TUBE_PROOF: { + return this.circuitProver.getTubeProof(inputs); + } + default: { const _exhaustive: never = type; return Promise.reject(new Error(`Invalid proof request type: ${type}`)); diff --git a/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts b/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts index 51f54b60c5ac..1cab8f282fab 100644 --- a/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts +++ b/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts @@ -1,5 +1,6 @@ import { BBNativeRollupProver, type BBProverConfig } from '@aztec/bb-prover'; -import { makePaddingProcessedTx } from '@aztec/circuit-types'; +import { makePaddingProcessedTxFromTubeProof } from '@aztec/circuit-types'; +import { NESTED_RECURSIVE_PROOF_LENGTH, makeEmptyRecursiveProof } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; @@ -38,12 +39,13 @@ describe('prover/bb_prover/base-rollup', () => { vkTreeRoot, }; - const paddingTxPublicInputsAndProof = await context.prover.getEmptyPrivateKernelProof(inputs); - const tx = makePaddingProcessedTx(paddingTxPublicInputsAndProof); + const paddingTxPublicInputsAndProof = await context.prover.getEmptyTubeProof(inputs); + const tx = makePaddingProcessedTxFromTubeProof(paddingTxPublicInputsAndProof); logger.verbose('Building base rollup inputs'); const baseRollupInputs = await buildBaseRollupInput( tx, + makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), context.globalVariables, context.actualDb, paddingTxPublicInputsAndProof.verificationKey, diff --git a/yarn-project/pxe/package.json b/yarn-project/pxe/package.json index 588fb9fec9b6..1f0e9c1aaf45 100644 --- a/yarn-project/pxe/package.json +++ b/yarn-project/pxe/package.json @@ -69,7 +69,9 @@ "@aztec/protocol-contracts": "workspace:^", "@aztec/simulator": "workspace:^", "@aztec/types": "workspace:^", + "@msgpack/msgpack": "^3.0.0-beta2", "@noir-lang/noirc_abi": "portal:../../noir/packages/noirc_abi", + "@noir-lang/types": "workspace:*", "koa": "^2.14.2", "koa-router": "^12.0.0", "lodash.omit": "^4.5.0", diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts index d41350b9aa5e..a3a0bf9d24f8 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts @@ -1,24 +1,21 @@ -import { Note, type ProofCreator } from '@aztec/circuit-types'; +import { Note, type PrivateKernelProver } from '@aztec/circuit-types'; import { FunctionData, FunctionSelector, MAX_NOTE_HASHES_PER_CALL, MAX_NOTE_HASHES_PER_TX, MembershipWitness, - NESTED_RECURSIVE_PROOF_LENGTH, NoteHash, PrivateCallStackItem, PrivateCircuitPublicInputs, PrivateKernelCircuitPublicInputs, PrivateKernelTailCircuitPublicInputs, PublicCallRequest, - RECURSIVE_PROOF_LENGTH, ScopedNoteHash, type TxRequest, VK_TREE_HEIGHT, VerificationKey, VerificationKeyAsFields, - makeRecursiveProof, } from '@aztec/circuits.js'; import { makeTxRequest } from '@aztec/circuits.js/testing'; import { NoteSelector } from '@aztec/foundation/abi'; @@ -35,7 +32,7 @@ import { type ProvingDataOracle } from './proving_data_oracle.js'; describe('Kernel Prover', () => { let txRequest: TxRequest; let oracle: ReturnType>; - let proofCreator: ReturnType>; + let proofCreator: ReturnType>; let prover: KernelProver; let dependencies: { [name: string]: string[] } = {}; @@ -84,7 +81,7 @@ describe('Kernel Prover', () => { }; }; - const createProofOutput = (newNoteIndices: number[]) => { + const simulateProofOutput = (newNoteIndices: number[]) => { const publicInputs = PrivateKernelCircuitPublicInputs.empty(); const noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, ScopedNoteHash.empty); for (let i = 0; i < newNoteIndices.length; i++) { @@ -96,12 +93,12 @@ describe('Kernel Prover', () => { publicInputs.end.noteHashes = noteHashes; return { publicInputs, - proof: makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), verificationKey: VerificationKeyAsFields.makeEmpty(), + outputWitness: new Map(), }; }; - const createProofOutputFinal = (newNoteIndices: number[]) => { + const simulateProofOutputFinal = (newNoteIndices: number[]) => { const publicInputs = PrivateKernelTailCircuitPublicInputs.empty(); const noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, () => Fr.ZERO); for (let i = 0; i < newNoteIndices.length; i++) { @@ -111,31 +108,30 @@ describe('Kernel Prover', () => { return { publicInputs, - proof: makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), + outputWitness: new Map(), verificationKey: VerificationKeyAsFields.makeEmpty(), }; }; - const createAppCircuitProofOutput = () => { + const computeAppCircuitVerificationKeyOutput = () => { return { - proof: makeRecursiveProof(RECURSIVE_PROOF_LENGTH), verificationKey: VerificationKeyAsFields.makeEmpty(), }; }; const expectExecution = (fns: string[]) => { - const callStackItemsInit = proofCreator.createProofInit.mock.calls.map(args => + const callStackItemsInit = proofCreator.simulateProofInit.mock.calls.map(args => String.fromCharCode(args[0].privateCall.callStackItem.functionData.selector.value), ); - const callStackItemsInner = proofCreator.createProofInner.mock.calls.map(args => + const callStackItemsInner = proofCreator.simulateProofInner.mock.calls.map(args => String.fromCharCode(args[0].privateCall.callStackItem.functionData.selector.value), ); - expect(proofCreator.createProofInit).toHaveBeenCalledTimes(Math.min(1, fns.length)); - expect(proofCreator.createProofInner).toHaveBeenCalledTimes(Math.max(0, fns.length - 1)); + expect(proofCreator.simulateProofInit).toHaveBeenCalledTimes(Math.min(1, fns.length)); + expect(proofCreator.simulateProofInner).toHaveBeenCalledTimes(Math.max(0, fns.length - 1)); expect(callStackItemsInit.concat(callStackItemsInner)).toEqual(fns); - proofCreator.createProofInner.mockClear(); - proofCreator.createProofInit.mockClear(); + proofCreator.simulateProofInner.mockClear(); + proofCreator.simulateProofInit.mockClear(); }; const prove = (executionResult: ExecutionResult) => prover.prove(txRequest, executionResult); @@ -158,15 +154,15 @@ describe('Kernel Prover', () => { privateFunctionsRoot: Fr.random(), }); - proofCreator = mock(); + proofCreator = mock(); proofCreator.getSiloedCommitments.mockImplementation(publicInputs => Promise.resolve(publicInputs.noteHashes.map(com => createFakeSiloedCommitment(com.value))), ); - proofCreator.createProofInit.mockResolvedValue(createProofOutput([])); - proofCreator.createProofInner.mockResolvedValue(createProofOutput([])); - proofCreator.createProofReset.mockResolvedValue(createProofOutput([])); - proofCreator.createProofTail.mockResolvedValue(createProofOutputFinal([])); - proofCreator.createAppCircuitProof.mockResolvedValue(createAppCircuitProofOutput()); + proofCreator.simulateProofInit.mockResolvedValue(simulateProofOutput([])); + proofCreator.simulateProofInner.mockResolvedValue(simulateProofOutput([])); + proofCreator.simulateProofReset.mockResolvedValue(simulateProofOutput([])); + proofCreator.simulateProofTail.mockResolvedValue(simulateProofOutputFinal([])); + proofCreator.computeAppCircuitVerificationKey.mockResolvedValue(computeAppCircuitVerificationKeyOutput()); prover = new KernelProver(oracle, proofCreator); }); diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts index 5a219fce08a7..728e41124012 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts @@ -1,4 +1,4 @@ -import { type KernelProofOutput, type ProofCreator } from '@aztec/circuit-types'; +import { type PrivateKernelProver, type PrivateKernelSimulateOutput } from '@aztec/circuit-types'; import { CallRequest, Fr, @@ -9,7 +9,6 @@ import { MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - NESTED_RECURSIVE_PROOF_LENGTH, PrivateCallData, PrivateKernelCircuitPublicInputs, PrivateKernelData, @@ -17,24 +16,32 @@ import { PrivateKernelInnerCircuitPrivateInputs, PrivateKernelTailCircuitPrivateInputs, type PrivateKernelTailCircuitPublicInputs, - type RECURSIVE_PROOF_LENGTH, - type RecursiveProof, type TxRequest, VK_TREE_HEIGHT, VerificationKeyAsFields, getNonEmptyItems, - makeRecursiveProof, } from '@aztec/circuits.js'; import { padArrayEnd } from '@aztec/foundation/collection'; import { createDebugLogger } from '@aztec/foundation/log'; import { assertLength } from '@aztec/foundation/serialize'; import { pushTestData } from '@aztec/foundation/testing'; -import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; +import { + ClientCircuitArtifacts, + PrivateResetTagToArtifactName, + getVKTreeRoot, +} from '@aztec/noir-protocol-circuits-types'; import { type ExecutionResult, collectNoteHashLeafIndexMap, collectNullifiedNoteHashCounters } from '@aztec/simulator'; +import { type WitnessMap } from '@noir-lang/types'; + import { buildPrivateKernelResetInputs } from './private_inputs_builders/index.js'; import { type ProvingDataOracle } from './proving_data_oracle.js'; +const NULL_PROVE_OUTPUT: PrivateKernelSimulateOutput = { + publicInputs: PrivateKernelCircuitPublicInputs.empty(), + verificationKey: VerificationKeyAsFields.makeEmpty(), + outputWitness: new Map(), +}; /** * The KernelProver class is responsible for generating kernel proofs. * It takes a transaction request, its signature, and the simulation result as inputs, and outputs a proof @@ -44,7 +51,7 @@ import { type ProvingDataOracle } from './proving_data_oracle.js'; export class KernelProver { private log = createDebugLogger('aztec:kernel-prover'); - constructor(private oracle: ProvingDataOracle, private proofCreator: ProofCreator) {} + constructor(private oracle: ProvingDataOracle, private proofCreator: PrivateKernelProver) {} /** * Generate a proof for a given transaction request and execution result. @@ -55,26 +62,37 @@ export class KernelProver { * @param txRequest - The authenticated transaction request object. * @param executionResult - The execution result object containing nested executions and preimages. * @returns A Promise that resolves to a KernelProverOutput object containing proof, public inputs, and output notes. + * TODO(#7368) this should be refactored to not recreate the ACIR bytecode now that it operates on a program stack */ async prove( txRequest: TxRequest, executionResult: ExecutionResult, - ): Promise> { + ): Promise> { const executionStack = [executionResult]; let firstIteration = true; - let output: KernelProofOutput = { - publicInputs: PrivateKernelCircuitPublicInputs.empty(), - proof: makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), - verificationKey: VerificationKeyAsFields.makeEmpty(), - }; + let output = NULL_PROVE_OUTPUT; const noteHashLeafIndexMap = collectNoteHashLeafIndexMap(executionResult); const noteHashNullifierCounterMap = collectNullifiedNoteHashCounters(executionResult); + // vector of gzipped bincode acirs + const acirs: Buffer[] = []; + const witnessStack: WitnessMap[] = []; while (executionStack.length) { if (!firstIteration && this.needsReset(executionStack, output)) { - output = await this.runReset(executionStack, output, noteHashLeafIndexMap, noteHashNullifierCounterMap); + const resetInputs = await this.getPrivateKernelResetInputs( + executionStack, + output, + noteHashLeafIndexMap, + noteHashNullifierCounterMap, + ); + output = await this.proofCreator.simulateProofReset(resetInputs); + // TODO(#7368) consider refactoring this redundant bytecode pushing + acirs.push( + Buffer.from(ClientCircuitArtifacts[PrivateResetTagToArtifactName[resetInputs.sizeTag]].bytecode, 'base64'), + ); + witnessStack.push(output.outputWitness); } const currentExecution = executionStack.pop()!; executionStack.push(...[...currentExecution.nestedExecutions].reverse()); @@ -89,47 +107,59 @@ export class KernelProver { currentExecution.callStackItem.functionData.selector, ); - const proofOutput = await this.proofCreator.createAppCircuitProof( - currentExecution.partialWitness, - currentExecution.acir, - functionName, - ); + const appVk = await this.proofCreator.computeAppCircuitVerificationKey(currentExecution.acir, functionName); + // TODO(#7368): This used to be associated with getDebugFunctionName + // TODO(#7368): Is there any way to use this with client IVC proving? + acirs.push(currentExecution.acir); + witnessStack.push(currentExecution.partialWitness); const privateCallData = await this.createPrivateCallData( currentExecution, publicCallRequests, publicTeardownCallRequest, - proofOutput.proof, - proofOutput.verificationKey, + appVk.verificationKey, ); if (firstIteration) { const proofInput = new PrivateKernelInitCircuitPrivateInputs(txRequest, getVKTreeRoot(), privateCallData); pushTestData('private-kernel-inputs-init', proofInput); - output = await this.proofCreator.createProofInit(proofInput); + output = await this.proofCreator.simulateProofInit(proofInput); + acirs.push(Buffer.from(ClientCircuitArtifacts.PrivateKernelInitArtifact.bytecode, 'base64')); + witnessStack.push(output.outputWitness); } else { const previousVkMembershipWitness = await this.oracle.getVkMembershipWitness(output.verificationKey); const previousKernelData = new PrivateKernelData( output.publicInputs, - output.proof, output.verificationKey, Number(previousVkMembershipWitness.leafIndex), assertLength(previousVkMembershipWitness.siblingPath, VK_TREE_HEIGHT), ); const proofInput = new PrivateKernelInnerCircuitPrivateInputs(previousKernelData, privateCallData); pushTestData('private-kernel-inputs-inner', proofInput); - output = await this.proofCreator.createProofInner(proofInput); + output = await this.proofCreator.simulateProofInner(proofInput); + acirs.push(Buffer.from(ClientCircuitArtifacts.PrivateKernelInnerArtifact.bytecode, 'base64')); + witnessStack.push(output.outputWitness); } firstIteration = false; } if (this.somethingToReset(output)) { - output = await this.runReset(executionStack, output, noteHashLeafIndexMap, noteHashNullifierCounterMap); + const resetInputs = await this.getPrivateKernelResetInputs( + executionStack, + output, + noteHashLeafIndexMap, + noteHashNullifierCounterMap, + ); + output = await this.proofCreator.simulateProofReset(resetInputs); + // TODO(#7368) consider refactoring this redundant bytecode pushing + acirs.push( + Buffer.from(ClientCircuitArtifacts[PrivateResetTagToArtifactName[resetInputs.sizeTag]].bytecode, 'base64'), + ); + witnessStack.push(output.outputWitness); } const previousVkMembershipWitness = await this.oracle.getVkMembershipWitness(output.verificationKey); const previousKernelData = new PrivateKernelData( output.publicInputs, - output.proof, output.verificationKey, Number(previousVkMembershipWitness.leafIndex), assertLength(previousVkMembershipWitness.siblingPath, VK_TREE_HEIGHT), @@ -142,10 +172,27 @@ export class KernelProver { const privateInputs = new PrivateKernelTailCircuitPrivateInputs(previousKernelData); pushTestData('private-kernel-inputs-ordering', privateInputs); - return await this.proofCreator.createProofTail(privateInputs); + const tailOutput = await this.proofCreator.simulateProofTail(privateInputs); + acirs.push( + Buffer.from( + privateInputs.isForPublic() + ? ClientCircuitArtifacts.PrivateKernelTailToPublicArtifact.bytecode + : ClientCircuitArtifacts.PrivateKernelTailArtifact.bytecode, + 'base64', + ), + ); + witnessStack.push(tailOutput.outputWitness); + + // TODO(#7368) how do we 'bincode' encode these inputs? + const ivcProof = await this.proofCreator.createClientIvcProof(acirs, witnessStack); + tailOutput.clientIvcProof = ivcProof; + return tailOutput; } - private needsReset(executionStack: ExecutionResult[], output: KernelProofOutput) { + private needsReset( + executionStack: ExecutionResult[], + output: PrivateKernelSimulateOutput, + ) { const nextIteration = executionStack[executionStack.length - 1]; return ( getNonEmptyItems(nextIteration.callStackItem.publicInputs.noteHashes).length + @@ -169,7 +216,7 @@ export class KernelProver { ); } - private somethingToReset(output: KernelProofOutput) { + private somethingToReset(output: PrivateKernelSimulateOutput) { return ( getNonEmptyItems(output.publicInputs.validationRequests.noteHashReadRequests).length > 0 || getNonEmptyItems(output.publicInputs.validationRequests.nullifierReadRequests).length > 0 || @@ -178,29 +225,26 @@ export class KernelProver { ); } - private async runReset( + private async getPrivateKernelResetInputs( executionStack: ExecutionResult[], - output: KernelProofOutput, + output: PrivateKernelSimulateOutput, noteHashLeafIndexMap: Map, noteHashNullifierCounterMap: Map, - ): Promise> { + ) { const previousVkMembershipWitness = await this.oracle.getVkMembershipWitness(output.verificationKey); const previousKernelData = new PrivateKernelData( output.publicInputs, - output.proof, output.verificationKey, Number(previousVkMembershipWitness.leafIndex), assertLength(previousVkMembershipWitness.siblingPath, VK_TREE_HEIGHT), ); - return this.proofCreator.createProofReset( - await buildPrivateKernelResetInputs( - executionStack, - previousKernelData, - noteHashLeafIndexMap, - noteHashNullifierCounterMap, - this.oracle, - ), + return await buildPrivateKernelResetInputs( + executionStack, + previousKernelData, + noteHashLeafIndexMap, + noteHashNullifierCounterMap, + this.oracle, ); } @@ -208,7 +252,6 @@ export class KernelProver { { callStackItem }: ExecutionResult, publicCallRequests: CallRequest[], publicTeardownCallRequest: CallRequest, - proof: RecursiveProof, vk: VerificationKeyAsFields, ) { const { contractAddress, functionData } = callStackItem; @@ -233,7 +276,6 @@ export class KernelProver { callStackItem, publicCallStack, publicTeardownCallRequest, - proof, vk, publicKeysHash, contractClassArtifactHash, diff --git a/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts b/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts index b9bf1ae03e5d..109cc33d8218 100644 --- a/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts +++ b/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts @@ -1,7 +1,11 @@ -import { type AppCircuitProofOutput, type KernelProofOutput, type ProofCreator } from '@aztec/circuit-types'; +import { + type AppCircuitSimulateOutput, + type PrivateKernelProver, + type PrivateKernelSimulateOutput, +} from '@aztec/circuit-types'; import type { CircuitName, CircuitSimulationStats } from '@aztec/circuit-types/stats'; import { - NESTED_RECURSIVE_PROOF_LENGTH, + ClientIvcProof, type PrivateCircuitPublicInputs, type PrivateKernelCircuitPublicInputs, type PrivateKernelInitCircuitPrivateInputs, @@ -9,9 +13,7 @@ import { type PrivateKernelResetCircuitPrivateInputsVariants, type PrivateKernelTailCircuitPrivateInputs, type PrivateKernelTailCircuitPublicInputs, - RECURSIVE_PROOF_LENGTH, VerificationKeyAsFields, - makeRecursiveProof, } from '@aztec/circuits.js'; import { siloNoteHash } from '@aztec/circuits.js/hash'; import { createDebugLogger } from '@aztec/foundation/log'; @@ -26,21 +28,27 @@ import { executeTailForPublic, } from '@aztec/noir-protocol-circuits-types'; +import { type WitnessMap } from '@noir-lang/types'; + /** * Test Proof Creator executes circuit simulations and provides fake proofs. */ -export class TestProofCreator implements ProofCreator { +export class TestPrivateKernelProver implements PrivateKernelProver { constructor(private log = createDebugLogger('aztec:test_proof_creator')) {} + createClientIvcProof(_acirs: Buffer[], _witnessStack: WitnessMap[]): Promise { + return Promise.resolve(ClientIvcProof.empty()); + } + public getSiloedCommitments(publicInputs: PrivateCircuitPublicInputs) { const contractAddress = publicInputs.callContext.storageContractAddress; return Promise.resolve(publicInputs.noteHashes.map(commitment => siloNoteHash(contractAddress, commitment.value))); } - public async createProofInit( + public async simulateProofInit( privateInputs: PrivateKernelInitCircuitPrivateInputs, - ): Promise> { + ): Promise> { const [duration, result] = await elapsed(() => executeInit(privateInputs)); this.log.debug(`Simulated private kernel init`, { eventName: 'circuit-simulation', @@ -49,12 +57,12 @@ export class TestProofCreator implements ProofCreator { inputSize: privateInputs.toBuffer().length, outputSize: result.toBuffer().length, } satisfies CircuitSimulationStats); - return this.makeEmptyKernelProofOutput(result, 'PrivateKernelInitArtifact'); + return this.makeEmptyKernelSimulateOutput(result, 'PrivateKernelInitArtifact'); } - public async createProofInner( + public async simulateProofInner( privateInputs: PrivateKernelInnerCircuitPrivateInputs, - ): Promise> { + ): Promise> { const [duration, result] = await elapsed(() => executeInner(privateInputs)); this.log.debug(`Simulated private kernel inner`, { eventName: 'circuit-simulation', @@ -63,12 +71,12 @@ export class TestProofCreator implements ProofCreator { inputSize: privateInputs.toBuffer().length, outputSize: result.toBuffer().length, } satisfies CircuitSimulationStats); - return this.makeEmptyKernelProofOutput(result, 'PrivateKernelInnerArtifact'); + return this.makeEmptyKernelSimulateOutput(result, 'PrivateKernelInnerArtifact'); } - public async createProofReset( + public async simulateProofReset( privateInputs: PrivateKernelResetCircuitPrivateInputsVariants, - ): Promise> { + ): Promise> { const [duration, result] = await elapsed(() => executeReset(privateInputs)); this.log.debug(`Simulated private kernel reset`, { eventName: 'circuit-simulation', @@ -77,12 +85,15 @@ export class TestProofCreator implements ProofCreator { inputSize: privateInputs.toBuffer().length, outputSize: result.toBuffer().length, } satisfies CircuitSimulationStats); - return this.makeEmptyKernelProofOutput(result, 'PrivateKernelResetFullArtifact'); + return this.makeEmptyKernelSimulateOutput( + result, + 'PrivateKernelResetFullArtifact', + ); } - public async createProofTail( + public async simulateProofTail( privateInputs: PrivateKernelTailCircuitPrivateInputs, - ): Promise> { + ): Promise> { const isForPublic = privateInputs.isForPublic(); const [duration, result] = await elapsed(() => isForPublic ? executeTailForPublic(privateInputs) : executeTail(privateInputs), @@ -94,25 +105,30 @@ export class TestProofCreator implements ProofCreator { inputSize: privateInputs.toBuffer().length, outputSize: result.toBuffer().length, } satisfies CircuitSimulationStats); - return this.makeEmptyKernelProofOutput( + return this.makeEmptyKernelSimulateOutput( result, isForPublic ? 'PrivateKernelTailToPublicArtifact' : 'PrivateKernelTailArtifact', ); } - createAppCircuitProof(_1: Map, _2: Buffer): Promise { - const appCircuitProofOutput: AppCircuitProofOutput = { - proof: makeRecursiveProof(RECURSIVE_PROOF_LENGTH), + computeAppCircuitVerificationKey( + _bytecode: Buffer, + _appCircuitName?: string | undefined, + ): Promise { + const appCircuitProofOutput: AppCircuitSimulateOutput = { verificationKey: VerificationKeyAsFields.makeEmpty(), }; return Promise.resolve(appCircuitProofOutput); } - private makeEmptyKernelProofOutput(publicInputs: PublicInputsType, circuitType: ProtocolArtifact) { - const kernelProofOutput: KernelProofOutput = { + private makeEmptyKernelSimulateOutput( + publicInputs: PublicInputsType, + circuitType: ProtocolArtifact, + ) { + const kernelProofOutput: PrivateKernelSimulateOutput = { publicInputs, - proof: makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), verificationKey: ProtocolCircuitVks[circuitType].keyAsFields, + outputWitness: new Map(), }; return kernelProofOutput; } diff --git a/yarn-project/pxe/src/pxe_service/create_pxe_service.ts b/yarn-project/pxe/src/pxe_service/create_pxe_service.ts index 6d55b11709c2..2b2589447012 100644 --- a/yarn-project/pxe/src/pxe_service/create_pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/create_pxe_service.ts @@ -1,5 +1,5 @@ -import { BBNativeProofCreator } from '@aztec/bb-prover'; -import { type AztecNode, type ProofCreator } from '@aztec/circuit-types'; +import { BBNativePrivateKernelProver } from '@aztec/bb-prover'; +import { type AztecNode, type PrivateKernelProver } from '@aztec/circuit-types'; import { randomBytes } from '@aztec/foundation/crypto'; import { createDebugLogger } from '@aztec/foundation/log'; import { KeyStore } from '@aztec/key-store'; @@ -16,7 +16,7 @@ import { join } from 'path'; import { type PXEServiceConfig } from '../config/index.js'; import { KVPxeDatabase } from '../database/kv_pxe_database.js'; -import { TestProofCreator } from '../kernel_prover/test/test_circuit_prover.js'; +import { TestPrivateKernelProver } from '../kernel_prover/test/test_circuit_prover.js'; import { PXEService } from './pxe_service.js'; /** @@ -34,7 +34,7 @@ export async function createPXEService( aztecNode: AztecNode, config: PXEServiceConfig, useLogSuffix: string | boolean | undefined = undefined, - proofCreator?: ProofCreator, + proofCreator?: PrivateKernelProver, ) { const logSuffix = typeof useLogSuffix === 'boolean' ? (useLogSuffix ? randomBytes(3).toString('hex') : undefined) : useLogSuffix; @@ -47,14 +47,14 @@ export async function createPXEService( const db = new KVPxeDatabase(await initStoreForRollup(AztecLmdbStore.open(pxeDbPath), l1Contracts.rollupAddress)); // (@PhilWindle) Temporary validation until WASM is implemented - let prover: ProofCreator | undefined = proofCreator; + let prover: PrivateKernelProver | undefined = proofCreator; if (!prover) { if (config.proverEnabled && (!config.bbBinaryPath || !config.bbWorkingDirectory)) { throw new Error(`Prover must be configured with binary path and working directory`); } prover = !config.proverEnabled - ? new TestProofCreator() - : new BBNativeProofCreator( + ? new TestPrivateKernelProver() + : new BBNativePrivateKernelProver( config.bbBinaryPath!, config.bbWorkingDirectory!, createDebugLogger('aztec:pxe:bb-native-prover' + (logSuffix ? `:${logSuffix}` : '')), diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 6dcf9d3f421e..0891f5f84d79 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -16,7 +16,7 @@ import { type OutgoingNotesFilter, type PXE, type PXEInfo, - type ProofCreator, + type PrivateKernelProver, SimulatedTx, SimulationError, TaggedLog, @@ -72,7 +72,7 @@ import { IncomingNoteDao } from '../database/incoming_note_dao.js'; import { type PxeDatabase } from '../database/index.js'; import { KernelOracle } from '../kernel_oracle/index.js'; import { KernelProver } from '../kernel_prover/kernel_prover.js'; -import { TestProofCreator } from '../kernel_prover/test/test_circuit_prover.js'; +import { TestPrivateKernelProver } from '../kernel_prover/test/test_circuit_prover.js'; import { getAcirSimulator } from '../simulator/index.js'; import { Synchronizer } from '../synchronizer/index.js'; @@ -89,13 +89,13 @@ export class PXEService implements PXE { // ensures that state is not changed while simulating private jobQueue = new SerialQueue(); - private fakeProofCreator = new TestProofCreator(); + private fakeProofCreator = new TestPrivateKernelProver(); constructor( private keyStore: KeyStore, private node: AztecNode, private db: PxeDatabase, - private proofCreator: ProofCreator, + private proofCreator: PrivateKernelProver, private config: PXEServiceConfig, logSuffix?: string, ) { @@ -750,7 +750,7 @@ export class PXEService implements PXE { */ async #simulateAndProve( txExecutionRequest: TxExecutionRequest, - proofCreator: ProofCreator, + proofCreator: PrivateKernelProver, msgSender?: AztecAddress, ): Promise { // Get values that allow us to reconstruct the block hash @@ -759,7 +759,10 @@ export class PXEService implements PXE { const kernelOracle = new KernelOracle(this.contractDataOracle, this.keyStore, this.node); const kernelProver = new KernelProver(kernelOracle, proofCreator); this.log.debug(`Executing kernel prover...`); - const { proof, publicInputs } = await kernelProver.prove(txExecutionRequest.toTxRequest(), executionResult); + const { clientIvcProof, publicInputs } = await kernelProver.prove( + txExecutionRequest.toTxRequest(), + executionResult, + ); const noteEncryptedLogs = new EncryptedNoteTxL2Logs([collectSortedNoteEncryptedLogs(executionResult)]); const unencryptedLogs = new UnencryptedTxL2Logs([collectSortedUnencryptedLogs(executionResult)]); @@ -769,7 +772,7 @@ export class PXEService implements PXE { const tx = new Tx( publicInputs, - proof.binaryProof, + clientIvcProof!, noteEncryptedLogs, encryptedLogs, unencryptedLogs, diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts index 3728d8683d37..c649d9445333 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts @@ -10,7 +10,7 @@ import { type MockProxy, mock } from 'jest-mock-extended'; import { KVPxeDatabase } from '../../database/kv_pxe_database.js'; import { type PxeDatabase } from '../../database/pxe_database.js'; import { type PXEServiceConfig } from '../../index.js'; -import { TestProofCreator } from '../../kernel_prover/test/test_circuit_prover.js'; +import { TestPrivateKernelProver } from '../../kernel_prover/test/test_circuit_prover.js'; import { PXEService } from '../pxe_service.js'; import { pxeTestSuite } from './pxe_test_suite.js'; @@ -36,7 +36,7 @@ function createPXEService(): Promise { }; node.getL1ContractAddresses.mockResolvedValue(mockedContracts); - return Promise.resolve(new PXEService(keyStore, node, db, new TestProofCreator(), config)); + return Promise.resolve(new PXEService(keyStore, node, db, new TestPrivateKernelProver(), config)); } pxeTestSuite('PXEService', createPXEService); @@ -61,7 +61,7 @@ describe('PXEService', () => { node.getTxEffect.mockResolvedValue(settledTx); - const pxe = new PXEService(keyStore, node, db, new TestProofCreator(), config); + const pxe = new PXEService(keyStore, node, db, new TestPrivateKernelProver(), config); await expect(pxe.sendTx(duplicateTx)).rejects.toThrow(/A settled tx with equal hash/); }); }); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index aef46a70db7c..dfe83e9de2d6 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -22,7 +22,6 @@ import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, makeEmptyProof, } from '@aztec/circuits.js'; -import { makeProof } from '@aztec/circuits.js/testing'; import { randomBytes } from '@aztec/foundation/crypto'; import { type Writeable } from '@aztec/foundation/types'; import { type P2P, P2PClientState } from '@aztec/p2p'; @@ -81,7 +80,7 @@ describe('sequencer', () => { publicProcessor = mock({ process: async txs => [ - await Promise.all(txs.map(tx => makeProcessedTx(tx, tx.data.toKernelCircuitPublicInputs(), makeProof(), []))), + await Promise.all(txs.map(tx => makeProcessedTx(tx, tx.data.toKernelCircuitPublicInputs(), []))), [], [], ], diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 31697c2a0314..72e949174b27 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -352,7 +352,7 @@ export class Sequencer { const toReturn: Tx[] = []; for (const tx of txs) { - const txSize = tx.getSize() - tx.proof.toBuffer().length; + const txSize = tx.getSize() - tx.clientIvcProof.clientIvcProofBuffer.length; if (totalSize + txSize > maxSize) { this.log.warn( `Dropping tx ${tx.getTxHash()} with estimated size ${txSize} due to exceeding ${maxSize} block size limit (currently at ${totalSize})`, diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.ts b/yarn-project/simulator/src/public/abstract_phase_manager.ts index 3428158116c2..9610f906deac 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.ts @@ -14,6 +14,7 @@ import { type AvmExecutionHints, AztecAddress, CallRequest, + ClientIvcProof, ContractStorageRead, ContractStorageUpdateRequest, Fr, @@ -419,7 +420,7 @@ export abstract class AbstractPhaseManager { const previousKernel = this.getPreviousKernelData(previousOutput, previousCircuit); // We take a deep copy (clone) of these inputs to be passed to the prover - const inputs = new PublicKernelCircuitPrivateInputs(previousKernel, callData); + const inputs = new PublicKernelCircuitPrivateInputs(previousKernel, ClientIvcProof.empty(), callData); switch (this.phase) { case PublicKernelType.SETUP: return [inputs.clone(), await this.publicKernel.publicKernelCircuitSetup(inputs), 'PublicKernelSetupArtifact']; diff --git a/yarn-project/simulator/src/public/public_processor.test.ts b/yarn-project/simulator/src/public/public_processor.test.ts index 09d1de5ef96d..b39fff577826 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -4,7 +4,6 @@ import { PublicDataWrite, PublicKernelType, SimulationError, - type Tx, type TxValidator, mockTx, toTxEffect, @@ -12,6 +11,7 @@ import { import { AppendOnlyTreeSnapshot, AztecAddress, + ClientIvcProof, ContractStorageRead, ContractStorageUpdateRequest, Fr, @@ -24,14 +24,12 @@ import { MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_DATA_TREE_HEIGHT, PartialStateReference, - type Proof, PublicAccumulatedDataBuilder, PublicCallRequest, PublicDataTreeLeafPreimage, PublicDataUpdateRequest, RevertCode, StateReference, - makeEmptyProof, } from '@aztec/circuits.js'; import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash'; import { fr, makeAztecAddress, makePublicCallRequest, makeSelector } from '@aztec/circuits.js/testing'; @@ -64,7 +62,7 @@ describe('public_processor', () => { let publicWorldStateDB: MockProxy; let prover: MockProxy; - let proof: Proof; + let proof: ClientIvcProof; let root: Buffer; let processor: PublicProcessor; @@ -76,7 +74,7 @@ describe('public_processor', () => { publicWorldStateDB = mock(); prover = mock(); - proof = makeEmptyProof(); + proof = ClientIvcProof.empty(); root = Buffer.alloc(32, 5); db.getTreeInfo.mockResolvedValue({ root } as TreeInfo); @@ -114,10 +112,10 @@ describe('public_processor', () => { const expected: ProcessedTx = { hash, data: tx.data.toKernelCircuitPublicInputs(), - proof: tx.proof, noteEncryptedLogs: tx.noteEncryptedLogs, encryptedLogs: tx.encryptedLogs, unencryptedLogs: tx.unencryptedLogs, + clientIvcProof: tx.clientIvcProof, isEmpty: false, revertReason: undefined, publicProvingRequests: [], @@ -225,12 +223,6 @@ describe('public_processor', () => { ); }); - const expectedTxByHash = (tx: Tx) => - expect.objectContaining({ - hash: tx.getTxHash(), - proof, - }); - it('runs a tx with enqueued public calls', async function () { const tx = mockTxWithPartialState({ hasLogs: true, @@ -252,7 +244,8 @@ describe('public_processor', () => { expect(failed.map(f => f.error)).toEqual([]); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(publicExecutor.simulate).toHaveBeenCalledTimes(2); expect(publicWorldStateDB.commit).toHaveBeenCalledTimes(1); expect(publicWorldStateDB.rollbackToCommit).toHaveBeenCalledTimes(0); @@ -283,7 +276,8 @@ describe('public_processor', () => { const [processed, failed] = await processor.process([tx], 1, prover); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(failed).toHaveLength(0); expect(publicExecutor.simulate).toHaveBeenCalledTimes(1); // we only call checkpoint after successful "setup" @@ -318,7 +312,10 @@ describe('public_processor', () => { const [processed, failed] = await processor.process(txs, 2, prover); expect(processed).toHaveLength(2); - expect(processed).toEqual([expectedTxByHash(txs[0]), expectedTxByHash(txs[1])]); + expect(processed[0].hash).toEqual(txs[0].getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); + expect(processed[1].hash).toEqual(txs[1].getTxHash()); + expect(processed[1].clientIvcProof).toEqual(proof); expect(failed).toHaveLength(0); expect(publicExecutor.simulate).toHaveBeenCalledTimes(2); expect(publicWorldStateDB.commit).toHaveBeenCalledTimes(2); @@ -449,7 +446,8 @@ describe('public_processor', () => { const [processed, failed] = await processor.process([tx], 1, prover); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(failed).toHaveLength(0); expect(setupSpy).toHaveBeenCalledTimes(1); @@ -681,7 +679,8 @@ describe('public_processor', () => { const [processed, failed] = await processor.process([tx], 1, prover); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(failed).toHaveLength(0); expect(setupSpy).toHaveBeenCalledTimes(2); @@ -807,7 +806,8 @@ describe('public_processor', () => { const [processed, failed] = await processor.process([tx], 1, prover); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(failed).toHaveLength(0); expect(setupSpy).toHaveBeenCalledTimes(2); @@ -965,7 +965,8 @@ describe('public_processor', () => { const [processed, failed] = await processor.process([tx], 1, prover); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(failed).toHaveLength(0); expect(setupSpy).toHaveBeenCalledTimes(1); @@ -1081,7 +1082,8 @@ describe('public_processor', () => { const [processed, failed] = await processor.process([tx], 1, prover); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(failed).toHaveLength(0); expect(setupSpy).toHaveBeenCalledTimes(0); @@ -1165,7 +1167,8 @@ describe('public_processor', () => { expect(failed.map(f => f.error)).toEqual([]); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(publicExecutor.simulate).toHaveBeenCalledTimes(2); expect(publicWorldStateDB.commit).toHaveBeenCalledTimes(1); expect(publicWorldStateDB.rollbackToCommit).toHaveBeenCalledTimes(0); @@ -1222,7 +1225,8 @@ describe('public_processor', () => { expect(failed.map(f => f.error)).toEqual([]); expect(processed).toHaveLength(1); - expect(processed).toEqual([expectedTxByHash(tx)]); + expect(processed[0].hash).toEqual(tx.getTxHash()); + expect(processed[0].clientIvcProof).toEqual(proof); expect(publicExecutor.simulate).toHaveBeenCalledTimes(2); expect(publicWorldStateDB.commit).toHaveBeenCalledTimes(1); expect(publicWorldStateDB.rollbackToCommit).toHaveBeenCalledTimes(0); diff --git a/yarn-project/simulator/src/public/public_processor.ts b/yarn-project/simulator/src/public/public_processor.ts index 86b9ed3ad27e..2277545a7595 100644 --- a/yarn-project/simulator/src/public/public_processor.ts +++ b/yarn-project/simulator/src/public/public_processor.ts @@ -126,7 +126,7 @@ export class PublicProcessor { } try { const [processedTx, returnValues] = !tx.hasPublicCalls() - ? [makeProcessedTx(tx, tx.data.toKernelCircuitPublicInputs(), tx.proof, [])] + ? [makeProcessedTx(tx, tx.data.toKernelCircuitPublicInputs(), [])] : await this.processTxWithPublicCalls(tx); // Set fee payment update request into the processed tx @@ -265,7 +265,7 @@ export class PublicProcessor { throw new Error('Final public kernel was not executed.'); } - const processedTx = makeProcessedTx(tx, finalKernelOutput, tx.proof, publicProvingRequests, revertReason, gasUsed); + const processedTx = makeProcessedTx(tx, finalKernelOutput, publicProvingRequests, revertReason, gasUsed); return [processedTx, returnValues]; } } diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 27fee5d58f3a..7349aebceeb7 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -239,6 +239,7 @@ __metadata: "@aztec/simulator": "workspace:^" "@aztec/telemetry-client": "workspace:^" "@jest/globals": ^29.5.0 + "@msgpack/msgpack": ^3.0.0-beta2 "@noir-lang/noirc_abi": "portal:../../noir/packages/noirc_abi" "@noir-lang/types": "portal:../../noir/packages/types" "@types/jest": ^29.5.0 @@ -820,7 +821,9 @@ __metadata: "@aztec/simulator": "workspace:^" "@aztec/types": "workspace:^" "@jest/globals": ^29.5.0 + "@msgpack/msgpack": ^3.0.0-beta2 "@noir-lang/noirc_abi": "portal:../../noir/packages/noirc_abi" + "@noir-lang/types": "workspace:*" "@types/jest": ^29.5.0 "@types/lodash.omit": ^4.5.7 "@types/node": ^18.7.23 @@ -2803,6 +2806,13 @@ __metadata: languageName: node linkType: hard +"@msgpack/msgpack@npm:^3.0.0-beta2": + version: 3.0.0-beta2 + resolution: "@msgpack/msgpack@npm:3.0.0-beta2" + checksum: d86e5d48146051952d6bea35a6cf733a401cf65ad5614d79689aa48c7076021737ca2c782978dd1b6c0c9c45888b246e379e45ae906179e3a0e8ef4ee6f221c1 + languageName: node + linkType: hard + "@msgpackr-extract/msgpackr-extract-darwin-arm64@npm:3.0.2": version: 3.0.2 resolution: "@msgpackr-extract/msgpackr-extract-darwin-arm64@npm:3.0.2" From 619501df5aa4c544cd8607dae5d4e20595109b2f Mon Sep 17 00:00:00 2001 From: ludamad Date: Wed, 10 Jul 2024 20:46:17 -0400 Subject: [PATCH 17/32] fix: pass secrets to ci-arm.yml (#7436) --- .github/workflows/ci-arm.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-arm.yml b/.github/workflows/ci-arm.yml index a08049ca9894..283d05be290d 100644 --- a/.github/workflows/ci-arm.yml +++ b/.github/workflows/ci-arm.yml @@ -36,7 +36,10 @@ jobs: set -eux git submodule update --init --recursive --recommend-shallow echo ${{ secrets.DOCKERHUB_PASSWORD }} | docker login -u aztecprotocolci --password-stdin - scripts/earthly-ci ./yarn-project+export-e2e-test-images + scripts/earthly-ci \ + --secret AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} \ + --secret AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} \ + ./yarn-project+export-e2e-test-images # all the end-to-end integration tests for aztec e2e: @@ -54,7 +57,10 @@ jobs: sudo shutdown -P 25 # hack until core part of the scripts set -eux echo ${{ secrets.DOCKERHUB_PASSWORD }} | docker login -u aztecprotocolci --password-stdin - scripts/earthly-ci -P --no-output ./yarn-project/end-to-end/+uniswap-trade-on-l1-from-l2 + scripts/earthly-ci \ + --secret AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} \ + --secret AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} \ + --no-output ./yarn-project/end-to-end/+uniswap-trade-on-l1-from-l2 # not notifying failures right now # notify: From 6f23ae650c2b91849067040233e25ca0f05e2b1a Mon Sep 17 00:00:00 2001 From: AztecBot Date: Thu, 11 Jul 2024 02:16:17 +0000 Subject: [PATCH 18/32] git subrepo push --branch=master barretenberg subrepo: subdir: "barretenberg" merged: "6fd24856b5" upstream: origin: "https://github.com/AztecProtocol/barretenberg" branch: "master" commit: "6fd24856b5" 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 ff54511d1d39..ad7cd08ea7dd 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = d79d195285882ddfd9937228f949b1a182b69476 - parent = a917198c6a17063414087419d8cb1de93e6dc21e + commit = 6fd24856b5b5bd9802ce5ef4ea1e2a92a97e1998 + parent = 619501df5aa4c544cd8607dae5d4e20595109b2f method = merge cmdver = 0.4.6 From 842f6d1978aaeba9d39e3433f06f2f402145b754 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Thu, 11 Jul 2024 02:16:49 +0000 Subject: [PATCH 19/32] chore: replace relative paths to noir-protocol-circuits --- noir-projects/aztec-nr/aztec/Nargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/aztec/Nargo.toml b/noir-projects/aztec-nr/aztec/Nargo.toml index 7a1f1af58631..765964790e97 100644 --- a/noir-projects/aztec-nr/aztec/Nargo.toml +++ b/noir-projects/aztec-nr/aztec/Nargo.toml @@ -5,4 +5,4 @@ compiler_version = ">=0.18.0" type = "lib" [dependencies] -protocol_types = { path = "../../noir-protocol-circuits/crates/types" } +protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.46.2", directory="noir-projects/noir-protocol-circuits/crates/types" } From 7248f21daca426efb670721403393484da7d5158 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Thu, 11 Jul 2024 02:16:49 +0000 Subject: [PATCH 20/32] git_subrepo.sh: Fix parent in .gitrepo file. [skip ci] --- noir-projects/aztec-nr/.gitrepo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index eab130bea6d3..80a1fd5905f1 100644 --- a/noir-projects/aztec-nr/.gitrepo +++ b/noir-projects/aztec-nr/.gitrepo @@ -9,4 +9,4 @@ commit = 3640ce1a88e8049d9fa5768ce962eb6b5d2c11ca method = merge cmdver = 0.4.6 - parent = 77f3a6c4cd85236fc6f37a3d39bbc009a60659fd + parent = 456b975e69a9d99b1ebe63edebb769848eb061c1 From 93ae0c7484902c97d2423600aa03aae033c67cca Mon Sep 17 00:00:00 2001 From: AztecBot Date: Thu, 11 Jul 2024 02:16:54 +0000 Subject: [PATCH 21/32] git subrepo push --branch=master noir-projects/aztec-nr subrepo: subdir: "noir-projects/aztec-nr" merged: "b826d5f193" upstream: origin: "https://github.com/AztecProtocol/aztec-nr" branch: "master" commit: "b826d5f193" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- noir-projects/aztec-nr/.gitrepo | 4 ++-- noir-projects/aztec-nr/aztec/Nargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index 80a1fd5905f1..2d594c72fa3f 100644 --- a/noir-projects/aztec-nr/.gitrepo +++ b/noir-projects/aztec-nr/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/aztec-nr branch = master - commit = 3640ce1a88e8049d9fa5768ce962eb6b5d2c11ca + commit = b826d5f1937d37ea69b4ad30cb0f72601b7967b6 method = merge cmdver = 0.4.6 - parent = 456b975e69a9d99b1ebe63edebb769848eb061c1 + parent = 1a86570ee82455042d60c731369f550ded0d1884 diff --git a/noir-projects/aztec-nr/aztec/Nargo.toml b/noir-projects/aztec-nr/aztec/Nargo.toml index 765964790e97..7a1f1af58631 100644 --- a/noir-projects/aztec-nr/aztec/Nargo.toml +++ b/noir-projects/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.46.2", directory="noir-projects/noir-protocol-circuits/crates/types" } +protocol_types = { path = "../../noir-protocol-circuits/crates/types" } From 5cbdc549f0ab137ab4fa601e20d80699871faaf4 Mon Sep 17 00:00:00 2001 From: ledwards2225 <98505400+ledwards2225@users.noreply.github.com> Date: Wed, 10 Jul 2024 20:57:20 -0700 Subject: [PATCH 22/32] feat: MSM sorting (#7351) Implements logic for reducing MSM inputs by first summing points which share a scalar. See description in `sorted_msm.hpp` for details of the approach. This is useful when the `scalars` input for an MSM contains many repeated values because point addition is much cheaper than scalar multiplication. For example, when using the structured trace, the permutation grand product polynomial is non-zero but constant over 'dead' regions between blocks. Note: For now this work is not integrated into the proving systems. That will be done in a follow on. At that time, considerations will be made for memory consumption (e.g. perhaps memory allocated in pippenger_runtime_state can be repurposed for the MSM sorting logic etc.) --------- Co-authored-by: zac-williamson --- .../ecc/scalar_multiplication/sorted_msm.cpp | 218 +++++++++++++++ .../ecc/scalar_multiplication/sorted_msm.hpp | 91 ++++++ .../scalar_multiplication/sorted_msm.test.cpp | 260 ++++++++++++++++++ .../srs/factories/file_crs_factory.hpp | 9 + 4 files changed, 578 insertions(+) create mode 100644 barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/sorted_msm.cpp create mode 100644 barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/sorted_msm.hpp create mode 100644 barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/sorted_msm.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/sorted_msm.cpp b/barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/sorted_msm.cpp new file mode 100644 index 000000000000..9c51d6125c8f --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/sorted_msm.cpp @@ -0,0 +1,218 @@ +#include "barretenberg/ecc/scalar_multiplication/sorted_msm.hpp" + +namespace bb { + +/** + * @brief Reduce MSM inputs such that the set of scalars contains no duplicates by summing points which share a scalar. + * @details Since point addition is substantially cheaper than scalar multiplication, it is more efficient in some cases + * to first sum all points which share a scalar then perform the MSM on the reduced set of inputs. This is achieved via + * the following procedure: + * + * 1) Sort the input {points, scalars} by scalar in order to group points into 'addition sequences' i.e. sets of points + * to be added together prior to performing the MSM. + * + * 2) For each sequence, perform pairwise addition on all points. (If the length of the sequence is odd, the unpaired + * point is simply carried over to the next round). The inverses needed in the addition formula are batch computed in a + * single go for all additions to be performed across all sequences in a given round. + * + * 3) Perform rounds of pair-wise addition until each sequence is reduced to a single point. + * + * @tparam Curve + * @param scalars + * @param points + * @return MsmSorter::ReducedMsmInputs + */ +template +MsmSorter::ReducedMsmInputs MsmSorter::reduce_msm_inputs(std::span scalars, std::span points) +{ + // Generate the addition sequences (sets of points sharing a scalar) + AdditionSequences addition_sequences = construct_addition_sequences(scalars, points); + + // Perform rounds of pairwise addition until all sets of points sharing a scalar have been reduced to a single point + batched_affine_add_in_place(addition_sequences); + + // The reduced MSM inputs are the unique scalars and the reduced points + std::span output_scalars(unique_scalars.data(), num_unique_scalars); + std::span output_points(updated_points.data(), num_unique_scalars); + return { output_scalars, output_points }; +} + +/** + * @brief Sort the MSM points by scalar so that points sharing a scalar can be summed prior to performing MSM + * + * @tparam Curve + * @param scalars + * @param points + * @return MsmSorter::AdditionSequences + */ +template +MsmSorter::AdditionSequences MsmSorter::construct_addition_sequences(std::span scalars, + std::span points) +{ + // Create the array containing the indices of the scalars and points sorted by scalar value + const size_t num_points = points.size(); + std::iota(index.begin(), index.end(), 0); +#ifdef NO_TBB + std::sort(index.begin(), index.end(), [&](size_t idx_1, size_t idx_2) { return scalars[idx_1] < scalars[idx_2]; }); +#else + std::sort(std::execution::par_unseq, index.begin(), index.end(), [&](size_t idx_1, size_t idx_2) { + return scalars[idx_1] < scalars[idx_2]; + }); +#endif + + // Store the unique scalar values, the input points sorted by scalar value, and the number of occurences of each + // unique scalar (i.e. the size of each addition sequence) + unique_scalars[0] = scalars[index[0]]; + updated_points[0] = points[index[0]]; + size_t seq_idx = 0; + sequence_counts[seq_idx] = 1; + for (size_t i = 1; i < scalars.size(); ++i) { + const Fr& current_scalar = scalars[index[i]]; + const Fr& prev_scalar = scalars[index[i - 1]]; + + // if the current scalar matches the previous, increment the count for this sequence + if (current_scalar == prev_scalar) { + sequence_counts[seq_idx]++; + } else { // otherwise, a new sequence begins + seq_idx++; + sequence_counts[seq_idx]++; + unique_scalars[seq_idx] = current_scalar; + } + + updated_points[i] = points[index[i]]; + } + + num_unique_scalars = seq_idx + 1; + + // Return the sorted points and the counts for each addition sequence + std::span seq_counts(sequence_counts.data(), num_unique_scalars); + std::span sorted_points(updated_points.data(), num_points); + return AdditionSequences{ seq_counts, sorted_points, {} }; +} + +/** + * @brief Batch compute inverses needed for a set of point addition sequences + * @details Addition of points P_1, P_2 requires computation of a term of the form 1/(P_2.x - P_1.x). For efficiency, + * these terms are computed all at once for a full set of addition sequences using batch inversion. + * + * @tparam Curve + * @param add_sequences + */ +template +void MsmSorter::batch_compute_point_addition_slope_inverses(AdditionSequences& add_sequences) +{ + auto points = add_sequences.points; + auto sequence_counts = add_sequences.sequence_counts; + + // Count the total number of point pairs to be added across all addition sequences + size_t total_num_pairs{ 0 }; + for (auto& count : sequence_counts) { + total_num_pairs += count >> 1; + } + + // Define scratch space for batched inverse computations and eventual storage of denominators + std::span scratch_space(denominators.data(), total_num_pairs); + std::vector differences; + differences.resize(total_num_pairs); + + // Compute and store successive products of differences (x_2 - x_1) + Fq accumulator = 1; + size_t point_idx = 0; + size_t pair_idx = 0; + for (auto& count : sequence_counts) { + const auto num_pairs = count >> 1; + for (size_t j = 0; j < num_pairs; ++j) { + const auto& x1 = points[point_idx++].x; + const auto& x2 = points[point_idx++].x; + + // It is assumed that the input points are random and thus w/h/p do not share an x-coordinate + ASSERT(x1 != x2); + + auto diff = x2 - x1; + differences[pair_idx] = diff; + + // Store and update the running product of differences at each stage + scratch_space[pair_idx++] = accumulator; + accumulator *= diff; + } + // If number of points in the sequence is odd, we skip the last one since it has no pair + point_idx += (count & 0x01ULL); + } + + // Invert the full product of differences + Fq inverse = accumulator.invert(); + + // Compute the individual point-pair addition denominators 1/(x2 - x1) + for (size_t i = 0; i < total_num_pairs; ++i) { + size_t idx = total_num_pairs - 1 - i; + scratch_space[idx] *= inverse; + inverse *= differences[idx]; + } +} + +/** + * @brief In-place summation to reduce a set of addition sequences to a single point for each sequence + * @details At each round, the set of points in each addition sequence is roughly halved by performing pairwise + * additions. For sequences with odd length, the unpaired point is simply carried over to the next round. For + * efficiency, the inverses needed in the point addition slope \lambda are batch computed for the full set of pairwise + * additions in each round. The method is called recursively until the sequences have all been reduced to a single + * point. + * + * @tparam Curve + * @param addition_sequences Set of points and counts indicating number of points in each addition chain + */ +template void MsmSorter::batched_affine_add_in_place(AdditionSequences addition_sequences) +{ + const size_t num_points = addition_sequences.points.size(); + if (num_points == 0 || num_points == 1) { // nothing to do + return; + } + + // Batch compute terms of the form 1/(x2 -x1) for each pair to be added in this round + batch_compute_point_addition_slope_inverses(addition_sequences); + + auto points = addition_sequences.points; + auto sequence_counts = addition_sequences.sequence_counts; + + // Compute pairwise in-place additions for all sequences with more than 1 point + size_t point_idx = 0; // index for points to be summed + size_t result_point_idx = 0; // index for result points + size_t pair_idx = 0; // index into array of denominators for each pair + bool more_additions = false; + for (auto& count : sequence_counts) { + const auto num_pairs = count >> 1; + const bool overflow = static_cast(count & 0x01ULL); + // Compute the sum of all pairs in the sequence and store the result in the same points array + for (size_t j = 0; j < num_pairs; ++j) { + const auto& point_1 = points[point_idx++]; // first summand + const auto& point_2 = points[point_idx++]; // second summand + const auto& denominator = denominators[pair_idx++]; // denominator needed in add formula + auto& result = points[result_point_idx++]; // target for addition result + + result = affine_add_with_denominator(point_1, point_2, denominator); + } + // If the sequence had an odd number of points, simply carry the unpaired point over to the next round + if (overflow) { + points[result_point_idx++] = points[point_idx++]; + } + + // Update the sequence counts in place for the next round + const uint64_t updated_sequence_count = static_cast(num_pairs) + static_cast(overflow); + count = updated_sequence_count; + + // More additions are required if any sequence has not yet been reduced to a single point + more_additions = more_additions || updated_sequence_count > 1; + } + + // Recursively perform pairwise additions until all sequences have been reduced to a single point + if (more_additions) { + const size_t updated_point_count = result_point_idx; + std::span updated_points(&points[0], updated_point_count); + return batched_affine_add_in_place( + AdditionSequences{ sequence_counts, updated_points, addition_sequences.scratch_space }); + } +} + +template class MsmSorter; +template class MsmSorter; +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/sorted_msm.hpp b/barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/sorted_msm.hpp new file mode 100644 index 000000000000..5022cfd3836e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/sorted_msm.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include "./runtime_states.hpp" +#include "barretenberg/ecc/curves/bn254/bn254.hpp" +#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" +#include +#include + +namespace bb { + +/** + * @brief Reduce MSM inputs such that the set of scalars contains no duplicates by summing points which share a scalar. + * + * @warning This class is intended to reduce MSMs with EC points that are fully random, e.g. those from an SRS. It does + * not necessarily handle the case where two adjacent points are equal or the inverse of one another (i.e. where x_i == + * x_{i+1}) + * + * @tparam Curve + */ +template class MsmSorter { + + public: + using G1 = typename Curve::AffineElement; + using Fr = typename Curve::ScalarField; + using Fq = typename Curve::BaseField; + + // Storage for a set of points to be sorted and reduced + struct AdditionSequences { + std::span sequence_counts; + std::span points; + std::optional> scratch_space; + }; + + // Set of reduced MSM inputs where all scalars are unique + struct ReducedMsmInputs { + std::span scalars; + std::span points; + }; + + size_t num_unique_scalars = 0; + std::vector sequence_counts; + std::vector unique_scalars; + std::vector updated_points; + std::vector index; + std::vector denominators; + + MsmSorter(const size_t num_scalars = 0) + { + sequence_counts.resize(num_scalars); + unique_scalars.resize(num_scalars); + updated_points.resize(num_scalars); + index.resize(num_scalars); + denominators.resize(num_scalars); + } + + ReducedMsmInputs reduce_msm_inputs(std::span scalars, std::span points); + + void batch_compute_point_addition_slope_inverses(AdditionSequences& add_sequences); + + void batched_affine_add_in_place(AdditionSequences addition_sequences); + + AdditionSequences construct_addition_sequences(std::span scalars, std::span points); + + /** + * @brief Add two affine elements with the inverse in the slope term \lambda provided as input + * @details The sum of two points (x1, y1), (x2, y2) is given by x3 = \lambda^2 - x1 - x2, y3 = \lambda*(x1 - x3) - + * y1, where \lambda = (y2 - y1)/(x2 - x1). When performing many additions at once, it is more efficient to batch + * compute the inverse component of \lambda for each pair of points. This gives rise to the need for a method like + * this one. + * + * @tparam Curve + * @param point_1 (x1, y1) + * @param point_2 (x2, y2) + * @param denominator 1/(x2 - x1) + * @return Curve::AffineElement + */ + inline G1 affine_add_with_denominator(const G1& point_1, const G1& point_2, const Fq& denominator) + { + const auto& x1 = point_1.x; + const auto& y1 = point_1.y; + const auto& x2 = point_2.x; + const auto& y2 = point_2.y; + + const Fq lambda = denominator * (y2 - y1); + Fq x3 = lambda.sqr() - x2 - x1; + Fq y3 = lambda * (x1 - x3) - y1; + return { x3, y3 }; + } +}; + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/sorted_msm.test.cpp b/barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/sorted_msm.test.cpp new file mode 100644 index 000000000000..baed46e780b5 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/sorted_msm.test.cpp @@ -0,0 +1,260 @@ +#include "barretenberg/ecc/scalar_multiplication/sorted_msm.hpp" +#include "barretenberg/common/mem.hpp" +#include "barretenberg/common/test.hpp" +#include "barretenberg/common/zip_view.hpp" +#include "barretenberg/ecc/scalar_multiplication/point_table.hpp" +#include "barretenberg/ecc/scalar_multiplication/scalar_multiplication.hpp" +#include "barretenberg/numeric/random/engine.hpp" +#include "barretenberg/srs/factories/file_crs_factory.hpp" +#include "barretenberg/srs/io.hpp" + +#include +#include + +namespace bb { + +namespace { +auto& engine = numeric::get_debug_randomness(); +} + +template class SortedMsmTests : public ::testing::Test { + + public: + using G1 = typename Curve::AffineElement; + using Fr = typename Curve::ScalarField; + + struct TestData { + size_t num_points; + std::vector points; + std::vector scalars; + G1 msm_result; + }; + + /** + * @brief Generate a set of random points and scalars based on an input sequence_counts + * @details E.g. given sequence counts {7, 2, 9}, generate a set of random points and scalars with only 3 unique + * scalar values repeated according to the sequence counts. Also compute the result of the corresponding MSM for + * test comparisons. + * + * @param sequence_counts + * @return TestData + */ + TestData generate_test_data_from_sequence_counts(std::span sequence_counts) + { + // Generate duplicate scalars corresponding to the sequence counts + size_t num_points{ 0 }; + std::vector scalars; + for (auto& count : sequence_counts) { + Fr repeated_scalar = Fr::random_element(); + for (size_t i = 0; i < count; ++i) { + scalars.emplace_back(repeated_scalar); + num_points++; + } + } + + // Randomly shuffle the scalars so duplicates are no longer grouped together + std::random_device rd; + std::shuffle(scalars.begin(), scalars.end(), std::default_random_engine(rd())); + + // Randomly generate as many points as scalars + std::vector points; + for (size_t i = 0; i < num_points; ++i) { + points.emplace_back(G1::random_element()); + } + + // Compute the result of the MSM + G1 msm_result = points[0] * scalars[0]; + for (size_t i = 1; i < num_points; ++i) { + msm_result = msm_result + points[i] * scalars[i]; + } + + return { num_points, points, scalars, msm_result }; + } +}; + +using Curves = ::testing::Types; + +TYPED_TEST_SUITE(SortedMsmTests, Curves); + +// Test method for a single affine addition with provided slope denominator +TYPED_TEST(SortedMsmTests, AffineAddWithDenominator) +{ + using Curve = TypeParam; + using G1 = typename Curve::AffineElement; + using Fq = typename Curve::BaseField; + using Sorter = MsmSorter; + + Sorter msm_sorter; + + G1 point_1 = G1::random_element(); + G1 point_2 = G1::random_element(); + Fq denominator = (point_2.x - point_1.x).invert(); + + G1 expected = point_1 + point_2; + + G1 result = msm_sorter.affine_add_with_denominator(point_1, point_2, denominator); + + EXPECT_EQ(result, expected); +} + +// Test method for batch computing slope denominators for a set of point addition sequences +TYPED_TEST(SortedMsmTests, ComputePointAdditionDenominators) +{ + using Curve = TypeParam; + using Fq = typename Curve::BaseField; + using Sorter = MsmSorter; + using AdditionSequences = typename Sorter::AdditionSequences; + + // Generate random MSM inputs based on a set of sequence counts + std::array sequence_counts{ 3, 2 }; + auto test_data = TestFixture::generate_test_data_from_sequence_counts(sequence_counts); + size_t num_points = test_data.num_points; + auto& points = test_data.points; + + AdditionSequences addition_sequences{ sequence_counts, test_data.points, {} }; + + const size_t num_pairs = 2; + std::array denominators_expected; + denominators_expected[0] = (points[1].x - points[0].x).invert(); + denominators_expected[1] = (points[4].x - points[3].x).invert(); + + Sorter msm_sorter(num_points); + msm_sorter.batch_compute_point_addition_slope_inverses(addition_sequences); + + for (size_t i = 0; i < num_pairs; ++i) { + Fq result = msm_sorter.denominators[i]; + Fq expected = denominators_expected[i]; + EXPECT_EQ(result, expected); + } +} + +// Test method for batched addition of point addition sequences in place +TYPED_TEST(SortedMsmTests, BatchedAffineAddInPlace) +{ + using Curve = TypeParam; + using G1 = typename Curve::AffineElement; + using Sorter = MsmSorter; + using AdditionSequences = typename Sorter::AdditionSequences; + + // Generate random MSM inputs based on a set of sequence counts + std::array sequence_counts{ 5, 2, 3 }; + auto [num_points, points, scalars, msm_result] = + TestFixture::generate_test_data_from_sequence_counts(sequence_counts); + + AdditionSequences addition_sequences{ sequence_counts, points, {} }; + + std::vector expected_points; + size_t point_idx = 0; + for (auto count : sequence_counts) { + G1 sum = points[point_idx++]; + for (size_t i = 1; i < count; ++i) { + sum = sum + points[point_idx++]; + } + expected_points.emplace_back(sum); + } + + Sorter msm_sorter(num_points); + msm_sorter.batched_affine_add_in_place(addition_sequences); + + for (size_t idx = 0; idx < expected_points.size(); ++idx) { + EXPECT_EQ(expected_points[idx], points[idx]); + } +} + +// Test generation of point addition sequences from an arbitrary set of points and scalars +TYPED_TEST(SortedMsmTests, GenerateAdditionSequences) +{ + using Curve = TypeParam; + using G1 = typename Curve::AffineElement; + using Fr = typename Curve::ScalarField; + using Sorter = MsmSorter; + using AdditionSequences = typename Sorter::AdditionSequences; + + // Generate random MSM inputs based on a set of sequence counts + std::array sequence_counts{ 5, 2, 3 }; + auto [num_points, points, scalars, expected_msm_result] = + TestFixture::generate_test_data_from_sequence_counts(sequence_counts); + + Sorter msm_sorter{ num_points }; + AdditionSequences result = msm_sorter.construct_addition_sequences(scalars, points); + + // The resulting sequence counts should match expectation but only as multisets + std::multiset expected_sequence_counts(sequence_counts.begin(), sequence_counts.end()); + std::multiset result_sequence_counts(result.sequence_counts.begin(), result.sequence_counts.end()); + EXPECT_EQ(expected_sequence_counts, result_sequence_counts); + + // The result points will be sorted but should match the original as multisets + std::multiset expected_points(points.begin(), points.end()); + std::multiset result_points(result.points.begin(), result.points.end()); + EXPECT_EQ(expected_points, result_points); + + G1 msm_result; + msm_result.self_set_infinity(); + size_t scalar_idx = 0; + size_t point_idx = 0; + for (auto count : result.sequence_counts) { + for (size_t i = 0; i < count; ++i) { + msm_result = msm_result + result.points[point_idx] * msm_sorter.unique_scalars[scalar_idx]; + point_idx++; + } + scalar_idx++; + } + + EXPECT_EQ(msm_result, expected_msm_result); +} + +// Test that the method reduce_msm_inputs can reduce a set of {points, scalars} with duplicate scalars to a reduced set +// of inputs {points', scalars'} such that all scalars in scalars' are unique and that perfoming the MSM on the reduced +// inputs yields the same result as with the original inputs +TYPED_TEST(SortedMsmTests, ReduceMsmInputsSimple) +{ + using Curve = TypeParam; + using G1 = typename Curve::AffineElement; + using Sorter = MsmSorter; + + // Generate random MSM inputs based on a set of sequence counts + std::array sequence_counts{ 5, 2, 3 }; + auto [num_points, points, scalars, expected_msm_result] = + TestFixture::generate_test_data_from_sequence_counts(sequence_counts); + + Sorter msm_sorter{ num_points }; + auto [result_scalars, result_points] = msm_sorter.reduce_msm_inputs(scalars, points); + + G1 msm_result = result_points[0] * result_scalars[0]; + for (size_t i = 1; i < result_points.size(); ++i) { + msm_result = msm_result + result_points[i] * result_scalars[i]; + } + + EXPECT_EQ(msm_result, expected_msm_result); +} + +// Test that the method reduce_msm_inputs can reduce a set of {points, scalars} with duplicate scalars to a reduced set +// of inputs {points', scalars'} such that all scalars in scalars' are unique and that perfoming the MSM on the reduced +// inputs yields the same result as with the original inputs +TYPED_TEST(SortedMsmTests, ReduceMsmInputs) +{ + using Curve = TypeParam; + using G1 = typename Curve::AffineElement; + using Sorter = MsmSorter; + + // Generate random MSM inputs based on a set of sequence counts + const size_t num_unique_scalars = 5; + std::array sequence_counts{ 75, 1, 28, 382, 3 }; + auto [num_points, points, scalars, expected_msm_result] = + TestFixture::generate_test_data_from_sequence_counts(sequence_counts); + + Sorter msm_sorter{ num_points }; + auto [result_scalars, result_points] = msm_sorter.reduce_msm_inputs(scalars, points); + + // Points and scalars should both be reduced to the number of unique scalars + EXPECT_EQ(result_scalars.size(), num_unique_scalars); + EXPECT_EQ(result_points.size(), num_unique_scalars); + + // Performing the MSM over the reduced inputs should yield the same result as the original + G1 msm_result = result_points[0] * result_scalars[0]; + for (size_t i = 1; i < result_points.size(); ++i) { + msm_result = msm_result + result_points[i] * result_scalars[i]; + } + EXPECT_EQ(msm_result, expected_msm_result); +} +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.hpp b/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.hpp index 149d97940989..cf6b524d6f12 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.hpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.hpp @@ -31,6 +31,15 @@ template class FileCrsFactory : public CrsFactory { template class FileProverCrs : public ProverCrs { public: + /** + * @brief Construct a prover CRS populated with a pippenger point table based on the SRS elements + * @details Allocates space in monomials_ for 2 * num_points affine elements, populates the first num_points with + * the raw SRS elements P_i, then overwrites the same memory with the 'pippenger point table' which contains the raw + * elements P_i at even indices and the endomorphism point (\beta * P_i.x, -P_i.y) at odd indices. + * + * @param num_points + * @param path + */ FileProverCrs(const size_t num_points, std::string const& path) : num_points(num_points) { From fd67da35da3949bf112392d7cf1d512c5eed23eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 11 Jul 2024 05:23:58 -0300 Subject: [PATCH 23/32] feat: remove ram tables in note_getter (#7434) --- .../aztec/src/note/note_getter/mod.nr | 38 +++++++------------ .../aztec/src/state_vars/private_set.nr | 2 +- .../aztec-nr/value-note/src/value_note.nr | 8 ++++ .../src/types/balances_map.nr | 2 +- .../src/types/token_note.nr | 8 ++++ .../contracts/test_contract/src/test_note.nr | 6 +++ .../src/types/balances_map.nr | 2 +- .../src/types/token_note.nr | 8 ++++ .../src/types/transparent_note.nr | 6 +++ .../token_contract/src/types/balances_map.nr | 2 +- .../token_contract/src/types/token_note.nr | 8 ++++ .../src/types/transparent_note.nr | 9 ++++- 12 files changed, 69 insertions(+), 30 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/note/note_getter/mod.nr b/noir-projects/aztec-nr/aztec/src/note/note_getter/mod.nr index b5df4dd7ce7b..e1051b269d92 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_getter/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_getter/mod.nr @@ -104,7 +104,7 @@ pub fn get_notes( context: &mut PrivateContext, storage_slot: Field, options: NoteGetterOptions -) -> BoundedVec where Note: NoteInterface { +) -> BoundedVec where Note: NoteInterface + Eq { let opt_notes = get_notes_internal(storage_slot, options); constrain_get_notes_internal(context, storage_slot, opt_notes, options) @@ -115,9 +115,7 @@ fn constrain_get_notes_internal( storage_slot: Field, opt_notes: [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], options: NoteGetterOptions -) -> BoundedVec where Note: NoteInterface { - let mut returned_notes = BoundedVec::new(); - +) -> BoundedVec where Note: NoteInterface + Eq { // The filter is applied first to avoid pushing note read requests for notes we're not interested in. Note that // while the filter function can technically mutate the contents of the notes (as opposed to simply removing some), // the private kernel will later validate that these note actually exist, so transformations would cause for that @@ -126,11 +124,18 @@ fn constrain_get_notes_internal( let filter_args = options.filter_args; let filtered_notes = filter_fn(opt_notes, filter_args); + let notes = crate::utils::collapse(filtered_notes); + + // We have now collapsed the sparse array of Options into a BoundedVec. This is a more ergonomic type and also + // results in reduced gate counts when setting a limit value, since we guarantee that the limit is an upper bound + // for the runtime length, and can therefore have fewer loop iterations. + assert(notes.len() <= options.limit, "Got more notes than limit."); + assert(notes.len() != 0, "Cannot return zero notes"); + let mut prev_fields = [0; N]; for i in 0..options.limit { - let opt_note = filtered_notes[i]; - if opt_note.is_some() { - let note = opt_note.unwrap_unchecked(); + if i < notes.len() { + let note = notes.get_unchecked(i); let fields = note.serialize_content(); check_note_header(*context, storage_slot, note); check_note_fields(fields, options.selects); @@ -143,27 +148,10 @@ fn constrain_get_notes_internal( // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1410): test to ensure // failure if malicious oracle injects 0 nonce here for a "pre-existing" note. context.push_note_hash_read_request(note_hash_for_read_request); - - // The below code is used to collapse a sparse array into one where the values are guaranteed to be at the - // front of the array. This is highly useful because the caller knows that the returned array won't have - // more than option.limits notes, and can therefore loop over this limit value instead of the entire array, - // resulting in a smaller circuit and faster proving times. - // We write at returned_notes[num_notes] because num_notes is only advanced when we have a value in - // filtered_notes. - returned_notes.push(note); }; } - // As long as we only loop till `options.limit` the array will be guaranteed to be at most of length `options.limit`. - assert(returned_notes.len() <= options.limit, "Got more notes than limit."); - // We will however check that nothing else was returned after the limit. - for i in options.limit..filtered_notes.len() { - assert(filtered_notes[i].is_none(), "Got more notes than limit."); - } - - assert(returned_notes.len() != 0, "Cannot return zero notes"); - - returned_notes + notes } unconstrained fn get_note_internal(storage_slot: Field) -> Note where Note: NoteInterface { diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr index 09426e7c207a..0b285013bb1b 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr @@ -55,7 +55,7 @@ impl PrivateSet { pub fn get_notes( self, options: NoteGetterOptions - ) -> BoundedVec where Note: NoteInterface { + ) -> BoundedVec where Note: NoteInterface + Eq { get_notes(self.context, self.storage_slot, options) } // docs:end:get_notes diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index 63bda30ecdd9..1b135577ec73 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -64,3 +64,11 @@ impl Serialize<7> for ValueNote { [self.value, self.npk_m_hash, self.randomness, header[0], header[1], header[2], header[3]] } } + +impl Eq for ValueNote { + fn eq(self, other: Self) -> bool { + (self.value == other.value) & + (self.npk_m_hash == other.npk_m_hash) & + (self.randomness == other.randomness) + } +} diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/balances_map.nr index 7ce8857dd2d5..b1f1837ef70b 100644 --- a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/balances_map.nr @@ -79,7 +79,7 @@ impl BalancesMap { self: Self, owner_npk_m_hash: Field, subtrahend: U128 - ) -> OuterNoteEmission where T: NoteInterface + OwnedNote { + ) -> OuterNoteEmission where T: NoteInterface + OwnedNote + Eq { let mut options = NoteGetterOptions::with_filter(filter_notes_min_sum, subtrahend); let notes = self.map.get_notes( options.select( diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr index 99c61356e142..7a45e9140b72 100644 --- a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr @@ -95,6 +95,14 @@ impl NoteInterface for TokenNote { } } +impl Eq for TokenNote { + fn eq(self, other: Self) -> bool { + (self.amount == other.amount) & + (self.npk_m_hash == other.npk_m_hash) & + (self.randomness == other.randomness) + } +} + impl OwnedNote for TokenNote { fn new(amount: U128, owner_npk_m_hash: Field) -> Self { Self { diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr b/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr index 04bfede64165..f6bbbd39eaea 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr @@ -34,3 +34,9 @@ impl TestNote { TestNote { value, header: NoteHeader::empty() } } } + +impl Eq for TestNote { + fn eq(self, other: Self) -> bool { + self.value == other.value + } +} diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr index a5436a93d954..f97784cd218f 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr @@ -80,7 +80,7 @@ impl BalancesMap { self: Self, owner: AztecAddress, subtrahend: U128 - ) -> OuterNoteEmission where T: NoteInterface + OwnedNote { + ) -> OuterNoteEmission where T: NoteInterface + OwnedNote + Eq { // docs:start:get_notes let options = NoteGetterOptions::with_filter(filter_notes_min_sum, subtrahend); let notes = self.map.at(owner).get_notes(options); diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr index 068d0c9e5529..6d26cd92158b 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr @@ -50,6 +50,14 @@ impl NoteInterface for TokenNote { } } +impl Eq for TokenNote { + fn eq(self, other: Self) -> bool { + (self.amount == other.amount) & + (self.npk_m_hash == other.npk_m_hash) & + (self.randomness == other.randomness) + } +} + impl OwnedNote for TokenNote { fn new(amount: U128, owner_npk_m_hash: Field) -> Self { Self { diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr index 35374fed7be4..aa5f8a496167 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr @@ -78,4 +78,10 @@ impl TransparentNote { } } } + +impl Eq for TransparentNote { + fn eq(self, other: Self) -> bool { + (self.amount == other.amount) & (self.secret_hash == other.secret_hash) + } +} // docs:end:token_types_all diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr index a13206360c33..25e745746bc4 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -83,7 +83,7 @@ impl BalancesMap { self: Self, owner: AztecAddress, subtrahend: U128 - ) -> OuterNoteEmission where T: NoteInterface + OwnedNote { + ) -> OuterNoteEmission where T: NoteInterface + OwnedNote + Eq { // docs:start:get_notes let options = NoteGetterOptions::with_filter(filter_notes_min_sum, subtrahend); let notes = self.map.at(owner).get_notes(options); diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index 068d0c9e5529..14ba48f7c08e 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -64,3 +64,11 @@ impl OwnedNote for TokenNote { self.amount } } + +impl Eq for TokenNote { + fn eq(self, other: Self) -> bool { + (self.amount == other.amount) & + (self.npk_m_hash == other.npk_m_hash) & + (self.randomness == other.randomness) + } +} diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr index 35374fed7be4..e3b028c722ad 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr @@ -78,4 +78,11 @@ impl TransparentNote { } } } -// docs:end:token_types_all + +impl Eq for TransparentNote { + fn eq(self, other: Self) -> bool { + (self.amount == other.amount) & (self.secret_hash == other.secret_hash) + } +} + +// docs:end:token_types_all \ No newline at end of file From 2a7494baec4396b9fa62f0a9c240b4b02f23fb1d Mon Sep 17 00:00:00 2001 From: Jean M <132435771+jeanmon@users.noreply.github.com> Date: Thu, 11 Jul 2024 10:43:45 +0200 Subject: [PATCH 24/32] fix(avm): fixes AVM full tests and decrease timeout to 35 minutes (#7438) Fixes failure in: https://github.com/AztecProtocol/aztec-packages/actions/runs/9885438673 Timeout decrease for the AVM full tests action to 35 minutes. --- .github/workflows/vm_full_tests.yml | 4 ++-- .../barretenberg/vm/tests/avm_arithmetic.test.cpp | 6 +++--- .../barretenberg/vm/tests/avm_execution.test.cpp | 13 +++++++++---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/.github/workflows/vm_full_tests.yml b/.github/workflows/vm_full_tests.yml index e1e135b02018..601ed966b803 100644 --- a/.github/workflows/vm_full_tests.yml +++ b/.github/workflows/vm_full_tests.yml @@ -55,7 +55,7 @@ jobs: concurrency_key: avm-full-tests-x86 - name: "AVM Full Tests" working-directory: ./barretenberg/cpp/ - timeout-minutes: 70 + timeout-minutes: 35 run: | - sudo shutdown -P 70 # hack until core part of the scripts + sudo shutdown -P 35 # hack until core part of the scripts earthly-ci --no-output +vm-full-test --hardware_concurrency=64 # limit our parallelism to half our cores diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp index 8418aa87ab48..96debab26820 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp @@ -412,7 +412,7 @@ TEST_F(AvmArithmeticTestsFF, subtraction) EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); std::vector const returndata = { 8, 9, 17 }; - validate_trace(std::move(trace), public_inputs, calldata); + validate_trace(std::move(trace), public_inputs, calldata, returndata); } // Test on basic multiplication over finite field type. @@ -483,7 +483,7 @@ TEST_F(AvmArithmeticTestsFF, fDivision) EXPECT_EQ(row->main_sel_mem_op_c, FF(1)); EXPECT_EQ(row->main_rwc, FF(1)); - std::vector const returndata = { 15, 315, 0 }; + std::vector const returndata = { 15, 315, 21 }; validate_trace(std::move(trace), public_inputs, calldata, returndata); } @@ -619,7 +619,7 @@ TEST_F(AvmArithmeticTestsFF, nonEquality) gen_trace_builder(calldata); trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [q - 1, q, 0, 0..] - trace_builder.op_return(0, 0, 0); + trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_eq(trace, elem, FF(0), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::FF); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp index 98591c279454..be6f99c52f9a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp @@ -1451,9 +1451,10 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) // The return data for this test should be a the opcodes in sequence, as the opcodes dst address lines up with // this array The returndata call above will then return this array - std::vector returndata = { sender, address, storage_address, function_selector, transaction_fee, - chainid, version, blocknumber, /*coinbase,*/ timestamp, feeperl2gas, - feeperdagas }; + std::vector const expected_returndata = { + address, storage_address, sender, function_selector, transaction_fee, chainid, version, + blocknumber, /*coinbase,*/ timestamp, feeperl2gas, feeperdagas, + }; // Set up public inputs to contain the above values // TODO: maybe have a javascript like object construction so that this is readable @@ -1476,8 +1477,12 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) public_inputs_vec[FEE_PER_DA_GAS_OFFSET] = feeperdagas; public_inputs_vec[FEE_PER_L2_GAS_OFFSET] = feeperl2gas; + std::vector returndata; auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec); + // Validate returndata + EXPECT_EQ(returndata, expected_returndata); + // Validate that the opcode read the correct value into ia // Check address auto address_row = @@ -1539,7 +1544,7 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_fee_per_l2_gas == 1; }); EXPECT_EQ(feeperl2gas_row->main_ia, feeperl2gas); - validate_trace(std::move(trace), Execution::convert_public_inputs(public_inputs_vec)); + validate_trace(std::move(trace), Execution::convert_public_inputs(public_inputs_vec), calldata, returndata); } // Positive test for L2GASLEFT opcode From 399917b3e6916805bb55596b47183e44700fe8f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Rodr=C3=ADguez?= Date: Thu, 11 Jul 2024 12:31:21 +0200 Subject: [PATCH 25/32] feat: Add reset tiny and optimize tail (#7422) --- .../src/core/libraries/ConstantsGen.sol | 1 + .../src/private_kernel_inner.nr | 4 ++- .../src/private_kernel_tail.nr | 4 ++- .../src/private_kernel_tail_to_public.nr | 4 ++- .../crates/types/src/constants.nr | 1 + .../types/src/tests/fixtures/vk_tree.nr | 4 ++- ...t_split_sorted_transformed_value_arrays.nr | 35 ++++++++++--------- .../reset_variants.json | 11 ++++++ yarn-project/bb-prover/src/stats.ts | 2 ++ yarn-project/circuit-types/src/stats/stats.ts | 1 + yarn-project/circuits.js/src/constants.gen.ts | 1 + .../src/artifacts.ts | 7 +++- .../noir-protocol-circuits-types/src/vks.ts | 4 +++ 13 files changed, 57 insertions(+), 22 deletions(-) diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 41ee122490fa..a6fb98c7c8cc 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -76,6 +76,7 @@ library Constants { uint256 internal constant PRIVATE_KERNEL_RESET_BIG_INDEX = 3; uint256 internal constant PRIVATE_KERNEL_RESET_MEDIUM_INDEX = 4; uint256 internal constant PRIVATE_KERNEL_RESET_SMALL_INDEX = 5; + uint256 internal constant PRIVATE_KERNEL_RESET_TINY_INDEX = 6; uint256 internal constant PRIVATE_KERNEL_TAIL_INDEX = 10; uint256 internal constant PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX = 11; uint256 internal constant EMPTY_NESTED_INDEX = 12; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr index 2f34b4de60b0..51ca50f4d3b7 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -12,7 +12,8 @@ use dep::types::{ }, constants::{ PRIVATE_KERNEL_INIT_INDEX, PRIVATE_KERNEL_INNER_INDEX, PRIVATE_KERNEL_RESET_FULL_INDEX, - PRIVATE_KERNEL_RESET_BIG_INDEX, PRIVATE_KERNEL_RESET_MEDIUM_INDEX, PRIVATE_KERNEL_RESET_SMALL_INDEX + PRIVATE_KERNEL_RESET_BIG_INDEX, PRIVATE_KERNEL_RESET_MEDIUM_INDEX, PRIVATE_KERNEL_RESET_SMALL_INDEX, + PRIVATE_KERNEL_RESET_TINY_INDEX } }; @@ -23,6 +24,7 @@ global ALLOWED_PREVIOUS_CIRCUITS = [ PRIVATE_KERNEL_RESET_BIG_INDEX, PRIVATE_KERNEL_RESET_MEDIUM_INDEX, PRIVATE_KERNEL_RESET_SMALL_INDEX, + PRIVATE_KERNEL_RESET_TINY_INDEX, ]; struct PrivateKernelInnerCircuitPrivateInputs { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr index c76e0cdeada1..401968696894 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr @@ -6,7 +6,8 @@ use dep::types::{ abis::{private_kernel_data::PrivateKernelData, kernel_circuit_public_inputs::KernelCircuitPublicInputs}, constants::{ PRIVATE_KERNEL_INIT_INDEX, PRIVATE_KERNEL_INNER_INDEX, PRIVATE_KERNEL_RESET_FULL_INDEX, - PRIVATE_KERNEL_RESET_BIG_INDEX, PRIVATE_KERNEL_RESET_MEDIUM_INDEX, PRIVATE_KERNEL_RESET_SMALL_INDEX + PRIVATE_KERNEL_RESET_BIG_INDEX, PRIVATE_KERNEL_RESET_MEDIUM_INDEX, PRIVATE_KERNEL_RESET_SMALL_INDEX, + PRIVATE_KERNEL_RESET_TINY_INDEX } }; @@ -17,6 +18,7 @@ global ALLOWED_PREVIOUS_CIRCUITS = [ PRIVATE_KERNEL_RESET_BIG_INDEX, PRIVATE_KERNEL_RESET_MEDIUM_INDEX, PRIVATE_KERNEL_RESET_SMALL_INDEX, + PRIVATE_KERNEL_RESET_TINY_INDEX, ]; struct PrivateKernelTailCircuitPrivateInputs { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr index 6a3aeaf375ad..6180ea6c315e 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr @@ -7,7 +7,8 @@ use dep::types::{ abis::{private_kernel_data::PrivateKernelData, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs}, constants::{ PRIVATE_KERNEL_INIT_INDEX, PRIVATE_KERNEL_INNER_INDEX, PRIVATE_KERNEL_RESET_FULL_INDEX, - PRIVATE_KERNEL_RESET_BIG_INDEX, PRIVATE_KERNEL_RESET_MEDIUM_INDEX, PRIVATE_KERNEL_RESET_SMALL_INDEX + PRIVATE_KERNEL_RESET_BIG_INDEX, PRIVATE_KERNEL_RESET_MEDIUM_INDEX, PRIVATE_KERNEL_RESET_SMALL_INDEX, + PRIVATE_KERNEL_RESET_TINY_INDEX } }; @@ -18,6 +19,7 @@ global ALLOWED_PREVIOUS_CIRCUITS = [ PRIVATE_KERNEL_RESET_BIG_INDEX, PRIVATE_KERNEL_RESET_MEDIUM_INDEX, PRIVATE_KERNEL_RESET_SMALL_INDEX, + PRIVATE_KERNEL_RESET_TINY_INDEX, ]; struct PrivateKernelTailToPublicCircuitPrivateInputs { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 49f67780fccd..e63fc49bd8f3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -104,6 +104,7 @@ global PRIVATE_KERNEL_RESET_FULL_INDEX: u32 = 2; global PRIVATE_KERNEL_RESET_BIG_INDEX: u32 = 3; global PRIVATE_KERNEL_RESET_MEDIUM_INDEX: u32 = 4; global PRIVATE_KERNEL_RESET_SMALL_INDEX: u32 = 5; +global PRIVATE_KERNEL_RESET_TINY_INDEX: u32 = 6; global PRIVATE_KERNEL_TAIL_INDEX: u32 = 10; global PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX: u32 = 11; global EMPTY_NESTED_INDEX: u32 = 12; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr index c26f9b125541..1069bfb9ec9f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/vk_tree.nr @@ -4,7 +4,8 @@ use crate::constants::{ PRIVATE_KERNEL_RESET_SMALL_INDEX, PRIVATE_KERNEL_TAIL_INDEX, PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, EMPTY_NESTED_INDEX, PRIVATE_KERNEL_EMPTY_INDEX, PUBLIC_KERNEL_SETUP_INDEX, PUBLIC_KERNEL_APP_LOGIC_INDEX, PUBLIC_KERNEL_TEARDOWN_INDEX, PUBLIC_KERNEL_TAIL_INDEX, - BASE_PARITY_INDEX, ROOT_PARITY_INDEX, BASE_ROLLUP_INDEX, MERGE_ROLLUP_INDEX, ROOT_ROLLUP_INDEX + BASE_PARITY_INDEX, ROOT_PARITY_INDEX, BASE_ROLLUP_INDEX, MERGE_ROLLUP_INDEX, ROOT_ROLLUP_INDEX, + PRIVATE_KERNEL_RESET_TINY_INDEX }; use crate::merkle_tree::merkle_tree::MerkleTree; @@ -25,6 +26,7 @@ pub fn get_vk_merkle_tree() -> MerkleTree { leaves[PRIVATE_KERNEL_RESET_BIG_INDEX] = 3; leaves[PRIVATE_KERNEL_RESET_MEDIUM_INDEX] = 4; leaves[PRIVATE_KERNEL_RESET_SMALL_INDEX] = 5; + leaves[PRIVATE_KERNEL_RESET_TINY_INDEX] = 6; leaves[PRIVATE_KERNEL_TAIL_INDEX] = 10; leaves[PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX] = 11; leaves[EMPTY_NESTED_INDEX] = 12; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr index 94e1871ab3f5..13213932d66c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr @@ -29,27 +29,13 @@ fn assert_split_sorted_transformed_value_arrays( let value = transformed_value_array[i]; let sorted_index = index_hints[i]; let is_lt = original.counter() < split_counter; - let (sorted_value, sorted_counter, num) = if is_lt { - ( - sorted_transformed_value_array_lt[sorted_index], sorted_counters_lt[sorted_index], num_lt - ) + let (sorted_value, sorted_counter) = if is_lt { + (sorted_transformed_value_array_lt[sorted_index], sorted_counters_lt[sorted_index]) } else { - ( - sorted_transformed_value_array_gte[sorted_index], sorted_counters_gte[sorted_index], num_gte - ) + (sorted_transformed_value_array_gte[sorted_index], sorted_counters_gte[sorted_index]) }; assert_eq(value, sorted_value, "mismatch sorted values"); assert_eq(original.counter(), sorted_counter, "mismatch counters"); - if num != 0 { - let (counter, prev_counter) = if is_lt { - (sorted_counters_lt[num], sorted_counters_lt[num - 1]) - } else { - (sorted_counters_gte[num], sorted_counters_gte[num - 1]) - }; - let is_incrementing = counter > prev_counter; - assert(ascending == is_incrementing, "value array must be sorted by counter"); - assert(counter != prev_counter, "counters must not be the same"); - } if is_lt { num_lt += 1; } else { @@ -58,6 +44,21 @@ fn assert_split_sorted_transformed_value_arrays( } } + for i in 1..N { + if i < num_lt { + let counter = sorted_counters_lt[i]; + let prev_counter = sorted_counters_lt[i - 1]; + assert(ascending == (counter > prev_counter), "value array must be sorted by counter"); + assert(counter != prev_counter, "counters must not be the same"); + } + if i < num_gte { + let counter = sorted_counters_gte[i]; + let prev_counter = sorted_counters_gte[i - 1]; + assert(ascending == (counter > prev_counter), "value array must be sorted by counter"); + assert(counter != prev_counter, "counters must not be the same"); + } + } + let num_non_empty_values_lt = validate_array(sorted_transformed_value_array_lt); assert_eq(num_non_empty_values_lt, num_lt, "mismatch number of values lt"); diff --git a/noir-projects/noir-protocol-circuits/reset_variants.json b/noir-projects/noir-protocol-circuits/reset_variants.json index 514570386cfd..88fdf280fa67 100644 --- a/noir-projects/noir-protocol-circuits/reset_variants.json +++ b/noir-projects/noir-protocol-circuits/reset_variants.json @@ -31,5 +31,16 @@ "NULLIFIER_SETTLED_AMOUNT": 8, "NULLIFIER_KEYS": 8 } + }, + { + "tag": "tiny", + "priority": 101, + "replacements": { + "NOTE_HASH_PENDING_AMOUNT": 4, + "NOTE_HASH_SETTLED_AMOUNT": 4, + "NULLIFIER_PENDING_AMOUNT": 4, + "NULLIFIER_SETTLED_AMOUNT": 4, + "NULLIFIER_KEYS": 4 + } } ] \ No newline at end of file diff --git a/yarn-project/bb-prover/src/stats.ts b/yarn-project/bb-prover/src/stats.ts index f31e611dd8cb..e7f3da9302a9 100644 --- a/yarn-project/bb-prover/src/stats.ts +++ b/yarn-project/bb-prover/src/stats.ts @@ -41,6 +41,8 @@ export function mapProtocolArtifactNameToCircuitName( return 'private-kernel-reset-medium'; case 'PrivateKernelResetSmallArtifact': return 'private-kernel-reset-small'; + case 'PrivateKernelResetTinyArtifact': + return 'private-kernel-reset-tiny'; case 'EmptyNestedArtifact': return 'empty-nested'; case 'PrivateKernelEmptyArtifact': diff --git a/yarn-project/circuit-types/src/stats/stats.ts b/yarn-project/circuit-types/src/stats/stats.ts index 8abab96dde99..ac87473565e4 100644 --- a/yarn-project/circuit-types/src/stats/stats.ts +++ b/yarn-project/circuit-types/src/stats/stats.ts @@ -83,6 +83,7 @@ export type CircuitName = | 'private-kernel-reset-big' | 'private-kernel-reset-medium' | 'private-kernel-reset-small' + | 'private-kernel-reset-tiny' | 'private-kernel-tail' | 'private-kernel-tail-to-public' | 'app-circuit' diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 308495143d7d..f3331eef1275 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -62,6 +62,7 @@ export const PRIVATE_KERNEL_RESET_FULL_INDEX = 2; export const PRIVATE_KERNEL_RESET_BIG_INDEX = 3; export const PRIVATE_KERNEL_RESET_MEDIUM_INDEX = 4; export const PRIVATE_KERNEL_RESET_SMALL_INDEX = 5; +export const PRIVATE_KERNEL_RESET_TINY_INDEX = 6; export const PRIVATE_KERNEL_TAIL_INDEX = 10; export const PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX = 11; export const EMPTY_NESTED_INDEX = 12; diff --git a/yarn-project/noir-protocol-circuits-types/src/artifacts.ts b/yarn-project/noir-protocol-circuits-types/src/artifacts.ts index 97ce2df7a70d..9d15d0ca234f 100644 --- a/yarn-project/noir-protocol-circuits-types/src/artifacts.ts +++ b/yarn-project/noir-protocol-circuits-types/src/artifacts.ts @@ -19,6 +19,7 @@ import PrivateKernelResetBigSimulatedJson from '../artifacts/private_kernel_rese import PrivateKernelResetMediumSimulatedJson from '../artifacts/private_kernel_reset_simulated_medium.json' assert { type: 'json' }; import PrivateKernelResetSmallSimulatedJson from '../artifacts/private_kernel_reset_simulated_small.json' assert { type: 'json' }; import PrivateKernelResetSmallJson from '../artifacts/private_kernel_reset_small.json' assert { type: 'json' }; +import PrivateKernelResetTinyJson from '../artifacts/private_kernel_reset_tiny.json' assert { type: 'json' }; import PrivateKernelTailJson from '../artifacts/private_kernel_tail.json' assert { type: 'json' }; import PrivateKernelTailSimulatedJson from '../artifacts/private_kernel_tail_simulated.json' assert { type: 'json' }; import PrivateKernelTailToPublicJson from '../artifacts/private_kernel_tail_to_public.json' assert { type: 'json' }; @@ -40,13 +41,15 @@ export type PrivateResetArtifacts = | 'PrivateKernelResetFullArtifact' | 'PrivateKernelResetBigArtifact' | 'PrivateKernelResetMediumArtifact' - | 'PrivateKernelResetSmallArtifact'; + | 'PrivateKernelResetSmallArtifact' + | 'PrivateKernelResetTinyArtifact'; export const PrivateResetTagToArtifactName: Record = { full: 'PrivateKernelResetFullArtifact', big: 'PrivateKernelResetBigArtifact', medium: 'PrivateKernelResetMediumArtifact', small: 'PrivateKernelResetSmallArtifact', + tiny: 'PrivateKernelResetTinyArtifact', }; export type ServerProtocolArtifact = @@ -104,6 +107,7 @@ export const ResetSimulatedArtifacts: Record = { @@ -113,6 +117,7 @@ export const ClientCircuitArtifacts: Record = { PrivateKernelResetBigArtifact: keyJsonToVKData(PrivateKernelResetBigVkJson), PrivateKernelResetMediumArtifact: keyJsonToVKData(PrivateKernelResetMediumVkJson), PrivateKernelResetSmallArtifact: keyJsonToVKData(PrivateKernelResetSmallVkJson), + PrivateKernelResetTinyArtifact: keyJsonToVKData(PrivateKernelResetTinyVkJson), PrivateKernelTailArtifact: keyJsonToVKData(PrivateKernelTailVkJson), PrivateKernelTailToPublicArtifact: keyJsonToVKData(PrivateKernelTailToPublicVkJson), }; @@ -108,6 +111,7 @@ export const ProtocolCircuitVkIndexes: Record = { PrivateKernelResetBigArtifact: PRIVATE_KERNEL_RESET_BIG_INDEX, PrivateKernelResetMediumArtifact: PRIVATE_KERNEL_RESET_MEDIUM_INDEX, PrivateKernelResetSmallArtifact: PRIVATE_KERNEL_RESET_SMALL_INDEX, + PrivateKernelResetTinyArtifact: PRIVATE_KERNEL_RESET_TINY_INDEX, PrivateKernelTailArtifact: PRIVATE_KERNEL_TAIL_INDEX, PrivateKernelTailToPublicArtifact: PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, PublicKernelSetupArtifact: PUBLIC_KERNEL_SETUP_INDEX, From 97ecff5ea76a0da878bdccc453b121147f726ec4 Mon Sep 17 00:00:00 2001 From: Aztec Bot <49558828+AztecBot@users.noreply.github.com> Date: Thu, 11 Jul 2024 07:42:33 -0400 Subject: [PATCH 26/32] feat: Sync from noir (#7432) Automated pull of development from the [noir](https://github.com/noir-lang/noir) programming language, a dependency of Aztec. BEGIN_COMMIT_OVERRIDE chore: unbundle `check_array_is_initialized` (https://github.com/noir-lang/noir/pull/5451) feat: Sync from aztec-packages (https://github.com/noir-lang/noir/pull/5467) chore: bump bb to 0.45.1 (https://github.com/noir-lang/noir/pull/5469) feat: prefix operator overload trait dispatch (https://github.com/noir-lang/noir/pull/5423) feat: add CLI argument for debugging comptime blocks (https://github.com/noir-lang/noir/pull/5192) chore: document EmbeddedCurvePoint (https://github.com/noir-lang/noir/pull/5468) feat: lsp rename/find-all-references for struct members (https://github.com/noir-lang/noir/pull/5443) feat(optimization): Deduplicate more instructions (https://github.com/noir-lang/noir/pull/5457) fix: remove compile-time error for invalid indices (https://github.com/noir-lang/noir/pull/5466) END_COMMIT_OVERRIDE --------- Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> Co-authored-by: benesjan --- .noir-sync-commit | 2 +- avm-transpiler/Cargo.lock | 1 + .../aztec/src/encrypted_logs/header.nr | 18 +- .../aztec/src/encrypted_logs/incoming_body.nr | 36 +- .../aztec/src/encrypted_logs/outgoing_body.nr | 32 +- .../aztec/src/encrypted_logs/payload.nr | 16 +- .../aztec-nr/aztec/src/keys/getters.nr | 2 +- .../aztec/src/keys/point_to_symmetric_key.nr | 18 +- .../aztec-nr/aztec/src/keys/public_keys.nr | 8 +- .../aztec-nr/aztec/src/oracle/keys.nr | 8 +- .../contracts/test_contract/src/main.nr | 3 +- .../src/private_kernel_reset.nr | 6 +- .../src/private_kernel_tail.nr | 6 +- .../src/private_kernel_tail_to_public.nr | 6 +- .../src/reset/key_validation_hint.nr | 3 +- .../key_validation_request.nr | 2 +- noir/bb-version | 2 +- .../acvm-repo/acir/src/circuit/mod.rs | 2 +- .../opcodes/black_box_function_call.rs | 2 +- .../acir/tests/test_program_serialization.rs | 2 +- .../compiler/optimizers/redundant_range.rs | 2 +- noir/noir-repo/compiler/fm/Cargo.toml | 1 + noir/noir-repo/compiler/fm/src/lib.rs | 21 + .../compiler/noirc_driver/src/lib.rs | 11 +- .../noirc_driver/tests/stdlib_warnings.rs | 2 +- .../compiler/noirc_errors/src/reporter.rs | 49 +- .../compiler/noirc_evaluator/src/errors.rs | 3 - .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 156 +++---- .../noirc_evaluator/src/ssa/ir/instruction.rs | 24 +- .../src/ssa/opt/constant_folding.rs | 128 +++++- .../src/elaborator/expressions.rs | 113 +++-- .../noirc_frontend/src/elaborator/mod.rs | 67 ++- .../noirc_frontend/src/elaborator/patterns.rs | 21 +- .../src/elaborator/statements.rs | 15 +- .../noirc_frontend/src/elaborator/traits.rs | 3 +- .../noirc_frontend/src/elaborator/types.rs | 132 +++--- .../noirc_frontend/src/hir/comptime/errors.rs | 20 +- .../src/hir/comptime/hir_to_display_ast.rs | 428 ++++++++++++++++++ .../src/hir/comptime/interpreter.rs | 20 +- .../noirc_frontend/src/hir/comptime/mod.rs | 1 + .../noirc_frontend/src/hir/comptime/scan.rs | 28 +- .../noirc_frontend/src/hir/comptime/tests.rs | 10 +- .../src/hir/def_collector/dc_crate.rs | 54 ++- .../noirc_frontend/src/hir/def_map/mod.rs | 2 + .../src/hir/resolution/resolver.rs | 3 +- .../src/hir/resolution/traits.rs | 3 +- .../src/hir/type_check/errors.rs | 3 + .../noirc_frontend/src/hir/type_check/expr.rs | 4 + .../noirc_frontend/src/hir_def/expr.rs | 4 + .../noirc_frontend/src/hir_def/types.rs | 5 + .../compiler/noirc_frontend/src/locations.rs | 5 + .../src/monomorphization/mod.rs | 49 +- .../noirc_frontend/src/node_interner.rs | 115 +++-- .../compiler/noirc_frontend/src/tests.rs | 3 +- .../src/collections/bounded_vec.nr | 47 +- .../noir_stdlib/src/embedded_curve_ops.nr | 27 +- noir/noir-repo/scripts/bump-bb.sh | 11 + noir/noir-repo/scripts/install_bb.sh | 2 +- .../Nargo.toml | 7 + .../src/main.nr | 4 + .../binary_operator_overloading/Nargo.toml | 7 + .../Prover.toml | 0 .../src/main.nr | 0 .../simple_shield/src/main.nr | 2 +- .../Nargo.toml | 2 +- .../unary_operator_overloading/Prover.toml | 1 + .../unary_operator_overloading/src/main.nr | 36 ++ noir/noir-repo/test_programs/gates_report.sh | 6 +- noir/noir-repo/tooling/lsp/src/lib.rs | 3 +- .../tooling/lsp/src/notifications/mod.rs | 12 +- .../lsp/src/requests/code_lens_request.rs | 2 +- .../noir-repo/tooling/lsp/src/requests/mod.rs | 2 +- .../tooling/lsp/src/requests/rename.rs | 5 + .../tooling/lsp/src/requests/test_run.rs | 2 +- .../tooling/lsp/src/requests/tests.rs | 2 +- .../test_programs/struct_member/Nargo.toml | 6 + .../test_programs/struct_member/src/main.nr | 12 + noir/noir-repo/tooling/nargo_cli/build.rs | 3 +- .../tooling/nargo_cli/src/cli/check_cmd.rs | 11 +- .../tooling/nargo_cli/src/cli/export_cmd.rs | 1 + .../tooling/nargo_cli/src/cli/test_cmd.rs | 2 + .../tooling/nargo_cli/tests/stdlib-tests.rs | 2 +- 82 files changed, 1501 insertions(+), 396 deletions(-) create mode 100644 noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs create mode 100755 noir/noir-repo/scripts/bump-bb.sh create mode 100644 noir/noir-repo/test_programs/compile_failure/unary_not_on_field_type_variable/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/unary_not_on_field_type_variable/src/main.nr create mode 100644 noir/noir-repo/test_programs/execution_success/binary_operator_overloading/Nargo.toml rename noir/noir-repo/test_programs/execution_success/{operator_overloading => binary_operator_overloading}/Prover.toml (100%) rename noir/noir-repo/test_programs/execution_success/{operator_overloading => binary_operator_overloading}/src/main.nr (100%) rename noir/noir-repo/test_programs/execution_success/{operator_overloading => unary_operator_overloading}/Nargo.toml (70%) create mode 100644 noir/noir-repo/test_programs/execution_success/unary_operator_overloading/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/unary_operator_overloading/src/main.nr create mode 100644 noir/noir-repo/tooling/lsp/test_programs/struct_member/Nargo.toml create mode 100644 noir/noir-repo/tooling/lsp/test_programs/struct_member/src/main.nr diff --git a/.noir-sync-commit b/.noir-sync-commit index 3222858403e7..88f10e68a4d0 100644 --- a/.noir-sync-commit +++ b/.noir-sync-commit @@ -1 +1 @@ -bb6913ac53620fabd73e24ca1a2b1369225903ec +e59ff8c6a12978407be4f9f474d5208bdabb8c29 diff --git a/avm-transpiler/Cargo.lock b/avm-transpiler/Cargo.lock index 965e79489c1c..890073034ccb 100644 --- a/avm-transpiler/Cargo.lock +++ b/avm-transpiler/Cargo.lock @@ -694,6 +694,7 @@ name = "fm" version = "0.31.0" dependencies = [ "codespan-reporting", + "iter-extended", "serde", ] diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr index 7d660e11853f..943a9636acbf 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr @@ -32,15 +32,15 @@ impl EncryptedLogHeader { fn test_encrypted_log_header() { let address = AztecAddress::from_field(0xdeadbeef); let header = EncryptedLogHeader::new(address); - let secret = Scalar::new( - 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd, - 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06 - ); - let point = Point::new( - 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186, - 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e, - false - ); + let secret = Scalar { + lo: 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd, + hi: 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06 + }; + let point = Point { + x: 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186, + y: 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e, + is_infinite: false + }; let ciphertext = header.compute_ciphertext(secret, point); diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr index c7052bbbbe40..3caaaeb845f5 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr @@ -118,15 +118,15 @@ mod test { let storage_slot = 2; - let eph_sk = Scalar::new( - 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd, - 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06 - ); - let ivpk_app = Point::new( - 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186, - 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e, - false - ); + let eph_sk = Scalar { + lo: 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd, + hi: 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06 + }; + let ivpk_app = Point { + x: 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186, + y: 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e, + is_infinite: false + }; let body = EncryptedLogIncomingBody::from_note(note, storage_slot); @@ -217,16 +217,16 @@ mod test { fn test_encrypted_log_event_incoming_body() { let test_event = TestEvent { value0: 1, value1: 2, value2: 3 }; - let eph_sk = Scalar::new( - 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd, - 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06 - ); + let eph_sk = Scalar { + lo: 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd, + hi: 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06 + }; - let ivpk_app = Point::new( - 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186, - 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e, - false - ); + let ivpk_app = Point { + x: 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186, + y: 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e, + is_infinite: false + }; let randomness = 2; diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr index c63a54baa6c3..d3cc68d1d4ac 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr @@ -2,7 +2,6 @@ use dep::protocol_types::{ address::AztecAddress, scalar::Scalar, point::Point, constants::GENERATOR_INDEX__SYMMETRIC_KEY, hash::poseidon2_hash }; - use std::aes128::aes128_encrypt; use crate::keys::point_to_symmetric_key::point_to_symmetric_key; @@ -65,26 +64,27 @@ mod test { address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER, scalar::Scalar, point::Point, hash::poseidon2_hash }; + use std::embedded_curve_ops::fixed_base_scalar_mul as derive_public_key; use crate::context::PrivateContext; #[test] fn test_encrypted_log_outgoing_body() { - let eph_sk = Scalar::new( - 0x00000000000000000000000000000000d0d302ee245dfaf2807e604eec4715fe, - 0x000000000000000000000000000000000f096b423017226a18461115fa8d34bb - ); - let recipient_ivsk_app = Scalar::new( - 0x000000000000000000000000000000004828f8f95676ebb481df163f87fd4022, - 0x000000000000000000000000000000000f4d97c25d578f9348251a71ca17ae31 - ); - let sender_ovsk_app = Scalar::new( - 0x0000000000000000000000000000000074d2e28c6bc5176ac02cf7c7d36a444e, - 0x00000000000000000000000000000000089c6887cb1446d86c64e81afc78048b - ); - - let eph_pk = eph_sk.derive_public_key(); - let recipient_ivpk_app = recipient_ivsk_app.derive_public_key(); + let eph_sk = Scalar { + lo: 0x00000000000000000000000000000000d0d302ee245dfaf2807e604eec4715fe, + hi: 0x000000000000000000000000000000000f096b423017226a18461115fa8d34bb + }; + let recipient_ivsk_app = Scalar { + lo: 0x000000000000000000000000000000004828f8f95676ebb481df163f87fd4022, + hi: 0x000000000000000000000000000000000f4d97c25d578f9348251a71ca17ae31 + }; + let sender_ovsk_app = Scalar { + lo: 0x0000000000000000000000000000000074d2e28c6bc5176ac02cf7c7d36a444e, + hi: 0x00000000000000000000000000000000089c6887cb1446d86c64e81afc78048b + }; + + let eph_pk = derive_public_key(eph_sk); + let recipient_ivpk_app = derive_public_key(recipient_ivsk_app); let recipient = AztecAddress::from_field(0xdeadbeef); diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr index d0dbde5450c6..9141fcbe4aef 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr @@ -2,7 +2,7 @@ use dep::protocol_types::{ address::AztecAddress, scalar::Scalar, point::{Point, pub_key_to_bytes}, constants::{GENERATOR_INDEX__IVSK_M, GENERATOR_INDEX__OVSK_M}, hash::poseidon2_hash }; - +use std::embedded_curve_ops::fixed_base_scalar_mul as derive_public_key; use std::field::bytes32_to_field; use crate::oracle::unsafe_rand::unsafe_rand; @@ -25,7 +25,7 @@ pub fn compute_encrypted_event_log( ) -> [u8; OB] where Event: EventInterface { // @todo Need to draw randomness from the full domain of Fq not only Fr let eph_sk: Scalar = fr_to_fq(unsafe_rand()); - let eph_pk = eph_sk.derive_public_key(); + let eph_pk = derive_public_key(eph_sk); // TODO: (#7177) This value needs to be populated! let recipient = AztecAddress::from_field(0); @@ -82,7 +82,7 @@ pub fn compute_encrypted_note_log( ) -> [u8; M] where Note: NoteInterface { // @todo Need to draw randomness from the full domain of Fq not only Fr let eph_sk: Scalar = fr_to_fq(unsafe_rand()); - let eph_pk = eph_sk.derive_public_key(); + let eph_pk = derive_public_key(eph_sk); // TODO: (#7177) This value needs to be populated! let recipient = AztecAddress::from_field(0); @@ -142,10 +142,10 @@ fn fr_to_fq(r: Field) -> Scalar { low_bytes[16 + i] = r_bytes[i + 16]; } - let low = bytes32_to_field(low_bytes); - let high = bytes32_to_field(high_bytes); + let lo = bytes32_to_field(low_bytes); + let hi = bytes32_to_field(high_bytes); - Scalar::new(low, high) + Scalar { lo, hi } } fn compute_ivpk_app(ivpk: Point, contract_address: AztecAddress) -> Point { @@ -158,12 +158,12 @@ fn compute_ivpk_app(ivpk: Point, contract_address: AztecAddress) -> Point { assert((ivpk.x != 0) & (ivpk.y != 0), "ivpk is infinite"); let i = fr_to_fq(poseidon2_hash([contract_address.to_field(), ivpk.x, ivpk.y, GENERATOR_INDEX__IVSK_M])); - let I = i.derive_public_key(); + let I = derive_public_key(i); let embed_I = Point { x: I.x, y: I.y, is_infinite: false }; let embed_ivpk = Point { x: ivpk.x, y: ivpk.y, is_infinite: false }; let embed_result = embedded_curve_add(embed_I, embed_ivpk); - Point::new(embed_result.x, embed_result.y)*/ + Point { x: embed_result.x, embed_result.y)*/ } diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index f966b104d0a1..372e3a433a53 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -86,7 +86,7 @@ fn fetch_key_from_registry( let x_coordinate = x_coordinate_registry.get_value_in_private(header); let y_coordinate = y_coordinate_registry.get_value_in_private(header); - Point::new(x_coordinate, y_coordinate, false) + Point { x: x_coordinate, y: y_coordinate, is_infinite: false } } // Passes only when keys were not rotated - is expected to be called only when keys were not registered yet diff --git a/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr b/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr index caa3173443fe..b3e1c544dda5 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr @@ -19,15 +19,15 @@ pub fn point_to_symmetric_key(secret: Scalar, point: Point) -> [u8; 32] { #[test] fn check_point_to_symmetric_key() { // Value taken from "derive shared secret" test in encrypt_buffer.test.ts - let secret = Scalar::new( - 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd, - 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06 - ); - let point = Point::new( - 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186, - 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e, - false - ); + let secret = Scalar { + lo: 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd, + hi: 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06 + }; + let point = Point { + x: 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186, + y: 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e, + is_infinite: false + }; let key = point_to_symmetric_key(secret, point); // The following value gets updated when running encrypt_buffer.test.ts with AZTEC_GENERATE_TEST_DATA=1 diff --git a/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr b/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr index 9ad4c01e200b..ac53b7601fc8 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr @@ -96,10 +96,10 @@ impl Serialize for PublicKeys { impl Deserialize for PublicKeys { fn deserialize(serialized: [Field; PUBLIC_KEYS_LENGTH]) -> PublicKeys { PublicKeys { - npk_m: Point::new(serialized[0], serialized[1], serialized[2] as bool), - ivpk_m: Point::new(serialized[3], serialized[4], serialized[5] as bool), - ovpk_m: Point::new(serialized[6], serialized[7], serialized[8] as bool), - tpk_m: Point::new(serialized[9], serialized[10], serialized[11] as bool) + npk_m: Point { x:serialized[0], y:serialized[1], is_infinite: serialized[2] as bool }, + ivpk_m: Point { x:serialized[3], y: serialized[4], is_infinite: serialized[5] as bool }, + ovpk_m: Point { x:serialized[6], y: serialized[7], is_infinite: serialized[8] as bool }, + tpk_m: Point { x:serialized[9], y: serialized[10], is_infinite: serialized[11] as bool } } } } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr index d7bd87c0c034..92403bf9eae7 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr @@ -12,10 +12,10 @@ fn get_public_keys_and_partial_address(address: AztecAddress) -> (PublicKeys, Pa let result = get_public_keys_and_partial_address_oracle_wrapper(address); let keys = PublicKeys { - npk_m: Point::new(result[0], result[1], result[2] as bool), - ivpk_m: Point::new(result[3], result[4], result[5] as bool), - ovpk_m: Point::new(result[6], result[7], result[8] as bool), - tpk_m: Point::new(result[9], result[10], result[11] as bool) + npk_m: Point { x: result[0], y: result[1], is_infinite: result[2] as bool }, + ivpk_m: Point { x: result[3], y: result[4], is_infinite: result[5] as bool }, + ovpk_m: Point { x: result[6], y: result[7], is_infinite: result[8] as bool }, + tpk_m: Point { x: result[9], y: result[10], is_infinite: result[11] as bool } }; let partial_address = PartialAddress::from_field(result[12]); diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index 97aaec35ace1..f0d020e3c61a 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -37,6 +37,7 @@ contract Test { }; use dep::token_portal_content_hash_lib::{get_mint_private_content_hash, get_mint_public_content_hash}; use dep::value_note::value_note::ValueNote; + use std::embedded_curve_ops::fixed_base_scalar_mul as derive_public_key; use crate::test_note::TestNote; @@ -427,7 +428,7 @@ contract Test { recipient_ivpk_app: Point, ovsk_app: Scalar ) -> [u8; 176] { - let eph_pk = eph_sk.derive_public_key(); + let eph_pk = derive_public_key(eph_sk); EncryptedLogOutgoingBody::new(eph_sk, recipient, recipient_ivpk_app).compute_ciphertext(ovsk_app, eph_pk) } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr index 8d8ef785f207..a57531c8d7bc 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr @@ -290,7 +290,11 @@ mod tests { let remaining_nullifier_rr_index = builder.previous_kernel.add_read_request_for_pending_nullifier(1); let nullifier_rr = builder.previous_kernel.nullifier_read_requests.storage[remaining_nullifier_rr_index]; - let key_validation_index = builder.previous_kernel.add_request_for_key_validation(Point::new(1, 2, false), 27, GENERATOR_INDEX__OVSK_M); + let key_validation_index = builder.previous_kernel.add_request_for_key_validation( + Point { x: 1, y: 2, is_infinite: false }, + 27, + GENERATOR_INDEX__OVSK_M + ); let key_validation = builder.previous_kernel.scoped_key_validation_requests_and_generators.storage[key_validation_index]; // Check that they have been propagated to the next kernel diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr index 401968696894..20433ada5cf3 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr @@ -334,7 +334,11 @@ mod tests { #[test(should_fail_with="Non empty key validation requests")] fn non_empty_key_validations() { let mut builder = PrivateKernelTailInputsBuilder::new(); - let _void = builder.previous_kernel.add_request_for_key_validation(Point::new(1, 2, false), 27, GENERATOR_INDEX__IVSK_M); + let _void = builder.previous_kernel.add_request_for_key_validation( + Point { x: 1, y: 2, is_infinite: false }, + 27, + GENERATOR_INDEX__IVSK_M + ); builder.failed(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr index 6180ea6c315e..f093f0bd07f4 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr @@ -325,7 +325,11 @@ mod tests { #[test(should_fail_with="Non empty key validation requests")] fn non_empty_key_validations() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); - let _void = builder.previous_kernel.add_request_for_key_validation(Point::new(1, 2, false), 27, GENERATOR_INDEX__TSK_M); + let _void = builder.previous_kernel.add_request_for_key_validation( + Point { x: 1, y: 2, is_infinite: false }, + 27, + GENERATOR_INDEX__TSK_M + ); builder.failed(); } diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/key_validation_hint.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/key_validation_hint.nr index a682550ccb41..dd5cdd193a20 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/key_validation_hint.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/key_validation_hint.nr @@ -3,6 +3,7 @@ use dep::types::{ constants::MAX_KEY_VALIDATION_REQUESTS_PER_TX, scalar::Scalar, hash::poseidon2_hash, utils::arrays::filter_array_to_bounded_vec }; +use std::embedded_curve_ops::fixed_base_scalar_mul as derive_public_key; struct KeyValidationHint { sk_m: Scalar, @@ -44,7 +45,7 @@ pub fn reset_key_validation_requests( let sk_app_generator = request_and_generator.sk_app_generator; // First we check that derived public key matches master public key from request - let pk_m = sk_m.derive_public_key(); + let pk_m = derive_public_key(sk_m); assert( pk_m.eq(request.pk_m), "Failed to derive matching master public key from the secret key." ); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr index a6088696f7aa..eec4479a8726 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr @@ -35,7 +35,7 @@ impl Serialize for KeyValidationRequest { impl Deserialize for KeyValidationRequest { fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_LENGTH]) -> Self { Self { - pk_m: Point::new(fields[0], fields[1], fields[2] as bool), + pk_m: Point { x:fields[0], y: fields[1], is_infinite: fields[2] as bool}, sk_app: fields[3], } } diff --git a/noir/bb-version b/noir/bb-version index 8298bb08b2d5..620104d82084 100644 --- a/noir/bb-version +++ b/noir/bb-version @@ -1 +1 @@ -0.43.0 +0.46.1 diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs index 115ecbf7992a..5d749e709b34 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs @@ -360,7 +360,7 @@ mod tests { use std::collections::BTreeSet; use super::{ - opcodes::{BlackBoxFuncCall, ConstantOrWitnessEnum, FunctionInput}, + opcodes::{BlackBoxFuncCall, FunctionInput}, Circuit, Compression, Opcode, PublicInputs, }; use crate::{ diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs index 7c560a0a3463..6478f0c7a19e 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs @@ -520,7 +520,7 @@ mod tests { use crate::{circuit::Opcode, native_types::Witness}; use acir_field::{AcirField, FieldElement}; - use super::{BlackBoxFuncCall, ConstantOrWitnessEnum, FunctionInput}; + use super::{BlackBoxFuncCall, FunctionInput}; fn keccakf1600_opcode() -> Opcode { let inputs: Box<[FunctionInput; 25]> = diff --git a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs index 3a42cc41d479..3047ac002e86 100644 --- a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs +++ b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs @@ -14,7 +14,7 @@ use std::collections::BTreeSet; use acir::{ circuit::{ brillig::{BrilligBytecode, BrilligInputs, BrilligOutputs}, - opcodes::{BlackBoxFuncCall, BlockId, ConstantOrWitnessEnum, FunctionInput, MemOp}, + opcodes::{BlackBoxFuncCall, BlockId, FunctionInput, MemOp}, Circuit, Opcode, Program, PublicInputs, }, native_types::{Expression, Witness}, diff --git a/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs b/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs index 87a026148d78..b03b6715abe1 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs @@ -150,7 +150,7 @@ mod tests { use crate::compiler::optimizers::redundant_range::RangeOptimizer; use acir::{ circuit::{ - opcodes::{BlackBoxFuncCall, ConstantOrWitnessEnum, FunctionInput}, + opcodes::{BlackBoxFuncCall, FunctionInput}, Circuit, ExpressionWidth, Opcode, PublicInputs, }, native_types::{Expression, Witness}, diff --git a/noir/noir-repo/compiler/fm/Cargo.toml b/noir/noir-repo/compiler/fm/Cargo.toml index 1a356d93d896..b48f445be367 100644 --- a/noir/noir-repo/compiler/fm/Cargo.toml +++ b/noir/noir-repo/compiler/fm/Cargo.toml @@ -10,6 +10,7 @@ license.workspace = true [dependencies] codespan-reporting.workspace = true +iter-extended.workspace = true serde.workspace = true [dev-dependencies] diff --git a/noir/noir-repo/compiler/fm/src/lib.rs b/noir/noir-repo/compiler/fm/src/lib.rs index 2e52d802479b..37da29fc9820 100644 --- a/noir/noir-repo/compiler/fm/src/lib.rs +++ b/noir/noir-repo/compiler/fm/src/lib.rs @@ -7,6 +7,7 @@ mod file_map; pub use file_map::{File, FileId, FileMap, PathString}; +use iter_extended::vecmap; // Re-export for the lsp pub use codespan_reporting::files as codespan_files; @@ -103,6 +104,26 @@ impl FileManager { pub fn name_to_id(&self, file_name: PathBuf) -> Option { self.file_map.get_file_id(&PathString::from_path(file_name)) } + + /// Find a file by its path suffix, e.g. "src/main.nr" is a suffix of + /// "some_dir/package_name/src/main.nr"` + pub fn find_by_path_suffix(&self, suffix: &str) -> Result, Vec> { + let suffix_path: Vec<_> = Path::new(suffix).components().rev().collect(); + let results: Vec<_> = self + .path_to_id + .iter() + .filter(|(path, _id)| { + path.components().rev().zip(suffix_path.iter()).all(|(x, y)| &x == y) + }) + .collect(); + if results.is_empty() { + Ok(None) + } else if results.len() == 1 { + Ok(Some(*results[0].1)) + } else { + Err(vecmap(results, |(path, _id)| path.clone())) + } + } } pub trait NormalizePath { diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index 4ba9b85f967b..2b0769e30d4a 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -103,6 +103,11 @@ pub struct CompileOptions { #[arg(long, hide = true)] pub use_legacy: bool, + /// Enable printing results of comptime evaluation: provide a path suffix + /// for the module to debug, e.g. "package_name/src/main.nr" + #[arg(long)] + pub debug_comptime_in_file: Option, + /// Outputs the paths to any modified artifacts #[arg(long, hide = true)] pub show_artifact_paths: bool, @@ -258,12 +263,14 @@ pub fn check_crate( deny_warnings: bool, disable_macros: bool, use_legacy: bool, + debug_comptime_in_file: Option<&str>, ) -> CompilationResult<()> { let macros: &[&dyn MacroProcessor] = if disable_macros { &[] } else { &[&aztec_macros::AztecMacro as &dyn MacroProcessor] }; let mut errors = vec![]; - let diagnostics = CrateDefMap::collect_defs(crate_id, context, use_legacy, macros); + let diagnostics = + CrateDefMap::collect_defs(crate_id, context, use_legacy, debug_comptime_in_file, macros); errors.extend(diagnostics.into_iter().map(|(error, file_id)| { let diagnostic = CustomDiagnostic::from(&error); diagnostic.in_file(file_id) @@ -301,6 +308,7 @@ pub fn compile_main( options.deny_warnings, options.disable_macros, options.use_legacy, + options.debug_comptime_in_file.as_deref(), )?; let main = context.get_main_function(&crate_id).ok_or_else(|| { @@ -342,6 +350,7 @@ pub fn compile_contract( options.deny_warnings, options.disable_macros, options.use_legacy, + options.debug_comptime_in_file.as_deref(), )?; // TODO: We probably want to error if contracts is empty diff --git a/noir/noir-repo/compiler/noirc_driver/tests/stdlib_warnings.rs b/noir/noir-repo/compiler/noirc_driver/tests/stdlib_warnings.rs index 47ce893d2025..0e098d0d0877 100644 --- a/noir/noir-repo/compiler/noirc_driver/tests/stdlib_warnings.rs +++ b/noir/noir-repo/compiler/noirc_driver/tests/stdlib_warnings.rs @@ -25,7 +25,7 @@ fn stdlib_does_not_produce_constant_warnings() -> Result<(), ErrorsAndWarnings> let root_crate_id = prepare_crate(&mut context, file_name); let ((), warnings) = - noirc_driver::check_crate(&mut context, root_crate_id, false, false, false)?; + noirc_driver::check_crate(&mut context, root_crate_id, false, false, false, None)?; assert_eq!(warnings, Vec::new(), "stdlib is producing {} warnings", warnings.len()); diff --git a/noir/noir-repo/compiler/noirc_errors/src/reporter.rs b/noir/noir-repo/compiler/noirc_errors/src/reporter.rs index ea7c97b1f251..3ce0f268715c 100644 --- a/noir/noir-repo/compiler/noirc_errors/src/reporter.rs +++ b/noir/noir-repo/compiler/noirc_errors/src/reporter.rs @@ -19,6 +19,7 @@ pub enum DiagnosticKind { Error, Bug, Warning, + Info, } /// A count of errors that have been already reported to stderr @@ -37,30 +38,57 @@ impl CustomDiagnostic { } } - pub fn simple_error( + fn simple_with_kind( primary_message: String, secondary_message: String, secondary_span: Span, + kind: DiagnosticKind, ) -> CustomDiagnostic { CustomDiagnostic { message: primary_message, secondaries: vec![CustomLabel::new(secondary_message, secondary_span)], notes: Vec::new(), - kind: DiagnosticKind::Error, + kind, } } + pub fn simple_error( + primary_message: String, + secondary_message: String, + secondary_span: Span, + ) -> CustomDiagnostic { + Self::simple_with_kind( + primary_message, + secondary_message, + secondary_span, + DiagnosticKind::Error, + ) + } + pub fn simple_warning( primary_message: String, secondary_message: String, secondary_span: Span, ) -> CustomDiagnostic { - CustomDiagnostic { - message: primary_message, - secondaries: vec![CustomLabel::new(secondary_message, secondary_span)], - notes: Vec::new(), - kind: DiagnosticKind::Warning, - } + Self::simple_with_kind( + primary_message, + secondary_message, + secondary_span, + DiagnosticKind::Warning, + ) + } + + pub fn simple_info( + primary_message: String, + secondary_message: String, + secondary_span: Span, + ) -> CustomDiagnostic { + Self::simple_with_kind( + primary_message, + secondary_message, + secondary_span, + DiagnosticKind::Info, + ) } pub fn simple_bug( @@ -96,6 +124,10 @@ impl CustomDiagnostic { matches!(self.kind, DiagnosticKind::Warning) } + pub fn is_info(&self) -> bool { + matches!(self.kind, DiagnosticKind::Info) + } + pub fn is_bug(&self) -> bool { matches!(self.kind, DiagnosticKind::Bug) } @@ -191,6 +223,7 @@ fn convert_diagnostic( ) -> Diagnostic { let diagnostic = match (cd.kind, deny_warnings) { (DiagnosticKind::Warning, false) => Diagnostic::warning(), + (DiagnosticKind::Info, _) => Diagnostic::note(), (DiagnosticKind::Bug, ..) => Diagnostic::bug(), _ => Diagnostic::error(), }; diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs b/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs index 2b3288982575..2c7ec0f8e1ad 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs @@ -19,8 +19,6 @@ use serde::{Deserialize, Serialize}; pub enum RuntimeError { #[error(transparent)] InternalError(#[from] InternalError), - #[error("Index out of bounds, array has size {array_size}, but index was {index}")] - IndexOutOfBounds { index: usize, array_size: usize, call_stack: CallStack }, #[error("Range constraint of {num_bits} bits is too large for the Field size")] InvalidRangeConstraint { num_bits: u32, call_stack: CallStack }, #[error("The value `{value:?}` cannot fit into `{typ}` which has range `{range}`")] @@ -145,7 +143,6 @@ impl RuntimeError { | InternalError::UndeclaredAcirVar { call_stack } | InternalError::Unexpected { call_stack, .. }, ) - | RuntimeError::IndexOutOfBounds { call_stack, .. } | RuntimeError::InvalidRangeConstraint { call_stack, .. } | RuntimeError::TypeConversion { call_stack, .. } | RuntimeError::UnInitialized { call_stack, .. } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index cfcc7a9a9976..1bdc9aaf4eb1 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -975,6 +975,8 @@ impl<'a> Context<'a> { .into()) } }; + // Ensure that array id is fully resolved. + let array = dfg.resolve(array); let array_id = dfg.resolve(array); let array_typ = dfg.type_of_value(array_id); @@ -992,7 +994,6 @@ impl<'a> Context<'a> { // If we find one, we will use it when computing the index under the enable_side_effect predicate // If not, array_get(..) will use a fallback costing one multiplication in the worst case. // cf. https://github.com/noir-lang/noir/pull/4971 - // For simplicity we compute the offset only for simple arrays let is_simple_array = dfg.instruction_results(instruction).len() == 1 && can_omit_element_sizes_array(&array_typ); @@ -1085,45 +1086,30 @@ impl<'a> Context<'a> { } }; - let side_effects_always_enabled = - self.acir_context.is_constant_one(&self.current_side_effects_enabled_var); - let index_out_of_bounds = index >= array_size; - - // Note that the value of `side_effects_always_enabled` doesn't affect the value which we return here for valid - // indices, just whether we return an error for invalid indices at compile time or defer until execution. - match (side_effects_always_enabled, index_out_of_bounds) { - (true, false) => { - let value = match store_value { - Some(store_value) => AcirValue::Array(array.update(index, store_value)), - None => array[index].clone(), - }; + if index >= array_size { + return Ok(false); + } + + if let Some(store_value) = store_value { + let side_effects_always_enabled = + self.acir_context.is_constant_one(&self.current_side_effects_enabled_var); + if side_effects_always_enabled { + // If we know that this write will always occur then we can perform it at compile time. + let value = AcirValue::Array(array.update(index, store_value)); self.define_result(dfg, instruction, value); Ok(true) + } else { + // If a predicate is applied however we must wait until runtime. + Ok(false) } - (false, false) => { - if store_value.is_none() { - // If there is a predicate and the index is not out of range, we can optimistically perform the - // read at compile time as if the predicate is true. - // - // This is as if the predicate is false, any side-effects will be disabled so the value returned - // will not affect the rest of execution. - self.define_result(dfg, instruction, array[index].clone()); - Ok(true) - } else { - // We do not do this for a array writes however. - Ok(false) - } - } - - // Report the error if side effects are enabled. - (true, true) => { - let call_stack = self.acir_context.get_call_stack(); - Err(RuntimeError::IndexOutOfBounds { index, array_size, call_stack }) - } - // Index is out of bounds but predicate may result in this array operation being skipped - // so we don't return an error now. - (false, true) => Ok(false), + } else { + // If the index is not out of range, we can optimistically perform the read at compile time + // as if the predicate were true. This is as if the predicate were to resolve to false then + // the result should not affect the rest of circuit execution. + let value = array[index].clone(); + self.define_result(dfg, instruction, value); + Ok(true) } } @@ -1138,13 +1124,14 @@ impl<'a> Context<'a> { /// It is a dummy value because in the case of a false predicate, the value stored at the requested index will be itself. fn convert_array_operation_inputs( &mut self, - array: ValueId, + array_id: ValueId, dfg: &DataFlowGraph, index: ValueId, store_value: Option, offset: usize, ) -> Result<(AcirVar, Option), RuntimeError> { - let (array_id, array_typ, block_id) = self.check_array_is_initialized(array, dfg)?; + let array_typ = dfg.type_of_value(array_id); + let block_id = self.ensure_array_is_initialized(array_id, dfg)?; let index_var = self.convert_numeric_value(index, dfg)?; let index_var = self.get_flattened_index(&array_typ, array_id, index_var, dfg)?; @@ -1263,22 +1250,22 @@ impl<'a> Context<'a> { dfg: &DataFlowGraph, mut index_side_effect: bool, ) -> Result { - let (array_id, _, block_id) = self.check_array_is_initialized(array, dfg)?; + let block_id = self.ensure_array_is_initialized(array, dfg)?; let results = dfg.instruction_results(instruction); let res_typ = dfg.type_of_value(results[0]); // Get operations to call-data parameters are replaced by a get to the call-data-bus array if let Some(call_data) = self.data_bus.call_data { - if self.data_bus.call_data_map.contains_key(&array_id) { + if self.data_bus.call_data_map.contains_key(&array) { // TODO: the block_id of call-data must be notified to the backend // TODO: should we do the same for return-data? let type_size = res_typ.flattened_size(); let type_size = self.acir_context.add_constant(FieldElement::from(type_size as i128)); let offset = self.acir_context.mul_var(var_index, type_size)?; - let bus_index = self.acir_context.add_constant(FieldElement::from( - self.data_bus.call_data_map[&array_id] as i128, - )); + let bus_index = self + .acir_context + .add_constant(FieldElement::from(self.data_bus.call_data_map[&array] as i128)); let new_index = self.acir_context.add_var(offset, bus_index)?; return self.array_get(instruction, call_data, new_index, dfg, index_side_effect); } @@ -1292,8 +1279,7 @@ impl<'a> Context<'a> { let mut value = self.array_get_value(&res_typ, block_id, &mut var_index)?; if let AcirValue::Var(value_var, typ) = &value { - let array_id = dfg.resolve(array_id); - let array_typ = dfg.type_of_value(array_id); + let array_typ = dfg.type_of_value(array); if let (Type::Numeric(numeric_type), AcirType::NumericType(num)) = (array_typ.first(), typ) { @@ -1377,7 +1363,7 @@ impl<'a> Context<'a> { } }; - let (array_id, array_typ, block_id) = self.check_array_is_initialized(array, dfg)?; + let block_id = self.ensure_array_is_initialized(array, dfg)?; // Every array has a length in its type, so we fetch that from // the SSA IR. @@ -1386,10 +1372,11 @@ impl<'a> Context<'a> { // However, this size is simply the capacity of a slice. The capacity is dependent upon the witness // and may contain data for which we want to restrict access. The true slice length is tracked in a // a separate SSA value and restrictions on slice indices should be generated elsewhere in the SSA. + let array_typ = dfg.type_of_value(array); let array_len = if !array_typ.contains_slice_element() { array_typ.flattened_size() } else { - self.flattened_slice_size(array_id, dfg) + self.flattened_slice_size(array, dfg) }; // Since array_set creates a new array, we create a new block ID for this @@ -1412,18 +1399,13 @@ impl<'a> Context<'a> { self.array_set_value(&store_value, result_block_id, &mut var_index)?; let element_type_sizes = if !can_omit_element_sizes_array(&array_typ) { - let acir_value = self.convert_value(array_id, dfg); - Some(self.init_element_type_sizes_array( - &array_typ, - array_id, - Some(&acir_value), - dfg, - )?) + let acir_value = self.convert_value(array, dfg); + Some(self.init_element_type_sizes_array(&array_typ, array, Some(&acir_value), dfg)?) } else { None }; - let value_types = self.convert_value(array_id, dfg).flat_numeric_types(); + let value_types = self.convert_value(array, dfg).flat_numeric_types(); // Compiler sanity check assert_eq!(value_types.len(), array_len, "ICE: The length of the flattened type array should match the length of the dynamic array"); @@ -1469,37 +1451,33 @@ impl<'a> Context<'a> { Ok(()) } - fn check_array_is_initialized( + fn ensure_array_is_initialized( &mut self, array: ValueId, dfg: &DataFlowGraph, - ) -> Result<(ValueId, Type, BlockId), RuntimeError> { - // Fetch the internal SSA ID for the array - let array_id = dfg.resolve(array); - - let array_typ = dfg.type_of_value(array_id); - + ) -> Result { // Use the SSA ID to get or create its block ID - let block_id = self.block_id(&array_id); + let block_id = self.block_id(&array); // Check if the array has already been initialized in ACIR gen // if not, we initialize it using the values from SSA let already_initialized = self.initialized_arrays.contains(&block_id); if !already_initialized { - let value = &dfg[array_id]; + let value = &dfg[array]; match value { Value::Array { .. } | Value::Instruction { .. } => { - let value = self.convert_value(array_id, dfg); + let value = self.convert_value(array, dfg); + let array_typ = dfg.type_of_value(array); let len = if !array_typ.contains_slice_element() { array_typ.flattened_size() } else { - self.flattened_slice_size(array_id, dfg) + self.flattened_slice_size(array, dfg) }; self.initialize_array(block_id, len, Some(value))?; } _ => { return Err(InternalError::General { - message: format!("Array {array_id} should be initialized"), + message: format!("Array {array} should be initialized"), call_stack: self.acir_context.get_call_stack(), } .into()); @@ -1507,7 +1485,7 @@ impl<'a> Context<'a> { } } - Ok((array_id, array_typ, block_id)) + Ok(block_id) } fn init_element_type_sizes_array( @@ -1761,7 +1739,7 @@ impl<'a> Context<'a> { /// Converts an SSA terminator's return values into their ACIR representations fn get_num_return_witnesses( - &mut self, + &self, terminator: &TerminatorInstruction, dfg: &DataFlowGraph, ) -> usize { @@ -1815,7 +1793,7 @@ impl<'a> Context<'a> { has_constant_return |= self.acir_context.is_constant(&acir_var); if is_databus { // We do not return value for the data bus. - self.check_array_is_initialized( + self.ensure_array_is_initialized( self.data_bus.return_data.expect( "`is_databus == true` implies `data_bus.return_data` is `Some`", ), @@ -2182,8 +2160,9 @@ impl<'a> Context<'a> { Ok(vec![AcirValue::Var(self.acir_context.add_constant(len), AcirType::field())]) } Intrinsic::AsSlice => { - let (slice_contents, slice_typ, block_id) = - self.check_array_is_initialized(arguments[0], dfg)?; + let slice_contents = arguments[0]; + let slice_typ = dfg.type_of_value(slice_contents); + let block_id = self.ensure_array_is_initialized(slice_contents, dfg)?; assert!(!slice_typ.is_nested_slice(), "ICE: Nested slice used in ACIR generation"); let result_block_id = self.block_id(&result_ids[1]); @@ -2227,8 +2206,9 @@ impl<'a> Context<'a> { Intrinsic::SlicePushBack => { // arguments = [slice_length, slice_contents, ...elements_to_push] let slice_length = self.convert_value(arguments[0], dfg).into_var()?; - let (slice_contents, slice_typ, _) = - self.check_array_is_initialized(arguments[1], dfg)?; + let slice_contents = arguments[1]; + let slice_typ = dfg.type_of_value(slice_contents); + assert!(!slice_typ.is_nested_slice(), "ICE: Nested slice used in ACIR generation"); let slice = self.convert_value(slice_contents, dfg); @@ -2294,9 +2274,8 @@ impl<'a> Context<'a> { Intrinsic::SlicePushFront => { // arguments = [slice_length, slice_contents, ...elements_to_push] let slice_length = self.convert_value(arguments[0], dfg).into_var()?; - - let (slice_contents, slice_typ, _) = - self.check_array_is_initialized(arguments[1], dfg)?; + let slice_contents = arguments[1]; + let slice_typ = dfg.type_of_value(slice_contents); assert!(!slice_typ.is_nested_slice(), "ICE: Nested slice used in ACIR generation"); let slice: AcirValue = self.convert_value(slice_contents, dfg); @@ -2359,6 +2338,7 @@ impl<'a> Context<'a> { Intrinsic::SlicePopBack => { // arguments = [slice_length, slice_contents] let slice_length = self.convert_value(arguments[0], dfg).into_var()?; + let slice_contents = arguments[1]; let one = self.acir_context.add_constant(FieldElement::one()); let new_slice_length = self.acir_context.sub_var(slice_length, one)?; @@ -2367,8 +2347,8 @@ impl<'a> Context<'a> { // the elements stored at that index will no longer be able to be accessed. let mut var_index = new_slice_length; - let (slice_contents, slice_typ, block_id) = - self.check_array_is_initialized(arguments[1], dfg)?; + let slice_typ = dfg.type_of_value(slice_contents); + let block_id = self.ensure_array_is_initialized(slice_contents, dfg)?; assert!(!slice_typ.is_nested_slice(), "ICE: Nested slice used in ACIR generation"); let mut popped_elements = Vec::new(); @@ -2393,9 +2373,11 @@ impl<'a> Context<'a> { Intrinsic::SlicePopFront => { // arguments = [slice_length, slice_contents] let slice_length = self.convert_value(arguments[0], dfg).into_var()?; + let slice_contents = arguments[1]; + + let slice_typ = dfg.type_of_value(slice_contents); + let block_id = self.ensure_array_is_initialized(slice_contents, dfg)?; - let (slice_contents, slice_typ, block_id) = - self.check_array_is_initialized(arguments[1], dfg)?; assert!(!slice_typ.is_nested_slice(), "ICE: Nested slice used in ACIR generation"); let one = self.acir_context.add_constant(FieldElement::one()); @@ -2434,9 +2416,11 @@ impl<'a> Context<'a> { Intrinsic::SliceInsert => { // arguments = [slice_length, slice_contents, insert_index, ...elements_to_insert] let slice_length = self.convert_value(arguments[0], dfg).into_var()?; + let slice_contents = arguments[1]; + + let slice_typ = dfg.type_of_value(slice_contents); + let block_id = self.ensure_array_is_initialized(slice_contents, dfg)?; - let (slice_contents, slice_typ, block_id) = - self.check_array_is_initialized(arguments[1], dfg)?; assert!(!slice_typ.is_nested_slice(), "ICE: Nested slice used in ACIR generation"); let slice = self.convert_value(slice_contents, dfg); @@ -2573,9 +2557,11 @@ impl<'a> Context<'a> { Intrinsic::SliceRemove => { // arguments = [slice_length, slice_contents, remove_index] let slice_length = self.convert_value(arguments[0], dfg).into_var()?; + let slice_contents = arguments[1]; + + let slice_typ = dfg.type_of_value(slice_contents); + let block_id = self.ensure_array_is_initialized(slice_contents, dfg)?; - let (slice_contents, slice_typ, block_id) = - self.check_array_is_initialized(arguments[1], dfg)?; assert!(!slice_typ.is_nested_slice(), "ICE: Nested slice used in ACIR generation"); let slice = self.convert_value(slice_contents, dfg); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs index b08283a9cebb..8cbae732ef96 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs @@ -288,25 +288,33 @@ impl Instruction { } /// Indicates if the instruction can be safely replaced with the results of another instruction with the same inputs. - pub(crate) fn can_be_deduplicated(&self, dfg: &DataFlowGraph) -> bool { + /// If `deduplicate_with_predicate` is set, we assume we're deduplicating with the instruction + /// and its predicate, rather than just the instruction. Setting this means instructions that + /// rely on predicates can be deduplicated as well. + pub(crate) fn can_be_deduplicated( + &self, + dfg: &DataFlowGraph, + deduplicate_with_predicate: bool, + ) -> bool { use Instruction::*; match self { // These either have side-effects or interact with memory - Constrain(..) - | EnableSideEffects { .. } + EnableSideEffects { .. } | Allocate | Load { .. } | Store { .. } | IncrementRc { .. } - | DecrementRc { .. } - | RangeCheck { .. } => false, + | DecrementRc { .. } => false, Call { func, .. } => match dfg[*func] { Value::Intrinsic(intrinsic) => !intrinsic.has_side_effects(), _ => false, }, + // We can deduplicate these instructions if we know the predicate is also the same. + Constrain(..) | RangeCheck { .. } => deduplicate_with_predicate, + // These can have different behavior depending on the EnableSideEffectsIf context. // Replacing them with a similar instruction potentially enables replacing an instruction // with one that was disabled. See @@ -317,7 +325,9 @@ impl Instruction { | Truncate { .. } | IfElse { .. } | ArrayGet { .. } - | ArraySet { .. } => !self.requires_acir_gen_predicate(dfg), + | ArraySet { .. } => { + deduplicate_with_predicate || !self.requires_acir_gen_predicate(dfg) + } } } @@ -372,7 +382,7 @@ impl Instruction { } /// If true the instruction will depends on enable_side_effects context during acir-gen - fn requires_acir_gen_predicate(&self, dfg: &DataFlowGraph) -> bool { + pub(crate) fn requires_acir_gen_predicate(&self, dfg: &DataFlowGraph) -> bool { match self { Instruction::Binary(binary) if matches!(binary.operator, BinaryOp::Div | BinaryOp::Mod) => diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs index d7cd366e9afb..160105d27e6b 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs @@ -87,12 +87,16 @@ struct Context { block_queue: Vec, } +/// HashMap from (Instruction, side_effects_enabled_var) to the results of the instruction. +/// Stored as a two-level map to avoid cloning Instructions during the `.get` call. +type InstructionResultCache = HashMap, Vec>>; + impl Context { fn fold_constants_in_block(&mut self, function: &mut Function, block: BasicBlockId) { let instructions = function.dfg[block].take_instructions(); // Cache of instructions without any side-effects along with their outputs. - let mut cached_instruction_results: HashMap> = HashMap::default(); + let mut cached_instruction_results = HashMap::default(); // Contains sets of values which are constrained to be equivalent to each other. // @@ -124,7 +128,7 @@ impl Context { dfg: &mut DataFlowGraph, block: BasicBlockId, id: InstructionId, - instruction_result_cache: &mut HashMap>, + instruction_result_cache: &mut InstructionResultCache, constraint_simplification_mappings: &mut HashMap>, side_effects_enabled_var: &mut ValueId, ) { @@ -134,7 +138,9 @@ impl Context { let old_results = dfg.instruction_results(id).to_vec(); // If a copy of this instruction exists earlier in the block, then reuse the previous results. - if let Some(cached_results) = instruction_result_cache.get(&instruction) { + if let Some(cached_results) = + Self::get_cached(dfg, instruction_result_cache, &instruction, *side_effects_enabled_var) + { Self::replace_result_ids(dfg, &old_results, cached_results); return; } @@ -150,6 +156,7 @@ impl Context { dfg, instruction_result_cache, constraint_simplification_mapping, + *side_effects_enabled_var, ); // If we just inserted an `Instruction::EnableSideEffects`, we need to update `side_effects_enabled_var` @@ -224,8 +231,9 @@ impl Context { instruction: Instruction, instruction_results: Vec, dfg: &DataFlowGraph, - instruction_result_cache: &mut HashMap>, + instruction_result_cache: &mut InstructionResultCache, constraint_simplification_mapping: &mut HashMap, + side_effects_enabled_var: ValueId, ) { if self.use_constraint_info { // If the instruction was a constraint, then create a link between the two `ValueId`s @@ -258,8 +266,15 @@ impl Context { // If the instruction doesn't have side-effects and if it won't interact with enable_side_effects during acir_gen, // we cache the results so we can reuse them if the same instruction appears again later in the block. - if instruction.can_be_deduplicated(dfg) { - instruction_result_cache.insert(instruction, instruction_results); + if instruction.can_be_deduplicated(dfg, self.use_constraint_info) { + let use_predicate = + self.use_constraint_info && instruction.requires_acir_gen_predicate(dfg); + let predicate = use_predicate.then_some(side_effects_enabled_var); + + instruction_result_cache + .entry(instruction) + .or_default() + .insert(predicate, instruction_results); } } @@ -273,6 +288,25 @@ impl Context { dfg.set_value_from_id(*old_result, *new_result); } } + + fn get_cached<'a>( + dfg: &DataFlowGraph, + instruction_result_cache: &'a mut InstructionResultCache, + instruction: &Instruction, + side_effects_enabled_var: ValueId, + ) -> Option<&'a Vec> { + let results_for_instruction = instruction_result_cache.get(instruction); + + // See if there's a cached version with no predicate first + if let Some(results) = results_for_instruction.and_then(|map| map.get(&None)) { + return Some(results); + } + + let predicate = + instruction.requires_acir_gen_predicate(dfg).then_some(side_effects_enabled_var); + + results_for_instruction.and_then(|map| map.get(&predicate)) + } } #[cfg(test)] @@ -725,4 +759,86 @@ mod test { let ending_instruction_count = instructions.len(); assert_eq!(starting_instruction_count, ending_instruction_count); } + + #[test] + fn deduplicate_instructions_with_predicates() { + // fn main f0 { + // b0(v0: bool, v1: bool, v2: [u32; 2]): + // enable_side_effects v0 + // v3 = array_get v2, index u32 0 + // v4 = array_set v2, index u32 1, value: u32 2 + // v5 = array_get v4, index u32 0 + // constrain_eq v3, v5 + // enable_side_effects v1 + // v6 = array_get v2, index u32 0 + // v7 = array_set v2, index u32 1, value: u32 2 + // v8 = array_get v7, index u32 0 + // constrain_eq v6, v8 + // enable_side_effects v0 + // v9 = array_get v2, index u32 0 + // v10 = array_set v2, index u32 1, value: u32 2 + // v11 = array_get v10, index u32 0 + // constrain_eq v9, v11 + // } + let main_id = Id::test_new(0); + + // Compiling main + let mut builder = FunctionBuilder::new("main".into(), main_id); + + let v0 = builder.add_parameter(Type::bool()); + let v1 = builder.add_parameter(Type::bool()); + let v2 = builder.add_parameter(Type::Array(Rc::new(vec![Type::field()]), 2)); + + let zero = builder.numeric_constant(0u128, Type::length_type()); + let one = builder.numeric_constant(1u128, Type::length_type()); + let two = builder.numeric_constant(2u128, Type::length_type()); + + builder.insert_enable_side_effects_if(v0); + let v3 = builder.insert_array_get(v2, zero, Type::length_type()); + let v4 = builder.insert_array_set(v2, one, two); + let v5 = builder.insert_array_get(v4, zero, Type::length_type()); + builder.insert_constrain(v3, v5, None); + + builder.insert_enable_side_effects_if(v1); + let v6 = builder.insert_array_get(v2, zero, Type::length_type()); + let v7 = builder.insert_array_set(v2, one, two); + let v8 = builder.insert_array_get(v7, zero, Type::length_type()); + builder.insert_constrain(v6, v8, None); + + // We expect all these instructions after the 'enable side effects' instruction to be removed. + builder.insert_enable_side_effects_if(v0); + let v9 = builder.insert_array_get(v2, zero, Type::length_type()); + let v10 = builder.insert_array_set(v2, one, two); + let v11 = builder.insert_array_get(v10, zero, Type::length_type()); + builder.insert_constrain(v9, v11, None); + + let ssa = builder.finish(); + println!("{ssa}"); + + let main = ssa.main(); + let instructions = main.dfg[main.entry_block()].instructions(); + assert_eq!(instructions.len(), 15); + + // Expected output: + // + // fn main f0 { + // b0(v0: bool, v1: bool, v2: [Field; 2]): + // enable_side_effects v0 + // v3 = array_get v2, index Field 0 + // v4 = array_set v2, index Field 1, value: Field 2 + // v5 = array_get v4, index Field 0 + // constrain_eq v3, v5 + // enable_side_effects v1 + // v7 = array_set v2, index Field 1, value: Field 2 + // v8 = array_get v7, index Field 0 + // constrain_eq v3, v8 + // enable_side_effects v0 + // } + let ssa = ssa.fold_constants_using_constraints(); + println!("{ssa}"); + + let main = ssa.main(); + let instructions = main.dfg[main.entry_block()].instructions(); + assert_eq!(instructions.len(), 10); + } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs index ad79af4e63d1..5cda87872416 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs @@ -9,25 +9,25 @@ use crate::{ UnresolvedTypeExpression, }, hir::{ - comptime::{self, Interpreter, InterpreterError}, + comptime::{self, InterpreterError}, resolution::{errors::ResolverError, resolver::LambdaContext}, type_check::TypeCheckError, }, hir_def::{ expr::{ HirArrayLiteral, HirBinaryOp, HirBlockExpression, HirCallExpression, HirCastExpression, - HirConstructorExpression, HirIfExpression, HirIndexExpression, HirInfixExpression, - HirLambda, HirMemberAccess, HirMethodCallExpression, HirMethodReference, - HirPrefixExpression, + HirConstructorExpression, HirExpression, HirIfExpression, HirIndexExpression, + HirInfixExpression, HirLambda, HirMemberAccess, HirMethodCallExpression, + HirMethodReference, HirPrefixExpression, }, traits::TraitConstraint, }, macros_api::{ - BlockExpression, CallExpression, CastExpression, Expression, ExpressionKind, HirExpression, - HirLiteral, HirStatement, Ident, IndexExpression, Literal, MemberAccessExpression, + BlockExpression, CallExpression, CastExpression, Expression, ExpressionKind, HirLiteral, + HirStatement, Ident, IndexExpression, Literal, MemberAccessExpression, MethodCallExpression, PrefixExpression, }, - node_interner::{DefinitionKind, ExprId, FuncId, ReferenceId}, + node_interner::{DefinitionKind, ExprId, FuncId, ReferenceId, TraitMethodId}, token::Tokens, QuotedType, Shared, StructType, Type, }; @@ -39,7 +39,7 @@ impl<'context> Elaborator<'context> { let (hir_expr, typ) = match expr.kind { ExpressionKind::Literal(literal) => self.elaborate_literal(literal, expr.span), ExpressionKind::Block(block) => self.elaborate_block(block), - ExpressionKind::Prefix(prefix) => self.elaborate_prefix(*prefix), + ExpressionKind::Prefix(prefix) => return self.elaborate_prefix(*prefix), ExpressionKind::Index(index) => self.elaborate_index(*index), ExpressionKind::Call(call) => self.elaborate_call(*call, expr.span), ExpressionKind::MethodCall(call) => self.elaborate_method_call(*call, expr.span), @@ -227,11 +227,22 @@ impl<'context> Elaborator<'context> { (HirExpression::Literal(HirLiteral::FmtStr(str, fmt_str_idents)), typ) } - fn elaborate_prefix(&mut self, prefix: PrefixExpression) -> (HirExpression, Type) { + fn elaborate_prefix(&mut self, prefix: PrefixExpression) -> (ExprId, Type) { let span = prefix.rhs.span; let (rhs, rhs_type) = self.elaborate_expression(prefix.rhs); - let ret_type = self.type_check_prefix_operand(&prefix.operator, &rhs_type, span); - (HirExpression::Prefix(HirPrefixExpression { operator: prefix.operator, rhs }), ret_type) + let trait_id = self.interner.get_prefix_operator_trait_method(&prefix.operator); + + let operator = prefix.operator; + let expr = + HirExpression::Prefix(HirPrefixExpression { operator, rhs, trait_method_id: trait_id }); + let expr_id = self.interner.push_expr(expr); + self.interner.push_expr_location(expr_id, span, self.file); + + let result = self.prefix_operand_type_rules(&operator, &rhs_type, span); + let typ = self.handle_operand_type_rules_result(result, &rhs_type, trait_id, expr_id, span); + + self.interner.push_expr_type(expr_id, typ.clone()); + (expr_id, typ) } fn elaborate_index(&mut self, index_expr: IndexExpression) -> (HirExpression, Type) { @@ -440,8 +451,13 @@ impl<'context> Elaborator<'context> { let mut unseen_fields = struct_type.borrow().field_names(); for (field_name, field) in fields { - let expected_type = field_types.iter().find(|(name, _)| name == &field_name.0.contents); - let expected_type = expected_type.map(|(_, typ)| typ).unwrap_or(&Type::Error); + let expected_field_with_index = field_types + .iter() + .enumerate() + .find(|(_, (name, _))| name == &field_name.0.contents); + let expected_index = expected_field_with_index.map(|(index, _)| index); + let expected_type = + expected_field_with_index.map(|(_, (_, typ))| typ).unwrap_or(&Type::Error); let field_span = field.span; let (resolved, field_type) = self.elaborate_expression(field); @@ -468,6 +484,14 @@ impl<'context> Elaborator<'context> { }); } + if let Some(expected_index) = expected_index { + let struct_id = struct_type.borrow().id; + let referenced = ReferenceId::StructMember(struct_id, expected_index); + let reference = + ReferenceId::Reference(Location::new(field_name.span(), self.file), false); + self.interner.add_reference(referenced, reference); + } + ret.push((field_name, resolved)); } @@ -489,10 +513,11 @@ impl<'context> Elaborator<'context> { ) -> (ExprId, Type) { let (lhs, lhs_type) = self.elaborate_expression(access.lhs); let rhs = access.rhs; + let rhs_span = rhs.span(); // `is_offset` is only used when lhs is a reference and we want to return a reference to rhs let access = HirMemberAccess { lhs, rhs, is_offset: false }; let expr_id = self.intern_expr(HirExpression::MemberAccess(access.clone()), span); - let typ = self.type_check_member_access(access, expr_id, lhs_type, span); + let typ = self.type_check_member_access(access, expr_id, lhs_type, rhs_span); self.interner.push_expr_type(expr_id, typ.clone()); (expr_id, typ) } @@ -527,19 +552,38 @@ impl<'context> Elaborator<'context> { let expr_id = self.interner.push_expr(expr); self.interner.push_expr_location(expr_id, span, self.file); - let typ = match self.infix_operand_type_rules(&lhs_type, &operator, &rhs_type, span) { + let result = self.infix_operand_type_rules(&lhs_type, &operator, &rhs_type, span); + let typ = + self.handle_operand_type_rules_result(result, &lhs_type, Some(trait_id), expr_id, span); + + self.interner.push_expr_type(expr_id, typ.clone()); + (expr_id, typ) + } + + fn handle_operand_type_rules_result( + &mut self, + result: Result<(Type, bool), TypeCheckError>, + operand_type: &Type, + trait_id: Option, + expr_id: ExprId, + span: Span, + ) -> Type { + match result { Ok((typ, use_impl)) => { if use_impl { + let trait_id = + trait_id.expect("ice: expected some trait_id when use_impl is true"); + // Delay checking the trait constraint until the end of the function. // Checking it now could bind an unbound type variable to any type // that implements the trait. let constraint = TraitConstraint { - typ: lhs_type.clone(), + typ: operand_type.clone(), trait_id: trait_id.trait_id, trait_generics: Vec::new(), }; self.push_trait_constraint(constraint, expr_id); - self.type_check_operator_method(expr_id, trait_id, &lhs_type, span); + self.type_check_operator_method(expr_id, trait_id, operand_type, span); } typ } @@ -547,10 +591,7 @@ impl<'context> Elaborator<'context> { self.push_err(error); Type::Error } - }; - - self.interner.push_expr_type(expr_id, typ.clone()); - (expr_id, typ) + } } fn elaborate_if(&mut self, if_expr: IfExpression) -> (HirExpression, Type) { @@ -660,12 +701,20 @@ impl<'context> Elaborator<'context> { // call is not yet solved for. self.function_context.push(Default::default()); let (block, _typ) = self.elaborate_block_expression(block); - self.check_and_pop_function_context(); - let mut interpreter = - Interpreter::new(self.interner, &mut self.comptime_scopes, self.crate_id); + self.check_and_pop_function_context(); + let mut interpreter_errors = vec![]; + let mut interpreter = self.setup_interpreter(&mut interpreter_errors); let value = interpreter.evaluate_block(block); - self.inline_comptime_value(value, span) + self.include_interpreter_errors(interpreter_errors); + let (id, typ) = self.inline_comptime_value(value, span); + + let location = self.interner.id_location(id); + self.debug_comptime(location, |interner| { + interner.expression(&id).to_display_ast(interner, location.span).kind + }); + + (id, typ) } pub(super) fn inline_comptime_value( @@ -736,9 +785,9 @@ impl<'context> Elaborator<'context> { } }; - let mut interpreter = - Interpreter::new(self.interner, &mut self.comptime_scopes, self.crate_id); - + let file = self.file; + let mut interpreter_errors = vec![]; + let mut interpreter = self.setup_interpreter(&mut interpreter_errors); let mut comptime_args = Vec::new(); let mut errors = Vec::new(); @@ -748,17 +797,19 @@ impl<'context> Elaborator<'context> { let location = interpreter.interner.expr_location(&argument); comptime_args.push((arg, location)); } - Err(error) => errors.push((error.into(), self.file)), + Err(error) => errors.push((error.into(), file)), } } + let bindings = interpreter.interner.get_instantiation_bindings(func).clone(); + let result = interpreter.call_function(function, comptime_args, bindings, location); + self.include_interpreter_errors(interpreter_errors); + if !errors.is_empty() { self.errors.append(&mut errors); return None; } - let bindings = interpreter.interner.get_instantiation_bindings(func).clone(); - let result = interpreter.call_function(function, comptime_args, bindings, location); let (expr_id, typ) = self.inline_comptime_value(result, location.span); Some((self.interner.expression(&expr_id), typ)) } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs index 6104da582a71..e1d104c4971c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs @@ -1,5 +1,6 @@ use std::{ collections::{BTreeMap, BTreeSet}, + fmt::Display, rc::Rc, }; @@ -157,6 +158,9 @@ pub struct Elaborator<'context> { /// up all currently visible definitions. The first scope is always the global scope. comptime_scopes: Vec>, + /// The scope of --debug-comptime, or None if unset + debug_comptime_in_file: Option, + /// These are the globals that have yet to be elaborated. /// This map is used to lazily evaluate these globals if they're encountered before /// they are elaborated (e.g. in a function's type or another global's RHS). @@ -178,7 +182,11 @@ struct FunctionContext { } impl<'context> Elaborator<'context> { - pub fn new(context: &'context mut Context, crate_id: CrateId) -> Self { + pub fn new( + context: &'context mut Context, + crate_id: CrateId, + debug_comptime_in_file: Option, + ) -> Self { Self { scopes: ScopeForest::default(), errors: Vec::new(), @@ -198,6 +206,7 @@ impl<'context> Elaborator<'context> { function_context: vec![FunctionContext::default()], current_trait_impl: None, comptime_scopes: vec![HashMap::default()], + debug_comptime_in_file, unresolved_globals: BTreeMap::new(), } } @@ -206,8 +215,9 @@ impl<'context> Elaborator<'context> { context: &'context mut Context, crate_id: CrateId, items: CollectedItems, + debug_comptime_in_file: Option, ) -> Vec<(CompilationError, FileId)> { - let mut this = Self::new(context, crate_id); + let mut this = Self::new(context, crate_id, debug_comptime_in_file); // Filter out comptime items to execute their functions first if needed. // This step is why comptime items can only refer to other comptime items @@ -1191,6 +1201,7 @@ impl<'context> Elaborator<'context> { let span = typ.struct_def.span; let fields = self.resolve_struct_fields(typ.struct_def, type_id); + let fields_len = fields.len(); self.interner.update_struct(type_id, |struct_def| { struct_def.set_fields(fields); @@ -1217,6 +1228,11 @@ impl<'context> Elaborator<'context> { } }); + for field_index in 0..fields_len { + self.interner + .add_definition_location(ReferenceId::StructMember(type_id, field_index)); + } + self.run_comptime_attributes_on_struct(attributes, type_id, span, &mut generated_items); } @@ -1276,15 +1292,15 @@ impl<'context> Elaborator<'context> { let DefinitionKind::Function(function) = definition.kind else { return Err((ResolverError::NonFunctionInAnnotation { span }.into(), self.file)); }; - let mut interpreter = - Interpreter::new(self.interner, &mut self.comptime_scopes, self.crate_id); - let location = Location::new(span, self.file); + let mut interpreter_errors = vec![]; + let mut interpreter = self.setup_interpreter(&mut interpreter_errors); let arguments = vec![(Value::StructDefinition(struct_id), location)]; let value = interpreter .call_function(function, arguments, TypeBindings::new(), location) .map_err(|error| error.into_compilation_error_pair())?; + self.include_interpreter_errors(interpreter_errors); if value != Value::Unit { let items = value @@ -1365,9 +1381,8 @@ impl<'context> Elaborator<'context> { let global = self.interner.get_global(global_id); let definition_id = global.definition_id; let location = global.location; - - let mut interpreter = - Interpreter::new(self.interner, &mut self.comptime_scopes, self.crate_id); + let mut interpreter_errors = vec![]; + let mut interpreter = self.setup_interpreter(&mut interpreter_errors); if let Err(error) = interpreter.evaluate_let(let_statement) { self.errors.push(error.into_compilation_error_pair()); @@ -1376,8 +1391,13 @@ impl<'context> Elaborator<'context> { .lookup_id(definition_id, location) .expect("The global should be defined since evaluate_let did not error"); + self.debug_comptime(location, |interner| { + interner.get_global(global_id).let_statement.to_display_ast(interner).kind + }); + self.interner.get_global_mut(global_id).value = Some(value); } + self.include_interpreter_errors(interpreter_errors); } fn define_function_metas( @@ -1473,6 +1493,10 @@ impl<'context> Elaborator<'context> { } } + fn include_interpreter_errors(&mut self, errors: Vec) { + self.errors.extend(errors.into_iter().map(InterpreterError::into_compilation_error_pair)); + } + /// True if we're currently within a `comptime` block, function, or global fn in_comptime_context(&self) -> bool { // The first context is the global context, followed by the function-specific context. @@ -1623,4 +1647,31 @@ impl<'context> Elaborator<'context> { } } } + + fn setup_interpreter<'a>( + &'a mut self, + interpreter_errors: &'a mut Vec, + ) -> Interpreter { + Interpreter::new( + self.interner, + &mut self.comptime_scopes, + self.crate_id, + self.debug_comptime_in_file, + interpreter_errors, + ) + } + + fn debug_comptime T>( + &mut self, + location: Location, + mut expr_f: F, + ) { + if Some(location.file) == self.debug_comptime_in_file { + let displayed_expr = expr_f(self.interner); + self.errors.push(( + InterpreterError::debug_evaluate_comptime(displayed_expr, location).into(), + location.file, + )); + } + } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs index b1c9b1b37ccc..7c920230b9db 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs @@ -202,10 +202,18 @@ impl<'context> Elaborator<'context> { new_definitions, ); - let referenced = ReferenceId::Struct(struct_type.borrow().id); + let struct_id = struct_type.borrow().id; + + let referenced = ReferenceId::Struct(struct_id); let reference = ReferenceId::Reference(Location::new(name_span, self.file), is_self_type); self.interner.add_reference(referenced, reference); + for (field_index, field) in fields.iter().enumerate() { + let referenced = ReferenceId::StructMember(struct_id, field_index); + let reference = ReferenceId::Reference(Location::new(field.0.span(), self.file), false); + self.interner.add_reference(referenced, reference); + } + HirPattern::Struct(expected_type, fields, location) } @@ -456,9 +464,16 @@ impl<'context> Elaborator<'context> { // Comptime variables must be replaced with their values if let Some(definition) = self.interner.try_definition(definition_id) { if definition.comptime && !self.in_comptime_context() { - let mut interpreter = - Interpreter::new(self.interner, &mut self.comptime_scopes, self.crate_id); + let mut interpreter_errors = vec![]; + let mut interpreter = Interpreter::new( + self.interner, + &mut self.comptime_scopes, + self.crate_id, + self.debug_comptime_in_file, + &mut interpreter_errors, + ); let value = interpreter.evaluate(id); + self.include_interpreter_errors(interpreter_errors); return self.inline_comptime_value(value, span); } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs index 1fc92ad28ba4..13c59e3494e0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs @@ -3,7 +3,6 @@ use noirc_errors::{Location, Span}; use crate::{ ast::{AssignStatement, ConstrainStatement, LValue}, hir::{ - comptime::Interpreter, resolution::errors::ResolverError, type_check::{Source, TypeCheckError}, }, @@ -381,6 +380,10 @@ impl<'context> Elaborator<'context> { Type::Struct(s, args) => { let s = s.borrow(); if let Some((field, index)) = s.get_field(field_name, args) { + let referenced = ReferenceId::StructMember(s.id, index); + let reference = ReferenceId::Reference(Location::new(span, self.file), false); + self.interner.add_reference(referenced, reference); + return Some((field, index)); } } @@ -444,11 +447,15 @@ impl<'context> Elaborator<'context> { let span = statement.span; let (hir_statement, _typ) = self.elaborate_statement(statement); self.check_and_pop_function_context(); - - let mut interpreter = - Interpreter::new(self.interner, &mut self.comptime_scopes, self.crate_id); + let mut interpreter_errors = vec![]; + let mut interpreter = self.setup_interpreter(&mut interpreter_errors); let value = interpreter.evaluate_statement(hir_statement); let (expr, typ) = self.inline_comptime_value(value, span); + self.include_interpreter_errors(interpreter_errors); + + let location = self.interner.id_location(hir_statement); + self.debug_comptime(location, |interner| expr.to_display_ast(interner).kind); + (HirStatement::Expression(expr), typ) } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs index 77ac8e476f81..4cd20820c566 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs @@ -47,7 +47,8 @@ impl<'context> Elaborator<'context> { // the interner may set `interner.ordering_type` based on the result type // of the Cmp trait, if this is it. if self.crate_id.is_stdlib() { - self.interner.try_add_operator_trait(trait_id); + self.interner.try_add_infix_operator_trait(trait_id); + self.interner.try_add_prefix_operator_trait(trait_id); } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs index 698114cfb5e8..4e9b36207606 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs @@ -670,57 +670,6 @@ impl<'context> Elaborator<'context> { } } - pub(super) fn type_check_prefix_operand( - &mut self, - op: &crate::ast::UnaryOp, - rhs_type: &Type, - span: Span, - ) -> Type { - let unify = |this: &mut Self, expected| { - this.unify(rhs_type, &expected, || TypeCheckError::TypeMismatch { - expr_typ: rhs_type.to_string(), - expected_typ: expected.to_string(), - expr_span: span, - }); - expected - }; - - match op { - crate::ast::UnaryOp::Minus => { - if rhs_type.is_unsigned() { - self.push_err(TypeCheckError::InvalidUnaryOp { - kind: rhs_type.to_string(), - span, - }); - } - let expected = self.polymorphic_integer_or_field(); - self.unify(rhs_type, &expected, || TypeCheckError::InvalidUnaryOp { - kind: rhs_type.to_string(), - span, - }); - expected - } - crate::ast::UnaryOp::Not => { - let rhs_type = rhs_type.follow_bindings(); - - // `!` can work on booleans or integers - if matches!(rhs_type, Type::Integer(..)) { - return rhs_type; - } - - unify(self, Type::Bool) - } - crate::ast::UnaryOp::MutableReference => { - Type::MutableReference(Box::new(rhs_type.follow_bindings())) - } - crate::ast::UnaryOp::Dereference { implicitly_added: _ } => { - let element_type = self.interner.next_type_variable(); - unify(self, Type::MutableReference(Box::new(element_type.clone()))); - element_type - } - } - } - /// Insert as many dereference operations as necessary to automatically dereference a method /// call object to its base value type T. pub(super) fn insert_auto_dereferences(&mut self, object: ExprId, typ: Type) -> (ExprId, Type) { @@ -730,6 +679,7 @@ impl<'context> Elaborator<'context> { let object = self.interner.push_expr(HirExpression::Prefix(HirPrefixExpression { operator: UnaryOp::Dereference { implicitly_added: true }, rhs: object, + trait_method_id: None, })); self.interner.push_expr_type(object, element.as_ref().clone()); self.interner.push_expr_location(object, location.span, location.file); @@ -1073,6 +1023,84 @@ impl<'context> Elaborator<'context> { } } + // Given a unary operator and a type, this method will produce the output type + // and a boolean indicating whether to use the trait impl corresponding to the operator + // or not. A value of false indicates the caller to use a primitive operation for this + // operator, while a true value indicates a user-provided trait impl is required. + pub(super) fn prefix_operand_type_rules( + &mut self, + op: &UnaryOp, + rhs_type: &Type, + span: Span, + ) -> Result<(Type, bool), TypeCheckError> { + use Type::*; + + match op { + crate::ast::UnaryOp::Minus | crate::ast::UnaryOp::Not => { + match rhs_type { + // An error type will always return an error + Error => Ok((Error, false)), + Alias(alias, args) => { + let alias = alias.borrow().get_type(args); + self.prefix_operand_type_rules(op, &alias, span) + } + + // Matches on TypeVariable must be first so that we follow any type + // bindings. + TypeVariable(int, _) => { + if let TypeBinding::Bound(binding) = &*int.borrow() { + return self.prefix_operand_type_rules(op, binding, span); + } + + // The `!` prefix operator is not valid for Field, so if this is a numeric + // type we constrain it to just (non-Field) integer types. + if matches!(op, crate::ast::UnaryOp::Not) && rhs_type.is_numeric() { + let integer_type = Type::polymorphic_integer(self.interner); + self.unify(rhs_type, &integer_type, || { + TypeCheckError::InvalidUnaryOp { kind: rhs_type.to_string(), span } + }); + } + + Ok((rhs_type.clone(), !rhs_type.is_numeric())) + } + Integer(sign_x, bit_width_x) => { + if *op == UnaryOp::Minus && *sign_x == Signedness::Unsigned { + return Err(TypeCheckError::InvalidUnaryOp { + kind: rhs_type.to_string(), + span, + }); + } + Ok((Integer(*sign_x, *bit_width_x), false)) + } + // The result of a Field is always a witness + FieldElement => { + if *op == UnaryOp::Not { + return Err(TypeCheckError::FieldNot { span }); + } + Ok((FieldElement, false)) + } + + Bool => Ok((Bool, false)), + + _ => Ok((rhs_type.clone(), true)), + } + } + crate::ast::UnaryOp::MutableReference => { + Ok((Type::MutableReference(Box::new(rhs_type.follow_bindings())), false)) + } + crate::ast::UnaryOp::Dereference { implicitly_added: _ } => { + let element_type = self.interner.next_type_variable(); + let expected = Type::MutableReference(Box::new(element_type.clone())); + self.unify(rhs_type, &expected, || TypeCheckError::TypeMismatch { + expr_typ: rhs_type.to_string(), + expected_typ: expected.to_string(), + expr_span: span, + }); + Ok((element_type, false)) + } + } + } + /// Prerequisite: verify_trait_constraint of the operator's trait constraint. /// /// Although by this point the operator is expected to already have a trait impl, @@ -1140,6 +1168,7 @@ impl<'context> Elaborator<'context> { *access_lhs = this.interner.push_expr(HirExpression::Prefix(HirPrefixExpression { operator: crate::ast::UnaryOp::Dereference { implicitly_added: true }, rhs: old_lhs, + trait_method_id: None, })); this.interner.push_expr_type(old_lhs, lhs_type); this.interner.push_expr_type(*access_lhs, element); @@ -1362,6 +1391,7 @@ impl<'context> Elaborator<'context> { self.interner.push_expr(HirExpression::Prefix(HirPrefixExpression { operator: UnaryOp::MutableReference, rhs: *object, + trait_method_id: None, })); self.interner.push_expr_type(new_object, new_type); self.interner.push_expr_location(new_object, location.span, location.file); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs index 25ff50085feb..0472b0040e52 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs @@ -1,3 +1,4 @@ +use std::fmt::Display; use std::rc::Rc; use crate::{ @@ -45,6 +46,7 @@ pub enum InterpreterError { NonStructInConstructor { typ: Type, location: Location }, CannotInlineMacro { value: Value, location: Location }, UnquoteFoundDuringEvaluation { location: Location }, + DebugEvaluateComptime { diagnostic: CustomDiagnostic, location: Location }, FailedToParseMacro { error: ParserError, tokens: Rc, rule: &'static str, file: FileId }, UnsupportedTopLevelItemUnquote { item: String, location: Location }, NonComptimeFnCallInSameCrate { function: String, location: Location }, @@ -117,7 +119,8 @@ impl InterpreterError { | InterpreterError::NoImpl { location, .. } | InterpreterError::ImplMethodTypeMismatch { location, .. } | InterpreterError::BreakNotInLoop { location, .. } - | InterpreterError::ContinueNotInLoop { location, .. } => *location, + | InterpreterError::DebugEvaluateComptime { location, .. } => *location, + InterpreterError::ContinueNotInLoop { location, .. } => *location, InterpreterError::FailedToParseMacro { error, file, .. } => { Location::new(error.span(), *file) } @@ -129,6 +132,20 @@ impl InterpreterError { } } } + + pub(crate) fn debug_evaluate_comptime(expr: impl Display, location: Location) -> Self { + let mut formatted_result = format!("{}", expr); + // if multi-line, display on a separate line from the message + if formatted_result.contains('\n') { + formatted_result.insert(0, '\n'); + } + let diagnostic = CustomDiagnostic::simple_info( + "`comptime` expression ran:".to_string(), + format!("After evaluation: {}", formatted_result), + location.span, + ); + InterpreterError::DebugEvaluateComptime { diagnostic, location } + } } impl<'a> From<&'a InterpreterError> for CustomDiagnostic { @@ -291,6 +308,7 @@ impl<'a> From<&'a InterpreterError> for CustomDiagnostic { let secondary = "This is a bug".into(); CustomDiagnostic::simple_error(msg, secondary, location.span) } + InterpreterError::DebugEvaluateComptime { diagnostic, .. } => diagnostic.clone(), InterpreterError::FailedToParseMacro { error, tokens, rule, file: _ } => { let message = format!("Failed to parse macro's token stream into {rule}"); let tokens = vecmap(&tokens.0, ToString::to_string).join(" "); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs new file mode 100644 index 000000000000..22763c9cb648 --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/hir_to_display_ast.rs @@ -0,0 +1,428 @@ +use iter_extended::vecmap; +use noirc_errors::{Span, Spanned}; + +use crate::ast::{ + ArrayLiteral, AssignStatement, BlockExpression, CallExpression, CastExpression, ConstrainKind, + ConstructorExpression, ExpressionKind, ForLoopStatement, ForRange, Ident, IfExpression, + IndexExpression, InfixExpression, LValue, Lambda, LetStatement, Literal, + MemberAccessExpression, MethodCallExpression, Path, Pattern, PrefixExpression, UnresolvedType, + UnresolvedTypeData, UnresolvedTypeExpression, +}; +use crate::ast::{ConstrainStatement, Expression, Statement, StatementKind}; +use crate::hir_def::expr::{HirArrayLiteral, HirBlockExpression, HirExpression, HirIdent}; +use crate::hir_def::stmt::{HirLValue, HirPattern, HirStatement}; +use crate::hir_def::types::{Type, TypeBinding, TypeVariableKind}; +use crate::macros_api::HirLiteral; +use crate::node_interner::{ExprId, NodeInterner, StmtId}; + +// TODO: +// - Full path for idents & types +// - Assert/AssertEq information lost +// - The type name span is lost in constructor patterns & expressions +// - All type spans are lost +// - Type::TypeVariable has no equivalent in the Ast + +impl HirStatement { + pub fn to_display_ast(&self, interner: &NodeInterner, span: Span) -> Statement { + let kind = match self { + HirStatement::Let(let_stmt) => { + let pattern = let_stmt.pattern.to_display_ast(interner); + let r#type = interner.id_type(let_stmt.expression).to_display_ast(); + let expression = let_stmt.expression.to_display_ast(interner); + StatementKind::Let(LetStatement { + pattern, + r#type, + expression, + comptime: false, + attributes: Vec::new(), + }) + } + HirStatement::Constrain(constrain) => { + let expr = constrain.0.to_display_ast(interner); + let message = constrain.2.map(|message| message.to_display_ast(interner)); + + // TODO: Find difference in usage between Assert & AssertEq + StatementKind::Constrain(ConstrainStatement(expr, message, ConstrainKind::Assert)) + } + HirStatement::Assign(assign) => StatementKind::Assign(AssignStatement { + lvalue: assign.lvalue.to_display_ast(interner), + expression: assign.expression.to_display_ast(interner), + }), + HirStatement::For(for_stmt) => StatementKind::For(ForLoopStatement { + identifier: for_stmt.identifier.to_display_ast(interner), + range: ForRange::Range( + for_stmt.start_range.to_display_ast(interner), + for_stmt.end_range.to_display_ast(interner), + ), + block: for_stmt.block.to_display_ast(interner), + span, + }), + HirStatement::Break => StatementKind::Break, + HirStatement::Continue => StatementKind::Continue, + HirStatement::Expression(expr) => { + StatementKind::Expression(expr.to_display_ast(interner)) + } + HirStatement::Semi(expr) => StatementKind::Semi(expr.to_display_ast(interner)), + HirStatement::Error => StatementKind::Error, + HirStatement::Comptime(statement) => { + StatementKind::Comptime(Box::new(statement.to_display_ast(interner))) + } + }; + + Statement { kind, span } + } +} + +impl StmtId { + /// Convert to AST for display (some details lost) + pub fn to_display_ast(self, interner: &NodeInterner) -> Statement { + let statement = interner.statement(&self); + let span = interner.statement_span(self); + + statement.to_display_ast(interner, span) + } +} + +impl HirExpression { + /// Convert to AST for display (some details lost) + pub fn to_display_ast(&self, interner: &NodeInterner, span: Span) -> Expression { + let kind = match self { + HirExpression::Ident(ident, generics) => { + let path = Path::from_ident(ident.to_display_ast(interner)); + ExpressionKind::Variable( + path, + generics.as_ref().map(|option| { + option.iter().map(|generic| generic.to_display_ast()).collect() + }), + ) + } + HirExpression::Literal(HirLiteral::Array(array)) => { + let array = array.to_display_ast(interner, span); + ExpressionKind::Literal(Literal::Array(array)) + } + HirExpression::Literal(HirLiteral::Slice(array)) => { + let array = array.to_display_ast(interner, span); + ExpressionKind::Literal(Literal::Slice(array)) + } + HirExpression::Literal(HirLiteral::Bool(value)) => { + ExpressionKind::Literal(Literal::Bool(*value)) + } + HirExpression::Literal(HirLiteral::Integer(value, sign)) => { + ExpressionKind::Literal(Literal::Integer(*value, *sign)) + } + HirExpression::Literal(HirLiteral::Str(string)) => { + ExpressionKind::Literal(Literal::Str(string.clone())) + } + HirExpression::Literal(HirLiteral::FmtStr(string, _exprs)) => { + // TODO: Is throwing away the exprs here valid? + ExpressionKind::Literal(Literal::FmtStr(string.clone())) + } + HirExpression::Literal(HirLiteral::Unit) => ExpressionKind::Literal(Literal::Unit), + HirExpression::Block(expr) => ExpressionKind::Block(expr.to_display_ast(interner)), + HirExpression::Prefix(prefix) => ExpressionKind::Prefix(Box::new(PrefixExpression { + operator: prefix.operator, + rhs: prefix.rhs.to_display_ast(interner), + })), + HirExpression::Infix(infix) => ExpressionKind::Infix(Box::new(InfixExpression { + lhs: infix.lhs.to_display_ast(interner), + operator: Spanned::from(infix.operator.location.span, infix.operator.kind), + rhs: infix.rhs.to_display_ast(interner), + })), + HirExpression::Index(index) => ExpressionKind::Index(Box::new(IndexExpression { + collection: index.collection.to_display_ast(interner), + index: index.index.to_display_ast(interner), + })), + HirExpression::Constructor(constructor) => { + let type_name = constructor.r#type.borrow().name.to_string(); + let type_name = Path::from_single(type_name, span); + let fields = vecmap(constructor.fields.clone(), |(name, expr): (Ident, ExprId)| { + (name, expr.to_display_ast(interner)) + }); + let struct_type = None; + + ExpressionKind::Constructor(Box::new(ConstructorExpression { + type_name, + fields, + struct_type, + })) + } + HirExpression::MemberAccess(access) => { + ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { + lhs: access.lhs.to_display_ast(interner), + rhs: access.rhs.clone(), + })) + } + HirExpression::Call(call) => { + let func = Box::new(call.func.to_display_ast(interner)); + let arguments = vecmap(call.arguments.clone(), |arg| arg.to_display_ast(interner)); + let is_macro_call = false; + ExpressionKind::Call(Box::new(CallExpression { func, arguments, is_macro_call })) + } + HirExpression::MethodCall(method_call) => { + ExpressionKind::MethodCall(Box::new(MethodCallExpression { + object: method_call.object.to_display_ast(interner), + method_name: method_call.method.clone(), + arguments: vecmap(method_call.arguments.clone(), |arg| { + arg.to_display_ast(interner) + }), + generics: method_call.generics.clone().map(|option| { + option.iter().map(|generic| generic.to_display_ast()).collect() + }), + is_macro_call: false, + })) + } + HirExpression::Cast(cast) => { + let lhs = cast.lhs.to_display_ast(interner); + let r#type = cast.r#type.to_display_ast(); + ExpressionKind::Cast(Box::new(CastExpression { lhs, r#type })) + } + HirExpression::If(if_expr) => ExpressionKind::If(Box::new(IfExpression { + condition: if_expr.condition.to_display_ast(interner), + consequence: if_expr.consequence.to_display_ast(interner), + alternative: if_expr.alternative.map(|expr| expr.to_display_ast(interner)), + })), + HirExpression::Tuple(fields) => { + ExpressionKind::Tuple(vecmap(fields, |field| field.to_display_ast(interner))) + } + HirExpression::Lambda(lambda) => { + let parameters = vecmap(lambda.parameters.clone(), |(pattern, typ)| { + (pattern.to_display_ast(interner), typ.to_display_ast()) + }); + let return_type = lambda.return_type.to_display_ast(); + let body = lambda.body.to_display_ast(interner); + ExpressionKind::Lambda(Box::new(Lambda { parameters, return_type, body })) + } + HirExpression::Error => ExpressionKind::Error, + HirExpression::Comptime(block) => { + ExpressionKind::Comptime(block.to_display_ast(interner), span) + } + HirExpression::Quote(block) => ExpressionKind::Quote(block.clone()), + + // A macro was evaluated here: return the quoted result + HirExpression::Unquote(block) => ExpressionKind::Quote(block.clone()), + }; + + Expression::new(kind, span) + } +} + +impl ExprId { + /// Convert to AST for display (some details lost) + pub fn to_display_ast(self, interner: &NodeInterner) -> Expression { + let expression = interner.expression(&self); + // TODO: empty 0 span + let span = interner.try_expr_span(&self).unwrap_or_else(|| Span::empty(0)); + expression.to_display_ast(interner, span) + } +} + +impl HirPattern { + /// Convert to AST for display (some details lost) + fn to_display_ast(&self, interner: &NodeInterner) -> Pattern { + match self { + HirPattern::Identifier(ident) => Pattern::Identifier(ident.to_display_ast(interner)), + HirPattern::Mutable(pattern, location) => { + let pattern = Box::new(pattern.to_display_ast(interner)); + Pattern::Mutable(pattern, location.span, false) + } + HirPattern::Tuple(patterns, location) => { + let patterns = vecmap(patterns, |pattern| pattern.to_display_ast(interner)); + Pattern::Tuple(patterns, location.span) + } + HirPattern::Struct(typ, patterns, location) => { + let patterns = vecmap(patterns, |(name, pattern)| { + (name.clone(), pattern.to_display_ast(interner)) + }); + let name = match typ.follow_bindings() { + Type::Struct(struct_def, _) => { + let struct_def = struct_def.borrow(); + struct_def.name.0.contents.clone() + } + // This pass shouldn't error so if the type isn't a struct we just get a string + // representation of any other type and use that. We're relying on name + // resolution to fail later when this Ast is re-converted to Hir. + other => other.to_string(), + }; + // The name span is lost here + let path = Path::from_single(name, location.span); + Pattern::Struct(path, patterns, location.span) + } + } + } +} + +impl HirIdent { + /// Convert to AST for display (some details lost) + fn to_display_ast(&self, interner: &NodeInterner) -> Ident { + let name = interner.definition_name(self.id).to_owned(); + Ident(Spanned::from(self.location.span, name)) + } +} + +impl Type { + /// Convert to AST for display (some details lost) + fn to_display_ast(&self) -> UnresolvedType { + let typ = match self { + Type::FieldElement => UnresolvedTypeData::FieldElement, + Type::Array(length, element) => { + let length = length.to_type_expression(); + let element = Box::new(element.to_display_ast()); + UnresolvedTypeData::Array(length, element) + } + Type::Slice(element) => { + let element = Box::new(element.to_display_ast()); + UnresolvedTypeData::Slice(element) + } + Type::Integer(sign, bit_size) => UnresolvedTypeData::Integer(*sign, *bit_size), + Type::Bool => UnresolvedTypeData::Bool, + Type::String(length) => { + let length = length.to_type_expression(); + UnresolvedTypeData::String(length) + } + Type::FmtString(length, element) => { + let length = length.to_type_expression(); + let element = Box::new(element.to_display_ast()); + UnresolvedTypeData::FormatString(length, element) + } + Type::Unit => UnresolvedTypeData::Unit, + Type::Tuple(fields) => { + let fields = vecmap(fields, |field| field.to_display_ast()); + UnresolvedTypeData::Tuple(fields) + } + Type::Struct(def, generics) => { + let struct_def = def.borrow(); + let generics = vecmap(generics, |generic| generic.to_display_ast()); + let name = Path::from_ident(struct_def.name.clone()); + UnresolvedTypeData::Named(name, generics, false) + } + Type::Alias(type_def, generics) => { + // Keep the alias name instead of expanding this in case the + // alias' definition was changed + let type_def = type_def.borrow(); + let generics = vecmap(generics, |generic| generic.to_display_ast()); + let name = Path::from_ident(type_def.name.clone()); + UnresolvedTypeData::Named(name, generics, false) + } + Type::TypeVariable(binding, kind) => { + match &*binding.borrow() { + TypeBinding::Bound(typ) => return typ.to_display_ast(), + TypeBinding::Unbound(id) => { + let expression = match kind { + // TODO: fix span or make Option + TypeVariableKind::Constant(value) => { + UnresolvedTypeExpression::Constant(*value, Span::empty(0)) + } + other_kind => { + let name = format!("var_{:?}_{}", other_kind, id); + + // TODO: fix span or make Option + let path = Path::from_single(name, Span::empty(0)); + UnresolvedTypeExpression::Variable(path) + } + }; + + UnresolvedTypeData::Expression(expression) + } + } + } + Type::TraitAsType(_, name, generics) => { + let generics = vecmap(generics, |generic| generic.to_display_ast()); + let name = Path::from_single(name.as_ref().clone(), Span::default()); + UnresolvedTypeData::TraitAsType(name, generics) + } + Type::NamedGeneric(_var, name, _kind) => { + let name = Path::from_single(name.as_ref().clone(), Span::default()); + UnresolvedTypeData::TraitAsType(name, Vec::new()) + } + Type::Function(args, ret, env) => { + let args = vecmap(args, |arg| arg.to_display_ast()); + let ret = Box::new(ret.to_display_ast()); + let env = Box::new(env.to_display_ast()); + UnresolvedTypeData::Function(args, ret, env) + } + Type::MutableReference(element) => { + let element = Box::new(element.to_display_ast()); + UnresolvedTypeData::MutableReference(element) + } + // Type::Forall is only for generic functions which don't store a type + // in their Ast so they don't need to call to_display_ast for their Forall type. + // Since there is no UnresolvedTypeData equivalent for Type::Forall, we use + // this to ignore this case since it shouldn't be needed anyway. + Type::Forall(_, typ) => return typ.to_display_ast(), + Type::Constant(_) => panic!("Type::Constant where a type was expected: {self:?}"), + Type::Quoted(quoted_type) => UnresolvedTypeData::Quoted(*quoted_type), + Type::Error => UnresolvedTypeData::Error, + }; + + UnresolvedType { typ, span: None } + } + + /// Convert to AST for display (some details lost) + fn to_type_expression(&self) -> UnresolvedTypeExpression { + let span = Span::default(); + + match self.follow_bindings() { + Type::Constant(length) => UnresolvedTypeExpression::Constant(length, span), + Type::NamedGeneric(_var, name, _kind) => { + let path = Path::from_single(name.as_ref().clone(), span); + UnresolvedTypeExpression::Variable(path) + } + // TODO: This should be turned into a proper error. + other => panic!("Cannot represent {other:?} as type expression"), + } + } +} + +impl HirLValue { + /// Convert to AST for display (some details lost) + fn to_display_ast(&self, interner: &NodeInterner) -> LValue { + match self { + HirLValue::Ident(ident, _) => LValue::Ident(ident.to_display_ast(interner)), + HirLValue::MemberAccess { object, field_name, field_index: _, typ: _, location } => { + let object = Box::new(object.to_display_ast(interner)); + LValue::MemberAccess { object, field_name: field_name.clone(), span: location.span } + } + HirLValue::Index { array, index, typ: _, location } => { + let array = Box::new(array.to_display_ast(interner)); + let index = index.to_display_ast(interner); + LValue::Index { array, index, span: location.span } + } + HirLValue::Dereference { lvalue, element_type: _, location } => { + let lvalue = Box::new(lvalue.to_display_ast(interner)); + LValue::Dereference(lvalue, location.span) + } + } + } +} + +impl HirArrayLiteral { + /// Convert to AST for display (some details lost) + fn to_display_ast(&self, interner: &NodeInterner, span: Span) -> ArrayLiteral { + match self { + HirArrayLiteral::Standard(elements) => { + ArrayLiteral::Standard(vecmap(elements, |element| element.to_display_ast(interner))) + } + HirArrayLiteral::Repeated { repeated_element, length } => { + let repeated_element = Box::new(repeated_element.to_display_ast(interner)); + let length = match length { + Type::Constant(length) => { + let literal = Literal::Integer((*length as u128).into(), false); + let kind = ExpressionKind::Literal(literal); + Box::new(Expression::new(kind, span)) + } + other => panic!("Cannot convert non-constant type for repeated array literal from Hir -> Ast: {other:?}"), + }; + ArrayLiteral::Repeated { repeated_element, length } + } + } + } +} + +impl HirBlockExpression { + /// Convert to AST for display (some details lost) + fn to_display_ast(&self, interner: &NodeInterner) -> BlockExpression { + let statements = + vecmap(self.statements.clone(), |statement| statement.to_display_ast(interner)); + BlockExpression { statements } + } +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs index 605a35780edd..02714f776055 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -1,6 +1,7 @@ use std::{collections::hash_map::Entry, rc::Rc}; use acvm::{acir::AcirField, FieldElement}; +use fm::FileId; use im::Vector; use iter_extended::try_vecmap; use noirc_errors::Location; @@ -19,7 +20,7 @@ use crate::{ hir_def::{ expr::{ HirArrayLiteral, HirBlockExpression, HirCallExpression, HirCastExpression, - HirConstructorExpression, HirIdent, HirIfExpression, HirIndexExpression, + HirConstructorExpression, HirExpression, HirIdent, HirIfExpression, HirIndexExpression, HirInfixExpression, HirLambda, HirMemberAccess, HirMethodCallExpression, HirPrefixExpression, }, @@ -28,7 +29,7 @@ use crate::{ HirPattern, }, }, - macros_api::{HirExpression, HirLiteral, HirStatement, NodeInterner}, + macros_api::{HirLiteral, HirStatement, NodeInterner}, node_interner::{DefinitionId, DefinitionKind, ExprId, FuncId, StmtId}, Shared, Type, TypeBinding, TypeBindings, TypeVariableKind, }; @@ -51,6 +52,10 @@ pub struct Interpreter<'interner> { crate_id: CrateId, + /// The scope of --debug-comptime, or None if unset + pub(super) debug_comptime_in_file: Option, + pub(super) debug_comptime_evaluations: &'interner mut Vec, + in_loop: bool, } @@ -60,8 +65,17 @@ impl<'a> Interpreter<'a> { interner: &'a mut NodeInterner, scopes: &'a mut Vec>, crate_id: CrateId, + debug_comptime_in_file: Option, + debug_comptime_evaluations: &'a mut Vec, ) -> Self { - Self { interner, scopes, crate_id, in_loop: false } + Self { + interner, + scopes, + crate_id, + debug_comptime_in_file, + debug_comptime_evaluations, + in_loop: false, + } } pub(crate) fn call_function( diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/mod.rs index ab984d2f2be5..3cc7b5f7e985 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/mod.rs @@ -1,4 +1,5 @@ mod errors; +mod hir_to_display_ast; mod interpreter; mod scan; mod tests; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/scan.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/scan.rs index 770c523bd7fb..f9cc54ef9e4b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/scan.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/scan.rs @@ -29,6 +29,8 @@ use super::{ Value, }; +use noirc_errors::Location; + #[allow(dead_code)] impl<'interner> Interpreter<'interner> { /// Scan through a function, evaluating any Comptime nodes found. @@ -80,9 +82,10 @@ impl<'interner> Interpreter<'interner> { HirExpression::Lambda(lambda) => self.scan_lambda(lambda), HirExpression::Comptime(block) => { let location = self.interner.expr_location(&expr); - let new_expr = + let new_expr_id = self.evaluate_block(block)?.into_hir_expression(self.interner, location)?; - let new_expr = self.interner.expression(&new_expr); + let new_expr = self.interner.expression(&new_expr_id); + self.debug_comptime(new_expr_id, location); self.interner.replace_expr(&expr, new_expr); Ok(()) } @@ -118,7 +121,9 @@ impl<'interner> Interpreter<'interner> { if let Ok(value) = self.evaluate_ident(ident, id) { // TODO(#4922): Inlining closures is currently unimplemented if !matches!(value, Value::Closure(..)) { - self.inline_expression(value, id)?; + let new_expr = self.inline_expression(value, id)?; + let location = self.interner.id_location(id); + self.debug_comptime(new_expr, location); } } Ok(()) @@ -231,6 +236,7 @@ impl<'interner> Interpreter<'interner> { let new_expr = self .evaluate_comptime(comptime)? .into_hir_expression(self.interner, location)?; + self.debug_comptime(new_expr, location); self.interner.replace_statement(statement, HirStatement::Expression(new_expr)); Ok(()) } @@ -247,11 +253,19 @@ impl<'interner> Interpreter<'interner> { Ok(()) } - fn inline_expression(&mut self, value: Value, expr: ExprId) -> IResult<()> { + fn inline_expression(&mut self, value: Value, expr: ExprId) -> IResult { let location = self.interner.expr_location(&expr); - let new_expr = value.into_hir_expression(self.interner, location)?; - let new_expr = self.interner.expression(&new_expr); + let new_expr_id = value.into_hir_expression(self.interner, location)?; + let new_expr = self.interner.expression(&new_expr_id); self.interner.replace_expr(&expr, new_expr); - Ok(()) + Ok(new_expr_id) + } + + fn debug_comptime(&mut self, expr: ExprId, location: Location) { + if Some(location.file) == self.debug_comptime_in_file { + let expr = expr.to_display_ast(self.interner); + self.debug_comptime_evaluations + .push(InterpreterError::debug_evaluate_comptime(expr, location)); + } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/tests.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/tests.rs index 870f2bc458a8..e8e05506c943 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/tests.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/tests.rs @@ -13,7 +13,15 @@ use crate::hir::type_check::test::type_check_src_code; fn interpret_helper(src: &str, func_namespace: Vec) -> Result { let (mut interner, main_id) = type_check_src_code(src, func_namespace); let mut scopes = vec![HashMap::default()]; - let mut interpreter = Interpreter::new(&mut interner, &mut scopes, CrateId::Root(0)); + let no_debug_evaluate_comptime = None; + let mut interpreter_errors = vec![]; + let mut interpreter = Interpreter::new( + &mut interner, + &mut scopes, + CrateId::Root(0), + no_debug_evaluate_comptime, + &mut interpreter_errors, + ); let no_location = Location::dummy(); interpreter.call_function(main_id, Vec::new(), HashMap::new(), no_location) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 43ab6224ea75..b474ccff0ccd 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -29,12 +29,14 @@ use crate::ast::{ }; use crate::parser::{ParserError, SortedModule}; +use noirc_errors::{CustomDiagnostic, Location, Span}; + use fm::FileId; use iter_extended::vecmap; -use noirc_errors::{CustomDiagnostic, Location, Span}; use rustc_hash::FxHashMap as HashMap; use std::collections::BTreeMap; - +use std::fmt::Write; +use std::path::PathBuf; use std::vec; #[derive(Default)] @@ -42,6 +44,7 @@ pub struct ResolvedModule { pub globals: Vec<(FileId, GlobalId)>, pub functions: Vec<(FileId, FuncId)>, pub trait_impl_functions: Vec<(FileId, FuncId)>, + pub debug_comptime_in_file: Option, pub errors: Vec<(CompilationError, FileId)>, } @@ -195,6 +198,7 @@ pub enum CompilationError { ResolverError(ResolverError), TypeError(TypeCheckError), InterpreterError(InterpreterError), + DebugComptimeScopeNotFound(Vec), } impl CompilationError { @@ -212,6 +216,16 @@ impl<'a> From<&'a CompilationError> for CustomDiagnostic { CompilationError::ResolverError(error) => error.into(), CompilationError::TypeError(error) => error.into(), CompilationError::InterpreterError(error) => error.into(), + CompilationError::DebugComptimeScopeNotFound(error) => { + let msg = "multiple files found matching --debug-comptime path".into(); + let secondary = error.iter().fold(String::new(), |mut output, path| { + let _ = writeln!(output, " {}", path.display()); + output + }); + // NOTE: this span is empty as it is not expected to be displayed + let dummy_span = Span::default(); + CustomDiagnostic::simple_error(msg, secondary, dummy_span) + } } } } @@ -271,6 +285,7 @@ impl DefCollector { ast: SortedModule, root_file_id: FileId, use_legacy: bool, + debug_comptime_in_file: Option<&str>, macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; @@ -288,6 +303,7 @@ impl DefCollector { dep.crate_id, context, use_legacy, + debug_comptime_in_file, macro_processors, )); @@ -396,13 +412,31 @@ impl DefCollector { } } + let handle_missing_file = |err| { + errors.push((CompilationError::DebugComptimeScopeNotFound(err), root_file_id)); + None + }; + let debug_comptime_in_file: Option = + debug_comptime_in_file.and_then(|debug_comptime_in_file| { + context + .file_manager + .find_by_path_suffix(debug_comptime_in_file) + .unwrap_or_else(handle_missing_file) + }); + if !use_legacy { - let mut more_errors = Elaborator::elaborate(context, crate_id, def_collector.items); + let mut more_errors = Elaborator::elaborate( + context, + crate_id, + def_collector.items, + debug_comptime_in_file, + ); errors.append(&mut more_errors); return errors; } - let mut resolved_module = ResolvedModule { errors, ..Default::default() }; + let mut resolved_module = + ResolvedModule { errors, debug_comptime_in_file, ..Default::default() }; // We must first resolve and intern the globals before we can resolve any stmts inside each function. // Each function uses its own resolver with a newly created ScopeForest, and must be resolved again to be within a function's scope @@ -621,7 +655,14 @@ impl ResolvedModule { fn evaluate_comptime(&mut self, interner: &mut NodeInterner, crate_id: CrateId) { if self.count_errors() == 0 { let mut scopes = vec![HashMap::default()]; - let mut interpreter = Interpreter::new(interner, &mut scopes, crate_id); + let mut interpreter_errors = vec![]; + let mut interpreter = Interpreter::new( + interner, + &mut scopes, + crate_id, + self.debug_comptime_in_file, + &mut interpreter_errors, + ); for (_file, global) in &self.globals { if let Err(error) = interpreter.scan_global(*global) { @@ -636,6 +677,9 @@ impl ResolvedModule { self.errors.push(error.into_compilation_error_pair()); } } + self.errors.extend( + interpreter_errors.into_iter().map(InterpreterError::into_compilation_error_pair), + ); } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs index 59205f74d89d..43d1548dc29f 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs @@ -74,6 +74,7 @@ impl CrateDefMap { crate_id: CrateId, context: &mut Context, use_legacy: bool, + debug_comptime_in_file: Option<&str>, macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { // Check if this Crate has already been compiled @@ -123,6 +124,7 @@ impl CrateDefMap { ast, root_file_id, use_legacy, + debug_comptime_in_file, macro_processors, )); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 793362bb3d60..856a769c9dd7 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -1548,6 +1548,7 @@ impl<'a> Resolver<'a> { ExpressionKind::Prefix(prefix) => { let operator = prefix.operator; let rhs = self.resolve_expression(prefix.rhs); + let trait_method_id = self.interner.get_prefix_operator_trait_method(&operator); if operator == UnaryOp::MutableReference { if let Err(error) = verify_mutable_reference(self.interner, rhs) { @@ -1555,7 +1556,7 @@ impl<'a> Resolver<'a> { } } - HirExpression::Prefix(HirPrefixExpression { operator, rhs }) + HirExpression::Prefix(HirPrefixExpression { operator, rhs, trait_method_id }) } ExpressionKind::Infix(infix) => { let lhs = self.resolve_expression(infix.lhs); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs index 6781c2833c43..28ee70393cdf 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs @@ -72,7 +72,8 @@ pub(crate) fn resolve_traits( // the interner may set `interner.ordering_type` based on the result type // of the Cmp trait, if this is it. if crate_id.is_stdlib() { - context.def_interner.try_add_operator_trait(trait_id); + context.def_interner.try_add_infix_operator_trait(trait_id); + context.def_interner.try_add_prefix_operator_trait(trait_id); } } all_errors diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs index e5c522130562..af168a10df9a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -83,6 +83,8 @@ pub enum TypeCheckError { IntegerAndFieldBinaryOperation { span: Span }, #[error("Cannot do modulo on Fields, try casting to an integer first")] FieldModulo { span: Span }, + #[error("Cannot do not (`!`) on Fields, try casting to an integer first")] + FieldNot { span: Span }, #[error("Fields cannot be compared, try casting to an integer first")] FieldComparison { span: Span }, #[error("The bit count in a bit-shift operation must fit in a u8, try casting the right hand side into a u8 first")] @@ -256,6 +258,7 @@ impl<'a> From<&'a TypeCheckError> for Diagnostic { | TypeCheckError::IntegerAndFieldBinaryOperation { span } | TypeCheckError::OverflowingAssignment { span, .. } | TypeCheckError::FieldModulo { span } + | TypeCheckError::FieldNot { span } | TypeCheckError::ConstrainedReferenceToUnconstrained { span } | TypeCheckError::UnconstrainedReferenceToConstrained { span } | TypeCheckError::UnconstrainedSliceReturnToConstrained { span } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs index 1f3e9103cde6..9dfe0901016b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -578,6 +578,7 @@ impl<'interner> TypeChecker<'interner> { self.interner.push_expr(HirExpression::Prefix(HirPrefixExpression { operator: UnaryOp::MutableReference, rhs: method_call.object, + trait_method_id: None, })); self.interner.push_expr_type(new_object, new_type); self.interner.push_expr_location(new_object, location.span, location.file); @@ -604,6 +605,7 @@ impl<'interner> TypeChecker<'interner> { let object = self.interner.push_expr(HirExpression::Prefix(HirPrefixExpression { operator: UnaryOp::Dereference { implicitly_added: true }, rhs: object, + trait_method_id: None, })); self.interner.push_expr_type(object, element.as_ref().clone()); self.interner.push_expr_location(object, location.span, location.file); @@ -799,9 +801,11 @@ impl<'interner> TypeChecker<'interner> { let dereference_lhs = |this: &mut Self, lhs_type, element| { let old_lhs = *access_lhs; + *access_lhs = this.interner.push_expr(HirExpression::Prefix(HirPrefixExpression { operator: crate::ast::UnaryOp::Dereference { implicitly_added: true }, rhs: old_lhs, + trait_method_id: None, })); this.interner.push_expr_type(old_lhs, lhs_type); this.interner.push_expr_type(*access_lhs, element); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs index 8de4f118774a..ab2344746d13 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs @@ -124,6 +124,10 @@ pub enum HirArrayLiteral { pub struct HirPrefixExpression { pub operator: UnaryOp, pub rhs: ExprId, + + /// The trait method id for the operator trait method that corresponds to this operator, + /// if such a trait exists (for example, there's no trait for the dereference operator). + pub trait_method_id: Option, } #[derive(Debug, Clone)] diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs index 6777c0d1c797..8183911c8453 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs @@ -342,6 +342,11 @@ impl StructType { vecmap(&self.fields, |(name, typ)| (name.0.contents.clone(), typ.clone())) } + /// Returns the field at the given index. Panics if no field exists at the given index. + pub fn field_at(&self, index: usize) -> &(Ident, Type) { + &self.fields[index] + } + pub fn field_names(&self) -> BTreeSet { self.fields.iter().map(|(name, _)| name.clone()).collect() } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/locations.rs b/noir/noir-repo/compiler/noirc_frontend/src/locations.rs index fcaef0a8dd69..0efe385aa0a4 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/locations.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/locations.rs @@ -38,6 +38,11 @@ impl NodeInterner { let struct_type = struct_type.borrow(); Location::new(struct_type.name.span(), struct_type.location.file) } + ReferenceId::StructMember(id, field_index) => { + let struct_type = self.get_struct(id); + let struct_type = struct_type.borrow(); + Location::new(struct_type.field_at(field_index).0.span(), struct_type.location.file) + } ReferenceId::Trait(id) => { let trait_type = self.get_trait(id); Location::new(trait_type.name.span(), trait_type.location.file) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs index fabfc74b901b..be222cc4e35d 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -444,13 +444,26 @@ impl<'interner> Monomorphizer<'interner> { HirExpression::Block(block) => self.block(block.statements)?, HirExpression::Prefix(prefix) => { + let rhs = self.expr(prefix.rhs)?; let location = self.interner.expr_location(&expr); - ast::Expression::Unary(ast::Unary { - operator: prefix.operator, - rhs: Box::new(self.expr(prefix.rhs)?), - result_type: Self::convert_type(&self.interner.id_type(expr), location)?, - location, - }) + + if self.interner.get_selected_impl_for_expression(expr).is_some() { + // If an impl was selected for this prefix operator, replace it + // with a method call to the appropriate trait impl method. + let (function_type, ret) = + self.interner.get_prefix_operator_type(expr, prefix.rhs); + + let method = prefix + .trait_method_id + .expect("ice: missing trait method if when impl was found"); + let func = self.resolve_trait_method_expr(expr, function_type, method)?; + self.create_prefix_operator_impl_call(func, rhs, ret, location)? + } else { + let operator = prefix.operator; + let rhs = Box::new(rhs); + let result_type = Self::convert_type(&self.interner.id_type(expr), location)?; + ast::Expression::Unary(ast::Unary { operator, rhs, result_type, location }) + } } HirExpression::Infix(infix) => { @@ -462,11 +475,12 @@ impl<'interner> Monomorphizer<'interner> { // If an impl was selected for this infix operator, replace it // with a method call to the appropriate trait impl method. let (function_type, ret) = - self.interner.get_operator_type(infix.lhs, operator, expr); + self.interner.get_infix_operator_type(infix.lhs, operator, expr); let method = infix.trait_method_id; let func = self.resolve_trait_method_expr(expr, function_type, method)?; - self.create_operator_impl_call(func, lhs, infix.operator, rhs, ret, location)? + let operator = infix.operator; + self.create_infix_operator_impl_call(func, lhs, operator, rhs, ret, location)? } else { let lhs = Box::new(lhs); let rhs = Box::new(rhs); @@ -1651,12 +1665,12 @@ impl<'interner> Monomorphizer<'interner> { }) } - /// Call an operator overloading method for the given operator. + /// Call an infix operator overloading method for the given operator. /// This function handles the special cases some operators have which don't map /// 1 to 1 onto their operator function. For example: != requires a negation on /// the result of its `eq` method, and the comparison operators each require a /// conversion from the `Ordering` result to a boolean. - fn create_operator_impl_call( + fn create_infix_operator_impl_call( &self, func: ast::Expression, lhs: ast::Expression, @@ -1715,6 +1729,21 @@ impl<'interner> Monomorphizer<'interner> { Ok(result) } + + /// Call an operator overloading method for the given prefix operator. + fn create_prefix_operator_impl_call( + &self, + func: ast::Expression, + rhs: ast::Expression, + ret: Type, + location: Location, + ) -> Result { + let arguments = vec![rhs]; + let func = Box::new(func); + let return_type = Self::convert_type(&ret, location)?; + + Ok(ast::Expression::Call(ast::Call { func, arguments, return_type, location })) + } } fn unwrap_tuple_type(typ: &HirType) -> Vec { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs index 588b56afa1a1..a009a42df53a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::collections::HashMap; use std::fmt; use std::hash::Hash; +use std::marker::Copy; use std::ops::Deref; use fm::FileId; @@ -18,6 +19,7 @@ use crate::hir::comptime; use crate::hir::def_collector::dc_crate::CompilationError; use crate::hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait, UnresolvedTypeAlias}; use crate::hir::def_map::{LocalModuleId, ModuleId}; +use crate::macros_api::UnaryOp; use crate::QuotedType; use crate::ast::{BinaryOpKind, FunctionDefinition, ItemVisibility}; @@ -139,8 +141,11 @@ pub struct NodeInterner { /// the context to get the concrete type of the object and select the correct impl itself. selected_trait_implementations: HashMap, - /// Holds the trait ids of the traits used for operator overloading - operator_traits: HashMap, + /// Holds the trait ids of the traits used for infix operator overloading + infix_operator_traits: HashMap, + + /// Holds the trait ids of the traits used for prefix operator overloading + prefix_operator_traits: HashMap, /// The `Ordering` type is a semi-builtin type that is the result of the comparison traits. ordering_type: Option, @@ -195,7 +200,7 @@ pub struct NodeInterner { /// Edges are directed from reference nodes to referenced nodes. /// For example: /// - /// ``` + /// ```text /// let foo = 3; /// // referenced /// // ^ @@ -241,6 +246,7 @@ pub enum DependencyId { pub enum ReferenceId { Module(ModuleId), Struct(StructId), + StructMember(StructId, usize), Trait(TraitId), Global(GlobalId), Function(FuncId), @@ -563,7 +569,8 @@ impl Default for NodeInterner { next_trait_implementation_id: 0, trait_implementation_map: HashMap::new(), selected_trait_implementations: HashMap::new(), - operator_traits: HashMap::new(), + infix_operator_traits: HashMap::new(), + prefix_operator_traits: HashMap::new(), ordering_type: None, instantiation_bindings: HashMap::new(), field_indices: HashMap::new(), @@ -1071,6 +1078,10 @@ impl NodeInterner { self.id_location(expr_id).span } + pub fn try_expr_span(&self, expr_id: &ExprId) -> Option { + self.try_id_location(expr_id).map(|location| location.span) + } + pub fn expr_location(&self, expr_id: &ExprId) -> Location { self.id_location(expr_id) } @@ -1175,8 +1186,14 @@ impl NodeInterner { } /// Returns the span of an item stored in the Interner - pub fn id_location(&self, index: impl Into) -> Location { - self.id_to_location.get(&index.into()).copied().unwrap() + pub fn id_location(&self, index: impl Into + Copy) -> Location { + self.try_id_location(index) + .unwrap_or_else(|| panic!("ID is missing a source location: {:?}", index.into())) + } + + /// Returns the span of an item stored in the Interner, if present + pub fn try_id_location(&self, index: impl Into) -> Option { + self.id_to_location.get(&index.into()).copied() } /// Replaces the HirExpression at the given ExprId with a new HirExpression @@ -1665,18 +1682,29 @@ impl NodeInterner { /// Retrieves the trait id for a given binary operator. /// All binary operators correspond to a trait - although multiple may correspond /// to the same trait (such as `==` and `!=`). - /// `self.operator_traits` is expected to be filled before name resolution, + /// `self.infix_operator_traits` is expected to be filled before name resolution, /// during definition collection. pub fn get_operator_trait_method(&self, operator: BinaryOpKind) -> TraitMethodId { - let trait_id = self.operator_traits[&operator]; + let trait_id = self.infix_operator_traits[&operator]; // Assume that the operator's method to be overloaded is the first method of the trait. TraitMethodId { trait_id, method_index: 0 } } + /// Retrieves the trait id for a given unary operator. + /// Only some unary operators correspond to a trait: `-` and `!`, but for example `*` does not. + /// `self.prefix_operator_traits` is expected to be filled before name resolution, + /// during definition collection. + pub fn get_prefix_operator_trait_method(&self, operator: &UnaryOp) -> Option { + let trait_id = self.prefix_operator_traits.get(operator)?; + + // Assume that the operator's method to be overloaded is the first method of the trait. + Some(TraitMethodId { trait_id: *trait_id, method_index: 0 }) + } + /// Add the given trait as an operator trait if its name matches one of the /// operator trait names (Add, Sub, ...). - pub fn try_add_operator_trait(&mut self, trait_id: TraitId) { + pub fn try_add_infix_operator_trait(&mut self, trait_id: TraitId) { let the_trait = self.get_trait(trait_id); let operator = match the_trait.name.0.contents.as_str() { @@ -1695,17 +1723,17 @@ impl NodeInterner { _ => return, }; - self.operator_traits.insert(operator, trait_id); + self.infix_operator_traits.insert(operator, trait_id); // Some operators also require we insert a matching entry for related operators match operator { BinaryOpKind::Equal => { - self.operator_traits.insert(BinaryOpKind::NotEqual, trait_id); + self.infix_operator_traits.insert(BinaryOpKind::NotEqual, trait_id); } BinaryOpKind::Less => { - self.operator_traits.insert(BinaryOpKind::LessEqual, trait_id); - self.operator_traits.insert(BinaryOpKind::Greater, trait_id); - self.operator_traits.insert(BinaryOpKind::GreaterEqual, trait_id); + self.infix_operator_traits.insert(BinaryOpKind::LessEqual, trait_id); + self.infix_operator_traits.insert(BinaryOpKind::Greater, trait_id); + self.infix_operator_traits.insert(BinaryOpKind::GreaterEqual, trait_id); let the_trait = self.get_trait(trait_id); self.ordering_type = match &the_trait.methods[0].typ { @@ -1720,27 +1748,43 @@ impl NodeInterner { } } + /// Add the given trait as an operator trait if its name matches one of the + /// prefix operator trait names (Not or Neg). + pub fn try_add_prefix_operator_trait(&mut self, trait_id: TraitId) { + let the_trait = self.get_trait(trait_id); + + let operator = match the_trait.name.0.contents.as_str() { + "Neg" => UnaryOp::Minus, + "Not" => UnaryOp::Not, + _ => return, + }; + + self.prefix_operator_traits.insert(operator, trait_id); + } + /// This function is needed when creating a NodeInterner for testing so that calls /// to `get_operator_trait` do not panic when the stdlib isn't present. #[cfg(test)] pub fn populate_dummy_operator_traits(&mut self) { let dummy_trait = TraitId(ModuleId::dummy_id()); - self.operator_traits.insert(BinaryOpKind::Add, dummy_trait); - self.operator_traits.insert(BinaryOpKind::Subtract, dummy_trait); - self.operator_traits.insert(BinaryOpKind::Multiply, dummy_trait); - self.operator_traits.insert(BinaryOpKind::Divide, dummy_trait); - self.operator_traits.insert(BinaryOpKind::Modulo, dummy_trait); - self.operator_traits.insert(BinaryOpKind::Equal, dummy_trait); - self.operator_traits.insert(BinaryOpKind::NotEqual, dummy_trait); - self.operator_traits.insert(BinaryOpKind::Less, dummy_trait); - self.operator_traits.insert(BinaryOpKind::LessEqual, dummy_trait); - self.operator_traits.insert(BinaryOpKind::Greater, dummy_trait); - self.operator_traits.insert(BinaryOpKind::GreaterEqual, dummy_trait); - self.operator_traits.insert(BinaryOpKind::And, dummy_trait); - self.operator_traits.insert(BinaryOpKind::Or, dummy_trait); - self.operator_traits.insert(BinaryOpKind::Xor, dummy_trait); - self.operator_traits.insert(BinaryOpKind::ShiftLeft, dummy_trait); - self.operator_traits.insert(BinaryOpKind::ShiftRight, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::Add, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::Subtract, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::Multiply, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::Divide, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::Modulo, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::Equal, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::NotEqual, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::Less, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::LessEqual, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::Greater, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::GreaterEqual, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::And, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::Or, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::Xor, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::ShiftLeft, dummy_trait); + self.infix_operator_traits.insert(BinaryOpKind::ShiftRight, dummy_trait); + self.prefix_operator_traits.insert(UnaryOp::Minus, dummy_trait); + self.prefix_operator_traits.insert(UnaryOp::Not, dummy_trait); } pub(crate) fn ordering_type(&self) -> Type { @@ -1873,7 +1917,7 @@ impl NodeInterner { } /// Returns the type of an operator (which is always a function), along with its return type. - pub fn get_operator_type( + pub fn get_infix_operator_type( &self, lhs: ExprId, operator: BinaryOpKind, @@ -1894,6 +1938,15 @@ impl NodeInterner { let env = Box::new(Type::Unit); (Type::Function(args, Box::new(ret.clone()), env), ret) } + + /// Returns the type of a prefix operator (which is always a function), along with its return type. + pub fn get_prefix_operator_type(&self, operator_expr: ExprId, rhs: ExprId) -> (Type, Type) { + let rhs_type = self.id_type(rhs); + let args = vec![rhs_type]; + let ret = self.id_type(operator_expr); + let env = Box::new(Type::Unit); + (Type::Function(args, Box::new(ret.clone()), env), ret) + } } impl Methods { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs index 70f8f785d68a..8cedeeeff0d0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs @@ -86,7 +86,8 @@ pub(crate) fn get_program( program.clone().into_sorted(), root_file_id, use_legacy, - &[], // No macro processors + None, // No debug_comptime_in_file + &[], // No macro processors )); } (program, context, errors) diff --git a/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr b/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr index c218ecd23481..a56d6f603902 100644 --- a/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr +++ b/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr @@ -14,7 +14,7 @@ impl BoundedVec { /// Get an element from the vector at the given index. /// Panics if the given index points beyond the end of the vector (`self.len()`). pub fn get(self, index: u32) -> T { - assert(index < self.len); + assert(index < self.len, "Attempted to read past end of BoundedVec"); self.get_unchecked(index) } @@ -152,25 +152,16 @@ impl From<[T; Len]> for BoundedVec } mod bounded_vec_tests { - // TODO: Allow imports from "super" - use crate::collections::bounded_vec::BoundedVec; - #[test] - fn empty_equality() { - let mut bounded_vec1: BoundedVec = BoundedVec::new(); - let mut bounded_vec2: BoundedVec = BoundedVec::new(); - - assert_eq(bounded_vec1, bounded_vec2); - } + mod get { + use crate::collections::bounded_vec::BoundedVec; - #[test] - fn inequality() { - let mut bounded_vec1: BoundedVec = BoundedVec::new(); - let mut bounded_vec2: BoundedVec = BoundedVec::new(); - bounded_vec1.push(1); - bounded_vec2.push(2); + #[test(should_fail_with = "Attempted to read past end of BoundedVec")] + fn panics_when_reading_elements_past_end_of_vec() { + let vec: BoundedVec = BoundedVec::new(); - assert(bounded_vec1 != bounded_vec2); + crate::println(vec.get(0)); + } } mod set { @@ -295,4 +286,26 @@ mod bounded_vec_tests { assert_eq(bounded_vec.storage()[1], 2); } } + + mod trait_eq { + use crate::collections::bounded_vec::BoundedVec; + + #[test] + fn empty_equality() { + let mut bounded_vec1: BoundedVec = BoundedVec::new(); + let mut bounded_vec2: BoundedVec = BoundedVec::new(); + + assert_eq(bounded_vec1, bounded_vec2); + } + + #[test] + fn inequality() { + let mut bounded_vec1: BoundedVec = BoundedVec::new(); + let mut bounded_vec2: BoundedVec = BoundedVec::new(); + bounded_vec1.push(1); + bounded_vec2.push(2); + + assert(bounded_vec1 != bounded_vec2); + } + } } diff --git a/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr b/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr index 916943b737cd..f02d2702d6b6 100644 --- a/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr +++ b/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr @@ -1,6 +1,9 @@ use crate::ops::arith::{Add, Sub, Neg}; use crate::cmp::Eq; +/// A point on the embedded elliptic curve +/// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field. +/// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false. struct EmbeddedCurvePoint { x: Field, y: Field, @@ -8,32 +11,35 @@ struct EmbeddedCurvePoint { } impl EmbeddedCurvePoint { - fn new(x: Field, y: Field, is_infinite: bool) -> Self { - Self { x, y, is_infinite } - } - + /// Elliptic curve point doubling operation + /// returns the doubled point of a point P, i.e P+P fn double(self) -> EmbeddedCurvePoint { embedded_curve_add(self, self) } + /// Returns the null element of the curve; 'the point at infinity' fn point_at_infinity() -> EmbeddedCurvePoint { EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true } } } impl Add for EmbeddedCurvePoint { + /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { embedded_curve_add(self, other) } } impl Sub for EmbeddedCurvePoint { + /// Points subtraction operation, using addition and negation fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { self + other.neg() } } impl Neg for EmbeddedCurvePoint { + /// Negates a point P, i.e returns -P, by negating the y coordinate. + /// If the point is at infinity, then the result is also at infinity. fn neg(self) -> EmbeddedCurvePoint { EmbeddedCurvePoint { x: self.x, @@ -44,12 +50,15 @@ impl Neg for EmbeddedCurvePoint { } impl Eq for EmbeddedCurvePoint { + /// Checks whether two points are equal fn eq(self: Self, b: EmbeddedCurvePoint) -> bool { (self.is_infinite & b.is_infinite) | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y)) } } -// Scalar represented as low and high limbs +/// Scalar for the embedded curve represented as low and high limbs +/// By definition, the scalar field of the embedded curve is base field of the proving system curve. +/// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs. struct EmbeddedCurveScalar { lo: Field, hi: Field, @@ -60,10 +69,6 @@ impl EmbeddedCurveScalar { EmbeddedCurveScalar { lo, hi } } - pub fn derive_public_key(self) -> EmbeddedCurvePoint { - fixed_base_scalar_mul(self) - } - #[field(bn254)] fn from_field(scalar: Field) -> EmbeddedCurveScalar { let (a,b) = crate::field::bn254::decompose(scalar); @@ -72,8 +77,8 @@ impl EmbeddedCurveScalar { } impl Eq for EmbeddedCurveScalar { - fn eq(self, key: EmbeddedCurveScalar) -> bool { - (key.hi == self.hi) & (key.lo == self.lo) + fn eq(self, other: Self) -> bool { + (other.hi == self.hi) & (other.lo == self.lo) } } diff --git a/noir/noir-repo/scripts/bump-bb.sh b/noir/noir-repo/scripts/bump-bb.sh new file mode 100755 index 000000000000..36c1f78ca059 --- /dev/null +++ b/noir/noir-repo/scripts/bump-bb.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +BB_VERSION=$1 + +sed -i.bak "s/^VERSION=.*/VERSION=\"$BB_VERSION\"/" ./scripts/install_bb.sh && rm ./scripts/install_bb.sh.bak + +tmp=$(mktemp) +BACKEND_BARRETENBERG_PACKAGE_JSON=./tooling/noir_js_backend_barretenberg/package.json +jq --arg v $BB_VERSION '.dependencies."@aztec/bb.js" = $v' $BACKEND_BARRETENBERG_PACKAGE_JSON > $tmp && mv $tmp $BACKEND_BARRETENBERG_PACKAGE_JSON + +YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install diff --git a/noir/noir-repo/scripts/install_bb.sh b/noir/noir-repo/scripts/install_bb.sh index b0d55b6ff1d4..95dcfdda8800 100755 --- a/noir/noir-repo/scripts/install_bb.sh +++ b/noir/noir-repo/scripts/install_bb.sh @@ -1,6 +1,6 @@ #!/bin/bash -VERSION="0.43.0" +VERSION="0.46.1" BBUP_PATH=~/.bb/bbup diff --git a/noir/noir-repo/test_programs/compile_failure/unary_not_on_field_type_variable/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/unary_not_on_field_type_variable/Nargo.toml new file mode 100644 index 000000000000..ae5c9ecb9c93 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/unary_not_on_field_type_variable/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unary_not_on_field_type_variable" +type = "bin" +authors = [""] +compiler_version = "" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/unary_not_on_field_type_variable/src/main.nr b/noir/noir-repo/test_programs/compile_failure/unary_not_on_field_type_variable/src/main.nr new file mode 100644 index 000000000000..1023f753c32d --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/unary_not_on_field_type_variable/src/main.nr @@ -0,0 +1,4 @@ +fn main() { + let num: Field = 0; + assert_eq(!0, num); +} diff --git a/noir/noir-repo/test_programs/execution_success/binary_operator_overloading/Nargo.toml b/noir/noir-repo/test_programs/execution_success/binary_operator_overloading/Nargo.toml new file mode 100644 index 000000000000..a43f38bdf302 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/binary_operator_overloading/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "binary_operator_overloading" +type = "bin" +authors = [""] +compiler_version = ">=0.20.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/operator_overloading/Prover.toml b/noir/noir-repo/test_programs/execution_success/binary_operator_overloading/Prover.toml similarity index 100% rename from noir/noir-repo/test_programs/execution_success/operator_overloading/Prover.toml rename to noir/noir-repo/test_programs/execution_success/binary_operator_overloading/Prover.toml diff --git a/noir/noir-repo/test_programs/execution_success/operator_overloading/src/main.nr b/noir/noir-repo/test_programs/execution_success/binary_operator_overloading/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/execution_success/operator_overloading/src/main.nr rename to noir/noir-repo/test_programs/execution_success/binary_operator_overloading/src/main.nr diff --git a/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr b/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr index 66ac0a2b3132..fd2fc20d08f0 100644 --- a/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr @@ -10,7 +10,7 @@ fn main( to_pubkey_x: Field, to_pubkey_y: Field ) -> pub [Field; 2] { - let priv_key_as_scalar = std::embedded_curve_ops::EmbeddedCurveScalar::new(priv_key, 0); + let priv_key_as_scalar = std::embedded_curve_ops::EmbeddedCurveScalar { lo: priv_key, hi: 0 }; // Compute public key from private key to show ownership let pubkey = std::embedded_curve_ops::fixed_base_scalar_mul(priv_key_as_scalar); // Compute input note commitment diff --git a/noir/noir-repo/test_programs/execution_success/operator_overloading/Nargo.toml b/noir/noir-repo/test_programs/execution_success/unary_operator_overloading/Nargo.toml similarity index 70% rename from noir/noir-repo/test_programs/execution_success/operator_overloading/Nargo.toml rename to noir/noir-repo/test_programs/execution_success/unary_operator_overloading/Nargo.toml index 7f9f18ff567a..ebc88faaaf46 100644 --- a/noir/noir-repo/test_programs/execution_success/operator_overloading/Nargo.toml +++ b/noir/noir-repo/test_programs/execution_success/unary_operator_overloading/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "operator_overloading" +name = "unary_operator_overloading" type = "bin" authors = [""] compiler_version = ">=0.20.0" diff --git a/noir/noir-repo/test_programs/execution_success/unary_operator_overloading/Prover.toml b/noir/noir-repo/test_programs/execution_success/unary_operator_overloading/Prover.toml new file mode 100644 index 000000000000..b95c23a4d316 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/unary_operator_overloading/Prover.toml @@ -0,0 +1 @@ +x = 3 diff --git a/noir/noir-repo/test_programs/execution_success/unary_operator_overloading/src/main.nr b/noir/noir-repo/test_programs/execution_success/unary_operator_overloading/src/main.nr new file mode 100644 index 000000000000..20cdac514344 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/unary_operator_overloading/src/main.nr @@ -0,0 +1,36 @@ +use std::ops::{Neg, Not}; + +// x = 3 +fn main(x: u32) { + let wx = Wrapper::new(x as i32); + let ex: i32 = 3; + + assert((-wx).inner == -ex); + assert((!wx).inner == !ex); + + // Check that it works with type variables (x's type isn't immediately known) + let x = 3; + assert(-3 == -x); +} + +struct Wrapper { + inner: i32 +} + +impl Wrapper { + fn new(inner: i32) -> Self { + Wrapper { inner } + } +} + +impl Neg for Wrapper { + fn neg(self) -> Wrapper { + Wrapper::new(-self.inner) + } +} + +impl Not for Wrapper { + fn not(self) -> Wrapper { + Wrapper::new(!self.inner) + } +} diff --git a/noir/noir-repo/test_programs/gates_report.sh b/noir/noir-repo/test_programs/gates_report.sh index b33e81b037c9..6c901ff24bc4 100755 --- a/noir/noir-repo/test_programs/gates_report.sh +++ b/noir/noir-repo/test_programs/gates_report.sh @@ -4,7 +4,7 @@ set -e BACKEND=${BACKEND:-bb} # These tests are incompatible with gas reporting -excluded_dirs=("workspace" "workspace_default_member" "double_verify_nested_proof") +excluded_dirs=("workspace" "workspace_default_member" "databus") current_dir=$(pwd) artifacts_path="$current_dir/acir_artifacts" @@ -18,6 +18,10 @@ NUM_ARTIFACTS=$(ls -1q "$artifacts_path" | wc -l) ITER="1" for pathname in $test_dirs; do ARTIFACT_NAME=$(basename "$pathname") + if [[ " ${excluded_dirs[@]} " =~ "$ARTIFACT_NAME" ]]; then + ITER=$(( $ITER + 1 )) + continue + fi GATES_INFO=$($BACKEND gates -b "$artifacts_path/$ARTIFACT_NAME/target/program.json") MAIN_FUNCTION_INFO=$(echo $GATES_INFO | jq -r '.functions[0] | .name = "main"') diff --git a/noir/noir-repo/tooling/lsp/src/lib.rs b/noir/noir-repo/tooling/lsp/src/lib.rs index e47dfff714ac..b62f97a49183 100644 --- a/noir/noir-repo/tooling/lsp/src/lib.rs +++ b/noir/noir-repo/tooling/lsp/src/lib.rs @@ -373,7 +373,8 @@ fn prepare_package_from_source_string() { let mut state = LspState::new(&client, acvm::blackbox_solver::StubbedBlackBoxSolver); let (mut context, crate_id) = crate::prepare_source(source.to_string(), &mut state); - let _check_result = noirc_driver::check_crate(&mut context, crate_id, false, false, false); + let _check_result = + noirc_driver::check_crate(&mut context, crate_id, false, false, false, None); let main_func_id = context.get_main_function(&crate_id); assert!(main_func_id.is_some()); } diff --git a/noir/noir-repo/tooling/lsp/src/notifications/mod.rs b/noir/noir-repo/tooling/lsp/src/notifications/mod.rs index ed0ac13fae56..46a7b1cf866c 100644 --- a/noir/noir-repo/tooling/lsp/src/notifications/mod.rs +++ b/noir/noir-repo/tooling/lsp/src/notifications/mod.rs @@ -56,7 +56,7 @@ pub(super) fn on_did_change_text_document( state.input_files.insert(params.text_document.uri.to_string(), text.clone()); let (mut context, crate_id) = prepare_source(text, state); - let _ = check_crate(&mut context, crate_id, false, false, false); + let _ = check_crate(&mut context, crate_id, false, false, false, None); let workspace = match resolve_workspace_for_source_path( params.text_document.uri.to_file_path().unwrap().as_path(), @@ -139,10 +139,11 @@ fn process_noir_document( let (mut context, crate_id) = crate::prepare_package(&workspace_file_manager, &parsed_files, package); - let file_diagnostics = match check_crate(&mut context, crate_id, false, false, false) { - Ok(((), warnings)) => warnings, - Err(errors_and_warnings) => errors_and_warnings, - }; + let file_diagnostics = + match check_crate(&mut context, crate_id, false, false, false, None) { + Ok(((), warnings)) => warnings, + Err(errors_and_warnings) => errors_and_warnings, + }; let package_root_dir: String = package.root_dir.as_os_str().to_string_lossy().into(); @@ -190,6 +191,7 @@ fn process_noir_document( let severity = match diagnostic.kind { DiagnosticKind::Error => DiagnosticSeverity::ERROR, DiagnosticKind::Warning => DiagnosticSeverity::WARNING, + DiagnosticKind::Info => DiagnosticSeverity::INFORMATION, DiagnosticKind::Bug => DiagnosticSeverity::WARNING, }; Some(Diagnostic { diff --git a/noir/noir-repo/tooling/lsp/src/requests/code_lens_request.rs b/noir/noir-repo/tooling/lsp/src/requests/code_lens_request.rs index 744bddedd9dc..0b8803edc6f4 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/code_lens_request.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/code_lens_request.rs @@ -67,7 +67,7 @@ fn on_code_lens_request_inner( let (mut context, crate_id) = prepare_source(source_string, state); // We ignore the warnings and errors produced by compilation for producing code lenses // because we can still get the test functions even if compilation fails - let _ = check_crate(&mut context, crate_id, false, false, false); + let _ = check_crate(&mut context, crate_id, false, false, false, None); let collected_lenses = collect_lenses_for_package(&context, crate_id, &workspace, package, None); diff --git a/noir/noir-repo/tooling/lsp/src/requests/mod.rs b/noir/noir-repo/tooling/lsp/src/requests/mod.rs index 266b5b124ac7..48299ff74591 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/mod.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/mod.rs @@ -294,7 +294,7 @@ where interner = def_interner; } else { // We ignore the warnings and errors produced by compilation while resolving the definition - let _ = noirc_driver::check_crate(&mut context, crate_id, false, false, false); + let _ = noirc_driver::check_crate(&mut context, crate_id, false, false, false, None); interner = &context.def_interner; } diff --git a/noir/noir-repo/tooling/lsp/src/requests/rename.rs b/noir/noir-repo/tooling/lsp/src/requests/rename.rs index ac6c6792e15f..906a5cbcaabb 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/rename.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/rename.rs @@ -199,4 +199,9 @@ mod rename_tests { async fn test_rename_local_variable() { check_rename_succeeds("local_variable", "some_var").await; } + + #[test] + async fn test_rename_struct_member() { + check_rename_succeeds("struct_member", "some_member").await; + } } diff --git a/noir/noir-repo/tooling/lsp/src/requests/test_run.rs b/noir/noir-repo/tooling/lsp/src/requests/test_run.rs index acd4f5800f38..b4b9b62d6b68 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/test_run.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/test_run.rs @@ -59,7 +59,7 @@ fn on_test_run_request_inner( Some(package) => { let (mut context, crate_id) = crate::prepare_package(&workspace_file_manager, &parsed_files, package); - if check_crate(&mut context, crate_id, false, false, false).is_err() { + if check_crate(&mut context, crate_id, false, false, false, None).is_err() { let result = NargoTestRunResult { id: params.id.clone(), result: "error".to_string(), diff --git a/noir/noir-repo/tooling/lsp/src/requests/tests.rs b/noir/noir-repo/tooling/lsp/src/requests/tests.rs index a2aa3ebc0bf5..fb8b845df04e 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/tests.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/tests.rs @@ -61,7 +61,7 @@ fn on_tests_request_inner( crate::prepare_package(&workspace_file_manager, &parsed_files, package); // We ignore the warnings and errors produced by compilation for producing tests // because we can still get the test functions even if compilation fails - let _ = check_crate(&mut context, crate_id, false, false, false); + let _ = check_crate(&mut context, crate_id, false, false, false, None); // We don't add test headings for a package if it contains no `#[test]` functions get_package_tests_in_crate(&context, &crate_id, &package.name) diff --git a/noir/noir-repo/tooling/lsp/test_programs/struct_member/Nargo.toml b/noir/noir-repo/tooling/lsp/test_programs/struct_member/Nargo.toml new file mode 100644 index 000000000000..5272b9abb68d --- /dev/null +++ b/noir/noir-repo/tooling/lsp/test_programs/struct_member/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "struct_member" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/tooling/lsp/test_programs/struct_member/src/main.nr b/noir/noir-repo/tooling/lsp/test_programs/struct_member/src/main.nr new file mode 100644 index 000000000000..3f1bac9df669 --- /dev/null +++ b/noir/noir-repo/tooling/lsp/test_programs/struct_member/src/main.nr @@ -0,0 +1,12 @@ +struct Foo { + some_member: Field +} + +fn main() { + let mut foo = Foo { some_member: 1 }; + foo.some_member = 2; + let _ = foo.some_member; + + let Foo { some_member } = foo; + let Foo { some_member: some_var } = foo; +} diff --git a/noir/noir-repo/tooling/nargo_cli/build.rs b/noir/noir-repo/tooling/nargo_cli/build.rs index 3789595aa263..9dfa0dfe861a 100644 --- a/noir/noir-repo/tooling/nargo_cli/build.rs +++ b/noir/noir-repo/tooling/nargo_cli/build.rs @@ -61,7 +61,7 @@ const IGNORED_BRILLIG_TESTS: [&str; 11] = [ /// Certain features are only available in the elaborator. /// We skip these tests for non-elaborator code since they are not /// expected to work there. This can be removed once the old code is removed. -const IGNORED_NEW_FEATURE_TESTS: [&str; 8] = [ +const IGNORED_NEW_FEATURE_TESTS: [&str; 9] = [ "macros", "wildcard_type", "type_definition_annotation", @@ -69,6 +69,7 @@ const IGNORED_NEW_FEATURE_TESTS: [&str; 8] = [ "derive_impl", "comptime_traits", "comptime_slice_methods", + "unary_operator_overloading", "unquote_multiple_items_from_annotation", ]; diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs index 2db3b10429a0..95726492418a 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs @@ -88,6 +88,7 @@ fn check_package( compile_options.disable_macros, compile_options.silence_warnings, compile_options.use_legacy, + compile_options.debug_comptime_in_file.as_deref(), )?; if package.is_library() || package.is_contract() { @@ -161,8 +162,16 @@ pub(crate) fn check_crate_and_report_errors( disable_macros: bool, silence_warnings: bool, use_legacy: bool, + debug_comptime_in_file: Option<&str>, ) -> Result<(), CompileError> { - let result = check_crate(context, crate_id, deny_warnings, disable_macros, use_legacy); + let result = check_crate( + context, + crate_id, + deny_warnings, + disable_macros, + use_legacy, + debug_comptime_in_file, + ); report_errors(result, &context.file_manager, deny_warnings, silence_warnings) } diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/export_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/export_cmd.rs index ee30b29b0f0e..105190c653f8 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/export_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/export_cmd.rs @@ -90,6 +90,7 @@ fn compile_exported_functions( compile_options.disable_macros, compile_options.silence_warnings, compile_options.use_legacy, + compile_options.debug_comptime_in_file.as_deref(), )?; let exported_functions = context.get_all_exported_functions_in_crate(&crate_id); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs index de9e8dc5d7c4..27c66c956d90 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs @@ -177,6 +177,7 @@ fn run_test + Default>( compile_options.deny_warnings, compile_options.disable_macros, compile_options.use_legacy, + compile_options.debug_comptime_in_file.as_deref(), ) .expect("Any errors should have occurred when collecting test functions"); @@ -244,6 +245,7 @@ fn get_tests_in_package( compile_options.disable_macros, compile_options.silence_warnings, compile_options.use_legacy, + compile_options.debug_comptime_in_file.as_deref(), )?; Ok(context diff --git a/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs b/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs index bf6614860e2d..10711b6d0111 100644 --- a/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs +++ b/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs @@ -32,7 +32,7 @@ fn run_stdlib_tests() { let (mut context, dummy_crate_id) = prepare_package(&file_manager, &parsed_files, &dummy_package); - let result = check_crate(&mut context, dummy_crate_id, false, false, false); + let result = check_crate(&mut context, dummy_crate_id, false, false, false, None); report_errors(result, &context.file_manager, true, false) .expect("Error encountered while compiling standard library"); From c92cf589efd49cd276ee9d7287957a1b91c1fdba Mon Sep 17 00:00:00 2001 From: Aztec Bot <49558828+AztecBot@users.noreply.github.com> Date: Thu, 11 Jul 2024 08:52:18 -0400 Subject: [PATCH 27/32] chore(master): Release 0.46.3 (#7423) :robot: I have created a release *beep* *boop* ---
aztec-package: 0.46.3 ## [0.46.3](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.46.2...aztec-package-v0.46.3) (2024-07-11) ### Miscellaneous * **aztec-package:** Synchronize aztec-packages versions
barretenberg.js: 0.46.3 ## [0.46.3](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.46.2...barretenberg.js-v0.46.3) (2024-07-11) ### Miscellaneous * **barretenberg.js:** Synchronize aztec-packages versions
aztec-packages: 0.46.3 ## [0.46.3](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.46.2...aztec-packages-v0.46.3) (2024-07-11) ### Features * Add CLI argument for debugging comptime blocks (https://github.com/noir-lang/noir/pull/5192) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) * Add reset tiny and optimize tail ([#7422](https://github.com/AztecProtocol/aztec-packages/issues/7422)) ([399917b](https://github.com/AztecProtocol/aztec-packages/commit/399917b3e6916805bb55596b47183e44700fe8f5)) * **avm:** Calldatacopy and return gadget ([#7415](https://github.com/AztecProtocol/aztec-packages/issues/7415)) ([ec39e4e](https://github.com/AztecProtocol/aztec-packages/commit/ec39e4e2ffecb6d6e355eb3963008b710cc11d2c)), closes [#7381](https://github.com/AztecProtocol/aztec-packages/issues/7381) [#7211](https://github.com/AztecProtocol/aztec-packages/issues/7211) * **avm:** Make ProverPolynomials::get_row return references ([#7419](https://github.com/AztecProtocol/aztec-packages/issues/7419)) ([108fc5f](https://github.com/AztecProtocol/aztec-packages/commit/108fc5f92e44b027b38fa31614e14f2b7a9f650a)) * Integrate new proving systems in e2e ([#6971](https://github.com/AztecProtocol/aztec-packages/issues/6971)) ([723a0c1](https://github.com/AztecProtocol/aztec-packages/commit/723a0c10c9010f3869f103c77f71950efbf7106c)) * Lsp rename/find-all-references for struct members (https://github.com/noir-lang/noir/pull/5443) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) * MSM sorting ([#7351](https://github.com/AztecProtocol/aztec-packages/issues/7351)) ([5cbdc54](https://github.com/AztecProtocol/aztec-packages/commit/5cbdc549f0ab137ab4fa601e20d80699871faaf4)) * **optimization:** Deduplicate more instructions (https://github.com/noir-lang/noir/pull/5457) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) * Prefix operator overload trait dispatch (https://github.com/noir-lang/noir/pull/5423) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) * Remove proof from L1 Rollup process ([#7347](https://github.com/AztecProtocol/aztec-packages/issues/7347)) ([2645eab](https://github.com/AztecProtocol/aztec-packages/commit/2645eab19bac030835c959eb01f8f3af27f89adf)), closes [#7346](https://github.com/AztecProtocol/aztec-packages/issues/7346) * Remove ram tables in note_getter ([#7434](https://github.com/AztecProtocol/aztec-packages/issues/7434)) ([fd67da3](https://github.com/AztecProtocol/aztec-packages/commit/fd67da35da3949bf112392d7cf1d512c5eed23eb)) * Sync from aztec-packages (https://github.com/noir-lang/noir/pull/5467) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) * Typing return values of embedded_curve_ops ([#7413](https://github.com/AztecProtocol/aztec-packages/issues/7413)) ([db96077](https://github.com/AztecProtocol/aztec-packages/commit/db960772abfead018e4f6da55ae259c6b3d574ef)) ### Bug Fixes * **avm:** Fixes AVM full tests and decrease timeout to 35 minutes ([#7438](https://github.com/AztecProtocol/aztec-packages/issues/7438)) ([2a7494b](https://github.com/AztecProtocol/aztec-packages/commit/2a7494baec4396b9fa62f0a9c240b4b02f23fb1d)) * Memory init with no other ops gate counting ([#7427](https://github.com/AztecProtocol/aztec-packages/issues/7427)) ([e7177ba](https://github.com/AztecProtocol/aztec-packages/commit/e7177ba0f96c1da3edbcdffdaaf88c128bbdd719)) * Pass secrets to ci-arm.yml ([#7436](https://github.com/AztecProtocol/aztec-packages/issues/7436)) ([619501d](https://github.com/AztecProtocol/aztec-packages/commit/619501df5aa4c544cd8607dae5d4e20595109b2f)) * Remove compile-time error for invalid indices (https://github.com/noir-lang/noir/pull/5466) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) * Using different generators in private refund ([#7414](https://github.com/AztecProtocol/aztec-packages/issues/7414)) ([59b92ca](https://github.com/AztecProtocol/aztec-packages/commit/59b92ca0f72ca3705dd6933b304897c91edc81c3)), closes [#7320](https://github.com/AztecProtocol/aztec-packages/issues/7320) ### Miscellaneous * **bb:** Fix double increment ([#7428](https://github.com/AztecProtocol/aztec-packages/issues/7428)) ([7870a58](https://github.com/AztecProtocol/aztec-packages/commit/7870a5815dc759aed7097dc9eb5ab8e10b3a1865)) * **boxes:** Adding an init command for an empty project ([#7398](https://github.com/AztecProtocol/aztec-packages/issues/7398)) ([a6a605d](https://github.com/AztecProtocol/aztec-packages/commit/a6a605d3cd83b2f4b8e47722ff262382a7a2ea1d)) * Bump bb to 0.45.1 (https://github.com/noir-lang/noir/pull/5469) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) * Disable flaky cheat code test ([7b8c2ba](https://github.com/AztecProtocol/aztec-packages/commit/7b8c2ba14600f4e51896bec15c6e7f3286885050)) * Document EmbeddedCurvePoint (https://github.com/noir-lang/noir/pull/5468) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) * Minimize usage of get_row in inverse computation ([#7431](https://github.com/AztecProtocol/aztec-packages/issues/7431)) ([f177887](https://github.com/AztecProtocol/aztec-packages/commit/f1778876eac8ef65edd06c49d1ddf2429d6583e5)) * Private refund cleanup ([#7403](https://github.com/AztecProtocol/aztec-packages/issues/7403)) ([ebec8ff](https://github.com/AztecProtocol/aztec-packages/commit/ebec8ff48900b48be3fce6bc9a52bcb566c79a7f)) * Replace relative paths to noir-protocol-circuits ([842f6d1](https://github.com/AztecProtocol/aztec-packages/commit/842f6d1978aaeba9d39e3433f06f2f402145b754)) * Unbundle `check_array_is_initialized` (https://github.com/noir-lang/noir/pull/5451) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4))
barretenberg: 0.46.3 ## [0.46.3](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.46.2...barretenberg-v0.46.3) (2024-07-11) ### Features * **avm:** Calldatacopy and return gadget ([#7415](https://github.com/AztecProtocol/aztec-packages/issues/7415)) ([ec39e4e](https://github.com/AztecProtocol/aztec-packages/commit/ec39e4e2ffecb6d6e355eb3963008b710cc11d2c)), closes [#7381](https://github.com/AztecProtocol/aztec-packages/issues/7381) [#7211](https://github.com/AztecProtocol/aztec-packages/issues/7211) * **avm:** Make ProverPolynomials::get_row return references ([#7419](https://github.com/AztecProtocol/aztec-packages/issues/7419)) ([108fc5f](https://github.com/AztecProtocol/aztec-packages/commit/108fc5f92e44b027b38fa31614e14f2b7a9f650a)) * Integrate new proving systems in e2e ([#6971](https://github.com/AztecProtocol/aztec-packages/issues/6971)) ([723a0c1](https://github.com/AztecProtocol/aztec-packages/commit/723a0c10c9010f3869f103c77f71950efbf7106c)) * MSM sorting ([#7351](https://github.com/AztecProtocol/aztec-packages/issues/7351)) ([5cbdc54](https://github.com/AztecProtocol/aztec-packages/commit/5cbdc549f0ab137ab4fa601e20d80699871faaf4)) ### Bug Fixes * **avm:** Fixes AVM full tests and decrease timeout to 35 minutes ([#7438](https://github.com/AztecProtocol/aztec-packages/issues/7438)) ([2a7494b](https://github.com/AztecProtocol/aztec-packages/commit/2a7494baec4396b9fa62f0a9c240b4b02f23fb1d)) * Memory init with no other ops gate counting ([#7427](https://github.com/AztecProtocol/aztec-packages/issues/7427)) ([e7177ba](https://github.com/AztecProtocol/aztec-packages/commit/e7177ba0f96c1da3edbcdffdaaf88c128bbdd719)) ### Miscellaneous * **bb:** Fix double increment ([#7428](https://github.com/AztecProtocol/aztec-packages/issues/7428)) ([7870a58](https://github.com/AztecProtocol/aztec-packages/commit/7870a5815dc759aed7097dc9eb5ab8e10b3a1865)) * Minimize usage of get_row in inverse computation ([#7431](https://github.com/AztecProtocol/aztec-packages/issues/7431)) ([f177887](https://github.com/AztecProtocol/aztec-packages/commit/f1778876eac8ef65edd06c49d1ddf2429d6583e5))
--- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- .release-please-manifest.json | 8 +++---- CHANGELOG.md | 41 +++++++++++++++++++++++++++++++++ barretenberg/CHANGELOG.md | 22 ++++++++++++++++++ barretenberg/cpp/CMakeLists.txt | 2 +- barretenberg/ts/CHANGELOG.md | 7 ++++++ barretenberg/ts/package.json | 2 +- yarn-project/aztec/CHANGELOG.md | 7 ++++++ yarn-project/aztec/package.json | 2 +- 8 files changed, 84 insertions(+), 7 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 40a6a4104df1..36d8b5d1d5db 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,7 +1,7 @@ { - ".": "0.46.2", + ".": "0.46.3", "yarn-project/cli": "0.35.1", - "yarn-project/aztec": "0.46.2", - "barretenberg": "0.46.2", - "barretenberg/ts": "0.46.2" + "yarn-project/aztec": "0.46.3", + "barretenberg": "0.46.3", + "barretenberg/ts": "0.46.3" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fbe4d178fd9..4a801c1da2c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,46 @@ # Changelog +## [0.46.3](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.46.2...aztec-packages-v0.46.3) (2024-07-11) + + +### Features + +* Add CLI argument for debugging comptime blocks (https://github.com/noir-lang/noir/pull/5192) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) +* Add reset tiny and optimize tail ([#7422](https://github.com/AztecProtocol/aztec-packages/issues/7422)) ([399917b](https://github.com/AztecProtocol/aztec-packages/commit/399917b3e6916805bb55596b47183e44700fe8f5)) +* **avm:** Calldatacopy and return gadget ([#7415](https://github.com/AztecProtocol/aztec-packages/issues/7415)) ([ec39e4e](https://github.com/AztecProtocol/aztec-packages/commit/ec39e4e2ffecb6d6e355eb3963008b710cc11d2c)), closes [#7381](https://github.com/AztecProtocol/aztec-packages/issues/7381) [#7211](https://github.com/AztecProtocol/aztec-packages/issues/7211) +* **avm:** Make ProverPolynomials::get_row return references ([#7419](https://github.com/AztecProtocol/aztec-packages/issues/7419)) ([108fc5f](https://github.com/AztecProtocol/aztec-packages/commit/108fc5f92e44b027b38fa31614e14f2b7a9f650a)) +* Integrate new proving systems in e2e ([#6971](https://github.com/AztecProtocol/aztec-packages/issues/6971)) ([723a0c1](https://github.com/AztecProtocol/aztec-packages/commit/723a0c10c9010f3869f103c77f71950efbf7106c)) +* Lsp rename/find-all-references for struct members (https://github.com/noir-lang/noir/pull/5443) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) +* MSM sorting ([#7351](https://github.com/AztecProtocol/aztec-packages/issues/7351)) ([5cbdc54](https://github.com/AztecProtocol/aztec-packages/commit/5cbdc549f0ab137ab4fa601e20d80699871faaf4)) +* **optimization:** Deduplicate more instructions (https://github.com/noir-lang/noir/pull/5457) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) +* Prefix operator overload trait dispatch (https://github.com/noir-lang/noir/pull/5423) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) +* Remove proof from L1 Rollup process ([#7347](https://github.com/AztecProtocol/aztec-packages/issues/7347)) ([2645eab](https://github.com/AztecProtocol/aztec-packages/commit/2645eab19bac030835c959eb01f8f3af27f89adf)), closes [#7346](https://github.com/AztecProtocol/aztec-packages/issues/7346) +* Remove ram tables in note_getter ([#7434](https://github.com/AztecProtocol/aztec-packages/issues/7434)) ([fd67da3](https://github.com/AztecProtocol/aztec-packages/commit/fd67da35da3949bf112392d7cf1d512c5eed23eb)) +* Sync from aztec-packages (https://github.com/noir-lang/noir/pull/5467) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) +* Typing return values of embedded_curve_ops ([#7413](https://github.com/AztecProtocol/aztec-packages/issues/7413)) ([db96077](https://github.com/AztecProtocol/aztec-packages/commit/db960772abfead018e4f6da55ae259c6b3d574ef)) + + +### Bug Fixes + +* **avm:** Fixes AVM full tests and decrease timeout to 35 minutes ([#7438](https://github.com/AztecProtocol/aztec-packages/issues/7438)) ([2a7494b](https://github.com/AztecProtocol/aztec-packages/commit/2a7494baec4396b9fa62f0a9c240b4b02f23fb1d)) +* Memory init with no other ops gate counting ([#7427](https://github.com/AztecProtocol/aztec-packages/issues/7427)) ([e7177ba](https://github.com/AztecProtocol/aztec-packages/commit/e7177ba0f96c1da3edbcdffdaaf88c128bbdd719)) +* Pass secrets to ci-arm.yml ([#7436](https://github.com/AztecProtocol/aztec-packages/issues/7436)) ([619501d](https://github.com/AztecProtocol/aztec-packages/commit/619501df5aa4c544cd8607dae5d4e20595109b2f)) +* Remove compile-time error for invalid indices (https://github.com/noir-lang/noir/pull/5466) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) +* Using different generators in private refund ([#7414](https://github.com/AztecProtocol/aztec-packages/issues/7414)) ([59b92ca](https://github.com/AztecProtocol/aztec-packages/commit/59b92ca0f72ca3705dd6933b304897c91edc81c3)), closes [#7320](https://github.com/AztecProtocol/aztec-packages/issues/7320) + + +### Miscellaneous + +* **bb:** Fix double increment ([#7428](https://github.com/AztecProtocol/aztec-packages/issues/7428)) ([7870a58](https://github.com/AztecProtocol/aztec-packages/commit/7870a5815dc759aed7097dc9eb5ab8e10b3a1865)) +* **boxes:** Adding an init command for an empty project ([#7398](https://github.com/AztecProtocol/aztec-packages/issues/7398)) ([a6a605d](https://github.com/AztecProtocol/aztec-packages/commit/a6a605d3cd83b2f4b8e47722ff262382a7a2ea1d)) +* Bump bb to 0.45.1 (https://github.com/noir-lang/noir/pull/5469) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) +* Disable flaky cheat code test ([7b8c2ba](https://github.com/AztecProtocol/aztec-packages/commit/7b8c2ba14600f4e51896bec15c6e7f3286885050)) +* Document EmbeddedCurvePoint (https://github.com/noir-lang/noir/pull/5468) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) +* Minimize usage of get_row in inverse computation ([#7431](https://github.com/AztecProtocol/aztec-packages/issues/7431)) ([f177887](https://github.com/AztecProtocol/aztec-packages/commit/f1778876eac8ef65edd06c49d1ddf2429d6583e5)) +* Private refund cleanup ([#7403](https://github.com/AztecProtocol/aztec-packages/issues/7403)) ([ebec8ff](https://github.com/AztecProtocol/aztec-packages/commit/ebec8ff48900b48be3fce6bc9a52bcb566c79a7f)) +* Replace relative paths to noir-protocol-circuits ([842f6d1](https://github.com/AztecProtocol/aztec-packages/commit/842f6d1978aaeba9d39e3433f06f2f402145b754)) +* Unbundle `check_array_is_initialized` (https://github.com/noir-lang/noir/pull/5451) ([97ecff5](https://github.com/AztecProtocol/aztec-packages/commit/97ecff5ea76a0da878bdccc453b121147f726ec4)) + ## [0.46.2](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.46.1...aztec-packages-v0.46.2) (2024-07-10) diff --git a/barretenberg/CHANGELOG.md b/barretenberg/CHANGELOG.md index 2c69bb01e868..bec04ddf0763 100644 --- a/barretenberg/CHANGELOG.md +++ b/barretenberg/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## [0.46.3](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.46.2...barretenberg-v0.46.3) (2024-07-11) + + +### Features + +* **avm:** Calldatacopy and return gadget ([#7415](https://github.com/AztecProtocol/aztec-packages/issues/7415)) ([ec39e4e](https://github.com/AztecProtocol/aztec-packages/commit/ec39e4e2ffecb6d6e355eb3963008b710cc11d2c)), closes [#7381](https://github.com/AztecProtocol/aztec-packages/issues/7381) [#7211](https://github.com/AztecProtocol/aztec-packages/issues/7211) +* **avm:** Make ProverPolynomials::get_row return references ([#7419](https://github.com/AztecProtocol/aztec-packages/issues/7419)) ([108fc5f](https://github.com/AztecProtocol/aztec-packages/commit/108fc5f92e44b027b38fa31614e14f2b7a9f650a)) +* Integrate new proving systems in e2e ([#6971](https://github.com/AztecProtocol/aztec-packages/issues/6971)) ([723a0c1](https://github.com/AztecProtocol/aztec-packages/commit/723a0c10c9010f3869f103c77f71950efbf7106c)) +* MSM sorting ([#7351](https://github.com/AztecProtocol/aztec-packages/issues/7351)) ([5cbdc54](https://github.com/AztecProtocol/aztec-packages/commit/5cbdc549f0ab137ab4fa601e20d80699871faaf4)) + + +### Bug Fixes + +* **avm:** Fixes AVM full tests and decrease timeout to 35 minutes ([#7438](https://github.com/AztecProtocol/aztec-packages/issues/7438)) ([2a7494b](https://github.com/AztecProtocol/aztec-packages/commit/2a7494baec4396b9fa62f0a9c240b4b02f23fb1d)) +* Memory init with no other ops gate counting ([#7427](https://github.com/AztecProtocol/aztec-packages/issues/7427)) ([e7177ba](https://github.com/AztecProtocol/aztec-packages/commit/e7177ba0f96c1da3edbcdffdaaf88c128bbdd719)) + + +### Miscellaneous + +* **bb:** Fix double increment ([#7428](https://github.com/AztecProtocol/aztec-packages/issues/7428)) ([7870a58](https://github.com/AztecProtocol/aztec-packages/commit/7870a5815dc759aed7097dc9eb5ab8e10b3a1865)) +* Minimize usage of get_row in inverse computation ([#7431](https://github.com/AztecProtocol/aztec-packages/issues/7431)) ([f177887](https://github.com/AztecProtocol/aztec-packages/commit/f1778876eac8ef65edd06c49d1ddf2429d6583e5)) + ## [0.46.2](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.46.1...barretenberg-v0.46.2) (2024-07-10) diff --git a/barretenberg/cpp/CMakeLists.txt b/barretenberg/cpp/CMakeLists.txt index 780eb8ed5e2a..99ed8ffdda5d 100644 --- a/barretenberg/cpp/CMakeLists.txt +++ b/barretenberg/cpp/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.24 FATAL_ERROR) project( Barretenberg DESCRIPTION "BN254 elliptic curve library, and PLONK SNARK prover" - VERSION 0.46.2 # x-release-please-version + VERSION 0.46.3 # x-release-please-version LANGUAGES CXX C ) # Insert version into `bb` config file diff --git a/barretenberg/ts/CHANGELOG.md b/barretenberg/ts/CHANGELOG.md index fa618342a086..51ae4110288a 100644 --- a/barretenberg/ts/CHANGELOG.md +++ b/barretenberg/ts/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.46.3](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.46.2...barretenberg.js-v0.46.3) (2024-07-11) + + +### Miscellaneous + +* **barretenberg.js:** Synchronize aztec-packages versions + ## [0.46.2](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.46.1...barretenberg.js-v0.46.2) (2024-07-10) diff --git a/barretenberg/ts/package.json b/barretenberg/ts/package.json index 822a88c4093c..a521ff717823 100644 --- a/barretenberg/ts/package.json +++ b/barretenberg/ts/package.json @@ -1,6 +1,6 @@ { "name": "@aztec/bb.js", - "version": "0.46.2", + "version": "0.46.3", "homepage": "https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg/ts", "license": "MIT", "type": "module", diff --git a/yarn-project/aztec/CHANGELOG.md b/yarn-project/aztec/CHANGELOG.md index bdacecd0833a..96a34aa66940 100644 --- a/yarn-project/aztec/CHANGELOG.md +++ b/yarn-project/aztec/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.46.3](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.46.2...aztec-package-v0.46.3) (2024-07-11) + + +### Miscellaneous + +* **aztec-package:** Synchronize aztec-packages versions + ## [0.46.2](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.46.1...aztec-package-v0.46.2) (2024-07-10) diff --git a/yarn-project/aztec/package.json b/yarn-project/aztec/package.json index 38418f3faf5c..1fdc2be8d15f 100644 --- a/yarn-project/aztec/package.json +++ b/yarn-project/aztec/package.json @@ -1,6 +1,6 @@ { "name": "@aztec/aztec", - "version": "0.46.2", + "version": "0.46.3", "type": "module", "exports": { ".": "./dest/index.js" From 2e41ac7d6b3c0e9e0bf02a8687f9c3d7446a08c6 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Thu, 11 Jul 2024 10:13:53 -0300 Subject: [PATCH 28/32] feat: Configure world-state to follow the proven chain only (#7430) Related to #7346 --- .../archiver/src/archiver/archiver.test.ts | 76 ++++++++++++++----- .../archiver/src/archiver/archiver.ts | 37 ++++++++- .../archiver/src/archiver/archiver_store.ts | 12 +++ .../archiver/kv_archiver_store/block_store.ts | 12 +++ .../kv_archiver_store/kv_archiver_store.ts | 8 ++ .../memory_archiver_store.ts | 10 +++ .../l2_block_downloader.ts | 23 ++++-- .../circuit-types/src/l2_block_source.ts | 9 ++- .../composed/integration_l1_publisher.test.ts | 1 + yarn-project/p2p/src/client/mocks.ts | 4 + yarn-project/p2p/src/client/p2p_client.ts | 5 +- .../world-state/src/synchronizer/config.ts | 18 ++--- .../server_world_state_synchronizer.test.ts | 1 + .../server_world_state_synchronizer.ts | 10 +-- 14 files changed, 182 insertions(+), 44 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver.test.ts b/yarn-project/archiver/src/archiver/archiver.test.ts index ea7cbba1883b..690c52e4f253 100644 --- a/yarn-project/archiver/src/archiver/archiver.test.ts +++ b/yarn-project/archiver/src/archiver/archiver.test.ts @@ -33,6 +33,7 @@ describe('Archiver', () => { const registryAddress = EthAddress.ZERO; const availabilityOracleAddress = EthAddress.ZERO; const blockNumbers = [1, 2, 3]; + let publicClient: MockProxy>; let archiverStore: ArchiverDataStore; @@ -61,23 +62,28 @@ describe('Archiver', () => { const rollupTxs = blocks.map(makeRollupTx); publicClient.getBlockNumber.mockResolvedValueOnce(2500n).mockResolvedValueOnce(2600n).mockResolvedValueOnce(2700n); - // logs should be created in order of how archiver syncs. - publicClient.getLogs - .mockResolvedValueOnce([makeMessageSentEvent(98n, 1n, 0n), makeMessageSentEvent(99n, 1n, 1n)]) - .mockResolvedValueOnce([makeTxsPublishedEvent(101n, blocks[0].body.getTxsEffectsHash())]) - .mockResolvedValueOnce([makeL2BlockProcessedEvent(101n, 1n)]) - .mockResolvedValueOnce([ + + mockGetLogs({ + messageSent: [makeMessageSentEvent(98n, 1n, 0n), makeMessageSentEvent(99n, 1n, 1n)], + txPublished: [makeTxsPublishedEvent(101n, blocks[0].body.getTxsEffectsHash())], + l2BlockProcessed: [makeL2BlockProcessedEvent(101n, 1n)], + proofVerified: [makeProofVerifiedEvent(102n, 1n)], + }); + + mockGetLogs({ + messageSent: [ makeMessageSentEvent(2504n, 2n, 0n), makeMessageSentEvent(2505n, 2n, 1n), makeMessageSentEvent(2505n, 2n, 2n), makeMessageSentEvent(2506n, 3n, 1n), - ]) - .mockResolvedValueOnce([ + ], + txPublished: [ makeTxsPublishedEvent(2510n, blocks[1].body.getTxsEffectsHash()), makeTxsPublishedEvent(2520n, blocks[2].body.getTxsEffectsHash()), - ]) - .mockResolvedValueOnce([makeL2BlockProcessedEvent(2510n, 2n), makeL2BlockProcessedEvent(2520n, 3n)]) - .mockResolvedValue([]); + ], + l2BlockProcessed: [makeL2BlockProcessedEvent(2510n, 2n), makeL2BlockProcessedEvent(2520n, 3n)], + }); + publicClient.getTransaction.mockResolvedValueOnce(publishTxs[0]); publicClient.getTransaction.mockResolvedValueOnce(rollupTxs[0]); @@ -141,6 +147,14 @@ describe('Archiver', () => { expect(totalNumUnencryptedLogs).toEqual(expectedTotalNumUnencryptedLogs); }); + // Check last proven block number + const provenBlockNumber = await archiver.getProvenBlockNumber(); + expect(provenBlockNumber).toEqual(1); + + // Check getting only proven blocks + expect((await archiver.getBlocks(1, 100)).map(b => b.number)).toEqual([1, 2, 3]); + expect((await archiver.getBlocks(1, 100, true)).map(b => b.number)).toEqual([1]); + await archiver.stop(); }, 10_000); @@ -167,15 +181,18 @@ describe('Archiver', () => { // Here we set the current L1 block number to 102. L1 to L2 messages after this should not be read. publicClient.getBlockNumber.mockResolvedValue(102n); - // add all of the L1 to L2 messages to the mock - publicClient.getLogs - .mockResolvedValueOnce([makeMessageSentEvent(66n, 1n, 0n), makeMessageSentEvent(68n, 1n, 1n)]) - .mockResolvedValueOnce([ + + mockGetLogs({ + messageSent: [makeMessageSentEvent(66n, 1n, 0n), makeMessageSentEvent(68n, 1n, 1n)], + txPublished: [ makeTxsPublishedEvent(70n, blocks[0].body.getTxsEffectsHash()), makeTxsPublishedEvent(80n, blocks[1].body.getTxsEffectsHash()), - ]) - .mockResolvedValueOnce([makeL2BlockProcessedEvent(70n, 1n), makeL2BlockProcessedEvent(80n, 2n)]) - .mockResolvedValue([]); + ], + l2BlockProcessed: [makeL2BlockProcessedEvent(70n, 1n), makeL2BlockProcessedEvent(80n, 2n)], + }); + + mockGetLogs({}); + publishTxs.slice(0, numL2BlocksInTest).forEach(tx => publicClient.getTransaction.mockResolvedValueOnce(tx)); rollupTxs.slice(0, numL2BlocksInTest).forEach(tx => publicClient.getTransaction.mockResolvedValueOnce(tx)); @@ -191,6 +208,20 @@ describe('Archiver', () => { await archiver.stop(); }, 10_000); + + // logs should be created in order of how archiver syncs. + const mockGetLogs = (logs: { + messageSent?: ReturnType[]; + txPublished?: ReturnType[]; + l2BlockProcessed?: ReturnType[]; + proofVerified?: ReturnType[]; + }) => { + publicClient.getLogs + .mockResolvedValueOnce(logs.messageSent ?? []) + .mockResolvedValueOnce(logs.txPublished ?? []) + .mockResolvedValueOnce(logs.l2BlockProcessed ?? []) + .mockResolvedValueOnce(logs.proofVerified ?? []); + }; }); /** @@ -240,6 +271,15 @@ function makeMessageSentEvent(l1BlockNum: bigint, l2BlockNumber: bigint, index: } as Log; } +function makeProofVerifiedEvent(l1BlockNum: bigint, l2BlockNumber: bigint) { + return { + blockNumber: l1BlockNum, + args: { + blockNumber: l2BlockNumber, + }, + } as Log; +} + /** * Makes a fake rollup tx for testing purposes. * @param block - The L2Block. diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index b03ce4d21153..b35cd83dcdf1 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -28,6 +28,7 @@ import { type EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { RunningPromise } from '@aztec/foundation/running-promise'; +import { RollupAbi } from '@aztec/l1-artifacts'; import { ClassRegistererAddress } from '@aztec/protocol-contracts/class-registerer'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { @@ -40,7 +41,7 @@ import { } from '@aztec/types/contracts'; import groupBy from 'lodash.groupby'; -import { type Chain, type HttpTransport, type PublicClient, createPublicClient, http } from 'viem'; +import { type Chain, type HttpTransport, type PublicClient, createPublicClient, getAbiItem, http } from 'viem'; import { type ArchiverDataStore } from './archiver_store.js'; import { type ArchiverConfig } from './config.js'; @@ -297,6 +298,28 @@ export class Archiver implements ArchiveSource { await this.store.addBlocks(retrievedBlocks); this.instrumentation.processNewBlocks(retrievedBlocks.retrievedData); + + // Fetch the logs for proven blocks in the block range and update the last proven block number. + // Note it's ok to read repeated data here, since we're just using the largest number we see on the logs. + await this.updateLastProvenL2Block(l1SynchPoint.blocksSynchedTo, currentL1BlockNumber); + } + + private async updateLastProvenL2Block(fromBlock: bigint, toBlock: bigint) { + const logs = await this.publicClient.getLogs({ + address: this.rollupAddress.toString(), + fromBlock, + toBlock, + strict: true, + event: getAbiItem({ abi: RollupAbi, name: 'L2ProofVerified' }), + }); + + const lastLog = logs[logs.length - 1]; + if (!lastLog) { + return; + } + + const provenBlockNumber = lastLog.args.blockNumber; + await this.store.setProvenL2BlockNumber(Number(provenBlockNumber)); } /** @@ -390,10 +413,14 @@ export class Archiver implements ArchiveSource { * Gets up to `limit` amount of L2 blocks starting from `from`. * @param from - Number of the first block to return (inclusive). * @param limit - The number of blocks to return. + * @param proven - If true, only return blocks that have been proven. * @returns The requested L2 blocks. */ - public getBlocks(from: number, limit: number): Promise { - return this.store.getBlocks(from, limit); + public async getBlocks(from: number, limit: number, proven?: boolean): Promise { + const limitWithProven = proven + ? Math.min(limit, Math.max((await this.store.getProvenL2BlockNumber()) - from + 1, 0)) + : limit; + return limitWithProven === 0 ? [] : this.store.getBlocks(from, limitWithProven); } /** @@ -471,6 +498,10 @@ export class Archiver implements ArchiveSource { return this.store.getSynchedL2BlockNumber(); } + public getProvenBlockNumber(): Promise { + return this.store.getProvenL2BlockNumber(); + } + public getContractClass(id: Fr): Promise { return this.store.getContractClass(id); } diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 9b397b6fa42c..7e388cbf52fd 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -148,6 +148,18 @@ export interface ArchiverDataStore { */ getSynchedL2BlockNumber(): Promise; + /** + * Gets the number of the latest proven L2 block processed. + * @returns The number of the latest proven L2 block processed. + */ + getProvenL2BlockNumber(): Promise; + + /** + * Stores the number of the latest proven L2 block processed. + * @param l2BlockNumber - The number of the latest proven L2 block processed. + */ + setProvenL2BlockNumber(l2BlockNumber: number): Promise; + /** * Gets the synch point of the archiver */ 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 d22537ae824f..c054abe73fd1 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 @@ -22,6 +22,9 @@ export class BlockStore { /** Stores L1 block number in which the last processed L2 block was included */ #lastSynchedL1Block: AztecSingleton; + /** Stores last proven L2 block number */ + #lastProvenL2Block: AztecSingleton; + /** Index mapping transaction hash (as a string) to its location in a block */ #txIndex: AztecMap; @@ -39,6 +42,7 @@ export class BlockStore { this.#txIndex = db.openMap('archiver_tx_index'); this.#contractIndex = db.openMap('archiver_contract_index'); this.#lastSynchedL1Block = db.openSingleton('archiver_last_synched_l1_block'); + this.#lastProvenL2Block = db.openSingleton('archiver_last_proven_l2_block'); } /** @@ -181,6 +185,14 @@ export class BlockStore { return this.#lastSynchedL1Block.get() ?? 0n; } + getProvenL2BlockNumber(): number { + return this.#lastProvenL2Block.get() ?? 0; + } + + async setProvenL2BlockNumber(blockNumber: number) { + await this.#lastProvenL2Block.set(blockNumber); + } + #computeBlockRange(start: number, limit: number): Required, 'start' | 'end'>> { if (limit < 1) { throw new Error(`Invalid limit: ${limit}`); diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts index ec8c98e55238..b0a174319531 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts @@ -246,6 +246,14 @@ export class KVArchiverDataStore implements ArchiverDataStore { return Promise.resolve(this.#blockStore.getSynchedL2BlockNumber()); } + getProvenL2BlockNumber(): Promise { + return Promise.resolve(this.#blockStore.getProvenL2BlockNumber()); + } + + async setProvenL2BlockNumber(blockNumber: number) { + await this.#blockStore.setProvenL2BlockNumber(blockNumber); + } + /** * Gets the last L1 block number processed by the archiver */ diff --git a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts index bbfbb6e311f1..8cad7257baae 100644 --- a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts @@ -84,6 +84,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { private lastL1BlockNewBlocks: bigint = 0n; private lastL1BlockNewMessages: bigint = 0n; + private lastProvenL2BlockNumber: number = 0; constructor( /** The max number of logs that can be obtained in 1 "getUnencryptedLogs" call. */ @@ -433,6 +434,15 @@ export class MemoryArchiverStore implements ArchiverDataStore { return Promise.resolve(this.l2Blocks[this.l2Blocks.length - 1].number); } + public getProvenL2BlockNumber(): Promise { + return Promise.resolve(this.lastProvenL2BlockNumber); + } + + public setProvenL2BlockNumber(l2BlockNumber: number): Promise { + this.lastProvenL2BlockNumber = l2BlockNumber; + return Promise.resolve(); + } + public getSynchPoint(): Promise { return Promise.resolve({ blocksSynchedTo: this.lastL1BlockNewBlocks, diff --git a/yarn-project/circuit-types/src/l2_block_downloader/l2_block_downloader.ts b/yarn-project/circuit-types/src/l2_block_downloader/l2_block_downloader.ts index 081d65633c8e..f4d412426a5b 100644 --- a/yarn-project/circuit-types/src/l2_block_downloader/l2_block_downloader.ts +++ b/yarn-project/circuit-types/src/l2_block_downloader/l2_block_downloader.ts @@ -19,12 +19,23 @@ export class L2BlockDownloader { private running = false; private from = 0; private interruptibleSleep = new InterruptibleSleep(); - private semaphore: Semaphore; - private jobQueue = new SerialQueue(); - private blockQueue = new MemoryFifo(); + private readonly semaphore: Semaphore; + private readonly jobQueue = new SerialQueue(); + private readonly blockQueue = new MemoryFifo(); + private readonly proven: boolean; + private readonly pollIntervalMS: number; - constructor(private l2BlockSource: L2BlockSource, maxQueueSize: number, private pollIntervalMS = 10000) { - this.semaphore = new Semaphore(maxQueueSize); + constructor( + private l2BlockSource: L2BlockSource, + opts: { + maxQueueSize: number; + proven?: boolean; + pollIntervalMS?: number; + }, + ) { + this.pollIntervalMS = opts.pollIntervalMS ?? 1000; + this.proven = opts.proven ?? false; + this.semaphore = new Semaphore(opts.maxQueueSize); } /** @@ -62,7 +73,7 @@ export class L2BlockDownloader { private async collectBlocks() { let totalBlocks = 0; while (true) { - const blocks = await this.l2BlockSource.getBlocks(this.from, 10); + const blocks = await this.l2BlockSource.getBlocks(this.from, 10, this.proven); if (!blocks.length) { return totalBlocks; } diff --git a/yarn-project/circuit-types/src/l2_block_source.ts b/yarn-project/circuit-types/src/l2_block_source.ts index 78b6078f0faa..45727f2156f1 100644 --- a/yarn-project/circuit-types/src/l2_block_source.ts +++ b/yarn-project/circuit-types/src/l2_block_source.ts @@ -27,6 +27,12 @@ export interface L2BlockSource { */ getBlockNumber(): Promise; + /** + * Gets the number of the latest L2 block proven seen by the block source implementation. + * @returns The number of the latest L2 block proven seen by the block source implementation. + */ + getProvenBlockNumber(): Promise; + /** * Gets an l2 block. If a negative number is passed, the block returned is the most recent. * @param number - The block number to return (inclusive). @@ -38,9 +44,10 @@ export interface L2BlockSource { * Gets up to `limit` amount of L2 blocks starting from `from`. * @param from - Number of the first block to return (inclusive). * @param limit - The maximum number of blocks to return. + * @param proven - If true, only return blocks that have been proven. * @returns The requested L2 blocks. */ - getBlocks(from: number, limit: number): Promise; + getBlocks(from: number, limit: number, proven?: boolean): Promise; /** * Gets a tx effect. diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 59656c44182c..3443492eb40d 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -140,6 +140,7 @@ describe('L1Publisher integration', () => { const worldStateConfig: WorldStateConfig = { worldStateBlockCheckIntervalMS: 10000, l2QueueSize: 10, + worldStateProvenBlocksOnly: false, }; const worldStateSynchronizer = new ServerWorldStateSynchronizer(tmpStore, builderDb, blockSource, worldStateConfig); await worldStateSynchronizer.start(); diff --git a/yarn-project/p2p/src/client/mocks.ts b/yarn-project/p2p/src/client/mocks.ts index 0d59a161ae01..4b8508811d3f 100644 --- a/yarn-project/p2p/src/client/mocks.ts +++ b/yarn-project/p2p/src/client/mocks.ts @@ -40,6 +40,10 @@ export class MockBlockSource implements L2BlockSource { return Promise.resolve(this.l2Blocks.length - 1); } + public getProvenBlockNumber(): Promise { + return this.getBlockNumber(); + } + /** * Gets an l2 block. * @param number - The block number to return (inclusive). diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index 96401b356850..f6fc0737b558 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -126,7 +126,10 @@ export class P2PClient implements P2P { private log = createDebugLogger('aztec:p2p'), ) { const { p2pBlockCheckIntervalMS: checkInterval, p2pL2QueueSize } = getP2PConfigEnvVars(); - this.blockDownloader = new L2BlockDownloader(l2BlockSource, p2pL2QueueSize, checkInterval); + this.blockDownloader = new L2BlockDownloader(l2BlockSource, { + maxQueueSize: p2pL2QueueSize, + pollIntervalMS: checkInterval, + }); this.synchedBlockNumber = store.openSingleton('p2p_pool_last_l2_block'); } diff --git a/yarn-project/world-state/src/synchronizer/config.ts b/yarn-project/world-state/src/synchronizer/config.ts index 5d42930d5b7a..7474b7e55e5f 100644 --- a/yarn-project/world-state/src/synchronizer/config.ts +++ b/yarn-project/world-state/src/synchronizer/config.ts @@ -1,16 +1,13 @@ -/** - * World State synchronizer configuration values. - */ +/** World State synchronizer configuration values. */ export interface WorldStateConfig { - /** - * The frequency in which to check. - */ + /** The frequency in which to check. */ worldStateBlockCheckIntervalMS: number; - /** - * Size of queue of L2 blocks to store. - */ + /** Size of queue of L2 blocks to store. */ l2QueueSize: number; + + /** Whether to follow only the proven chain. */ + worldStateProvenBlocksOnly: boolean; } /** @@ -18,10 +15,11 @@ export interface WorldStateConfig { * @returns The configuration values for the world state synchronizer. */ export function getConfigEnvVars(): WorldStateConfig { - const { WS_BLOCK_CHECK_INTERVAL_MS, WS_L2_BLOCK_QUEUE_SIZE } = process.env; + const { WS_BLOCK_CHECK_INTERVAL_MS, WS_L2_BLOCK_QUEUE_SIZE, WS_PROVEN_BLOCKS_ONLY } = process.env; const envVars: WorldStateConfig = { worldStateBlockCheckIntervalMS: WS_BLOCK_CHECK_INTERVAL_MS ? +WS_BLOCK_CHECK_INTERVAL_MS : 100, l2QueueSize: WS_L2_BLOCK_QUEUE_SIZE ? +WS_L2_BLOCK_QUEUE_SIZE : 1000, + worldStateProvenBlocksOnly: ['1', 'true'].includes(WS_PROVEN_BLOCKS_ONLY!), }; return envVars; } diff --git a/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.test.ts b/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.test.ts index c7bc0fc5cbf9..7e585c12ae70 100644 --- a/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.test.ts +++ b/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.test.ts @@ -92,6 +92,7 @@ describe('server_world_state_synchronizer', () => { const worldStateConfig: WorldStateConfig = { worldStateBlockCheckIntervalMS: blockCheckInterval, l2QueueSize: 1000, + worldStateProvenBlocksOnly: false, }; return new ServerWorldStateSynchronizer( diff --git a/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.ts b/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.ts index 059fddfb4d8c..579a0cbf6ba3 100644 --- a/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.ts +++ b/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.ts @@ -48,11 +48,11 @@ export class ServerWorldStateSynchronizer implements WorldStateSynchronizer { private log = createDebugLogger('aztec:world_state'), ) { this.blockNumber = store.openSingleton('world_state_synch_last_block_number'); - this.l2BlockDownloader = new L2BlockDownloader( - l2BlockSource, - config.l2QueueSize, - config.worldStateBlockCheckIntervalMS, - ); + this.l2BlockDownloader = new L2BlockDownloader(l2BlockSource, { + maxQueueSize: config.l2QueueSize, + pollIntervalMS: config.worldStateBlockCheckIntervalMS, + proven: config.worldStateProvenBlocksOnly, + }); } public getLatest(): MerkleTreeOperations { From e31887e0091e31fcec59b8c792ec6af36d835f04 Mon Sep 17 00:00:00 2001 From: Facundo Date: Thu, 11 Jul 2024 14:51:44 +0100 Subject: [PATCH 29/32] chore(avm): codegen cleanup (#7439) --- .../src/barretenberg/flavor/flavor_macros.hpp | 9 +- .../vm/generated/avm_circuit_builder.cpp | 853 ---------- .../vm/generated/avm_circuit_builder.hpp | 86 +- .../barretenberg/vm/generated/avm_flavor.hpp | 1434 ++--------------- .../bb-pil-backend/src/flavor_builder.rs | 8 +- .../templates/circuit_builder.hpp.hbs | 9 +- .../bb-pil-backend/templates/flavor.hpp.hbs | 43 +- 7 files changed, 210 insertions(+), 2232 deletions(-) delete mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor_macros.hpp b/barretenberg/cpp/src/barretenberg/flavor/flavor_macros.hpp index c24955812856..6593e7f62138 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor_macros.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor_macros.hpp @@ -37,6 +37,9 @@ template auto _concatenate_base_class_get_la } } // namespace bb::detail +// Needed to force expansion of __VA_ARGS__ before converting to string. +#define VARARGS_TO_STRING(...) #__VA_ARGS__ + #define DEFINE_REF_VIEW(...) \ [[nodiscard]] auto get_all() \ { \ @@ -57,9 +60,11 @@ template auto _concatenate_base_class_get_la #define DEFINE_FLAVOR_MEMBERS(DataType, ...) \ DataType __VA_ARGS__; \ DEFINE_REF_VIEW(__VA_ARGS__) \ - std::vector get_labels() const \ + const std::vector& get_labels() const \ { \ - return bb::detail::split_and_trim(#__VA_ARGS__, ','); \ + static const std::vector labels = \ + bb::detail::split_and_trim(VARARGS_TO_STRING(__VA_ARGS__), ','); \ + return labels; \ } \ constexpr std::size_t size() const \ { \ diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp deleted file mode 100644 index f39307155a5c..000000000000 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp +++ /dev/null @@ -1,853 +0,0 @@ -#include "barretenberg/vm/generated/avm_circuit_builder.hpp" - -namespace bb { -namespace { - -template std::string field_to_string(const FF& ff) -{ - std::ostringstream os; - os << ff; - std::string raw = os.str(); - auto first_not_zero = raw.find_first_not_of('0', 2); - std::string result = "0x" + (first_not_zero != std::string::npos ? raw.substr(first_not_zero) : "0"); - return result; -} - -} // namespace - -template std::vector AvmFullRow::names() -{ - return { "main_clk", - "main_sel_first", - "kernel_kernel_inputs", - "kernel_kernel_value_out", - "kernel_kernel_side_effect_out", - "kernel_kernel_metadata_out", - "main_calldata", - "main_returndata", - "alu_a_hi", - "alu_a_lo", - "alu_b_hi", - "alu_b_lo", - "alu_borrow", - "alu_cf", - "alu_clk", - "alu_cmp_rng_ctr", - "alu_div_u16_r0", - "alu_div_u16_r1", - "alu_div_u16_r2", - "alu_div_u16_r3", - "alu_div_u16_r4", - "alu_div_u16_r5", - "alu_div_u16_r6", - "alu_div_u16_r7", - "alu_divisor_hi", - "alu_divisor_lo", - "alu_ff_tag", - "alu_ia", - "alu_ib", - "alu_ic", - "alu_in_tag", - "alu_op_add", - "alu_op_cast", - "alu_op_cast_prev", - "alu_op_div", - "alu_op_div_a_lt_b", - "alu_op_div_std", - "alu_op_eq", - "alu_op_eq_diff_inv", - "alu_op_lt", - "alu_op_lte", - "alu_op_mul", - "alu_op_not", - "alu_op_shl", - "alu_op_shr", - "alu_op_sub", - "alu_p_a_borrow", - "alu_p_b_borrow", - "alu_p_sub_a_hi", - "alu_p_sub_a_lo", - "alu_p_sub_b_hi", - "alu_p_sub_b_lo", - "alu_partial_prod_hi", - "alu_partial_prod_lo", - "alu_quotient_hi", - "alu_quotient_lo", - "alu_remainder", - "alu_res_hi", - "alu_res_lo", - "alu_sel_alu", - "alu_sel_cmp", - "alu_sel_div_rng_chk", - "alu_sel_rng_chk", - "alu_sel_rng_chk_lookup", - "alu_sel_shift_which", - "alu_shift_lt_bit_len", - "alu_t_sub_s_bits", - "alu_two_pow_s", - "alu_two_pow_t_sub_s", - "alu_u128_tag", - "alu_u16_r0", - "alu_u16_r1", - "alu_u16_r10", - "alu_u16_r11", - "alu_u16_r12", - "alu_u16_r13", - "alu_u16_r14", - "alu_u16_r2", - "alu_u16_r3", - "alu_u16_r4", - "alu_u16_r5", - "alu_u16_r6", - "alu_u16_r7", - "alu_u16_r8", - "alu_u16_r9", - "alu_u16_tag", - "alu_u32_tag", - "alu_u64_tag", - "alu_u8_r0", - "alu_u8_r1", - "alu_u8_tag", - "binary_acc_ia", - "binary_acc_ib", - "binary_acc_ic", - "binary_clk", - "binary_ia_bytes", - "binary_ib_bytes", - "binary_ic_bytes", - "binary_in_tag", - "binary_mem_tag_ctr", - "binary_mem_tag_ctr_inv", - "binary_op_id", - "binary_sel_bin", - "binary_start", - "byte_lookup_sel_bin", - "byte_lookup_table_byte_lengths", - "byte_lookup_table_in_tags", - "byte_lookup_table_input_a", - "byte_lookup_table_input_b", - "byte_lookup_table_op_id", - "byte_lookup_table_output", - "conversion_clk", - "conversion_input", - "conversion_num_limbs", - "conversion_radix", - "conversion_sel_to_radix_le", - "gas_da_gas_fixed_table", - "gas_l2_gas_fixed_table", - "gas_sel_gas_cost", - "keccakf1600_clk", - "keccakf1600_input", - "keccakf1600_output", - "keccakf1600_sel_keccakf1600", - "kernel_emit_l2_to_l1_msg_write_offset", - "kernel_emit_note_hash_write_offset", - "kernel_emit_nullifier_write_offset", - "kernel_emit_unencrypted_log_write_offset", - "kernel_kernel_in_offset", - "kernel_kernel_out_offset", - "kernel_l1_to_l2_msg_exists_write_offset", - "kernel_note_hash_exist_write_offset", - "kernel_nullifier_exists_write_offset", - "kernel_nullifier_non_exists_write_offset", - "kernel_q_public_input_kernel_add_to_table", - "kernel_q_public_input_kernel_out_add_to_table", - "kernel_side_effect_counter", - "kernel_sload_write_offset", - "kernel_sstore_write_offset", - "main_abs_da_rem_gas_hi", - "main_abs_da_rem_gas_lo", - "main_abs_l2_rem_gas_hi", - "main_abs_l2_rem_gas_lo", - "main_alu_in_tag", - "main_bin_op_id", - "main_call_ptr", - "main_da_gas_op_cost", - "main_da_gas_remaining", - "main_da_out_of_gas", - "main_ia", - "main_ib", - "main_ic", - "main_id", - "main_id_zero", - "main_ind_addr_a", - "main_ind_addr_b", - "main_ind_addr_c", - "main_ind_addr_d", - "main_internal_return_ptr", - "main_inv", - "main_l2_gas_op_cost", - "main_l2_gas_remaining", - "main_l2_out_of_gas", - "main_mem_addr_a", - "main_mem_addr_b", - "main_mem_addr_c", - "main_mem_addr_d", - "main_op_err", - "main_opcode_val", - "main_pc", - "main_r_in_tag", - "main_rwa", - "main_rwb", - "main_rwc", - "main_rwd", - "main_sel_alu", - "main_sel_bin", - "main_sel_calldata", - "main_sel_gas_accounting_active", - "main_sel_last", - "main_sel_mem_op_a", - "main_sel_mem_op_activate_gas", - "main_sel_mem_op_b", - "main_sel_mem_op_c", - "main_sel_mem_op_d", - "main_sel_mov_ia_to_ic", - "main_sel_mov_ib_to_ic", - "main_sel_op_add", - "main_sel_op_address", - "main_sel_op_and", - "main_sel_op_block_number", - "main_sel_op_calldata_copy", - "main_sel_op_cast", - "main_sel_op_chain_id", - "main_sel_op_cmov", - "main_sel_op_coinbase", - "main_sel_op_dagasleft", - "main_sel_op_div", - "main_sel_op_emit_l2_to_l1_msg", - "main_sel_op_emit_note_hash", - "main_sel_op_emit_nullifier", - "main_sel_op_emit_unencrypted_log", - "main_sel_op_eq", - "main_sel_op_external_call", - "main_sel_op_external_return", - "main_sel_op_fdiv", - "main_sel_op_fee_per_da_gas", - "main_sel_op_fee_per_l2_gas", - "main_sel_op_function_selector", - "main_sel_op_get_contract_instance", - "main_sel_op_halt", - "main_sel_op_internal_call", - "main_sel_op_internal_return", - "main_sel_op_jump", - "main_sel_op_jumpi", - "main_sel_op_keccak", - "main_sel_op_l1_to_l2_msg_exists", - "main_sel_op_l2gasleft", - "main_sel_op_lt", - "main_sel_op_lte", - "main_sel_op_mov", - "main_sel_op_mul", - "main_sel_op_not", - "main_sel_op_note_hash_exists", - "main_sel_op_nullifier_exists", - "main_sel_op_or", - "main_sel_op_pedersen", - "main_sel_op_poseidon2", - "main_sel_op_radix_le", - "main_sel_op_sender", - "main_sel_op_sha256", - "main_sel_op_shl", - "main_sel_op_shr", - "main_sel_op_sload", - "main_sel_op_sstore", - "main_sel_op_storage_address", - "main_sel_op_sub", - "main_sel_op_timestamp", - "main_sel_op_transaction_fee", - "main_sel_op_version", - "main_sel_op_xor", - "main_sel_q_kernel_lookup", - "main_sel_q_kernel_output_lookup", - "main_sel_resolve_ind_addr_a", - "main_sel_resolve_ind_addr_b", - "main_sel_resolve_ind_addr_c", - "main_sel_resolve_ind_addr_d", - "main_sel_returndata", - "main_sel_rng_16", - "main_sel_rng_8", - "main_sel_slice_gadget", - "main_space_id", - "main_tag_err", - "main_w_in_tag", - "mem_addr", - "mem_clk", - "mem_diff_hi", - "mem_diff_lo", - "mem_diff_mid", - "mem_glob_addr", - "mem_last", - "mem_lastAccess", - "mem_one_min_inv", - "mem_r_in_tag", - "mem_rw", - "mem_sel_mem", - "mem_sel_mov_ia_to_ic", - "mem_sel_mov_ib_to_ic", - "mem_sel_op_a", - "mem_sel_op_b", - "mem_sel_op_c", - "mem_sel_op_cmov", - "mem_sel_op_d", - "mem_sel_op_slice", - "mem_sel_resolve_ind_addr_a", - "mem_sel_resolve_ind_addr_b", - "mem_sel_resolve_ind_addr_c", - "mem_sel_resolve_ind_addr_d", - "mem_sel_rng_chk", - "mem_skip_check_tag", - "mem_space_id", - "mem_tag", - "mem_tag_err", - "mem_tsp", - "mem_val", - "mem_w_in_tag", - "pedersen_clk", - "pedersen_input", - "pedersen_output", - "pedersen_sel_pedersen", - "poseidon2_clk", - "poseidon2_input", - "poseidon2_output", - "poseidon2_sel_poseidon_perm", - "powers_power_of_2", - "sha256_clk", - "sha256_input", - "sha256_output", - "sha256_sel_sha256_compression", - "sha256_state", - "slice_addr", - "slice_clk", - "slice_cnt", - "slice_col_offset", - "slice_one_min_inv", - "slice_sel_cd_cpy", - "slice_sel_mem_active", - "slice_sel_return", - "slice_sel_start", - "slice_space_id", - "slice_val", - "perm_slice_mem", - "perm_main_alu", - "perm_main_bin", - "perm_main_conv", - "perm_main_pos2_perm", - "perm_main_pedersen", - "perm_main_slice", - "perm_main_mem_a", - "perm_main_mem_b", - "perm_main_mem_c", - "perm_main_mem_d", - "perm_main_mem_ind_addr_a", - "perm_main_mem_ind_addr_b", - "perm_main_mem_ind_addr_c", - "perm_main_mem_ind_addr_d", - "lookup_byte_lengths", - "lookup_byte_operations", - "lookup_cd_value", - "lookup_ret_value", - "lookup_opcode_gas", - "range_check_l2_gas_hi", - "range_check_l2_gas_lo", - "range_check_da_gas_hi", - "range_check_da_gas_lo", - "kernel_output_lookup", - "lookup_into_kernel", - "incl_main_tag_err", - "incl_mem_tag_err", - "lookup_mem_rng_chk_lo", - "lookup_mem_rng_chk_mid", - "lookup_mem_rng_chk_hi", - "lookup_pow_2_0", - "lookup_pow_2_1", - "lookup_u8_0", - "lookup_u8_1", - "lookup_u16_0", - "lookup_u16_1", - "lookup_u16_2", - "lookup_u16_3", - "lookup_u16_4", - "lookup_u16_5", - "lookup_u16_6", - "lookup_u16_7", - "lookup_u16_8", - "lookup_u16_9", - "lookup_u16_10", - "lookup_u16_11", - "lookup_u16_12", - "lookup_u16_13", - "lookup_u16_14", - "lookup_div_u16_0", - "lookup_div_u16_1", - "lookup_div_u16_2", - "lookup_div_u16_3", - "lookup_div_u16_4", - "lookup_div_u16_5", - "lookup_div_u16_6", - "lookup_div_u16_7", - "lookup_byte_lengths_counts", - "lookup_byte_operations_counts", - "lookup_cd_value_counts", - "lookup_ret_value_counts", - "lookup_opcode_gas_counts", - "range_check_l2_gas_hi_counts", - "range_check_l2_gas_lo_counts", - "range_check_da_gas_hi_counts", - "range_check_da_gas_lo_counts", - "kernel_output_lookup_counts", - "lookup_into_kernel_counts", - "incl_main_tag_err_counts", - "incl_mem_tag_err_counts", - "lookup_mem_rng_chk_lo_counts", - "lookup_mem_rng_chk_mid_counts", - "lookup_mem_rng_chk_hi_counts", - "lookup_pow_2_0_counts", - "lookup_pow_2_1_counts", - "lookup_u8_0_counts", - "lookup_u8_1_counts", - "lookup_u16_0_counts", - "lookup_u16_1_counts", - "lookup_u16_2_counts", - "lookup_u16_3_counts", - "lookup_u16_4_counts", - "lookup_u16_5_counts", - "lookup_u16_6_counts", - "lookup_u16_7_counts", - "lookup_u16_8_counts", - "lookup_u16_9_counts", - "lookup_u16_10_counts", - "lookup_u16_11_counts", - "lookup_u16_12_counts", - "lookup_u16_13_counts", - "lookup_u16_14_counts", - "lookup_div_u16_0_counts", - "lookup_div_u16_1_counts", - "lookup_div_u16_2_counts", - "lookup_div_u16_3_counts", - "lookup_div_u16_4_counts", - "lookup_div_u16_5_counts", - "lookup_div_u16_6_counts", - "lookup_div_u16_7_counts" }; -} - -template std::ostream& operator<<(std::ostream& os, AvmFullRow const& row) -{ - return os << field_to_string(row.main_clk) // - << "," << field_to_string(row.main_sel_first) // - << "," << field_to_string(row.kernel_kernel_inputs) // - << "," << field_to_string(row.kernel_kernel_value_out) // - << "," << field_to_string(row.kernel_kernel_side_effect_out) // - << "," << field_to_string(row.kernel_kernel_metadata_out) // - << "," << field_to_string(row.main_calldata) // - << "," << field_to_string(row.main_returndata) // - << "," << field_to_string(row.alu_a_hi) // - << "," << field_to_string(row.alu_a_lo) // - << "," << field_to_string(row.alu_b_hi) // - << "," << field_to_string(row.alu_b_lo) // - << "," << field_to_string(row.alu_borrow) // - << "," << field_to_string(row.alu_cf) // - << "," << field_to_string(row.alu_clk) // - << "," << field_to_string(row.alu_cmp_rng_ctr) // - << "," << field_to_string(row.alu_div_u16_r0) // - << "," << field_to_string(row.alu_div_u16_r1) // - << "," << field_to_string(row.alu_div_u16_r2) // - << "," << field_to_string(row.alu_div_u16_r3) // - << "," << field_to_string(row.alu_div_u16_r4) // - << "," << field_to_string(row.alu_div_u16_r5) // - << "," << field_to_string(row.alu_div_u16_r6) // - << "," << field_to_string(row.alu_div_u16_r7) // - << "," << field_to_string(row.alu_divisor_hi) // - << "," << field_to_string(row.alu_divisor_lo) // - << "," << field_to_string(row.alu_ff_tag) // - << "," << field_to_string(row.alu_ia) // - << "," << field_to_string(row.alu_ib) // - << "," << field_to_string(row.alu_ic) // - << "," << field_to_string(row.alu_in_tag) // - << "," << field_to_string(row.alu_op_add) // - << "," << field_to_string(row.alu_op_cast) // - << "," << field_to_string(row.alu_op_cast_prev) // - << "," << field_to_string(row.alu_op_div) // - << "," << field_to_string(row.alu_op_div_a_lt_b) // - << "," << field_to_string(row.alu_op_div_std) // - << "," << field_to_string(row.alu_op_eq) // - << "," << field_to_string(row.alu_op_eq_diff_inv) // - << "," << field_to_string(row.alu_op_lt) // - << "," << field_to_string(row.alu_op_lte) // - << "," << field_to_string(row.alu_op_mul) // - << "," << field_to_string(row.alu_op_not) // - << "," << field_to_string(row.alu_op_shl) // - << "," << field_to_string(row.alu_op_shr) // - << "," << field_to_string(row.alu_op_sub) // - << "," << field_to_string(row.alu_p_a_borrow) // - << "," << field_to_string(row.alu_p_b_borrow) // - << "," << field_to_string(row.alu_p_sub_a_hi) // - << "," << field_to_string(row.alu_p_sub_a_lo) // - << "," << field_to_string(row.alu_p_sub_b_hi) // - << "," << field_to_string(row.alu_p_sub_b_lo) // - << "," << field_to_string(row.alu_partial_prod_hi) // - << "," << field_to_string(row.alu_partial_prod_lo) // - << "," << field_to_string(row.alu_quotient_hi) // - << "," << field_to_string(row.alu_quotient_lo) // - << "," << field_to_string(row.alu_remainder) // - << "," << field_to_string(row.alu_res_hi) // - << "," << field_to_string(row.alu_res_lo) // - << "," << field_to_string(row.alu_sel_alu) // - << "," << field_to_string(row.alu_sel_cmp) // - << "," << field_to_string(row.alu_sel_div_rng_chk) // - << "," << field_to_string(row.alu_sel_rng_chk) // - << "," << field_to_string(row.alu_sel_rng_chk_lookup) // - << "," << field_to_string(row.alu_sel_shift_which) // - << "," << field_to_string(row.alu_shift_lt_bit_len) // - << "," << field_to_string(row.alu_t_sub_s_bits) // - << "," << field_to_string(row.alu_two_pow_s) // - << "," << field_to_string(row.alu_two_pow_t_sub_s) // - << "," << field_to_string(row.alu_u128_tag) // - << "," << field_to_string(row.alu_u16_r0) // - << "," << field_to_string(row.alu_u16_r1) // - << "," << field_to_string(row.alu_u16_r10) // - << "," << field_to_string(row.alu_u16_r11) // - << "," << field_to_string(row.alu_u16_r12) // - << "," << field_to_string(row.alu_u16_r13) // - << "," << field_to_string(row.alu_u16_r14) // - << "," << field_to_string(row.alu_u16_r2) // - << "," << field_to_string(row.alu_u16_r3) // - << "," << field_to_string(row.alu_u16_r4) // - << "," << field_to_string(row.alu_u16_r5) // - << "," << field_to_string(row.alu_u16_r6) // - << "," << field_to_string(row.alu_u16_r7) // - << "," << field_to_string(row.alu_u16_r8) // - << "," << field_to_string(row.alu_u16_r9) // - << "," << field_to_string(row.alu_u16_tag) // - << "," << field_to_string(row.alu_u32_tag) // - << "," << field_to_string(row.alu_u64_tag) // - << "," << field_to_string(row.alu_u8_r0) // - << "," << field_to_string(row.alu_u8_r1) // - << "," << field_to_string(row.alu_u8_tag) // - << "," << field_to_string(row.binary_acc_ia) // - << "," << field_to_string(row.binary_acc_ib) // - << "," << field_to_string(row.binary_acc_ic) // - << "," << field_to_string(row.binary_clk) // - << "," << field_to_string(row.binary_ia_bytes) // - << "," << field_to_string(row.binary_ib_bytes) // - << "," << field_to_string(row.binary_ic_bytes) // - << "," << field_to_string(row.binary_in_tag) // - << "," << field_to_string(row.binary_mem_tag_ctr) // - << "," << field_to_string(row.binary_mem_tag_ctr_inv) // - << "," << field_to_string(row.binary_op_id) // - << "," << field_to_string(row.binary_sel_bin) // - << "," << field_to_string(row.binary_start) // - << "," << field_to_string(row.byte_lookup_sel_bin) // - << "," << field_to_string(row.byte_lookup_table_byte_lengths) // - << "," << field_to_string(row.byte_lookup_table_in_tags) // - << "," << field_to_string(row.byte_lookup_table_input_a) // - << "," << field_to_string(row.byte_lookup_table_input_b) // - << "," << field_to_string(row.byte_lookup_table_op_id) // - << "," << field_to_string(row.byte_lookup_table_output) // - << "," << field_to_string(row.conversion_clk) // - << "," << field_to_string(row.conversion_input) // - << "," << field_to_string(row.conversion_num_limbs) // - << "," << field_to_string(row.conversion_radix) // - << "," << field_to_string(row.conversion_sel_to_radix_le) // - << "," << field_to_string(row.gas_da_gas_fixed_table) // - << "," << field_to_string(row.gas_l2_gas_fixed_table) // - << "," << field_to_string(row.gas_sel_gas_cost) // - << "," << field_to_string(row.keccakf1600_clk) // - << "," << field_to_string(row.keccakf1600_input) // - << "," << field_to_string(row.keccakf1600_output) // - << "," << field_to_string(row.keccakf1600_sel_keccakf1600) // - << "," << field_to_string(row.kernel_emit_l2_to_l1_msg_write_offset) // - << "," << field_to_string(row.kernel_emit_note_hash_write_offset) // - << "," << field_to_string(row.kernel_emit_nullifier_write_offset) // - << "," << field_to_string(row.kernel_emit_unencrypted_log_write_offset) // - << "," << field_to_string(row.kernel_kernel_in_offset) // - << "," << field_to_string(row.kernel_kernel_out_offset) // - << "," << field_to_string(row.kernel_l1_to_l2_msg_exists_write_offset) // - << "," << field_to_string(row.kernel_note_hash_exist_write_offset) // - << "," << field_to_string(row.kernel_nullifier_exists_write_offset) // - << "," << field_to_string(row.kernel_nullifier_non_exists_write_offset) // - << "," << field_to_string(row.kernel_q_public_input_kernel_add_to_table) // - << "," << field_to_string(row.kernel_q_public_input_kernel_out_add_to_table) // - << "," << field_to_string(row.kernel_side_effect_counter) // - << "," << field_to_string(row.kernel_sload_write_offset) // - << "," << field_to_string(row.kernel_sstore_write_offset) // - << "," << field_to_string(row.main_abs_da_rem_gas_hi) // - << "," << field_to_string(row.main_abs_da_rem_gas_lo) // - << "," << field_to_string(row.main_abs_l2_rem_gas_hi) // - << "," << field_to_string(row.main_abs_l2_rem_gas_lo) // - << "," << field_to_string(row.main_alu_in_tag) // - << "," << field_to_string(row.main_bin_op_id) // - << "," << field_to_string(row.main_call_ptr) // - << "," << field_to_string(row.main_da_gas_op_cost) // - << "," << field_to_string(row.main_da_gas_remaining) // - << "," << field_to_string(row.main_da_out_of_gas) // - << "," << field_to_string(row.main_ia) // - << "," << field_to_string(row.main_ib) // - << "," << field_to_string(row.main_ic) // - << "," << field_to_string(row.main_id) // - << "," << field_to_string(row.main_id_zero) // - << "," << field_to_string(row.main_ind_addr_a) // - << "," << field_to_string(row.main_ind_addr_b) // - << "," << field_to_string(row.main_ind_addr_c) // - << "," << field_to_string(row.main_ind_addr_d) // - << "," << field_to_string(row.main_internal_return_ptr) // - << "," << field_to_string(row.main_inv) // - << "," << field_to_string(row.main_l2_gas_op_cost) // - << "," << field_to_string(row.main_l2_gas_remaining) // - << "," << field_to_string(row.main_l2_out_of_gas) // - << "," << field_to_string(row.main_mem_addr_a) // - << "," << field_to_string(row.main_mem_addr_b) // - << "," << field_to_string(row.main_mem_addr_c) // - << "," << field_to_string(row.main_mem_addr_d) // - << "," << field_to_string(row.main_op_err) // - << "," << field_to_string(row.main_opcode_val) // - << "," << field_to_string(row.main_pc) // - << "," << field_to_string(row.main_r_in_tag) // - << "," << field_to_string(row.main_rwa) // - << "," << field_to_string(row.main_rwb) // - << "," << field_to_string(row.main_rwc) // - << "," << field_to_string(row.main_rwd) // - << "," << field_to_string(row.main_sel_alu) // - << "," << field_to_string(row.main_sel_bin) // - << "," << field_to_string(row.main_sel_calldata) // - << "," << field_to_string(row.main_sel_gas_accounting_active) // - << "," << field_to_string(row.main_sel_last) // - << "," << field_to_string(row.main_sel_mem_op_a) // - << "," << field_to_string(row.main_sel_mem_op_activate_gas) // - << "," << field_to_string(row.main_sel_mem_op_b) // - << "," << field_to_string(row.main_sel_mem_op_c) // - << "," << field_to_string(row.main_sel_mem_op_d) // - << "," << field_to_string(row.main_sel_mov_ia_to_ic) // - << "," << field_to_string(row.main_sel_mov_ib_to_ic) // - << "," << field_to_string(row.main_sel_op_add) // - << "," << field_to_string(row.main_sel_op_address) // - << "," << field_to_string(row.main_sel_op_and) // - << "," << field_to_string(row.main_sel_op_block_number) // - << "," << field_to_string(row.main_sel_op_calldata_copy) // - << "," << field_to_string(row.main_sel_op_cast) // - << "," << field_to_string(row.main_sel_op_chain_id) // - << "," << field_to_string(row.main_sel_op_cmov) // - << "," << field_to_string(row.main_sel_op_coinbase) // - << "," << field_to_string(row.main_sel_op_dagasleft) // - << "," << field_to_string(row.main_sel_op_div) // - << "," << field_to_string(row.main_sel_op_emit_l2_to_l1_msg) // - << "," << field_to_string(row.main_sel_op_emit_note_hash) // - << "," << field_to_string(row.main_sel_op_emit_nullifier) // - << "," << field_to_string(row.main_sel_op_emit_unencrypted_log) // - << "," << field_to_string(row.main_sel_op_eq) // - << "," << field_to_string(row.main_sel_op_external_call) // - << "," << field_to_string(row.main_sel_op_external_return) // - << "," << field_to_string(row.main_sel_op_fdiv) // - << "," << field_to_string(row.main_sel_op_fee_per_da_gas) // - << "," << field_to_string(row.main_sel_op_fee_per_l2_gas) // - << "," << field_to_string(row.main_sel_op_function_selector) // - << "," << field_to_string(row.main_sel_op_get_contract_instance) // - << "," << field_to_string(row.main_sel_op_halt) // - << "," << field_to_string(row.main_sel_op_internal_call) // - << "," << field_to_string(row.main_sel_op_internal_return) // - << "," << field_to_string(row.main_sel_op_jump) // - << "," << field_to_string(row.main_sel_op_jumpi) // - << "," << field_to_string(row.main_sel_op_keccak) // - << "," << field_to_string(row.main_sel_op_l1_to_l2_msg_exists) // - << "," << field_to_string(row.main_sel_op_l2gasleft) // - << "," << field_to_string(row.main_sel_op_lt) // - << "," << field_to_string(row.main_sel_op_lte) // - << "," << field_to_string(row.main_sel_op_mov) // - << "," << field_to_string(row.main_sel_op_mul) // - << "," << field_to_string(row.main_sel_op_not) // - << "," << field_to_string(row.main_sel_op_note_hash_exists) // - << "," << field_to_string(row.main_sel_op_nullifier_exists) // - << "," << field_to_string(row.main_sel_op_or) // - << "," << field_to_string(row.main_sel_op_pedersen) // - << "," << field_to_string(row.main_sel_op_poseidon2) // - << "," << field_to_string(row.main_sel_op_radix_le) // - << "," << field_to_string(row.main_sel_op_sender) // - << "," << field_to_string(row.main_sel_op_sha256) // - << "," << field_to_string(row.main_sel_op_shl) // - << "," << field_to_string(row.main_sel_op_shr) // - << "," << field_to_string(row.main_sel_op_sload) // - << "," << field_to_string(row.main_sel_op_sstore) // - << "," << field_to_string(row.main_sel_op_storage_address) // - << "," << field_to_string(row.main_sel_op_sub) // - << "," << field_to_string(row.main_sel_op_timestamp) // - << "," << field_to_string(row.main_sel_op_transaction_fee) // - << "," << field_to_string(row.main_sel_op_version) // - << "," << field_to_string(row.main_sel_op_xor) // - << "," << field_to_string(row.main_sel_q_kernel_lookup) // - << "," << field_to_string(row.main_sel_q_kernel_output_lookup) // - << "," << field_to_string(row.main_sel_resolve_ind_addr_a) // - << "," << field_to_string(row.main_sel_resolve_ind_addr_b) // - << "," << field_to_string(row.main_sel_resolve_ind_addr_c) // - << "," << field_to_string(row.main_sel_resolve_ind_addr_d) // - << "," << field_to_string(row.main_sel_returndata) // - << "," << field_to_string(row.main_sel_rng_16) // - << "," << field_to_string(row.main_sel_rng_8) // - << "," << field_to_string(row.main_sel_slice_gadget) // - << "," << field_to_string(row.main_space_id) // - << "," << field_to_string(row.main_tag_err) // - << "," << field_to_string(row.main_w_in_tag) // - << "," << field_to_string(row.mem_addr) // - << "," << field_to_string(row.mem_clk) // - << "," << field_to_string(row.mem_diff_hi) // - << "," << field_to_string(row.mem_diff_lo) // - << "," << field_to_string(row.mem_diff_mid) // - << "," << field_to_string(row.mem_glob_addr) // - << "," << field_to_string(row.mem_last) // - << "," << field_to_string(row.mem_lastAccess) // - << "," << field_to_string(row.mem_one_min_inv) // - << "," << field_to_string(row.mem_r_in_tag) // - << "," << field_to_string(row.mem_rw) // - << "," << field_to_string(row.mem_sel_mem) // - << "," << field_to_string(row.mem_sel_mov_ia_to_ic) // - << "," << field_to_string(row.mem_sel_mov_ib_to_ic) // - << "," << field_to_string(row.mem_sel_op_a) // - << "," << field_to_string(row.mem_sel_op_b) // - << "," << field_to_string(row.mem_sel_op_c) // - << "," << field_to_string(row.mem_sel_op_cmov) // - << "," << field_to_string(row.mem_sel_op_d) // - << "," << field_to_string(row.mem_sel_op_slice) // - << "," << field_to_string(row.mem_sel_resolve_ind_addr_a) // - << "," << field_to_string(row.mem_sel_resolve_ind_addr_b) // - << "," << field_to_string(row.mem_sel_resolve_ind_addr_c) // - << "," << field_to_string(row.mem_sel_resolve_ind_addr_d) // - << "," << field_to_string(row.mem_sel_rng_chk) // - << "," << field_to_string(row.mem_skip_check_tag) // - << "," << field_to_string(row.mem_space_id) // - << "," << field_to_string(row.mem_tag) // - << "," << field_to_string(row.mem_tag_err) // - << "," << field_to_string(row.mem_tsp) // - << "," << field_to_string(row.mem_val) // - << "," << field_to_string(row.mem_w_in_tag) // - << "," << field_to_string(row.pedersen_clk) // - << "," << field_to_string(row.pedersen_input) // - << "," << field_to_string(row.pedersen_output) // - << "," << field_to_string(row.pedersen_sel_pedersen) // - << "," << field_to_string(row.poseidon2_clk) // - << "," << field_to_string(row.poseidon2_input) // - << "," << field_to_string(row.poseidon2_output) // - << "," << field_to_string(row.poseidon2_sel_poseidon_perm) // - << "," << field_to_string(row.powers_power_of_2) // - << "," << field_to_string(row.sha256_clk) // - << "," << field_to_string(row.sha256_input) // - << "," << field_to_string(row.sha256_output) // - << "," << field_to_string(row.sha256_sel_sha256_compression) // - << "," << field_to_string(row.sha256_state) // - << "," << field_to_string(row.slice_addr) // - << "," << field_to_string(row.slice_clk) // - << "," << field_to_string(row.slice_cnt) // - << "," << field_to_string(row.slice_col_offset) // - << "," << field_to_string(row.slice_one_min_inv) // - << "," << field_to_string(row.slice_sel_cd_cpy) // - << "," << field_to_string(row.slice_sel_mem_active) // - << "," << field_to_string(row.slice_sel_return) // - << "," << field_to_string(row.slice_sel_start) // - << "," << field_to_string(row.slice_space_id) // - << "," << field_to_string(row.slice_val) // - << "," << field_to_string(row.perm_slice_mem) // - << "," << field_to_string(row.perm_main_alu) // - << "," << field_to_string(row.perm_main_bin) // - << "," << field_to_string(row.perm_main_conv) // - << "," << field_to_string(row.perm_main_pos2_perm) // - << "," << field_to_string(row.perm_main_pedersen) // - << "," << field_to_string(row.perm_main_slice) // - << "," << field_to_string(row.perm_main_mem_a) // - << "," << field_to_string(row.perm_main_mem_b) // - << "," << field_to_string(row.perm_main_mem_c) // - << "," << field_to_string(row.perm_main_mem_d) // - << "," << field_to_string(row.perm_main_mem_ind_addr_a) // - << "," << field_to_string(row.perm_main_mem_ind_addr_b) // - << "," << field_to_string(row.perm_main_mem_ind_addr_c) // - << "," << field_to_string(row.perm_main_mem_ind_addr_d) // - << "," << field_to_string(row.lookup_byte_lengths) // - << "," << field_to_string(row.lookup_byte_operations) // - << "," << field_to_string(row.lookup_cd_value) // - << "," << field_to_string(row.lookup_ret_value) // - << "," << field_to_string(row.lookup_opcode_gas) // - << "," << field_to_string(row.range_check_l2_gas_hi) // - << "," << field_to_string(row.range_check_l2_gas_lo) // - << "," << field_to_string(row.range_check_da_gas_hi) // - << "," << field_to_string(row.range_check_da_gas_lo) // - << "," << field_to_string(row.kernel_output_lookup) // - << "," << field_to_string(row.lookup_into_kernel) // - << "," << field_to_string(row.incl_main_tag_err) // - << "," << field_to_string(row.incl_mem_tag_err) // - << "," << field_to_string(row.lookup_mem_rng_chk_lo) // - << "," << field_to_string(row.lookup_mem_rng_chk_mid) // - << "," << field_to_string(row.lookup_mem_rng_chk_hi) // - << "," << field_to_string(row.lookup_pow_2_0) // - << "," << field_to_string(row.lookup_pow_2_1) // - << "," << field_to_string(row.lookup_u8_0) // - << "," << field_to_string(row.lookup_u8_1) // - << "," << field_to_string(row.lookup_u16_0) // - << "," << field_to_string(row.lookup_u16_1) // - << "," << field_to_string(row.lookup_u16_2) // - << "," << field_to_string(row.lookup_u16_3) // - << "," << field_to_string(row.lookup_u16_4) // - << "," << field_to_string(row.lookup_u16_5) // - << "," << field_to_string(row.lookup_u16_6) // - << "," << field_to_string(row.lookup_u16_7) // - << "," << field_to_string(row.lookup_u16_8) // - << "," << field_to_string(row.lookup_u16_9) // - << "," << field_to_string(row.lookup_u16_10) // - << "," << field_to_string(row.lookup_u16_11) // - << "," << field_to_string(row.lookup_u16_12) // - << "," << field_to_string(row.lookup_u16_13) // - << "," << field_to_string(row.lookup_u16_14) // - << "," << field_to_string(row.lookup_div_u16_0) // - << "," << field_to_string(row.lookup_div_u16_1) // - << "," << field_to_string(row.lookup_div_u16_2) // - << "," << field_to_string(row.lookup_div_u16_3) // - << "," << field_to_string(row.lookup_div_u16_4) // - << "," << field_to_string(row.lookup_div_u16_5) // - << "," << field_to_string(row.lookup_div_u16_6) // - << "," << field_to_string(row.lookup_div_u16_7) // - << "," << field_to_string(row.lookup_byte_lengths_counts) // - << "," << field_to_string(row.lookup_byte_operations_counts) // - << "," << field_to_string(row.lookup_cd_value_counts) // - << "," << field_to_string(row.lookup_ret_value_counts) // - << "," << field_to_string(row.lookup_opcode_gas_counts) // - << "," << field_to_string(row.range_check_l2_gas_hi_counts) // - << "," << field_to_string(row.range_check_l2_gas_lo_counts) // - << "," << field_to_string(row.range_check_da_gas_hi_counts) // - << "," << field_to_string(row.range_check_da_gas_lo_counts) // - << "," << field_to_string(row.kernel_output_lookup_counts) // - << "," << field_to_string(row.lookup_into_kernel_counts) // - << "," << field_to_string(row.incl_main_tag_err_counts) // - << "," << field_to_string(row.incl_mem_tag_err_counts) // - << "," << field_to_string(row.lookup_mem_rng_chk_lo_counts) // - << "," << field_to_string(row.lookup_mem_rng_chk_mid_counts) // - << "," << field_to_string(row.lookup_mem_rng_chk_hi_counts) // - << "," << field_to_string(row.lookup_pow_2_0_counts) // - << "," << field_to_string(row.lookup_pow_2_1_counts) // - << "," << field_to_string(row.lookup_u8_0_counts) // - << "," << field_to_string(row.lookup_u8_1_counts) // - << "," << field_to_string(row.lookup_u16_0_counts) // - << "," << field_to_string(row.lookup_u16_1_counts) // - << "," << field_to_string(row.lookup_u16_2_counts) // - << "," << field_to_string(row.lookup_u16_3_counts) // - << "," << field_to_string(row.lookup_u16_4_counts) // - << "," << field_to_string(row.lookup_u16_5_counts) // - << "," << field_to_string(row.lookup_u16_6_counts) // - << "," << field_to_string(row.lookup_u16_7_counts) // - << "," << field_to_string(row.lookup_u16_8_counts) // - << "," << field_to_string(row.lookup_u16_9_counts) // - << "," << field_to_string(row.lookup_u16_10_counts) // - << "," << field_to_string(row.lookup_u16_11_counts) // - << "," << field_to_string(row.lookup_u16_12_counts) // - << "," << field_to_string(row.lookup_u16_13_counts) // - << "," << field_to_string(row.lookup_u16_14_counts) // - << "," << field_to_string(row.lookup_div_u16_0_counts) // - << "," << field_to_string(row.lookup_div_u16_1_counts) // - << "," << field_to_string(row.lookup_div_u16_2_counts) // - << "," << field_to_string(row.lookup_div_u16_3_counts) // - << "," << field_to_string(row.lookup_div_u16_4_counts) // - << "," << field_to_string(row.lookup_div_u16_5_counts) // - << "," << field_to_string(row.lookup_div_u16_6_counts) // - << "," << field_to_string(row.lookup_div_u16_7_counts) // - ; -} - -// Explicit template instantiation. -template std::ostream& operator<<(std::ostream& os, AvmFullRow const& row); -template std::vector AvmFullRow::names(); - -} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp index 9a2382b1d0fd..02850ae6e717 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp @@ -402,86 +402,9 @@ class AvmCircuitBuilder { polys.lookup_div_u16_7_counts[i] = rows[i].lookup_div_u16_7_counts; } - polys.alu_a_hi_shift = Polynomial(polys.alu_a_hi.shifted()); - polys.alu_a_lo_shift = Polynomial(polys.alu_a_lo.shifted()); - polys.alu_b_hi_shift = Polynomial(polys.alu_b_hi.shifted()); - polys.alu_b_lo_shift = Polynomial(polys.alu_b_lo.shifted()); - polys.alu_cmp_rng_ctr_shift = Polynomial(polys.alu_cmp_rng_ctr.shifted()); - polys.alu_div_u16_r0_shift = Polynomial(polys.alu_div_u16_r0.shifted()); - polys.alu_div_u16_r1_shift = Polynomial(polys.alu_div_u16_r1.shifted()); - polys.alu_div_u16_r2_shift = Polynomial(polys.alu_div_u16_r2.shifted()); - polys.alu_div_u16_r3_shift = Polynomial(polys.alu_div_u16_r3.shifted()); - polys.alu_div_u16_r4_shift = Polynomial(polys.alu_div_u16_r4.shifted()); - polys.alu_div_u16_r5_shift = Polynomial(polys.alu_div_u16_r5.shifted()); - polys.alu_div_u16_r6_shift = Polynomial(polys.alu_div_u16_r6.shifted()); - polys.alu_div_u16_r7_shift = Polynomial(polys.alu_div_u16_r7.shifted()); - polys.alu_op_add_shift = Polynomial(polys.alu_op_add.shifted()); - polys.alu_op_cast_prev_shift = Polynomial(polys.alu_op_cast_prev.shifted()); - polys.alu_op_cast_shift = Polynomial(polys.alu_op_cast.shifted()); - polys.alu_op_div_shift = Polynomial(polys.alu_op_div.shifted()); - polys.alu_op_mul_shift = Polynomial(polys.alu_op_mul.shifted()); - polys.alu_op_shl_shift = Polynomial(polys.alu_op_shl.shifted()); - polys.alu_op_shr_shift = Polynomial(polys.alu_op_shr.shifted()); - polys.alu_op_sub_shift = Polynomial(polys.alu_op_sub.shifted()); - polys.alu_p_sub_a_hi_shift = Polynomial(polys.alu_p_sub_a_hi.shifted()); - polys.alu_p_sub_a_lo_shift = Polynomial(polys.alu_p_sub_a_lo.shifted()); - polys.alu_p_sub_b_hi_shift = Polynomial(polys.alu_p_sub_b_hi.shifted()); - polys.alu_p_sub_b_lo_shift = Polynomial(polys.alu_p_sub_b_lo.shifted()); - polys.alu_sel_alu_shift = Polynomial(polys.alu_sel_alu.shifted()); - polys.alu_sel_cmp_shift = Polynomial(polys.alu_sel_cmp.shifted()); - polys.alu_sel_div_rng_chk_shift = Polynomial(polys.alu_sel_div_rng_chk.shifted()); - polys.alu_sel_rng_chk_lookup_shift = Polynomial(polys.alu_sel_rng_chk_lookup.shifted()); - polys.alu_sel_rng_chk_shift = Polynomial(polys.alu_sel_rng_chk.shifted()); - polys.alu_u16_r0_shift = Polynomial(polys.alu_u16_r0.shifted()); - polys.alu_u16_r1_shift = Polynomial(polys.alu_u16_r1.shifted()); - polys.alu_u16_r2_shift = Polynomial(polys.alu_u16_r2.shifted()); - polys.alu_u16_r3_shift = Polynomial(polys.alu_u16_r3.shifted()); - polys.alu_u16_r4_shift = Polynomial(polys.alu_u16_r4.shifted()); - polys.alu_u16_r5_shift = Polynomial(polys.alu_u16_r5.shifted()); - polys.alu_u16_r6_shift = Polynomial(polys.alu_u16_r6.shifted()); - polys.alu_u8_r0_shift = Polynomial(polys.alu_u8_r0.shifted()); - polys.alu_u8_r1_shift = Polynomial(polys.alu_u8_r1.shifted()); - polys.binary_acc_ia_shift = Polynomial(polys.binary_acc_ia.shifted()); - polys.binary_acc_ib_shift = Polynomial(polys.binary_acc_ib.shifted()); - polys.binary_acc_ic_shift = Polynomial(polys.binary_acc_ic.shifted()); - polys.binary_mem_tag_ctr_shift = Polynomial(polys.binary_mem_tag_ctr.shifted()); - polys.binary_op_id_shift = Polynomial(polys.binary_op_id.shifted()); - polys.kernel_emit_l2_to_l1_msg_write_offset_shift = - Polynomial(polys.kernel_emit_l2_to_l1_msg_write_offset.shifted()); - polys.kernel_emit_note_hash_write_offset_shift = Polynomial(polys.kernel_emit_note_hash_write_offset.shifted()); - polys.kernel_emit_nullifier_write_offset_shift = Polynomial(polys.kernel_emit_nullifier_write_offset.shifted()); - polys.kernel_emit_unencrypted_log_write_offset_shift = - Polynomial(polys.kernel_emit_unencrypted_log_write_offset.shifted()); - polys.kernel_l1_to_l2_msg_exists_write_offset_shift = - Polynomial(polys.kernel_l1_to_l2_msg_exists_write_offset.shifted()); - polys.kernel_note_hash_exist_write_offset_shift = - Polynomial(polys.kernel_note_hash_exist_write_offset.shifted()); - polys.kernel_nullifier_exists_write_offset_shift = - Polynomial(polys.kernel_nullifier_exists_write_offset.shifted()); - polys.kernel_nullifier_non_exists_write_offset_shift = - Polynomial(polys.kernel_nullifier_non_exists_write_offset.shifted()); - polys.kernel_side_effect_counter_shift = Polynomial(polys.kernel_side_effect_counter.shifted()); - polys.kernel_sload_write_offset_shift = Polynomial(polys.kernel_sload_write_offset.shifted()); - polys.kernel_sstore_write_offset_shift = Polynomial(polys.kernel_sstore_write_offset.shifted()); - polys.main_da_gas_remaining_shift = Polynomial(polys.main_da_gas_remaining.shifted()); - polys.main_internal_return_ptr_shift = Polynomial(polys.main_internal_return_ptr.shifted()); - polys.main_l2_gas_remaining_shift = Polynomial(polys.main_l2_gas_remaining.shifted()); - polys.main_pc_shift = Polynomial(polys.main_pc.shifted()); - polys.mem_glob_addr_shift = Polynomial(polys.mem_glob_addr.shifted()); - polys.mem_rw_shift = Polynomial(polys.mem_rw.shifted()); - polys.mem_sel_mem_shift = Polynomial(polys.mem_sel_mem.shifted()); - polys.mem_tag_shift = Polynomial(polys.mem_tag.shifted()); - polys.mem_tsp_shift = Polynomial(polys.mem_tsp.shifted()); - polys.mem_val_shift = Polynomial(polys.mem_val.shifted()); - polys.slice_addr_shift = Polynomial(polys.slice_addr.shifted()); - polys.slice_clk_shift = Polynomial(polys.slice_clk.shifted()); - polys.slice_cnt_shift = Polynomial(polys.slice_cnt.shifted()); - polys.slice_col_offset_shift = Polynomial(polys.slice_col_offset.shifted()); - polys.slice_sel_cd_cpy_shift = Polynomial(polys.slice_sel_cd_cpy.shifted()); - polys.slice_sel_mem_active_shift = Polynomial(polys.slice_sel_mem_active.shifted()); - polys.slice_sel_return_shift = Polynomial(polys.slice_sel_return.shifted()); - polys.slice_sel_start_shift = Polynomial(polys.slice_sel_start.shifted()); - polys.slice_space_id_shift = Polynomial(polys.slice_space_id.shifted()); + for (auto [shifted, to_be_shifted] : zip_view(polys.get_shifted(), polys.get_to_be_shifted())) { + shifted = to_be_shifted.shifted(); + } return polys; } @@ -868,8 +791,7 @@ class AvmCircuitBuilder { // Wait for lookup evaluations to complete for (auto& future : relation_futures) { - int result = future.get(); - if (!result) { + if (!future.get()) { return false; } } diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index 7ea67f9bfb65..62ea2eea3478 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -29,7 +29,7 @@ #include "barretenberg/relations/generated/avm/powers.hpp" #include "barretenberg/relations/generated/avm/sha256.hpp" -// Lookup relations +// Lookup and permutation relations #include "barretenberg/relations/generated/avm/incl_main_tag_err.hpp" #include "barretenberg/relations/generated/avm/incl_mem_tag_err.hpp" #include "barretenberg/relations/generated/avm/kernel_output_lookup.hpp" @@ -88,11 +88,20 @@ #include "barretenberg/relations/generated/avm/range_check_da_gas_lo.hpp" #include "barretenberg/relations/generated/avm/range_check_l2_gas_hi.hpp" #include "barretenberg/relations/generated/avm/range_check_l2_gas_lo.hpp" -#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" // Metaprogramming to concatenate tuple types. template using tuple_cat_t = decltype(std::tuple_cat(std::declval()...)); +// The entities that will be used in the flavor. +// clang-format off +#define PRECOMPUTED_ENTITIES main_clk, main_sel_first +#define WIRE_ENTITIES kernel_kernel_inputs, kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, main_calldata, main_returndata, alu_a_hi, alu_a_lo, alu_b_hi, alu_b_lo, alu_borrow, alu_cf, alu_clk, alu_cmp_rng_ctr, alu_div_u16_r0, alu_div_u16_r1, alu_div_u16_r2, alu_div_u16_r3, alu_div_u16_r4, alu_div_u16_r5, alu_div_u16_r6, alu_div_u16_r7, alu_divisor_hi, alu_divisor_lo, alu_ff_tag, alu_ia, alu_ib, alu_ic, alu_in_tag, alu_op_add, alu_op_cast, alu_op_cast_prev, alu_op_div, alu_op_div_a_lt_b, alu_op_div_std, alu_op_eq, alu_op_eq_diff_inv, alu_op_lt, alu_op_lte, alu_op_mul, alu_op_not, alu_op_shl, alu_op_shr, alu_op_sub, alu_p_a_borrow, alu_p_b_borrow, alu_p_sub_a_hi, alu_p_sub_a_lo, alu_p_sub_b_hi, alu_p_sub_b_lo, alu_partial_prod_hi, alu_partial_prod_lo, alu_quotient_hi, alu_quotient_lo, alu_remainder, alu_res_hi, alu_res_lo, alu_sel_alu, alu_sel_cmp, alu_sel_div_rng_chk, alu_sel_rng_chk, alu_sel_rng_chk_lookup, alu_sel_shift_which, alu_shift_lt_bit_len, alu_t_sub_s_bits, alu_two_pow_s, alu_two_pow_t_sub_s, alu_u128_tag, alu_u16_r0, alu_u16_r1, alu_u16_r10, alu_u16_r11, alu_u16_r12, alu_u16_r13, alu_u16_r14, alu_u16_r2, alu_u16_r3, alu_u16_r4, alu_u16_r5, alu_u16_r6, alu_u16_r7, alu_u16_r8, alu_u16_r9, alu_u16_tag, alu_u32_tag, alu_u64_tag, alu_u8_r0, alu_u8_r1, alu_u8_tag, binary_acc_ia, binary_acc_ib, binary_acc_ic, binary_clk, binary_ia_bytes, binary_ib_bytes, binary_ic_bytes, binary_in_tag, binary_mem_tag_ctr, binary_mem_tag_ctr_inv, binary_op_id, binary_sel_bin, binary_start, byte_lookup_sel_bin, byte_lookup_table_byte_lengths, byte_lookup_table_in_tags, byte_lookup_table_input_a, byte_lookup_table_input_b, byte_lookup_table_op_id, byte_lookup_table_output, conversion_clk, conversion_input, conversion_num_limbs, conversion_radix, conversion_sel_to_radix_le, gas_da_gas_fixed_table, gas_l2_gas_fixed_table, gas_sel_gas_cost, keccakf1600_clk, keccakf1600_input, keccakf1600_output, keccakf1600_sel_keccakf1600, kernel_emit_l2_to_l1_msg_write_offset, kernel_emit_note_hash_write_offset, kernel_emit_nullifier_write_offset, kernel_emit_unencrypted_log_write_offset, kernel_kernel_in_offset, kernel_kernel_out_offset, kernel_l1_to_l2_msg_exists_write_offset, kernel_note_hash_exist_write_offset, kernel_nullifier_exists_write_offset, kernel_nullifier_non_exists_write_offset, kernel_q_public_input_kernel_add_to_table, kernel_q_public_input_kernel_out_add_to_table, kernel_side_effect_counter, kernel_sload_write_offset, kernel_sstore_write_offset, main_abs_da_rem_gas_hi, main_abs_da_rem_gas_lo, main_abs_l2_rem_gas_hi, main_abs_l2_rem_gas_lo, main_alu_in_tag, main_bin_op_id, main_call_ptr, main_da_gas_op_cost, main_da_gas_remaining, main_da_out_of_gas, main_ia, main_ib, main_ic, main_id, main_id_zero, main_ind_addr_a, main_ind_addr_b, main_ind_addr_c, main_ind_addr_d, main_internal_return_ptr, main_inv, main_l2_gas_op_cost, main_l2_gas_remaining, main_l2_out_of_gas, main_mem_addr_a, main_mem_addr_b, main_mem_addr_c, main_mem_addr_d, main_op_err, main_opcode_val, main_pc, main_r_in_tag, main_rwa, main_rwb, main_rwc, main_rwd, main_sel_alu, main_sel_bin, main_sel_calldata, main_sel_gas_accounting_active, main_sel_last, main_sel_mem_op_a, main_sel_mem_op_activate_gas, main_sel_mem_op_b, main_sel_mem_op_c, main_sel_mem_op_d, main_sel_mov_ia_to_ic, main_sel_mov_ib_to_ic, main_sel_op_add, main_sel_op_address, main_sel_op_and, main_sel_op_block_number, main_sel_op_calldata_copy, main_sel_op_cast, main_sel_op_chain_id, main_sel_op_cmov, main_sel_op_coinbase, main_sel_op_dagasleft, main_sel_op_div, main_sel_op_emit_l2_to_l1_msg, main_sel_op_emit_note_hash, main_sel_op_emit_nullifier, main_sel_op_emit_unencrypted_log, main_sel_op_eq, main_sel_op_external_call, main_sel_op_external_return, main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, main_sel_op_function_selector, main_sel_op_get_contract_instance, main_sel_op_halt, main_sel_op_internal_call, main_sel_op_internal_return, main_sel_op_jump, main_sel_op_jumpi, main_sel_op_keccak, main_sel_op_l1_to_l2_msg_exists, main_sel_op_l2gasleft, main_sel_op_lt, main_sel_op_lte, main_sel_op_mov, main_sel_op_mul, main_sel_op_not, main_sel_op_note_hash_exists, main_sel_op_nullifier_exists, main_sel_op_or, main_sel_op_pedersen, main_sel_op_poseidon2, main_sel_op_radix_le, main_sel_op_sender, main_sel_op_sha256, main_sel_op_shl, main_sel_op_shr, main_sel_op_sload, main_sel_op_sstore, main_sel_op_storage_address, main_sel_op_sub, main_sel_op_timestamp, main_sel_op_transaction_fee, main_sel_op_version, main_sel_op_xor, main_sel_q_kernel_lookup, main_sel_q_kernel_output_lookup, main_sel_resolve_ind_addr_a, main_sel_resolve_ind_addr_b, main_sel_resolve_ind_addr_c, main_sel_resolve_ind_addr_d, main_sel_returndata, main_sel_rng_16, main_sel_rng_8, main_sel_slice_gadget, main_space_id, main_tag_err, main_w_in_tag, mem_addr, mem_clk, mem_diff_hi, mem_diff_lo, mem_diff_mid, mem_glob_addr, mem_last, mem_lastAccess, mem_one_min_inv, mem_r_in_tag, mem_rw, mem_sel_mem, mem_sel_mov_ia_to_ic, mem_sel_mov_ib_to_ic, mem_sel_op_a, mem_sel_op_b, mem_sel_op_c, mem_sel_op_cmov, mem_sel_op_d, mem_sel_op_slice, mem_sel_resolve_ind_addr_a, mem_sel_resolve_ind_addr_b, mem_sel_resolve_ind_addr_c, mem_sel_resolve_ind_addr_d, mem_sel_rng_chk, mem_skip_check_tag, mem_space_id, mem_tag, mem_tag_err, mem_tsp, mem_val, mem_w_in_tag, pedersen_clk, pedersen_input, pedersen_output, pedersen_sel_pedersen, poseidon2_clk, poseidon2_input, poseidon2_output, poseidon2_sel_poseidon_perm, powers_power_of_2, sha256_clk, sha256_input, sha256_output, sha256_sel_sha256_compression, sha256_state, slice_addr, slice_clk, slice_cnt, slice_col_offset, slice_one_min_inv, slice_sel_cd_cpy, slice_sel_mem_active, slice_sel_return, slice_sel_start, slice_space_id, slice_val, lookup_byte_lengths_counts, lookup_byte_operations_counts, lookup_cd_value_counts, lookup_ret_value_counts, lookup_opcode_gas_counts, range_check_l2_gas_hi_counts, range_check_l2_gas_lo_counts, range_check_da_gas_hi_counts, range_check_da_gas_lo_counts, kernel_output_lookup_counts, lookup_into_kernel_counts, incl_main_tag_err_counts, incl_mem_tag_err_counts, lookup_mem_rng_chk_lo_counts, lookup_mem_rng_chk_mid_counts, lookup_mem_rng_chk_hi_counts, lookup_pow_2_0_counts, lookup_pow_2_1_counts, lookup_u8_0_counts, lookup_u8_1_counts, lookup_u16_0_counts, lookup_u16_1_counts, lookup_u16_2_counts, lookup_u16_3_counts, lookup_u16_4_counts, lookup_u16_5_counts, lookup_u16_6_counts, lookup_u16_7_counts, lookup_u16_8_counts, lookup_u16_9_counts, lookup_u16_10_counts, lookup_u16_11_counts, lookup_u16_12_counts, lookup_u16_13_counts, lookup_u16_14_counts, lookup_div_u16_0_counts, lookup_div_u16_1_counts, lookup_div_u16_2_counts, lookup_div_u16_3_counts, lookup_div_u16_4_counts, lookup_div_u16_5_counts, lookup_div_u16_6_counts, lookup_div_u16_7_counts +#define DERIVED_WITNESS_ENTITIES perm_slice_mem, perm_main_alu, perm_main_bin, perm_main_conv, perm_main_pos2_perm, perm_main_pedersen, perm_main_slice, perm_main_mem_a, perm_main_mem_b, perm_main_mem_c, perm_main_mem_d, perm_main_mem_ind_addr_a, perm_main_mem_ind_addr_b, perm_main_mem_ind_addr_c, perm_main_mem_ind_addr_d, lookup_byte_lengths, lookup_byte_operations, lookup_cd_value, lookup_ret_value, lookup_opcode_gas, range_check_l2_gas_hi, range_check_l2_gas_lo, range_check_da_gas_hi, range_check_da_gas_lo, kernel_output_lookup, lookup_into_kernel, incl_main_tag_err, incl_mem_tag_err, lookup_mem_rng_chk_lo, lookup_mem_rng_chk_mid, lookup_mem_rng_chk_hi, lookup_pow_2_0, lookup_pow_2_1, lookup_u8_0, lookup_u8_1, lookup_u16_0, lookup_u16_1, lookup_u16_2, lookup_u16_3, lookup_u16_4, lookup_u16_5, lookup_u16_6, lookup_u16_7, lookup_u16_8, lookup_u16_9, lookup_u16_10, lookup_u16_11, lookup_u16_12, lookup_u16_13, lookup_u16_14, lookup_div_u16_0, lookup_div_u16_1, lookup_div_u16_2, lookup_div_u16_3, lookup_div_u16_4, lookup_div_u16_5, lookup_div_u16_6, lookup_div_u16_7 +#define SHIFTED_ENTITIES alu_a_hi_shift, alu_a_lo_shift, alu_b_hi_shift, alu_b_lo_shift, alu_cmp_rng_ctr_shift, alu_div_u16_r0_shift, alu_div_u16_r1_shift, alu_div_u16_r2_shift, alu_div_u16_r3_shift, alu_div_u16_r4_shift, alu_div_u16_r5_shift, alu_div_u16_r6_shift, alu_div_u16_r7_shift, alu_op_add_shift, alu_op_cast_prev_shift, alu_op_cast_shift, alu_op_div_shift, alu_op_mul_shift, alu_op_shl_shift, alu_op_shr_shift, alu_op_sub_shift, alu_p_sub_a_hi_shift, alu_p_sub_a_lo_shift, alu_p_sub_b_hi_shift, alu_p_sub_b_lo_shift, alu_sel_alu_shift, alu_sel_cmp_shift, alu_sel_div_rng_chk_shift, alu_sel_rng_chk_lookup_shift, alu_sel_rng_chk_shift, alu_u16_r0_shift, alu_u16_r1_shift, alu_u16_r2_shift, alu_u16_r3_shift, alu_u16_r4_shift, alu_u16_r5_shift, alu_u16_r6_shift, alu_u8_r0_shift, alu_u8_r1_shift, binary_acc_ia_shift, binary_acc_ib_shift, binary_acc_ic_shift, binary_mem_tag_ctr_shift, binary_op_id_shift, kernel_emit_l2_to_l1_msg_write_offset_shift, kernel_emit_note_hash_write_offset_shift, kernel_emit_nullifier_write_offset_shift, kernel_emit_unencrypted_log_write_offset_shift, kernel_l1_to_l2_msg_exists_write_offset_shift, kernel_note_hash_exist_write_offset_shift, kernel_nullifier_exists_write_offset_shift, kernel_nullifier_non_exists_write_offset_shift, kernel_side_effect_counter_shift, kernel_sload_write_offset_shift, kernel_sstore_write_offset_shift, main_da_gas_remaining_shift, main_internal_return_ptr_shift, main_l2_gas_remaining_shift, main_pc_shift, mem_glob_addr_shift, mem_rw_shift, mem_sel_mem_shift, mem_tag_shift, mem_tsp_shift, mem_val_shift, slice_addr_shift, slice_clk_shift, slice_cnt_shift, slice_col_offset_shift, slice_sel_cd_cpy_shift, slice_sel_mem_active_shift, slice_sel_return_shift, slice_sel_start_shift, slice_space_id_shift +#define TO_BE_SHIFTED(e) e.alu_a_hi, e.alu_a_lo, e.alu_b_hi, e.alu_b_lo, e.alu_cmp_rng_ctr, e.alu_div_u16_r0, e.alu_div_u16_r1, e.alu_div_u16_r2, e.alu_div_u16_r3, e.alu_div_u16_r4, e.alu_div_u16_r5, e.alu_div_u16_r6, e.alu_div_u16_r7, e.alu_op_add, e.alu_op_cast_prev, e.alu_op_cast, e.alu_op_div, e.alu_op_mul, e.alu_op_shl, e.alu_op_shr, e.alu_op_sub, e.alu_p_sub_a_hi, e.alu_p_sub_a_lo, e.alu_p_sub_b_hi, e.alu_p_sub_b_lo, e.alu_sel_alu, e.alu_sel_cmp, e.alu_sel_div_rng_chk, e.alu_sel_rng_chk_lookup, e.alu_sel_rng_chk, e.alu_u16_r0, e.alu_u16_r1, e.alu_u16_r2, e.alu_u16_r3, e.alu_u16_r4, e.alu_u16_r5, e.alu_u16_r6, e.alu_u8_r0, e.alu_u8_r1, e.binary_acc_ia, e.binary_acc_ib, e.binary_acc_ic, e.binary_mem_tag_ctr, e.binary_op_id, e.kernel_emit_l2_to_l1_msg_write_offset, e.kernel_emit_note_hash_write_offset, e.kernel_emit_nullifier_write_offset, e.kernel_emit_unencrypted_log_write_offset, e.kernel_l1_to_l2_msg_exists_write_offset, e.kernel_note_hash_exist_write_offset, e.kernel_nullifier_exists_write_offset, e.kernel_nullifier_non_exists_write_offset, e.kernel_side_effect_counter, e.kernel_sload_write_offset, e.kernel_sstore_write_offset, e.main_da_gas_remaining, e.main_internal_return_ptr, e.main_l2_gas_remaining, e.main_pc, e.mem_glob_addr, e.mem_rw, e.mem_sel_mem, e.mem_tag, e.mem_tsp, e.mem_val, e.slice_addr, e.slice_clk, e.slice_cnt, e.slice_col_offset, e.slice_sel_cd_cpy, e.slice_sel_mem_active, e.slice_sel_return, e.slice_sel_start, e.slice_space_id +#define ALL_ENTITIES PRECOMPUTED_ENTITIES, WIRE_ENTITIES, DERIVED_WITNESS_ENTITIES, SHIFTED_ENTITIES +// clang-format on + namespace bb { class AvmFlavor { @@ -218,9 +227,9 @@ class AvmFlavor { public: using DataType = DataType_; - DEFINE_FLAVOR_MEMBERS(DataType, main_clk, main_sel_first) + DEFINE_FLAVOR_MEMBERS(DataType, PRECOMPUTED_ENTITIES) - RefVector get_selectors() { return { main_clk, main_sel_first }; } + RefVector get_selectors() { return get_all(); } RefVector get_sigma_polynomials() { return {}; } RefVector get_id_polynomials() { return {}; } RefVector get_table_polynomials() { return {}; } @@ -228,579 +237,23 @@ class AvmFlavor { template class WireEntities { public: - DEFINE_FLAVOR_MEMBERS(DataType, - kernel_kernel_inputs, - kernel_kernel_value_out, - kernel_kernel_side_effect_out, - kernel_kernel_metadata_out, - main_calldata, - main_returndata, - alu_a_hi, - alu_a_lo, - alu_b_hi, - alu_b_lo, - alu_borrow, - alu_cf, - alu_clk, - alu_cmp_rng_ctr, - alu_div_u16_r0, - alu_div_u16_r1, - alu_div_u16_r2, - alu_div_u16_r3, - alu_div_u16_r4, - alu_div_u16_r5, - alu_div_u16_r6, - alu_div_u16_r7, - alu_divisor_hi, - alu_divisor_lo, - alu_ff_tag, - alu_ia, - alu_ib, - alu_ic, - alu_in_tag, - alu_op_add, - alu_op_cast, - alu_op_cast_prev, - alu_op_div, - alu_op_div_a_lt_b, - alu_op_div_std, - alu_op_eq, - alu_op_eq_diff_inv, - alu_op_lt, - alu_op_lte, - alu_op_mul, - alu_op_not, - alu_op_shl, - alu_op_shr, - alu_op_sub, - alu_p_a_borrow, - alu_p_b_borrow, - alu_p_sub_a_hi, - alu_p_sub_a_lo, - alu_p_sub_b_hi, - alu_p_sub_b_lo, - alu_partial_prod_hi, - alu_partial_prod_lo, - alu_quotient_hi, - alu_quotient_lo, - alu_remainder, - alu_res_hi, - alu_res_lo, - alu_sel_alu, - alu_sel_cmp, - alu_sel_div_rng_chk, - alu_sel_rng_chk, - alu_sel_rng_chk_lookup, - alu_sel_shift_which, - alu_shift_lt_bit_len, - alu_t_sub_s_bits, - alu_two_pow_s, - alu_two_pow_t_sub_s, - alu_u128_tag, - alu_u16_r0, - alu_u16_r1, - alu_u16_r10, - alu_u16_r11, - alu_u16_r12, - alu_u16_r13, - alu_u16_r14, - alu_u16_r2, - alu_u16_r3, - alu_u16_r4, - alu_u16_r5, - alu_u16_r6, - alu_u16_r7, - alu_u16_r8, - alu_u16_r9, - alu_u16_tag, - alu_u32_tag, - alu_u64_tag, - alu_u8_r0, - alu_u8_r1, - alu_u8_tag, - binary_acc_ia, - binary_acc_ib, - binary_acc_ic, - binary_clk, - binary_ia_bytes, - binary_ib_bytes, - binary_ic_bytes, - binary_in_tag, - binary_mem_tag_ctr, - binary_mem_tag_ctr_inv, - binary_op_id, - binary_sel_bin, - binary_start, - byte_lookup_sel_bin, - byte_lookup_table_byte_lengths, - byte_lookup_table_in_tags, - byte_lookup_table_input_a, - byte_lookup_table_input_b, - byte_lookup_table_op_id, - byte_lookup_table_output, - conversion_clk, - conversion_input, - conversion_num_limbs, - conversion_radix, - conversion_sel_to_radix_le, - gas_da_gas_fixed_table, - gas_l2_gas_fixed_table, - gas_sel_gas_cost, - keccakf1600_clk, - keccakf1600_input, - keccakf1600_output, - keccakf1600_sel_keccakf1600, - kernel_emit_l2_to_l1_msg_write_offset, - kernel_emit_note_hash_write_offset, - kernel_emit_nullifier_write_offset, - kernel_emit_unencrypted_log_write_offset, - kernel_kernel_in_offset, - kernel_kernel_out_offset, - kernel_l1_to_l2_msg_exists_write_offset, - kernel_note_hash_exist_write_offset, - kernel_nullifier_exists_write_offset, - kernel_nullifier_non_exists_write_offset, - kernel_q_public_input_kernel_add_to_table, - kernel_q_public_input_kernel_out_add_to_table, - kernel_side_effect_counter, - kernel_sload_write_offset, - kernel_sstore_write_offset, - main_abs_da_rem_gas_hi, - main_abs_da_rem_gas_lo, - main_abs_l2_rem_gas_hi, - main_abs_l2_rem_gas_lo, - main_alu_in_tag, - main_bin_op_id, - main_call_ptr, - main_da_gas_op_cost, - main_da_gas_remaining, - main_da_out_of_gas, - main_ia, - main_ib, - main_ic, - main_id, - main_id_zero, - main_ind_addr_a, - main_ind_addr_b, - main_ind_addr_c, - main_ind_addr_d, - main_internal_return_ptr, - main_inv, - main_l2_gas_op_cost, - main_l2_gas_remaining, - main_l2_out_of_gas, - main_mem_addr_a, - main_mem_addr_b, - main_mem_addr_c, - main_mem_addr_d, - main_op_err, - main_opcode_val, - main_pc, - main_r_in_tag, - main_rwa, - main_rwb, - main_rwc, - main_rwd, - main_sel_alu, - main_sel_bin, - main_sel_calldata, - main_sel_gas_accounting_active, - main_sel_last, - main_sel_mem_op_a, - main_sel_mem_op_activate_gas, - main_sel_mem_op_b, - main_sel_mem_op_c, - main_sel_mem_op_d, - main_sel_mov_ia_to_ic, - main_sel_mov_ib_to_ic, - main_sel_op_add, - main_sel_op_address, - main_sel_op_and, - main_sel_op_block_number, - main_sel_op_calldata_copy, - main_sel_op_cast, - main_sel_op_chain_id, - main_sel_op_cmov, - main_sel_op_coinbase, - main_sel_op_dagasleft, - main_sel_op_div, - main_sel_op_emit_l2_to_l1_msg, - main_sel_op_emit_note_hash, - main_sel_op_emit_nullifier, - main_sel_op_emit_unencrypted_log, - main_sel_op_eq, - main_sel_op_external_call, - main_sel_op_external_return, - main_sel_op_fdiv, - main_sel_op_fee_per_da_gas, - main_sel_op_fee_per_l2_gas, - main_sel_op_function_selector, - main_sel_op_get_contract_instance, - main_sel_op_halt, - main_sel_op_internal_call, - main_sel_op_internal_return, - main_sel_op_jump, - main_sel_op_jumpi, - main_sel_op_keccak, - main_sel_op_l1_to_l2_msg_exists, - main_sel_op_l2gasleft, - main_sel_op_lt, - main_sel_op_lte, - main_sel_op_mov, - main_sel_op_mul, - main_sel_op_not, - main_sel_op_note_hash_exists, - main_sel_op_nullifier_exists, - main_sel_op_or, - main_sel_op_pedersen, - main_sel_op_poseidon2, - main_sel_op_radix_le, - main_sel_op_sender, - main_sel_op_sha256, - main_sel_op_shl, - main_sel_op_shr, - main_sel_op_sload, - main_sel_op_sstore, - main_sel_op_storage_address, - main_sel_op_sub, - main_sel_op_timestamp, - main_sel_op_transaction_fee, - main_sel_op_version, - main_sel_op_xor, - main_sel_q_kernel_lookup, - main_sel_q_kernel_output_lookup, - main_sel_resolve_ind_addr_a, - main_sel_resolve_ind_addr_b, - main_sel_resolve_ind_addr_c, - main_sel_resolve_ind_addr_d, - main_sel_returndata, - main_sel_rng_16, - main_sel_rng_8, - main_sel_slice_gadget, - main_space_id, - main_tag_err, - main_w_in_tag, - mem_addr, - mem_clk, - mem_diff_hi, - mem_diff_lo, - mem_diff_mid, - mem_glob_addr, - mem_last, - mem_lastAccess, - mem_one_min_inv, - mem_r_in_tag, - mem_rw, - mem_sel_mem, - mem_sel_mov_ia_to_ic, - mem_sel_mov_ib_to_ic, - mem_sel_op_a, - mem_sel_op_b, - mem_sel_op_c, - mem_sel_op_cmov, - mem_sel_op_d, - mem_sel_op_slice, - mem_sel_resolve_ind_addr_a, - mem_sel_resolve_ind_addr_b, - mem_sel_resolve_ind_addr_c, - mem_sel_resolve_ind_addr_d, - mem_sel_rng_chk, - mem_skip_check_tag, - mem_space_id, - mem_tag, - mem_tag_err, - mem_tsp, - mem_val, - mem_w_in_tag, - pedersen_clk, - pedersen_input, - pedersen_output, - pedersen_sel_pedersen, - poseidon2_clk, - poseidon2_input, - poseidon2_output, - poseidon2_sel_poseidon_perm, - powers_power_of_2, - sha256_clk, - sha256_input, - sha256_output, - sha256_sel_sha256_compression, - sha256_state, - slice_addr, - slice_clk, - slice_cnt, - slice_col_offset, - slice_one_min_inv, - slice_sel_cd_cpy, - slice_sel_mem_active, - slice_sel_return, - slice_sel_start, - slice_space_id, - slice_val, - lookup_byte_lengths_counts, - lookup_byte_operations_counts, - lookup_cd_value_counts, - lookup_ret_value_counts, - lookup_opcode_gas_counts, - range_check_l2_gas_hi_counts, - range_check_l2_gas_lo_counts, - range_check_da_gas_hi_counts, - range_check_da_gas_lo_counts, - kernel_output_lookup_counts, - lookup_into_kernel_counts, - incl_main_tag_err_counts, - incl_mem_tag_err_counts, - lookup_mem_rng_chk_lo_counts, - lookup_mem_rng_chk_mid_counts, - lookup_mem_rng_chk_hi_counts, - lookup_pow_2_0_counts, - lookup_pow_2_1_counts, - lookup_u8_0_counts, - lookup_u8_1_counts, - lookup_u16_0_counts, - lookup_u16_1_counts, - lookup_u16_2_counts, - lookup_u16_3_counts, - lookup_u16_4_counts, - lookup_u16_5_counts, - lookup_u16_6_counts, - lookup_u16_7_counts, - lookup_u16_8_counts, - lookup_u16_9_counts, - lookup_u16_10_counts, - lookup_u16_11_counts, - lookup_u16_12_counts, - lookup_u16_13_counts, - lookup_u16_14_counts, - lookup_div_u16_0_counts, - lookup_div_u16_1_counts, - lookup_div_u16_2_counts, - lookup_div_u16_3_counts, - lookup_div_u16_4_counts, - lookup_div_u16_5_counts, - lookup_div_u16_6_counts, - lookup_div_u16_7_counts) + DEFINE_FLAVOR_MEMBERS(DataType, WIRE_ENTITIES) }; template class DerivedWitnessEntities { public: - DEFINE_FLAVOR_MEMBERS(DataType, - perm_slice_mem, - perm_main_alu, - perm_main_bin, - perm_main_conv, - perm_main_pos2_perm, - perm_main_pedersen, - perm_main_slice, - perm_main_mem_a, - perm_main_mem_b, - perm_main_mem_c, - perm_main_mem_d, - perm_main_mem_ind_addr_a, - perm_main_mem_ind_addr_b, - perm_main_mem_ind_addr_c, - perm_main_mem_ind_addr_d, - lookup_byte_lengths, - lookup_byte_operations, - lookup_cd_value, - lookup_ret_value, - lookup_opcode_gas, - range_check_l2_gas_hi, - range_check_l2_gas_lo, - range_check_da_gas_hi, - range_check_da_gas_lo, - kernel_output_lookup, - lookup_into_kernel, - incl_main_tag_err, - incl_mem_tag_err, - lookup_mem_rng_chk_lo, - lookup_mem_rng_chk_mid, - lookup_mem_rng_chk_hi, - lookup_pow_2_0, - lookup_pow_2_1, - lookup_u8_0, - lookup_u8_1, - lookup_u16_0, - lookup_u16_1, - lookup_u16_2, - lookup_u16_3, - lookup_u16_4, - lookup_u16_5, - lookup_u16_6, - lookup_u16_7, - lookup_u16_8, - lookup_u16_9, - lookup_u16_10, - lookup_u16_11, - lookup_u16_12, - lookup_u16_13, - lookup_u16_14, - lookup_div_u16_0, - lookup_div_u16_1, - lookup_div_u16_2, - lookup_div_u16_3, - lookup_div_u16_4, - lookup_div_u16_5, - lookup_div_u16_6, - lookup_div_u16_7) + DEFINE_FLAVOR_MEMBERS(DataType, DERIVED_WITNESS_ENTITIES) }; template class ShiftedEntities { public: - DEFINE_FLAVOR_MEMBERS(DataType, - alu_a_hi_shift, - alu_a_lo_shift, - alu_b_hi_shift, - alu_b_lo_shift, - alu_cmp_rng_ctr_shift, - alu_div_u16_r0_shift, - alu_div_u16_r1_shift, - alu_div_u16_r2_shift, - alu_div_u16_r3_shift, - alu_div_u16_r4_shift, - alu_div_u16_r5_shift, - alu_div_u16_r6_shift, - alu_div_u16_r7_shift, - alu_op_add_shift, - alu_op_cast_prev_shift, - alu_op_cast_shift, - alu_op_div_shift, - alu_op_mul_shift, - alu_op_shl_shift, - alu_op_shr_shift, - alu_op_sub_shift, - alu_p_sub_a_hi_shift, - alu_p_sub_a_lo_shift, - alu_p_sub_b_hi_shift, - alu_p_sub_b_lo_shift, - alu_sel_alu_shift, - alu_sel_cmp_shift, - alu_sel_div_rng_chk_shift, - alu_sel_rng_chk_lookup_shift, - alu_sel_rng_chk_shift, - alu_u16_r0_shift, - alu_u16_r1_shift, - alu_u16_r2_shift, - alu_u16_r3_shift, - alu_u16_r4_shift, - alu_u16_r5_shift, - alu_u16_r6_shift, - alu_u8_r0_shift, - alu_u8_r1_shift, - binary_acc_ia_shift, - binary_acc_ib_shift, - binary_acc_ic_shift, - binary_mem_tag_ctr_shift, - binary_op_id_shift, - kernel_emit_l2_to_l1_msg_write_offset_shift, - kernel_emit_note_hash_write_offset_shift, - kernel_emit_nullifier_write_offset_shift, - kernel_emit_unencrypted_log_write_offset_shift, - kernel_l1_to_l2_msg_exists_write_offset_shift, - kernel_note_hash_exist_write_offset_shift, - kernel_nullifier_exists_write_offset_shift, - kernel_nullifier_non_exists_write_offset_shift, - kernel_side_effect_counter_shift, - kernel_sload_write_offset_shift, - kernel_sstore_write_offset_shift, - main_da_gas_remaining_shift, - main_internal_return_ptr_shift, - main_l2_gas_remaining_shift, - main_pc_shift, - mem_glob_addr_shift, - mem_rw_shift, - mem_sel_mem_shift, - mem_tag_shift, - mem_tsp_shift, - mem_val_shift, - slice_addr_shift, - slice_clk_shift, - slice_cnt_shift, - slice_col_offset_shift, - slice_sel_cd_cpy_shift, - slice_sel_mem_active_shift, - slice_sel_return_shift, - slice_sel_start_shift, - slice_space_id_shift) + DEFINE_FLAVOR_MEMBERS(DataType, SHIFTED_ENTITIES) }; template static auto get_to_be_shifted(PrecomputedAndWitnessEntitiesSuperset& entities) { - return RefArray{ entities.alu_a_hi, - entities.alu_a_lo, - entities.alu_b_hi, - entities.alu_b_lo, - entities.alu_cmp_rng_ctr, - entities.alu_div_u16_r0, - entities.alu_div_u16_r1, - entities.alu_div_u16_r2, - entities.alu_div_u16_r3, - entities.alu_div_u16_r4, - entities.alu_div_u16_r5, - entities.alu_div_u16_r6, - entities.alu_div_u16_r7, - entities.alu_op_add, - entities.alu_op_cast_prev, - entities.alu_op_cast, - entities.alu_op_div, - entities.alu_op_mul, - entities.alu_op_shl, - entities.alu_op_shr, - entities.alu_op_sub, - entities.alu_p_sub_a_hi, - entities.alu_p_sub_a_lo, - entities.alu_p_sub_b_hi, - entities.alu_p_sub_b_lo, - entities.alu_sel_alu, - entities.alu_sel_cmp, - entities.alu_sel_div_rng_chk, - entities.alu_sel_rng_chk_lookup, - entities.alu_sel_rng_chk, - entities.alu_u16_r0, - entities.alu_u16_r1, - entities.alu_u16_r2, - entities.alu_u16_r3, - entities.alu_u16_r4, - entities.alu_u16_r5, - entities.alu_u16_r6, - entities.alu_u8_r0, - entities.alu_u8_r1, - entities.binary_acc_ia, - entities.binary_acc_ib, - entities.binary_acc_ic, - entities.binary_mem_tag_ctr, - entities.binary_op_id, - entities.kernel_emit_l2_to_l1_msg_write_offset, - entities.kernel_emit_note_hash_write_offset, - entities.kernel_emit_nullifier_write_offset, - entities.kernel_emit_unencrypted_log_write_offset, - entities.kernel_l1_to_l2_msg_exists_write_offset, - entities.kernel_note_hash_exist_write_offset, - entities.kernel_nullifier_exists_write_offset, - entities.kernel_nullifier_non_exists_write_offset, - entities.kernel_side_effect_counter, - entities.kernel_sload_write_offset, - entities.kernel_sstore_write_offset, - entities.main_da_gas_remaining, - entities.main_internal_return_ptr, - entities.main_l2_gas_remaining, - entities.main_pc, - entities.mem_glob_addr, - entities.mem_rw, - entities.mem_sel_mem, - entities.mem_tag, - entities.mem_tsp, - entities.mem_val, - entities.slice_addr, - entities.slice_clk, - entities.slice_cnt, - entities.slice_col_offset, - entities.slice_sel_cd_cpy, - entities.slice_sel_mem_active, - entities.slice_sel_return, - entities.slice_sel_start, - entities.slice_space_id }; + return RefArray{ TO_BE_SHIFTED(entities) }; } template @@ -835,83 +288,7 @@ class AvmFlavor { using Base = ProvingKeyAvm_, WitnessEntities, CommitmentKey>; using Base::Base; - RefVector get_to_be_shifted() - { - return { alu_a_hi, - alu_a_lo, - alu_b_hi, - alu_b_lo, - alu_cmp_rng_ctr, - alu_div_u16_r0, - alu_div_u16_r1, - alu_div_u16_r2, - alu_div_u16_r3, - alu_div_u16_r4, - alu_div_u16_r5, - alu_div_u16_r6, - alu_div_u16_r7, - alu_op_add, - alu_op_cast_prev, - alu_op_cast, - alu_op_div, - alu_op_mul, - alu_op_shl, - alu_op_shr, - alu_op_sub, - alu_p_sub_a_hi, - alu_p_sub_a_lo, - alu_p_sub_b_hi, - alu_p_sub_b_lo, - alu_sel_alu, - alu_sel_cmp, - alu_sel_div_rng_chk, - alu_sel_rng_chk_lookup, - alu_sel_rng_chk, - alu_u16_r0, - alu_u16_r1, - alu_u16_r2, - alu_u16_r3, - alu_u16_r4, - alu_u16_r5, - alu_u16_r6, - alu_u8_r0, - alu_u8_r1, - binary_acc_ia, - binary_acc_ib, - binary_acc_ic, - binary_mem_tag_ctr, - binary_op_id, - kernel_emit_l2_to_l1_msg_write_offset, - kernel_emit_note_hash_write_offset, - kernel_emit_nullifier_write_offset, - kernel_emit_unencrypted_log_write_offset, - kernel_l1_to_l2_msg_exists_write_offset, - kernel_note_hash_exist_write_offset, - kernel_nullifier_exists_write_offset, - kernel_nullifier_non_exists_write_offset, - kernel_side_effect_counter, - kernel_sload_write_offset, - kernel_sstore_write_offset, - main_da_gas_remaining, - main_internal_return_ptr, - main_l2_gas_remaining, - main_pc, - mem_glob_addr, - mem_rw, - mem_sel_mem, - mem_tag, - mem_tsp, - mem_val, - slice_addr, - slice_clk, - slice_cnt, - slice_col_offset, - slice_sel_cd_cpy, - slice_sel_mem_active, - slice_sel_return, - slice_sel_start, - slice_space_id }; - } + auto get_to_be_shifted() { return AvmFlavor::get_to_be_shifted(*this); } }; using VerificationKey = VerificationKey_, VerifierCommitmentKey>; @@ -926,492 +303,7 @@ class AvmFlavor { public: using DataType = const FF&; - DEFINE_FLAVOR_MEMBERS(DataType, - main_clk, - main_sel_first, - kernel_kernel_inputs, - kernel_kernel_value_out, - kernel_kernel_side_effect_out, - kernel_kernel_metadata_out, - main_calldata, - main_returndata, - alu_a_hi, - alu_a_lo, - alu_b_hi, - alu_b_lo, - alu_borrow, - alu_cf, - alu_clk, - alu_cmp_rng_ctr, - alu_div_u16_r0, - alu_div_u16_r1, - alu_div_u16_r2, - alu_div_u16_r3, - alu_div_u16_r4, - alu_div_u16_r5, - alu_div_u16_r6, - alu_div_u16_r7, - alu_divisor_hi, - alu_divisor_lo, - alu_ff_tag, - alu_ia, - alu_ib, - alu_ic, - alu_in_tag, - alu_op_add, - alu_op_cast, - alu_op_cast_prev, - alu_op_div, - alu_op_div_a_lt_b, - alu_op_div_std, - alu_op_eq, - alu_op_eq_diff_inv, - alu_op_lt, - alu_op_lte, - alu_op_mul, - alu_op_not, - alu_op_shl, - alu_op_shr, - alu_op_sub, - alu_p_a_borrow, - alu_p_b_borrow, - alu_p_sub_a_hi, - alu_p_sub_a_lo, - alu_p_sub_b_hi, - alu_p_sub_b_lo, - alu_partial_prod_hi, - alu_partial_prod_lo, - alu_quotient_hi, - alu_quotient_lo, - alu_remainder, - alu_res_hi, - alu_res_lo, - alu_sel_alu, - alu_sel_cmp, - alu_sel_div_rng_chk, - alu_sel_rng_chk, - alu_sel_rng_chk_lookup, - alu_sel_shift_which, - alu_shift_lt_bit_len, - alu_t_sub_s_bits, - alu_two_pow_s, - alu_two_pow_t_sub_s, - alu_u128_tag, - alu_u16_r0, - alu_u16_r1, - alu_u16_r10, - alu_u16_r11, - alu_u16_r12, - alu_u16_r13, - alu_u16_r14, - alu_u16_r2, - alu_u16_r3, - alu_u16_r4, - alu_u16_r5, - alu_u16_r6, - alu_u16_r7, - alu_u16_r8, - alu_u16_r9, - alu_u16_tag, - alu_u32_tag, - alu_u64_tag, - alu_u8_r0, - alu_u8_r1, - alu_u8_tag, - binary_acc_ia, - binary_acc_ib, - binary_acc_ic, - binary_clk, - binary_ia_bytes, - binary_ib_bytes, - binary_ic_bytes, - binary_in_tag, - binary_mem_tag_ctr, - binary_mem_tag_ctr_inv, - binary_op_id, - binary_sel_bin, - binary_start, - byte_lookup_sel_bin, - byte_lookup_table_byte_lengths, - byte_lookup_table_in_tags, - byte_lookup_table_input_a, - byte_lookup_table_input_b, - byte_lookup_table_op_id, - byte_lookup_table_output, - conversion_clk, - conversion_input, - conversion_num_limbs, - conversion_radix, - conversion_sel_to_radix_le, - gas_da_gas_fixed_table, - gas_l2_gas_fixed_table, - gas_sel_gas_cost, - keccakf1600_clk, - keccakf1600_input, - keccakf1600_output, - keccakf1600_sel_keccakf1600, - kernel_emit_l2_to_l1_msg_write_offset, - kernel_emit_note_hash_write_offset, - kernel_emit_nullifier_write_offset, - kernel_emit_unencrypted_log_write_offset, - kernel_kernel_in_offset, - kernel_kernel_out_offset, - kernel_l1_to_l2_msg_exists_write_offset, - kernel_note_hash_exist_write_offset, - kernel_nullifier_exists_write_offset, - kernel_nullifier_non_exists_write_offset, - kernel_q_public_input_kernel_add_to_table, - kernel_q_public_input_kernel_out_add_to_table, - kernel_side_effect_counter, - kernel_sload_write_offset, - kernel_sstore_write_offset, - main_abs_da_rem_gas_hi, - main_abs_da_rem_gas_lo, - main_abs_l2_rem_gas_hi, - main_abs_l2_rem_gas_lo, - main_alu_in_tag, - main_bin_op_id, - main_call_ptr, - main_da_gas_op_cost, - main_da_gas_remaining, - main_da_out_of_gas, - main_ia, - main_ib, - main_ic, - main_id, - main_id_zero, - main_ind_addr_a, - main_ind_addr_b, - main_ind_addr_c, - main_ind_addr_d, - main_internal_return_ptr, - main_inv, - main_l2_gas_op_cost, - main_l2_gas_remaining, - main_l2_out_of_gas, - main_mem_addr_a, - main_mem_addr_b, - main_mem_addr_c, - main_mem_addr_d, - main_op_err, - main_opcode_val, - main_pc, - main_r_in_tag, - main_rwa, - main_rwb, - main_rwc, - main_rwd, - main_sel_alu, - main_sel_bin, - main_sel_calldata, - main_sel_gas_accounting_active, - main_sel_last, - main_sel_mem_op_a, - main_sel_mem_op_activate_gas, - main_sel_mem_op_b, - main_sel_mem_op_c, - main_sel_mem_op_d, - main_sel_mov_ia_to_ic, - main_sel_mov_ib_to_ic, - main_sel_op_add, - main_sel_op_address, - main_sel_op_and, - main_sel_op_block_number, - main_sel_op_calldata_copy, - main_sel_op_cast, - main_sel_op_chain_id, - main_sel_op_cmov, - main_sel_op_coinbase, - main_sel_op_dagasleft, - main_sel_op_div, - main_sel_op_emit_l2_to_l1_msg, - main_sel_op_emit_note_hash, - main_sel_op_emit_nullifier, - main_sel_op_emit_unencrypted_log, - main_sel_op_eq, - main_sel_op_external_call, - main_sel_op_external_return, - main_sel_op_fdiv, - main_sel_op_fee_per_da_gas, - main_sel_op_fee_per_l2_gas, - main_sel_op_function_selector, - main_sel_op_get_contract_instance, - main_sel_op_halt, - main_sel_op_internal_call, - main_sel_op_internal_return, - main_sel_op_jump, - main_sel_op_jumpi, - main_sel_op_keccak, - main_sel_op_l1_to_l2_msg_exists, - main_sel_op_l2gasleft, - main_sel_op_lt, - main_sel_op_lte, - main_sel_op_mov, - main_sel_op_mul, - main_sel_op_not, - main_sel_op_note_hash_exists, - main_sel_op_nullifier_exists, - main_sel_op_or, - main_sel_op_pedersen, - main_sel_op_poseidon2, - main_sel_op_radix_le, - main_sel_op_sender, - main_sel_op_sha256, - main_sel_op_shl, - main_sel_op_shr, - main_sel_op_sload, - main_sel_op_sstore, - main_sel_op_storage_address, - main_sel_op_sub, - main_sel_op_timestamp, - main_sel_op_transaction_fee, - main_sel_op_version, - main_sel_op_xor, - main_sel_q_kernel_lookup, - main_sel_q_kernel_output_lookup, - main_sel_resolve_ind_addr_a, - main_sel_resolve_ind_addr_b, - main_sel_resolve_ind_addr_c, - main_sel_resolve_ind_addr_d, - main_sel_returndata, - main_sel_rng_16, - main_sel_rng_8, - main_sel_slice_gadget, - main_space_id, - main_tag_err, - main_w_in_tag, - mem_addr, - mem_clk, - mem_diff_hi, - mem_diff_lo, - mem_diff_mid, - mem_glob_addr, - mem_last, - mem_lastAccess, - mem_one_min_inv, - mem_r_in_tag, - mem_rw, - mem_sel_mem, - mem_sel_mov_ia_to_ic, - mem_sel_mov_ib_to_ic, - mem_sel_op_a, - mem_sel_op_b, - mem_sel_op_c, - mem_sel_op_cmov, - mem_sel_op_d, - mem_sel_op_slice, - mem_sel_resolve_ind_addr_a, - mem_sel_resolve_ind_addr_b, - mem_sel_resolve_ind_addr_c, - mem_sel_resolve_ind_addr_d, - mem_sel_rng_chk, - mem_skip_check_tag, - mem_space_id, - mem_tag, - mem_tag_err, - mem_tsp, - mem_val, - mem_w_in_tag, - pedersen_clk, - pedersen_input, - pedersen_output, - pedersen_sel_pedersen, - poseidon2_clk, - poseidon2_input, - poseidon2_output, - poseidon2_sel_poseidon_perm, - powers_power_of_2, - sha256_clk, - sha256_input, - sha256_output, - sha256_sel_sha256_compression, - sha256_state, - slice_addr, - slice_clk, - slice_cnt, - slice_col_offset, - slice_one_min_inv, - slice_sel_cd_cpy, - slice_sel_mem_active, - slice_sel_return, - slice_sel_start, - slice_space_id, - slice_val, - perm_slice_mem, - perm_main_alu, - perm_main_bin, - perm_main_conv, - perm_main_pos2_perm, - perm_main_pedersen, - perm_main_slice, - perm_main_mem_a, - perm_main_mem_b, - perm_main_mem_c, - perm_main_mem_d, - perm_main_mem_ind_addr_a, - perm_main_mem_ind_addr_b, - perm_main_mem_ind_addr_c, - perm_main_mem_ind_addr_d, - lookup_byte_lengths, - lookup_byte_operations, - lookup_cd_value, - lookup_ret_value, - lookup_opcode_gas, - range_check_l2_gas_hi, - range_check_l2_gas_lo, - range_check_da_gas_hi, - range_check_da_gas_lo, - kernel_output_lookup, - lookup_into_kernel, - incl_main_tag_err, - incl_mem_tag_err, - lookup_mem_rng_chk_lo, - lookup_mem_rng_chk_mid, - lookup_mem_rng_chk_hi, - lookup_pow_2_0, - lookup_pow_2_1, - lookup_u8_0, - lookup_u8_1, - lookup_u16_0, - lookup_u16_1, - lookup_u16_2, - lookup_u16_3, - lookup_u16_4, - lookup_u16_5, - lookup_u16_6, - lookup_u16_7, - lookup_u16_8, - lookup_u16_9, - lookup_u16_10, - lookup_u16_11, - lookup_u16_12, - lookup_u16_13, - lookup_u16_14, - lookup_div_u16_0, - lookup_div_u16_1, - lookup_div_u16_2, - lookup_div_u16_3, - lookup_div_u16_4, - lookup_div_u16_5, - lookup_div_u16_6, - lookup_div_u16_7, - lookup_byte_lengths_counts, - lookup_byte_operations_counts, - lookup_cd_value_counts, - lookup_ret_value_counts, - lookup_opcode_gas_counts, - range_check_l2_gas_hi_counts, - range_check_l2_gas_lo_counts, - range_check_da_gas_hi_counts, - range_check_da_gas_lo_counts, - kernel_output_lookup_counts, - lookup_into_kernel_counts, - incl_main_tag_err_counts, - incl_mem_tag_err_counts, - lookup_mem_rng_chk_lo_counts, - lookup_mem_rng_chk_mid_counts, - lookup_mem_rng_chk_hi_counts, - lookup_pow_2_0_counts, - lookup_pow_2_1_counts, - lookup_u8_0_counts, - lookup_u8_1_counts, - lookup_u16_0_counts, - lookup_u16_1_counts, - lookup_u16_2_counts, - lookup_u16_3_counts, - lookup_u16_4_counts, - lookup_u16_5_counts, - lookup_u16_6_counts, - lookup_u16_7_counts, - lookup_u16_8_counts, - lookup_u16_9_counts, - lookup_u16_10_counts, - lookup_u16_11_counts, - lookup_u16_12_counts, - lookup_u16_13_counts, - lookup_u16_14_counts, - lookup_div_u16_0_counts, - lookup_div_u16_1_counts, - lookup_div_u16_2_counts, - lookup_div_u16_3_counts, - lookup_div_u16_4_counts, - lookup_div_u16_5_counts, - lookup_div_u16_6_counts, - lookup_div_u16_7_counts, - alu_a_hi_shift, - alu_a_lo_shift, - alu_b_hi_shift, - alu_b_lo_shift, - alu_cmp_rng_ctr_shift, - alu_div_u16_r0_shift, - alu_div_u16_r1_shift, - alu_div_u16_r2_shift, - alu_div_u16_r3_shift, - alu_div_u16_r4_shift, - alu_div_u16_r5_shift, - alu_div_u16_r6_shift, - alu_div_u16_r7_shift, - alu_op_add_shift, - alu_op_cast_prev_shift, - alu_op_cast_shift, - alu_op_div_shift, - alu_op_mul_shift, - alu_op_shl_shift, - alu_op_shr_shift, - alu_op_sub_shift, - alu_p_sub_a_hi_shift, - alu_p_sub_a_lo_shift, - alu_p_sub_b_hi_shift, - alu_p_sub_b_lo_shift, - alu_sel_alu_shift, - alu_sel_cmp_shift, - alu_sel_div_rng_chk_shift, - alu_sel_rng_chk_lookup_shift, - alu_sel_rng_chk_shift, - alu_u16_r0_shift, - alu_u16_r1_shift, - alu_u16_r2_shift, - alu_u16_r3_shift, - alu_u16_r4_shift, - alu_u16_r5_shift, - alu_u16_r6_shift, - alu_u8_r0_shift, - alu_u8_r1_shift, - binary_acc_ia_shift, - binary_acc_ib_shift, - binary_acc_ic_shift, - binary_mem_tag_ctr_shift, - binary_op_id_shift, - kernel_emit_l2_to_l1_msg_write_offset_shift, - kernel_emit_note_hash_write_offset_shift, - kernel_emit_nullifier_write_offset_shift, - kernel_emit_unencrypted_log_write_offset_shift, - kernel_l1_to_l2_msg_exists_write_offset_shift, - kernel_note_hash_exist_write_offset_shift, - kernel_nullifier_exists_write_offset_shift, - kernel_nullifier_non_exists_write_offset_shift, - kernel_side_effect_counter_shift, - kernel_sload_write_offset_shift, - kernel_sstore_write_offset_shift, - main_da_gas_remaining_shift, - main_internal_return_ptr_shift, - main_l2_gas_remaining_shift, - main_pc_shift, - mem_glob_addr_shift, - mem_rw_shift, - mem_sel_mem_shift, - mem_tag_shift, - mem_tsp_shift, - mem_val_shift, - slice_addr_shift, - slice_clk_shift, - slice_cnt_shift, - slice_col_offset_shift, - slice_sel_cd_cpy_shift, - slice_sel_mem_active_shift, - slice_sel_return_shift, - slice_sel_start_shift, - slice_space_id_shift) + DEFINE_FLAVOR_MEMBERS(DataType, ALL_ENTITIES) AllConstRefValues(const RefArray& il) : main_clk(il[0]) @@ -1724,107 +616,107 @@ class AvmFlavor { , slice_sel_start(il[307]) , slice_space_id(il[308]) , slice_val(il[309]) - , perm_slice_mem(il[310]) - , perm_main_alu(il[311]) - , perm_main_bin(il[312]) - , perm_main_conv(il[313]) - , perm_main_pos2_perm(il[314]) - , perm_main_pedersen(il[315]) - , perm_main_slice(il[316]) - , perm_main_mem_a(il[317]) - , perm_main_mem_b(il[318]) - , perm_main_mem_c(il[319]) - , perm_main_mem_d(il[320]) - , perm_main_mem_ind_addr_a(il[321]) - , perm_main_mem_ind_addr_b(il[322]) - , perm_main_mem_ind_addr_c(il[323]) - , perm_main_mem_ind_addr_d(il[324]) - , lookup_byte_lengths(il[325]) - , lookup_byte_operations(il[326]) - , lookup_cd_value(il[327]) - , lookup_ret_value(il[328]) - , lookup_opcode_gas(il[329]) - , range_check_l2_gas_hi(il[330]) - , range_check_l2_gas_lo(il[331]) - , range_check_da_gas_hi(il[332]) - , range_check_da_gas_lo(il[333]) - , kernel_output_lookup(il[334]) - , lookup_into_kernel(il[335]) - , incl_main_tag_err(il[336]) - , incl_mem_tag_err(il[337]) - , lookup_mem_rng_chk_lo(il[338]) - , lookup_mem_rng_chk_mid(il[339]) - , lookup_mem_rng_chk_hi(il[340]) - , lookup_pow_2_0(il[341]) - , lookup_pow_2_1(il[342]) - , lookup_u8_0(il[343]) - , lookup_u8_1(il[344]) - , lookup_u16_0(il[345]) - , lookup_u16_1(il[346]) - , lookup_u16_2(il[347]) - , lookup_u16_3(il[348]) - , lookup_u16_4(il[349]) - , lookup_u16_5(il[350]) - , lookup_u16_6(il[351]) - , lookup_u16_7(il[352]) - , lookup_u16_8(il[353]) - , lookup_u16_9(il[354]) - , lookup_u16_10(il[355]) - , lookup_u16_11(il[356]) - , lookup_u16_12(il[357]) - , lookup_u16_13(il[358]) - , lookup_u16_14(il[359]) - , lookup_div_u16_0(il[360]) - , lookup_div_u16_1(il[361]) - , lookup_div_u16_2(il[362]) - , lookup_div_u16_3(il[363]) - , lookup_div_u16_4(il[364]) - , lookup_div_u16_5(il[365]) - , lookup_div_u16_6(il[366]) - , lookup_div_u16_7(il[367]) - , lookup_byte_lengths_counts(il[368]) - , lookup_byte_operations_counts(il[369]) - , lookup_cd_value_counts(il[370]) - , lookup_ret_value_counts(il[371]) - , lookup_opcode_gas_counts(il[372]) - , range_check_l2_gas_hi_counts(il[373]) - , range_check_l2_gas_lo_counts(il[374]) - , range_check_da_gas_hi_counts(il[375]) - , range_check_da_gas_lo_counts(il[376]) - , kernel_output_lookup_counts(il[377]) - , lookup_into_kernel_counts(il[378]) - , incl_main_tag_err_counts(il[379]) - , incl_mem_tag_err_counts(il[380]) - , lookup_mem_rng_chk_lo_counts(il[381]) - , lookup_mem_rng_chk_mid_counts(il[382]) - , lookup_mem_rng_chk_hi_counts(il[383]) - , lookup_pow_2_0_counts(il[384]) - , lookup_pow_2_1_counts(il[385]) - , lookup_u8_0_counts(il[386]) - , lookup_u8_1_counts(il[387]) - , lookup_u16_0_counts(il[388]) - , lookup_u16_1_counts(il[389]) - , lookup_u16_2_counts(il[390]) - , lookup_u16_3_counts(il[391]) - , lookup_u16_4_counts(il[392]) - , lookup_u16_5_counts(il[393]) - , lookup_u16_6_counts(il[394]) - , lookup_u16_7_counts(il[395]) - , lookup_u16_8_counts(il[396]) - , lookup_u16_9_counts(il[397]) - , lookup_u16_10_counts(il[398]) - , lookup_u16_11_counts(il[399]) - , lookup_u16_12_counts(il[400]) - , lookup_u16_13_counts(il[401]) - , lookup_u16_14_counts(il[402]) - , lookup_div_u16_0_counts(il[403]) - , lookup_div_u16_1_counts(il[404]) - , lookup_div_u16_2_counts(il[405]) - , lookup_div_u16_3_counts(il[406]) - , lookup_div_u16_4_counts(il[407]) - , lookup_div_u16_5_counts(il[408]) - , lookup_div_u16_6_counts(il[409]) - , lookup_div_u16_7_counts(il[410]) + , lookup_byte_lengths_counts(il[310]) + , lookup_byte_operations_counts(il[311]) + , lookup_cd_value_counts(il[312]) + , lookup_ret_value_counts(il[313]) + , lookup_opcode_gas_counts(il[314]) + , range_check_l2_gas_hi_counts(il[315]) + , range_check_l2_gas_lo_counts(il[316]) + , range_check_da_gas_hi_counts(il[317]) + , range_check_da_gas_lo_counts(il[318]) + , kernel_output_lookup_counts(il[319]) + , lookup_into_kernel_counts(il[320]) + , incl_main_tag_err_counts(il[321]) + , incl_mem_tag_err_counts(il[322]) + , lookup_mem_rng_chk_lo_counts(il[323]) + , lookup_mem_rng_chk_mid_counts(il[324]) + , lookup_mem_rng_chk_hi_counts(il[325]) + , lookup_pow_2_0_counts(il[326]) + , lookup_pow_2_1_counts(il[327]) + , lookup_u8_0_counts(il[328]) + , lookup_u8_1_counts(il[329]) + , lookup_u16_0_counts(il[330]) + , lookup_u16_1_counts(il[331]) + , lookup_u16_2_counts(il[332]) + , lookup_u16_3_counts(il[333]) + , lookup_u16_4_counts(il[334]) + , lookup_u16_5_counts(il[335]) + , lookup_u16_6_counts(il[336]) + , lookup_u16_7_counts(il[337]) + , lookup_u16_8_counts(il[338]) + , lookup_u16_9_counts(il[339]) + , lookup_u16_10_counts(il[340]) + , lookup_u16_11_counts(il[341]) + , lookup_u16_12_counts(il[342]) + , lookup_u16_13_counts(il[343]) + , lookup_u16_14_counts(il[344]) + , lookup_div_u16_0_counts(il[345]) + , lookup_div_u16_1_counts(il[346]) + , lookup_div_u16_2_counts(il[347]) + , lookup_div_u16_3_counts(il[348]) + , lookup_div_u16_4_counts(il[349]) + , lookup_div_u16_5_counts(il[350]) + , lookup_div_u16_6_counts(il[351]) + , lookup_div_u16_7_counts(il[352]) + , perm_slice_mem(il[353]) + , perm_main_alu(il[354]) + , perm_main_bin(il[355]) + , perm_main_conv(il[356]) + , perm_main_pos2_perm(il[357]) + , perm_main_pedersen(il[358]) + , perm_main_slice(il[359]) + , perm_main_mem_a(il[360]) + , perm_main_mem_b(il[361]) + , perm_main_mem_c(il[362]) + , perm_main_mem_d(il[363]) + , perm_main_mem_ind_addr_a(il[364]) + , perm_main_mem_ind_addr_b(il[365]) + , perm_main_mem_ind_addr_c(il[366]) + , perm_main_mem_ind_addr_d(il[367]) + , lookup_byte_lengths(il[368]) + , lookup_byte_operations(il[369]) + , lookup_cd_value(il[370]) + , lookup_ret_value(il[371]) + , lookup_opcode_gas(il[372]) + , range_check_l2_gas_hi(il[373]) + , range_check_l2_gas_lo(il[374]) + , range_check_da_gas_hi(il[375]) + , range_check_da_gas_lo(il[376]) + , kernel_output_lookup(il[377]) + , lookup_into_kernel(il[378]) + , incl_main_tag_err(il[379]) + , incl_mem_tag_err(il[380]) + , lookup_mem_rng_chk_lo(il[381]) + , lookup_mem_rng_chk_mid(il[382]) + , lookup_mem_rng_chk_hi(il[383]) + , lookup_pow_2_0(il[384]) + , lookup_pow_2_1(il[385]) + , lookup_u8_0(il[386]) + , lookup_u8_1(il[387]) + , lookup_u16_0(il[388]) + , lookup_u16_1(il[389]) + , lookup_u16_2(il[390]) + , lookup_u16_3(il[391]) + , lookup_u16_4(il[392]) + , lookup_u16_5(il[393]) + , lookup_u16_6(il[394]) + , lookup_u16_7(il[395]) + , lookup_u16_8(il[396]) + , lookup_u16_9(il[397]) + , lookup_u16_10(il[398]) + , lookup_u16_11(il[399]) + , lookup_u16_12(il[400]) + , lookup_u16_13(il[401]) + , lookup_u16_14(il[402]) + , lookup_div_u16_0(il[403]) + , lookup_div_u16_1(il[404]) + , lookup_div_u16_2(il[405]) + , lookup_div_u16_3(il[406]) + , lookup_div_u16_4(il[407]) + , lookup_div_u16_5(il[408]) + , lookup_div_u16_6(il[409]) + , lookup_div_u16_7(il[410]) , alu_a_hi_shift(il[411]) , alu_a_lo_shift(il[412]) , alu_b_hi_shift(il[413]) @@ -2244,6 +1136,49 @@ class AvmFlavor { slice_sel_start[row_idx], slice_space_id[row_idx], slice_val[row_idx], + lookup_byte_lengths_counts[row_idx], + lookup_byte_operations_counts[row_idx], + lookup_cd_value_counts[row_idx], + lookup_ret_value_counts[row_idx], + lookup_opcode_gas_counts[row_idx], + range_check_l2_gas_hi_counts[row_idx], + range_check_l2_gas_lo_counts[row_idx], + range_check_da_gas_hi_counts[row_idx], + range_check_da_gas_lo_counts[row_idx], + kernel_output_lookup_counts[row_idx], + lookup_into_kernel_counts[row_idx], + incl_main_tag_err_counts[row_idx], + incl_mem_tag_err_counts[row_idx], + lookup_mem_rng_chk_lo_counts[row_idx], + lookup_mem_rng_chk_mid_counts[row_idx], + lookup_mem_rng_chk_hi_counts[row_idx], + lookup_pow_2_0_counts[row_idx], + lookup_pow_2_1_counts[row_idx], + lookup_u8_0_counts[row_idx], + lookup_u8_1_counts[row_idx], + lookup_u16_0_counts[row_idx], + lookup_u16_1_counts[row_idx], + lookup_u16_2_counts[row_idx], + lookup_u16_3_counts[row_idx], + lookup_u16_4_counts[row_idx], + lookup_u16_5_counts[row_idx], + lookup_u16_6_counts[row_idx], + lookup_u16_7_counts[row_idx], + lookup_u16_8_counts[row_idx], + lookup_u16_9_counts[row_idx], + lookup_u16_10_counts[row_idx], + lookup_u16_11_counts[row_idx], + lookup_u16_12_counts[row_idx], + lookup_u16_13_counts[row_idx], + lookup_u16_14_counts[row_idx], + lookup_div_u16_0_counts[row_idx], + lookup_div_u16_1_counts[row_idx], + lookup_div_u16_2_counts[row_idx], + lookup_div_u16_3_counts[row_idx], + lookup_div_u16_4_counts[row_idx], + lookup_div_u16_5_counts[row_idx], + lookup_div_u16_6_counts[row_idx], + lookup_div_u16_7_counts[row_idx], perm_slice_mem[row_idx], perm_main_alu[row_idx], perm_main_bin[row_idx], @@ -2302,49 +1237,6 @@ class AvmFlavor { lookup_div_u16_5[row_idx], lookup_div_u16_6[row_idx], lookup_div_u16_7[row_idx], - lookup_byte_lengths_counts[row_idx], - lookup_byte_operations_counts[row_idx], - lookup_cd_value_counts[row_idx], - lookup_ret_value_counts[row_idx], - lookup_opcode_gas_counts[row_idx], - range_check_l2_gas_hi_counts[row_idx], - range_check_l2_gas_lo_counts[row_idx], - range_check_da_gas_hi_counts[row_idx], - range_check_da_gas_lo_counts[row_idx], - kernel_output_lookup_counts[row_idx], - lookup_into_kernel_counts[row_idx], - incl_main_tag_err_counts[row_idx], - incl_mem_tag_err_counts[row_idx], - lookup_mem_rng_chk_lo_counts[row_idx], - lookup_mem_rng_chk_mid_counts[row_idx], - lookup_mem_rng_chk_hi_counts[row_idx], - lookup_pow_2_0_counts[row_idx], - lookup_pow_2_1_counts[row_idx], - lookup_u8_0_counts[row_idx], - lookup_u8_1_counts[row_idx], - lookup_u16_0_counts[row_idx], - lookup_u16_1_counts[row_idx], - lookup_u16_2_counts[row_idx], - lookup_u16_3_counts[row_idx], - lookup_u16_4_counts[row_idx], - lookup_u16_5_counts[row_idx], - lookup_u16_6_counts[row_idx], - lookup_u16_7_counts[row_idx], - lookup_u16_8_counts[row_idx], - lookup_u16_9_counts[row_idx], - lookup_u16_10_counts[row_idx], - lookup_u16_11_counts[row_idx], - lookup_u16_12_counts[row_idx], - lookup_u16_13_counts[row_idx], - lookup_u16_14_counts[row_idx], - lookup_div_u16_0_counts[row_idx], - lookup_div_u16_1_counts[row_idx], - lookup_div_u16_2_counts[row_idx], - lookup_div_u16_3_counts[row_idx], - lookup_div_u16_4_counts[row_idx], - lookup_div_u16_5_counts[row_idx], - lookup_div_u16_6_counts[row_idx], - lookup_div_u16_7_counts[row_idx], alu_a_hi_shift[row_idx], alu_a_lo_shift[row_idx], alu_b_hi_shift[row_idx], diff --git a/bb-pilcom/bb-pil-backend/src/flavor_builder.rs b/bb-pilcom/bb-pil-backend/src/flavor_builder.rs index 535fbc1d094d..ff818ab19cb8 100644 --- a/bb-pilcom/bb-pil-backend/src/flavor_builder.rs +++ b/bb-pilcom/bb-pil-backend/src/flavor_builder.rs @@ -1,5 +1,6 @@ use crate::{file_writer::BBFiles, utils::snake_case}; -use handlebars::Handlebars; +use handlebars::{handlebars_helper, Handlebars}; +use itertools::Itertools; use serde_json::json; pub trait FlavorBuilder { @@ -51,6 +52,11 @@ impl FlavorBuilder for BBFiles { "witness_without_inverses": witness_without_inverses, }); + handlebars_helper!(join: |*args| + args.iter().map(|v| v.as_array().unwrap().to_owned()).collect_vec().concat() + ); + handlebars.register_helper("join", Box::new(join)); + handlebars .register_template_string( "flavor.hpp", diff --git a/bb-pilcom/bb-pil-backend/templates/circuit_builder.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/circuit_builder.hpp.hbs index ed14f5dab717..47c681dc9bd4 100644 --- a/bb-pilcom/bb-pil-backend/templates/circuit_builder.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/circuit_builder.hpp.hbs @@ -50,9 +50,9 @@ class {{name}}CircuitBuilder { {{/each}} } - {{#each to_be_shifted as |poly|}} - polys.{{poly}}_shift = Polynomial(polys.{{poly}}.shifted()); - {{/each}} + for (auto [shifted, to_be_shifted] : zip_view(polys.get_shifted(), polys.get_to_be_shifted())) { + shifted = to_be_shifted.shifted(); + } return polys; } @@ -153,8 +153,7 @@ class {{name}}CircuitBuilder { // Wait for lookup evaluations to complete for (auto& future : relation_futures) { - int result = future.get(); - if (!result) { + if (!future.get()) { return false; } } diff --git a/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs index 948fb907d011..c6d3c9c7c123 100644 --- a/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs @@ -19,8 +19,7 @@ #include "barretenberg/relations/generated/{{snakeCase ../name}}/{{r}}.hpp" {{/each}} -// Lookup relations -#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" +// Lookup and permutation relations {{#each lookups as |r|}} #include "barretenberg/relations/generated/{{snakeCase ../name}}/{{r}}.hpp" {{/each}} @@ -28,6 +27,16 @@ // Metaprogramming to concatenate tuple types. template using tuple_cat_t = decltype(std::tuple_cat(std::declval()...)); +// The entities that will be used in the flavor. +// clang-format off +#define PRECOMPUTED_ENTITIES {{#each fixed as |item|}}{{#if @index}}, {{/if}}{{item}}{{/each}} +#define WIRE_ENTITIES {{#each witness_without_inverses as |item|}}{{#if @index}}, {{/if}}{{item}}{{/each}} +#define DERIVED_WITNESS_ENTITIES {{#each lookups as |item|}}{{#if @index}}, {{/if}}{{item}}{{/each}} +#define SHIFTED_ENTITIES {{#each shifted as |item|}}{{#if @index}}, {{/if}}{{item}}{{/each}} +#define TO_BE_SHIFTED(e) {{#each to_be_shifted as |item|}}{{#if @index}}, {{/if}}e.{{item}}{{/each}} +#define ALL_ENTITIES PRECOMPUTED_ENTITIES, WIRE_ENTITIES, DERIVED_WITNESS_ENTITIES, SHIFTED_ENTITIES +// clang-format on + namespace bb { class {{name}}Flavor { @@ -86,11 +95,9 @@ class {{name}}Flavor { public: using DataType = DataType_; - DEFINE_FLAVOR_MEMBERS(DataType, {{#each fixed as |item|}}{{#if @index}},{{/if}}{{item}}{{/each}}) + DEFINE_FLAVOR_MEMBERS(DataType, PRECOMPUTED_ENTITIES) - RefVector get_selectors() { return { - {{#each fixed as |item|}}{{#if @index}},{{/if}}{{item}}{{/each}} - }; } + RefVector get_selectors() { return get_all(); } RefVector get_sigma_polynomials() { return {}; } RefVector get_id_polynomials() { return {}; } RefVector get_table_polynomials() { return {}; } @@ -99,26 +106,24 @@ class {{name}}Flavor { template class WireEntities { public: - DEFINE_FLAVOR_MEMBERS(DataType, {{#each witness_without_inverses as |item|}}{{#if @index}},{{/if}}{{item}}{{/each}}) + DEFINE_FLAVOR_MEMBERS(DataType, WIRE_ENTITIES) }; template class DerivedWitnessEntities { public: - DEFINE_FLAVOR_MEMBERS(DataType, {{#each lookups as |item|}}{{#if @index}},{{/if}}{{item}}{{/each}}) + DEFINE_FLAVOR_MEMBERS(DataType, DERIVED_WITNESS_ENTITIES) }; template class ShiftedEntities { public: - DEFINE_FLAVOR_MEMBERS(DataType, {{#each shifted as |item|}}{{#if @index}},{{/if}}{{item}}{{/each}}) + DEFINE_FLAVOR_MEMBERS(DataType, SHIFTED_ENTITIES) }; template static auto get_to_be_shifted(PrecomputedAndWitnessEntitiesSuperset& entities) { - return RefArray{ - {{#each to_be_shifted as |item|}}{{#if @index}},{{/if}}entities.{{item}}{{/each}} - }; + return RefArray{ TO_BE_SHIFTED(entities) }; } template @@ -151,9 +156,9 @@ class {{name}}Flavor { using Base = ProvingKey{{name}}_, WitnessEntities, CommitmentKey>; using Base::Base; - RefVector get_to_be_shifted() { return { - {{#each to_be_shifted as |item|}}{{#if @index}},{{/if}}{{item}}{{/each}} - }; } + auto get_to_be_shifted() { + return {{name}}Flavor::get_to_be_shifted(*this); + } }; using VerificationKey = VerificationKey_, VerifierCommitmentKey>; @@ -175,10 +180,12 @@ class {{name}}Flavor { If we did inherit from AllEntities, we have to define a special constructor for AllEntities, and all the classes that AllEntities inherits from, in cascade. --}} - DEFINE_FLAVOR_MEMBERS(DataType, {{#each all_cols_and_shifts as |item|}}{{#if @index}},{{/if}}{{item}}{{/each}}) + DEFINE_FLAVOR_MEMBERS(DataType, ALL_ENTITIES) AllConstRefValues(const RefArray& il) : - {{#each all_cols_and_shifts as |item|}}{{item}}(il[{{@index}}]){{#unless @last}},{{/unless}}{{/each}} + {{#each (join fixed witness_without_inverses lookups shifted) as |item|}} + {{item}}(il[{{@index}}]){{#unless @last}},{{/unless}} + {{/each}} {} }; @@ -226,7 +233,7 @@ class {{name}}Flavor { return AllConstRefValues(refs); --}} return AllConstRefValues(RefArray{ - {{#each all_cols_and_shifts as |item|}} + {{#each (join fixed witness_without_inverses lookups shifted) as |item|}} {{item}}[row_idx]{{#unless @last}},{{/unless}} {{/each}} }); From 86eafa0ca43645252852d1aa4def33de86156ff6 Mon Sep 17 00:00:00 2001 From: ludamad Date: Thu, 11 Jul 2024 10:28:11 -0400 Subject: [PATCH 30/32] chore(proving): post honk branch fixes (#7435) The original PR https://github.com/AztecProtocol/aztec-packages/pull/6971 was too much to delay, these are the straggler fixups post merge --- .vscode/launch.json | 3 ++- .vscode/settings.json | 2 +- barretenberg/.vscode/launch.json | 20 ------------------- barretenberg/cpp/src/barretenberg/bb/main.cpp | 5 ----- .../arithmetization/arithmetization.hpp | 2 +- 5 files changed, 4 insertions(+), 28 deletions(-) delete mode 100644 barretenberg/.vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json index 1c9a6801e9c4..7679ca97f300 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,8 @@ "version": "0.2.0", "configurations": [ { - "port": 9229, + "address": "${config:mainframeAddress}", + "port": 9221, "type": "node", "request": "attach", "name": "Attach to Remote", diff --git a/.vscode/settings.json b/.vscode/settings.json index 1df0f7fc2e0a..6bde2bae40ae 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -120,7 +120,7 @@ "editor.defaultFormatter": "hashicorp.terraform" }, "[typescript]": { - "editor.defaultFormatter": "vscode.typescript-language-features" + "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" diff --git a/barretenberg/.vscode/launch.json b/barretenberg/.vscode/launch.json deleted file mode 100644 index 5ea1dbb12277..000000000000 --- a/barretenberg/.vscode/launch.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "LLDB: Prove Ultra Honk Output All", - "type": "lldb", - "request": "launch", - "program": "/mnt/user-data/adam/aztec-packages/barretenberg/cpp/build-debug/bin/bb", - "args": [ - "prove_ultra_honk_output_all", - "-o", "/tmp/bb-095XQV/tmp-PPXk0y", - "-b", "/tmp/bb-095XQV/tmp-PPXk0y/PrivateKernelInitArtifact-bytecode", - "-w", "/tmp/bb-095XQV/tmp-PPXk0y/witness.gz", - "-v" - ], - "cwd": "${workspaceFolder}", - "stopOnEntry": false - } - ] -} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 3c1fa44785a6..f1814970b3a4 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -245,11 +245,6 @@ bool proveAndVerifyHonkProgram(const std::string& bytecodePath, const std::strin return true; } -struct VectorOfAcirAndWitnesses { - std::vector> acirGzippedBincoes; - std::vector> witnessMaps; -}; - // TODO(#7371): this could probably be more idiomatic template T unpack_from_file(const std::string& filename) { diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp index be21ac1c4305..e31d31b871a1 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp @@ -354,7 +354,7 @@ template class UltraHonkArith { std::array fixed_block_sizes{ 1 << 10, // ecc_op; 30000, // pub_inputs; - 755000, // arithmetic; + 600000, // arithmetic; 140000, // delta_range; 600000, // elliptic; 1400000, // aux; From 840a4b987f363626667b48febd46787f13a0f917 Mon Sep 17 00:00:00 2001 From: spypsy Date: Thu, 11 Jul 2024 16:24:26 +0100 Subject: [PATCH 31/32] fix: missing secrets in docs publish (#7445) --- .github/workflows/publish-docs.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index e1abe1531d9b..d4978e5c7628 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -28,7 +28,13 @@ jobs: concurrency_key: docs-preview-${{ inputs.username || github.actor }}-x86 - timeout-minutes: 25 - run: earthly-ci --no-output ./docs/+deploy-prod --NETLIFY_AUTH_TOKEN=${{ secrets.NETLIFY_AUTH_TOKEN }} --NETLIFY_SITE_ID=${{ secrets.NETLIFY_SITE_ID }} --COMMIT_TAG=${{ inputs.tag }} + run: | + earthly-ci --no-output ./docs/+deploy-prod \ + --NETLIFY_AUTH_TOKEN=${{ secrets.NETLIFY_AUTH_TOKEN }} \ + --NETLIFY_SITE_ID=${{ secrets.NETLIFY_SITE_ID }} \ + --COMMIT_TAG=${{ inputs.tag }} \ + --secret AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} \ + --secret AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} \ pdf: needs: setup From bb201f2fc8543cf752e2b5d5ec7ec15d3e7cdac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 11 Jul 2024 12:27:44 -0300 Subject: [PATCH 32/32] chore: apply where statement to impls instead of fns (#7433) Now that we can have a `where` that [affects an entire `impl`](https://github.com/noir-lang/noir/issues/4508), I thought I'd give this a try in the state variables. Often I've felt tricked by these implementations, since when trying to work with them the requirements for a given generic `T` seem fairly low, but then they add up as I start calling more and more functions, which each add their own trait bounds. The interface ends up feeling dishonest and not really showing all you need to do (all the traits that must be implemented) in order to be able to use the thing. With this change, the entire impl now requests up front all trait bounds, though it does mean we're a bit more restrictive than strictly needed. I don't think this is an issue - yes, you don't need to be able to serialize in order to read a public mutable, but you can only read if you write before, and that requires serialization. So all in all it seems like we always end up indirectly requiring all traits. --------- Co-authored-by: benesjan --- .../aztec/src/state_vars/private_mutable.nr | 23 ++++++------------ .../aztec/src/state_vars/private_set.nr | 20 ++++++++-------- .../aztec/src/state_vars/public_immutable.nr | 10 ++++---- .../aztec/src/state_vars/public_mutable.nr | 10 ++++---- .../aztec/src/state_vars/shared_immutable.nr | 14 +++++------ .../shared_mutable/shared_mutable.nr | 24 +++++++++---------- .../shared_mutable_private_getter.nr | 4 ++-- .../src/types/card_note.nr | 10 +++++++- .../src/types/balances_map.nr | 2 +- .../src/types/balances_map.nr | 2 +- .../token_contract/src/types/balances_map.nr | 2 +- 11 files changed, 60 insertions(+), 61 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr index a518ef4ed771..497f9dc987bd 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr @@ -43,12 +43,9 @@ impl PrivateMutable { } } -impl PrivateMutable { +impl PrivateMutable where Note: NoteInterface { // docs:start:initialize - pub fn initialize( - self, - note: &mut Note - ) -> NoteEmission where Note: NoteInterface { + pub fn initialize(self, note: &mut Note) -> NoteEmission { // Nullify the storage slot. let nullifier = self.compute_initialization_nullifier(); self.context.push_nullifier(nullifier, 0); @@ -58,10 +55,7 @@ impl PrivateMutable { // docs:end:initialize // docs:start:replace - pub fn replace( - self, - new_note: &mut Note - ) -> NoteEmission where Note: NoteInterface { + pub fn replace(self, new_note: &mut Note) -> NoteEmission { let prev_note: Note = get_note(self.context, self.storage_slot); // Nullify previous note. @@ -72,10 +66,7 @@ impl PrivateMutable { } // docs:end:replace - pub fn initialize_or_replace( - self, - note: &mut Note - ) -> NoteEmission where Note: NoteInterface { + pub fn initialize_or_replace(self, note: &mut Note) -> NoteEmission { let is_initialized = check_nullifier_exists(self.compute_initialization_nullifier()); // check_nullifier_exists() is an unconstrained function - we can constrain a true value by providing an @@ -96,7 +87,7 @@ impl PrivateMutable { } // docs:start:get_note - pub fn get_note(self) -> NoteEmission where Note: NoteInterface { + pub fn get_note(self) -> NoteEmission { let mut note = get_note(self.context, self.storage_slot); // Nullify current note to make sure it's reading the latest note. @@ -109,14 +100,14 @@ impl PrivateMutable { // docs:end:get_note } -impl PrivateMutable { +impl PrivateMutable where Note: NoteInterface { unconstrained pub fn is_initialized(self) -> bool { let nullifier = self.compute_initialization_nullifier(); check_nullifier_exists(nullifier) } // docs:start:view_note - unconstrained pub fn view_note(self) -> Note where Note: NoteInterface { + unconstrained pub fn view_note(self) -> Note { let mut options = NoteViewerOptions::new(); view_notes(self.storage_slot, options.set_limit(1)).get(0) } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr index 0b285013bb1b..c94b8a25bfa1 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr @@ -26,23 +26,23 @@ impl PrivateSet { // docs:end:new } -impl PrivateSet { +impl PrivateSet where Note: NoteInterface { // docs:start:insert_from_public - pub fn insert_from_public(self, note: &mut Note) where Note: NoteInterface { + pub fn insert_from_public(self, note: &mut Note) { create_note_hash_from_public(self.context, self.storage_slot, note); } // docs:end:insert_from_public } -impl PrivateSet { +impl PrivateSet where Note: NoteInterface + Eq { // docs:start:insert - pub fn insert(self, note: &mut Note) -> NoteEmission where Note: NoteInterface { + pub fn insert(self, note: &mut Note) -> NoteEmission { create_note(self.context, self.storage_slot, note) } // docs:end:insert // docs:start:remove - pub fn remove(self, note: Note) where Note: NoteInterface { + pub fn remove(self, note: Note) { let note_hash = compute_note_hash_for_read_request(note); let has_been_read = self.context.note_hash_read_requests.any(|r: ReadRequest| r.value == note_hash); assert(has_been_read, "Can only remove a note that has been read from the set."); @@ -52,21 +52,21 @@ impl PrivateSet { // docs:end:remove // docs:start:get_notes - pub fn get_notes( + pub fn get_notes( self, options: NoteGetterOptions - ) -> BoundedVec where Note: NoteInterface + Eq { + ) -> BoundedVec { get_notes(self.context, self.storage_slot, options) } // docs:end:get_notes } -impl PrivateSet { +impl PrivateSet where Note: NoteInterface { // docs:start:view_notes - unconstrained pub fn view_notes( + unconstrained pub fn view_notes( self, options: NoteViewerOptions - ) -> BoundedVec where Note: NoteInterface { + ) -> BoundedVec { view_notes(self.storage_slot, options) } // docs:end:view_notes diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr index 1206916cf798..0ee3326bd84f 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr @@ -27,9 +27,9 @@ impl PublicImmutable { // docs:end:public_immutable_struct_new } -impl PublicImmutable { +impl PublicImmutable where T: Serialize + Deserialize { // docs:start:public_immutable_struct_write - pub fn initialize(self, value: T) where T: Serialize { + pub fn initialize(self, value: T) { // We check that the struct is not yet initialized by checking if the initialization slot is 0 let initialization_slot = INITIALIZATION_SLOT_SEPARATOR + self.storage_slot; let init_field: Field = self.context.storage_read(initialization_slot); @@ -43,14 +43,14 @@ impl PublicImmutable { // Note that we don't access the context, but we do call oracles that are only available in public // docs:start:public_immutable_struct_read - pub fn read(self) -> T where T: Deserialize { + pub fn read(self) -> T { self.context.storage_read(self.storage_slot) } // docs:end:public_immutable_struct_read } -impl PublicImmutable { - unconstrained pub fn read(self) -> T where T: Deserialize { +impl PublicImmutablewhere T: Deserialize { + unconstrained pub fn read(self) -> T { self.context.storage_read(self.storage_slot) } } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr index 07038e14984d..6c300e7575f7 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr @@ -25,22 +25,22 @@ impl PublicMutable { // docs:end:public_mutable_struct_new } -impl PublicMutable { +impl PublicMutable where T: Serialize + Deserialize { // docs:start:public_mutable_struct_read - pub fn read(self) -> T where T: Deserialize { + pub fn read(self) -> T { self.context.storage_read(self.storage_slot) } // docs:end:public_mutable_struct_read // docs:start:public_mutable_struct_write - pub fn write(self, value: T) where T: Serialize { + pub fn write(self, value: T) { self.context.storage_write(self.storage_slot, value); } // docs:end:public_mutable_struct_write } -impl PublicMutable { - unconstrained pub fn read(self) -> T where T: Deserialize { +impl PublicMutable where T: Deserialize { + unconstrained pub fn read(self) -> T { self.context.storage_read(self.storage_slot) } } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr index c366a38cfd1e..39848738dbb8 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr @@ -23,9 +23,9 @@ impl SharedImmutable { } } -impl SharedImmutable { +impl SharedImmutable where T: Serialize + Deserialize { // Intended to be only called once. - pub fn initialize(self, value: T) where T: Serialize { + pub fn initialize(self, value: T) { // We check that the struct is not yet initialized by checking if the initialization slot is 0 let initialization_slot = INITIALIZATION_SLOT_SEPARATOR + self.storage_slot; let init_field: Field = self.context.storage_read(initialization_slot); @@ -36,19 +36,19 @@ impl SharedImmutable { self.context.storage_write(self.storage_slot, value); } - pub fn read_public(self) -> T where T: Deserialize { + pub fn read_public(self) -> T { self.context.storage_read(self.storage_slot) } } -impl SharedImmutable { - unconstrained pub fn read_public(self) -> T where T: Deserialize { +impl SharedImmutable where T: Serialize + Deserialize { + unconstrained pub fn read_public(self) -> T { self.context.storage_read(self.storage_slot) } } -impl SharedImmutable { - pub fn read_private(self) -> T where T: Deserialize { +impl SharedImmutable where T: Serialize + Deserialize { + pub fn read_private(self) -> T { let header = self.context.get_header(); let mut fields = [0; T_SERIALIZED_LEN]; diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr index 9823b25d8c95..2bf0d0001de8 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr @@ -13,7 +13,7 @@ use dep::std::unsafe::zeroed; mod test; -struct SharedMutable { +struct SharedMutable { context: Context, storage_slot: Field, } @@ -51,7 +51,7 @@ fn concat_arrays(arr_n: [Field; N], arr_m: [Field; M]) -> [Field; O] { // future, so that they can guarantee the value will not have possibly changed by then (because of the delay). // The delay for changing a value is initially equal to INITIAL_DELAY, but can be changed by calling // `schedule_delay_change`. -impl SharedMutable { +impl SharedMutable where T: ToField + FromField + Eq { pub fn new(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 } @@ -60,7 +60,7 @@ impl SharedMutable { fn hash_scheduled_data( value_change: ScheduledValueChange, delay_change: ScheduledDelayChange - ) -> Field where T: ToField { + ) -> Field { // TODO(#5491 and https://github.com/noir-lang/noir/issues/4784): update this so that we don't need to rely on // ScheduledValueChange serializing to 3 and ScheduledDelayChange serializing to 1 let concatenated: [Field; 4] = concat_arrays(value_change.serialize(), delay_change.serialize()); @@ -93,7 +93,7 @@ impl SharedMutable { self, header: Header, address: AztecAddress - ) -> (ScheduledValueChange, ScheduledDelayChange, u32) where T: FromField + ToField + Eq { + ) -> (ScheduledValueChange, ScheduledDelayChange, u32) { let historical_block_number = header.global_variables.block_number as u32; // We could simply produce historical inclusion proofs for both the ScheduledValueChange and @@ -127,8 +127,8 @@ impl SharedMutable { } } -impl SharedMutable { - pub fn schedule_value_change(self, new_value: T) where T: ToField { +impl SharedMutable where T: ToField + FromField + Eq { + pub fn schedule_value_change(self, new_value: T) { let mut value_change = self.read_value_change(); let delay_change = self.read_delay_change(); @@ -143,7 +143,7 @@ impl SharedMutable { self.write(value_change, delay_change); } - pub fn schedule_delay_change(self, new_delay: u32) where T: ToField { + pub fn schedule_delay_change(self, new_delay: u32) { let mut delay_change = self.read_delay_change(); let block_number = self.context.block_number() as u32; @@ -183,7 +183,7 @@ impl SharedMutable { self, value_change: ScheduledValueChange, delay_change: ScheduledDelayChange - ) where T: ToField { + ) { // Whenever we write to public storage, we write both the value change and delay change as well as the hash of // them both. This guarantees that the hash is always kept up to date. // While this makes for more costly writes, it also makes private proofs much simpler because they only need to @@ -199,8 +199,8 @@ impl SharedMutable { } } -impl SharedMutable { - pub fn get_current_value_in_private(self) -> T where T: FromField + ToField + Eq { +impl SharedMutable where T: ToField + FromField + Eq { + pub fn get_current_value_in_private(self) -> T { // When reading the current value in private we construct a historical state proof for the public value. // However, since this value might change, we must constrain the maximum transaction block number as this proof // will only be valid for however many blocks we can ensure the value will not change, which will depend on the @@ -229,12 +229,12 @@ unconstrained fn get_public_storage_hints( address: AztecAddress, storage_slot: Field, block_number: u32 -) -> (ScheduledValueChange, ScheduledDelayChange) { +) -> (ScheduledValueChange, ScheduledDelayChange) where T: ToField + FromField + Eq { // This function cannot be part of the &mut PrivateContext impl because that'd mean that by passing `self` we'd also // be passing a mutable reference to an unconstrained function, which is not allowed. We therefore create a dummy // state variable here so that we can access the methods to compute storage slots. This will all be removed in the // future once we do proper storage slot allocation (#5492). - let dummy = SharedMutable::new((), storage_slot); + let dummy: SharedMutable = SharedMutable::new((), storage_slot); ( storage_read(address, dummy.get_value_change_storage_slot(), block_number), storage_read(address, dummy.get_delay_change_storage_slot(), block_number) diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr index 78c7cc66bb3e..e389721ccabd 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr @@ -25,7 +25,7 @@ struct SharedMutablePrivateGetter { // We have this as a view-only interface to reading Shared Mutables in other contracts. // Currently the Shared Mutable does not support this. We can adapt SharedMutable at a later date -impl SharedMutablePrivateGetter { +impl SharedMutablePrivateGetter where T: FromField + ToField + Eq { pub fn new( context: &mut PrivateContext, other_contract_address: AztecAddress, @@ -36,7 +36,7 @@ impl SharedMutablePrivateGetter { Self { context, other_contract_address, storage_slot, _dummy: [0; INITIAL_DELAY] } } - pub fn get_value_in_private(self, header: Header) -> T where T: FromField + ToField + Eq { + pub fn get_value_in_private(self, header: Header) -> T { // We create a dummy SharedMutable state variable so that we can reuse its historical_read_from_public_storage // method, greatly reducing code duplication. let dummy: SharedMutable = SharedMutable::new((), self.storage_slot); diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr index 467457651531..f4a2094051fe 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr @@ -1,7 +1,7 @@ use dep::aztec::prelude::{AztecAddress, NoteInterface, NoteHeader, PrivateContext}; use dep::aztec::{ note::{utils::compute_note_hash_for_consumption}, keys::getters::get_nsk_app, - protocol_types::{traits::{Empty, Serialize}, constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash} + protocol_types::{traits::{Empty, Eq, Serialize}, constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash} }; // Shows how to create a custom note @@ -55,3 +55,11 @@ impl Serialize<3> for CardNote { [ self.points.to_field(), self.randomness, self.npk_m_hash.to_field() ] } } + +impl Eq for CardNote { + fn eq(self, other: Self) -> bool { + (self.points == other.points) & + (self.npk_m_hash == other.npk_m_hash) & + (self.randomness == other.randomness) + } +} diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/balances_map.nr index b1f1837ef70b..d70e62fa91c2 100644 --- a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/balances_map.nr @@ -70,7 +70,7 @@ impl BalancesMap { self: Self, owner_npk_m_hash: Field, addend: U128 - ) -> OuterNoteEmission where T: NoteInterface + OwnedNote { + ) -> OuterNoteEmission where T: NoteInterface + OwnedNote + Eq { let mut addend_note = T::new(addend, owner_npk_m_hash); OuterNoteEmission::new(Option::some(self.map.insert(&mut addend_note))) } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr index f97784cd218f..882364d9f655 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr @@ -59,7 +59,7 @@ impl BalancesMap { self: Self, owner: AztecAddress, addend: U128 - ) -> OuterNoteEmission where T: NoteInterface + OwnedNote { + ) -> OuterNoteEmission where T: NoteInterface + OwnedNote + Eq { if addend == U128::from_integer(0) { OuterNoteEmission::new(Option::none()) } else { diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr index 25e745746bc4..63a0092ea5c9 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -62,7 +62,7 @@ impl BalancesMap { self: Self, owner: AztecAddress, addend: U128 - ) -> OuterNoteEmission where T: NoteInterface + OwnedNote { + ) -> OuterNoteEmission where T: NoteInterface + OwnedNote + Eq { if addend == U128::from_integer(0) { OuterNoteEmission::new(Option::none()) } else {