diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json deleted file mode 100644 index 2dc5f952c11..00000000000 --- a/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "configurations": [ - { - "name": "Linux", - "includePath": [ - "${workspaceFolder}/**", - "${workspaceFolder}/circuits/src", - "${workspaceFolder}/circuits/barretenberg/cpp/src/aztec" - ], - "defines": [], - "compilerPath": "/usr/bin/clang", - "cStandard": "c11", - "cppStandard": "c++20", - "intelliSenseMode": "clang-x64" - } - ], - "version": 4 -} diff --git a/.vscode/launch.json b/.vscode/launch.json index 6ee6323034c..fa4b77b4ad0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -14,41 +14,5 @@ "localRoot": "${workspaceFolder}", "sourceMaps": true }, - /////////////////////////////////////// - // C++/Circuits targets - /////////////////////////////////////// - { - "name": "(lldb) Launch native - Circuits C++", - "type": "lldb", - "request": "launch", - "program": "${command:cmake.launchTargetPath}", - "args": [ "--gtest_filter=*" ], - "cwd": "${workspaceFolder}/circuits/cpp/build", - "internalConsoleOptions": "openOnSessionStart", - "console": "internalConsole" - }, - { - "name": "(lldb) Launch in WASM - Circuits C++", - "type": "lldb", - "request": "launch", - "program": "~/.wasmtime/bin/wasmtime", - "args": [ - "-g", // tell wasmtime to generate debug info - "--disable-cache", // necessary or wasmtime throws a error: - // thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ()', crates/jit/src/debug.rs:147:58 - // in: wasmtime_jit::debug::create_gdbjit_image - "--dir", // give wasmtime the parent dir as a sandbox - "..", // needs this to find srs - "${command:cmake.launchTargetPath}", // the test exe - "--", - "--gtest_filter=*", // filter tests - "--gtest_color=1" // color gtest output (off by default in wasm) - ], - "cwd": "${workspaceFolder}/circuits/cpp/build-wasm", - "internalConsoleOptions": "openOnSessionStart", - "console": "internalConsole" - }, - // End C++/Circuits targets - /////////////////////////////////////// ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 663bec37526..394dd741ab1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -114,7 +114,6 @@ "**/.yalc": true, "**/node_modules": true, "**/.pnp.*": true, - "circuits/cpp/barretenberg/**": true, "**/msgpack-c/**": true }, "[terraform]": { @@ -141,12 +140,6 @@ // "clangd.path": "clangd-15", // - // CMake - // - // Location of base CMakeLists file - "cmake.sourceDirectory": "${workspaceFolder}/circuits/cpp/", - "cmake.buildDirectory": "${workspaceFolder}/circuits/cpp/build", - // // C/C++ (should be disabled) // // Make sure all C++ IntelliSense features are disabled @@ -160,15 +153,5 @@ "C_Cpp.default.enableConfigurationSquiggles": false, "C_Cpp.formatting": "disabled", "C_Cpp.vcpkg.enabled": false, - "C_Cpp.default.includePath": ["cpp/barretenberg/cpp/src"], - // - // TestMate C++ - // - // Ensures tests are run from the `build` directory - // which ensures SRS can be read - "testMate.cpp.test.workingDirectory": "${workspaceFolder}/circuits/cpp/build", - // Filter all binaries that are not tests - "testMate.cpp.test.executables": "${workspaceFolder}/circuits/cpp/build/bin/*{test,Test,TEST}*" - // End C++/Circuits settings - /////////////////////////////////////// + "C_Cpp.default.includePath": ["barretenberg/cpp/src"], } diff --git a/barretenberg/README.md b/barretenberg/README.md index f76fc1cd2b2..687bb4c67b2 100644 --- a/barretenberg/README.md +++ b/barretenberg/README.md @@ -242,7 +242,7 @@ A default configuration for VS Code is provided by the file [`barretenberg.code- ### Integration tests with Aztec in Monorepo -CI will automatically run integration tests against Aztec. The tests in `circuits/cpp` folder use the embedded barretenberg, and can be used to integration test it. +CI will automatically run integration tests against Aztec. It is located in the `barretenberg` folder. ### Integration tests with Aztec in Barretenberg Standalone Repo diff --git a/barretenberg/cpp/src/barretenberg/proof_system/types/circuit_type.hpp b/barretenberg/cpp/src/barretenberg/proof_system/types/circuit_type.hpp index aaab7a8809f..f722e602c2f 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/types/circuit_type.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/types/circuit_type.hpp @@ -3,7 +3,6 @@ #include namespace bb { -// TODO(#731): Changing the explicit value of these enum elements breaks brittle and outdated tests in circuits/cpp. enum class CircuitType : uint32_t { STANDARD = 0, ULTRA = 2, UNDEFINED = 3 }; template diff --git a/circuits/.gitignore b/circuits/.gitignore deleted file mode 100644 index 3dd5576ae74..00000000000 --- a/circuits/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.vscode -node_modules -.yarn/cache -.yarn/install-state.gz -ts/dest -/build diff --git a/circuits/CODING_STANDARD.md b/circuits/CODING_STANDARD.md deleted file mode 100644 index dc77bd5c71d..00000000000 --- a/circuits/CODING_STANDARD.md +++ /dev/null @@ -1,308 +0,0 @@ -## C++ Standard for Aztec Circuits - -### Sticking to the Standard - -Read the standards and stick to them! There is some automation to help with this, but **the automation is far from comprehensive**. - -Here are the types of automation that should help stick to the standard: -1. The VSCode workspace file `circuits.code-workspace` is configured to automatically format your code nicely when you save a C++ file. - * It uses `cpp/.clang-format` for this -2. These workspace settings are also configured to warn you (with yellow squiggles) when something does not follow some of the rules. - * It uses `cpp/.clangd` for this -3. A tidy check is run in CI - * Job fails if your code would be changed by `./scripts/tidy.sh fix` -4. To perform some auto-tidying of your code, run `./scripts/tidy.sh fix` from `cpp/` - * **Commit your code first** since tidying will occasionally mess up your code! - * This will run `clang-tidy` on all C++ source files - * It uses `cpp/.clang-tidy` * and formats tidied code with `cpp/.clang-format` - * **Manually review any fixes to your code!** - * If you disagree with an auto-fix or if it is buggy, use `// NOLINT...` ([more here](https://clang.llvm.org/extra/clang-tidy/#suppressing-undesired-diagnostics)) - * If you believe we should reject an entire class of tidy fixes, consider explicitly omitting from our checks or errors in `./clang-tidy` - * Discuss with others first - * _Note:_ tidying takes a while! - * **You may need to run this multiple times!** - * An error (with an auto-fix) in one round may prevent certain subsequent fixes - * A fix in the one round may introduce more potential for fixes - -### The Standard - -1. **general** - * when something is not covered below, fall back to [Google's style guide](https://google.github.io/styleguide/cppguide.html) - * all TODOs should mention a username, email or bug number - ``` - // TODO(dbanks12) - // TODO(david@aztecprotocol.com) - // TODO(bug 12345) - ``` - * if your editor warns you about a line of code fix it! - * consider doing so even if you didn't write that code -1. **spacing** - * 4 spaces except for access-specifiers (`public`/`protected`/`private`) which can use 2 - * namespaces are not indented - * for continued indentation, just be sane - * remove trailing spaces at end of line (use a plugin) - * include a newline at the end of a file - ``` - namespace my_namespace { - class MyClass { - public: - // ... public stuff - - protected: - // ... protected stuff - - private: - // ... private stuff - - void my_private_function0(int arg0, - int arg1) - { - // ... - } - - void my_private_function1( - int arg0, - int arg1) - { - // ... - } - } - } // namespace my_namespace - - ``` -1. **braces** - * functions use curly brace alone on newline - * namespaces, classes, structs, enums, ifs, and loops use curely brace on same line - * examples - ``` - void my_function() - { - // ... - } - - for (int i = 0; i < max; i++) { - // ... - } - - if (something_is_true) { - // ... - } - - struct MyStruct { - // ... - } - ``` -1. **naming** - * `snake_case` for files, namespaces and local variables/members - * `CamelCase` for classes, structs, enums, types - * exceptions types can be made for types if trying to mimic a std type's name like `uint` or `field_ct` - * `ALL_CAPS` for `constexpr`s, global constants, and macros - * do use - * Clear names - * Descriptive names - * don't use - * abbreviations - * words with letters removed - * acronyms - * single letter names - * Unless writing maths, in which case use your best judgement and follow the naming of a _linked_ paper -1. `auto` - * include `*`, `&`, and/or `const` even when using `auto` - * use when type is evident - * use when type should be deduced automatically based on expr - * use in loops to iterate over members of a container - * don't use if it makes type unclear - * don't use you need to enforce a type - * examples - ``` - auto my_var = my_function_with_unclear_return_type(); // BAD - auto my_var = get_new_of_type_a(); // GOOD - ``` -1. `const` and `constexpr` - * use `const` whenever possible to express immutability - * use `constexpr` whenever a `const` can be computed at compile-time - * place `const`/`constexpr` BEFORE the core type as is done in bberg stdlib - * examples - ``` - const int my_const = 0; - constexpr int MY_CONST = 0; - ``` -1. `namespace` and `using` - * never do `using namespace my_namespace;` which causes namespace pollution and reduces readability - * [see here for google's corresponding rule](https://clang.llvm.org/extra/clang-tidy/checks/google/build-using-namespace.html) - * avoid doing `typedef my::OldType NewType` and instead do `using NewType = my::OldType` - * namespaces should exactly match directory structure. If you create a nested namespace, create a nested directory for it - * example for directory `aztec3/circuits/abis/private_kernel`: - ``` - namespace aztec3::circuits::abis::private_kernel { - // ... - } // namespace aztec3::circuits::abis::private_kernel - ``` - * use`init.hpp` *only* for core/critical renames like `NT/CT` and for toggling core types like `CircuitBuilder` - * use unnamed/anonymous namespaces to import and shorten external names into *just this one file* - * all of a file's external imports belong in a single anonymous namespace `namespace { ...\n } // namespace` at the very top of the file directly after `#include`s - * use `using Rename = old::namespace::prefix::Name;` to import and shorten names from external namespaces - * avoid using renames to obscure template params (`using A = A;`) - * never use renames to remove the `std::` prefix - * never use renames to remove a `NT::` or `CT::` prefix - * `test.cpp` tests must always explicitly import every single name they intend to use - * they might want to test over multiple namespaces, native and circuit types, and builder types - * avoid calling barretenberg's functions directly and instead go through interface files like `circuit_types` and -`native_types` - * `using` statements should be sorted case according to the `LexicographicNumeric` rules - * see the `SortUsingDeclarations` section of the [LLVM Clang Format Style Options document](https://clang.llvm.org/docs/ClangFormatStyleOptions.html) - * if your IDE is telling you that an include or name is unused in a file, remove it! -1. **includes** - * start every header with `#pragma once` - * `index.hpp` should include common headers that will be referenced by most cpp/hpp files in the current directory - * `init.hpp` should inject ONLY critical renames (like `NT`/`CT`) and type toggles (like CircuitBuilder) - * example `using NT = aztec3::utils::types::NativeTypes;` - * avoid including headers via relative paths (`../../other_dir`) unless they are a subdir (`subdir/header.hpp`) - * use full path like `aztec3/circuits/hash.hpp` - * ordering of includes - * this source file's header - * essentials (if present) - * `"index.hpp"` - * `"init.hpp"` - * headers nearby - * headers from this directory (no `/`) - * headers from this project using relative path (`"private/private_kernel_inputs.hpp"`) - * Note: headers in this group are sorted in the above order (no `/` first, relative paths second) - * headers from this project using full path (starts with aztec3: `"aztec3/constants.hpp"`) - * barretenberg headers - * `` or other third party headers specified in `.clang-format` - * C++ standard library headers - * use quotes internal headers - * use angle braces for std library and external library headers - * this includes barretenberg - * each group of includes should be sorted case sensitive alphabetically - * each group of includes should be newline-separated - * example: - ``` - #include "this_file.hpp" - - #include "index.hpp" - #include "init.hpp" - - #include "my_file_a_in_this_dir.hpp" - #include "my_file_b_in_this_dir.hpp" - #include "other_dir/file_a_nearby.hpp" - #include "other_dir/file_b_nearby.hpp" - - #include "aztec3/file_a_in_project.hpp" - #include "aztec3/file_b_in_project.hpp" - - #include - #include - - #include - - #include - #include - ``` -1. **access specifiers** - * order them `public`, `protected`, `private` -1. **struct and array initialization** - * use `MyStruct my_inst{};` - * will call default constructor if exists and otherwise will value-initialize members to zero (or will call *their* default constructors if they exist) - * explicitly initialize struct members with default values: `NT::fr my_fr = 0;` - * initialize arrays using `std::array my_arr{};` - * this value-initializes all entries to 0 if T has no default constructor, otherwise calls default constructor for each - * For arrays of fields `fr`, it is particularly important to use the direct initialization form with empty initializer list - ` - std::array vk_path{}; - ` - because the default constructor of `fr` is NOT initializing the array field values to 0. For large arrays and performance considerations, it may be useful to not initialize the field array elements using `std::array vk_path();` -1. **references** - * use them whenever possible for function arguments since pass by reference is cheaper - * make arg references "const" if they should not be modified inside a function -1. **avoid C-style coding** - * avoid `malloc/free` - * use `std::array/vector` instead of `int[]` - * use references instead of pointers when possible - * if pointers are necessary, use smart pointers (`std::unique_ptr/shared_ptr`) instead of raw pointers - * avoid C-style casts (use `static_cast` or `reinterpret_cast`) -1. **comments** - * use doxygen docstrings (will include format example) - ``` - /** - * @brief Brief description - * @details more details - * @tparam mytemplateparam description - * @param myfunctionarg description - * @return describe return value - * @see otherRelevantFunction() - * @see [mylink](url) - */ - ``` - * every file should have a meaningful comment - * every class/struct/function/test should have a meaningful comment - * class/struct comment might == file comment - * comment function preconditions ("arg x must be < 100") -1. **side-effects** - * avoid functions with side effects when it is easy enough to just have pure functions - * if a function modifies its arguments, it should be made very clear that this is happening - * same with class methods that modify members - * function arguments should be `const` when they will not be modified -1. **global state** - * no -1. **docs** - * every subdir should have a readme -1. **functions** - * use `[[nodiscard]]` if it makes no sense to call this function and discard return value - ``` - [[nodiscard] int my_function() - { - // ... - return some_int; - } - - // later can't do - my_function(); - - // can only do - int capture_ret = my_function(); - ``` - * if there is a name clash, prefix parameter with underscore like `_myparam` - ``` - void my_function(int _my_var) - { - my_var = _my_var; - } - ``` -1. **macros** - * avoid macros as much as possible with exceptions for - * testing - * debug utilities - * agreed upon macro infrastructure (like cbinds) -1. **misc** - * use `uintN_t` instead of a primitive type (e.g. `size_t`) when a specific type width must be guaranteed - * avoid signed types (`int`, `long`, `char` etc) unless signedness is required - * signed types are susceptible to undefined behavior on overflow/underflow - * initialize pointers to `nullptr` - * constructors with single arguments should be marked `explicit` to prevent unwanted conversions - * if a constructor is meant to do nothing, do `A() = default;` instead of `A(){}` ([explanation here](https://clang.llvm.org/extra/clang-tidy/checks/modernize/use-equals-default.html)) - * definitely don't do `A(){};` (with semicolon) which can't even be auto-fixed by `clang-tidy` - * explicitly use `override` when overriding a parent class' member ([explanation here](https://clang.llvm.org/extra/clang-tidy/checks/modernize/use-override.html)) - * avoid multiple declarations on the same line - * do: - ``` - int a = 0; - int b = 0; - ``` - * dont: - ``` - int a, b = 0, 0; - ``` - * use `std::vector::emplace_back` instead of `push_back` - * don't use `std::make_pair` when using `emplace_back` ([unnecessary as explained here](https://clang.llvm.org/extra/clang-tidy/checks/modernize/use-emplace.html)) - * **no magic numbers** even if there is a comment explaining them - - -## References - -1. [Mike's Draft C++ Standard](https://hackmd.io/@aztec-network/B1r36lhmj?type=view) -2. [Barretenberg's `.clangd`](https://github.com/AztecProtocol/barretenberg/blob/master/cpp/.clangd) -3. [Barretenberg's `.clang-format`](https://github.com/AztecProtocol/barretenberg/blob/master/cpp/.clang-format) -4. [LLVM's Clang Format Style Options](https://clang.llvm.org/docs/ClangFormatStyleOptions.html) -5. [Google's Style Guide](https://google.github.io/styleguide/cppguide.html) \ No newline at end of file diff --git a/circuits/README.md b/circuits/README.md deleted file mode 100644 index e9e03574020..00000000000 --- a/circuits/README.md +++ /dev/null @@ -1,295 +0,0 @@ -# Aztec 3 Circuit Onboarding - -###### tags: `aztec-3, circuits` - -## Contributing - -See [CODING_STANDARD.md](./CODING_STANDARD.md)\*\* before contributing! - -## Repository Overview - -The [`aztec3-circuits`](https://github.com/AztecProtocol/aztec3-packages) circuits folder contains circuits and related C++ code (`cpp/`) for Aztec3 along with Typescript wrappers (`ts/`). - -### Dependencies - -- cmake >= 3.24 -- Ninja (used by the presets as the default generator) -- clang16 -- clang-format -- wasm-opt (part of the [Binaryen](https://github.com/WebAssembly/binaryen) toolkit) -- [wasmtime](https://docs.wasmtime.dev/cli-install.html) for running tests in a wasm environment - -### Resources - -- [Circuits project board](https://github.com/orgs/AztecProtocol/projects/22/views/2) -- [[DO NOT EDIT] Diagram with pseudocode for circuits](https://miro.com/app/board/uXjVPlafJWM=/) - - This diagram's contents are likely more up-to-date than code and than the other links below -- Kernel circuits - - [Slides - Dive into Kernel Circuits](https://drive.google.com/file/d/1BaspihHDUgny6MHAKMtTkWKvfah7PYtv/view?usp=share_link) - - [Recording of presentation](https://drive.google.com/file/d/1Uh-vLdc1_rsMUHL_c4HZ93jrjpuDsqD3/view?usp=share_link) - - [Kernel circuit mentioned in M1.1 Contract Deployment document](https://hackmd.io/ouVCnacHQRq2o1oRc5ksNA#Kernel-Circuit-functionality) - - [More info on the kernel circuit for Contract Creation](https://hackmd.io/@aztec-network/rkyRaXqPj#Kernel-Circuit-Logic) - - _Note:_ [Base rollup circuits in Aztec Connect](https://github.com/AztecProtocol/aztec-connect-cpp/tree/defi-bridge-project/src/rollup/proofs/rollup) are relevant to kernel circuits -- Rollup circuits - - [Rollup circuit mentioned in M1.1 Contract Deployment document](https://hackmd.io/ouVCnacHQRq2o1oRc5ksNA#Rollup-Circuit-functionality) - - [More info on the rollup circuit for Contract Creation](https://hackmd.io/@aztec-network/rkyRaXqPj#Rollup-Circuit-Logic) - - [Rollup circuits in Aztec Connect](https://github.com/AztecProtocol/aztec-connect-cpp/tree/defi-bridge-project/src/rollup/proofs) - - [[DO NOT EDIT] Diagram with different options for merkle insertions in rollup circuits](https://miro.com/app/board/uXjVMfITC3c=/) -- [Outdated specs](https://github.com/AztecProtocol/aztec2-internal/blob/3.0/markdown/specs/aztec3/src/SUMMARY.md) -- [Explanation of Indexed Merkle Tree (for nullifiers)](https://hackmd.io/AjR1uGh8SzSc7k3Gcu02mQ) - -### Getting Started with C++ - -Clone the repo and build the C++: - -``` -git clone git@github.com:AztecProtocol/aztec3-packages.git -cd circuits -git submodule update --init --recursive -cd cpp -./bootstrap.sh -``` - -Here is an example of rapidly rebuilding and running all tests for `x86_64`: - -``` -./bootstrap.sh -./scripts/run_tests_local x86_64 glob -``` - -> **WARNING:** the `x86_64` (and `wasm` used below) as well as the keyword `glob` **MUST BE LOWERCASE**! - -Here is an example of rapidly rebuilding and running only the abis tests for `wasm`: - -``` -./bootstrap.sh aztec3_circuits_abis_tests -./scripts/run_tests_local wasm aztec3_circuits_abis_tests -``` - -> _Note:_ to run wasm tests you must first follow the [instructions here](https://docs.wasmtime.dev/cli-install.html) to install `wasmtime`. - -You can choose which tests will run via a gtest filter. This one below runs only tests that _omit_ the string '.circuit': - -``` -./scripts/run_tests_local wasm aztec3_circuits_abis_tests -*.circuit* -``` - ---- - -Here's a list of the tests currently available (conveniently combined with the command to build, then execute them on `x86_64`, for easy copy-pasta): - -- `aztec3_circuits_abis_tests` - - - `./bootstrap.sh aztec3_circuits_abis_tests && ./scripts/run_tests_local x86_64 aztec3_circuits_abis_tests` - -- `aztec3_circuits_apps_tests` - - - `./bootstrap.sh aztec3_circuits_apps_tests && ./scripts/run_tests_local x86_64 aztec3_circuits_apps_tests` - -- `aztec3_circuits_kernel_tests` - - - `./bootstrap.sh aztec3_circuits_kernel_tests && ./scripts/run_tests_local x86_64 aztec3_circuits_kernel_tests` - -- `aztec3_circuits_recursion_tests` - - - `./bootstrap.sh aztec3_circuits_recursion_tests && ./scripts/run_tests_local x86_64 aztec3_circuits_recursion_tests` - -- `aztec3_circuits_rollup_tests` - - `./bootstrap.sh aztec3_circuits_rollup_tests && ./scripts/run_tests_local x86_64 aztec3_circuits_rollup_tests` - ---- - -#### Using docker to replicate CI failures - -You can also run tests in docker. This is useful for replicating CI failures that you can't replicate with your standard local environment. - -To build and run all tests in an `x86_64` docker image: - -``` -./bootstrap.sh -./scripts/build_run_tests_docker_local 1 x86_64 glob -``` - -You can choose `wasm` instead of `x86_64`. You can also specify individual test executables instead of `glob` and can use gtest filters exactly as described for `run_tests_local`. - -> At this time, it is common to run wasm tests with the filter `-*.circuit*` as there are circuit issues in wasm. - -> The `build_run_tests_docker_local` script builds the chosen docker image (`x86_64` or `wasm`) and then launches a container from that image to run the `run_tests_local` script (used above). - -#### Generating code coverage reports - -You can generate coverage reports for your tests. -To build and run coverage on all tests: - -``` -./bootstrap.sh -./scripts/run_coverage -``` - -Producing coverage reports is computationally intensive -You can select a specific test suite to run coverage on by supplying it as an argument to the `run_coverage`. For example, to only compile and produce - -``` -./bootstrap.sh -./scripts/run_coverage aztec3_circuits_abis_tests -``` - -**Toggles** -Running with the `CLEAN` environment variable set will delete the existing `build-coverage` folder. -Running with the `CLEAR_COV` environment variable will delete any existing `lcov.info` file. - -#### Viewing coverage reports - -Once a report has been generated, you can view them within the `build-coverage` folder in html format. If you ran coverage with any tests in mind, the report will exist in a folder prefixed with its name, otherwise they can be found in one labelled all_tests. - -#### Viewing coverage reports inside vscode - -It may be useful to view coverage information from within vscode. The `./scripts/run_coverage` will produce an `lcov.info` file that should automatically be picked up by the `coverage-gutters` vscode extension. - ---- - -#### Using the VSCode debugger - -> **WARNING:** to debug in WASM (to use the `-g` option to `wasmtime`) you will unfortunately need to revert to `wasmtime` version `1.0.0` until [this bug](https://github.com/bytecodealliance/wasmtime/issues/3999) is fixed. To install that version, remove the `~/.wasmtime` directory and run `curl https://wasmtime.dev/install.sh -sSf | bash /dev/stdin --version v1.0.0` - -1. Make sure you have the recommended plugins installed - - Open the command palette (`Ctrl+Shift+P`) - - `Cmd+Shift+P` on Macs - - Type and select "Extensions: Show Recommended Extensions" - - Install any plugins shown not already installed -1. Configure CMake for whichever preset you'd like to use - - Open the command palette (`Ctrl+Shift+P`) - - Type and select "CMake: Select Configure Preset" - - Choose a debug preset such as: - - "Debugging build with Clang-16" - - "Debugging build for WASM" - - Redo this step later to switch between Clang-16/native and wasm -1. Go to the "Run and Debug" panel - - Button (usually on left) that looks like a play button with a bug - - Or `Ctrl+Shift+D` -1. Select the proper launch option at the top of the "Run and Debug" panel - - "Launch native" - - "Launch in WASM" -1. Select the test executable to debug - - Open the command palette (`Ctrl+Shift+P`) - - Type and select "CMake: Set Debug Target" - - Select executable to debug like `aztec3_circuits_abis_tests` -1. Check output for progress -1. [OPTIONAL] change `gtest_filter` args to filter specific test cases - - In `circuits.code-workspace`'s `launch->configurations->` - - Don't commit these changes -1. [OPTIONAL] set breakpoints in C++ files - -> _Note:_ redo steps 3-5 to switch between debugging Clang-16/native test executables and WASM test executables - ---- - -### C++ Repository Layout - -This repository submodules [`barretenberg`](https://github.com/AztecProtocol/barretenberg) as a C++ library containing proving systems and utilities at `cpp/barretenberg/`. - -The core Aztec 3 C++ code lives in `cpp/src/aztec3/`, and is split into the following subdirectories/files: - -- `constants.hpp`: top-level constants relevant to Aztec 3 -- `circuits`: circuits and their types and interfaces - - `apps`: infrastructure and early prototypes for application circuits ([more here](https://github.com/AztecProtocol/aztec3-packages/tree/master/circuits/cpp/src/aztec3/circuits/apps)) - - `abis`: types, interfaces, and cbinds for representing/constructing outputs of application circuits that will be fed into kernel circuits ([more here](https://github.com/AztecProtocol/aztec3-packages/tree/master/circuits/cpp/src/aztec3/circuits/abis)) - - `kernel`: kernel circuits, their interfaces, and their tests - - `rollup`: rollup circuits, their interfaces and tests - - `recursion`: types and examples for aggregation of recursive proof objects - - `mock`: mock circuits -- `oracle`: used to fetch external information (like private data notes) and inject them as inputs into the circuit during execution of circuit logic ([more here](https://github.com/AztecProtocol/aztec3-packages/tree/master/circuits/cpp/src/aztec3/oracle)) -- `dbs`: database infrastructure (_e.g._ PrivateStateDb) - -### Typescript - -All typescript code was moved from here into `aztec3-packages/yarn-project/circuits.js`. - -## Private Kernel Circuit - -The private kernel circuit validates that a particular private function was correctly executed by the user. Therefore, the private kernel circuit is going to be run on the user's device. A private function execution can involve calls to other private functions from the same contract or private functions from other contracts. Each call to another private function needs to be proven that the execution was correct. Therefore, each nested call to another private function will have its own circuit execution proof, and that proof must then be validated by the private kernel circuit. The proof generated by the private kernel circuit will be submitted to the transaction pool, from where rollup providers will include those private kernel proofs in their L2 blocks. - -The private kernel circuit in Aztec 3 is implemented in [`circuit/kernel/private`](https://github.com/AztecProtocol/aztec3-packages/tree/master/circuits/cpp/src/aztec3/circuits/kernel/private) directory. The input and output interface of the private kernel circuit is written in [`circuits/abis/private_kernel`](https://github.com/AztecProtocol/aztec3-packages/tree/master/circuits/cpp/src/aztec3/circuits/abis/private_kernel). - -See pseudocode in [this diagram](https://miro.com/app/board/uXjVPlafJWM=/) and the slides [here](https://drive.google.com/file/d/1BaspihHDUgny6MHAKMtTkWKvfah7PYtv/view?usp=share_link) for a deeper dive into the private kernel circuit. - -## Public Kernel Circuit - -The public kernel circuit performs many of the functions of the private kernel circuit but for public functions. Public functions differ from public functions in that they they are executed by the sequencer and can modify the public state tree. Like private functions, public functions can include calls to other public functions and these calls are validated within the circuit. - -The public kernel circuit in Aztec 3 is implemented in [`circuit/kernel/public`](https://github.com/AztecProtocol/aztec3-packages/tree/master/circuits/cpp/src/aztec3/circuits/kernel/publlic) directory. The input and output interface of the private kernel circuit is written in [`circuits/abis/public_kernel`](https://github.com/AztecProtocol/aztec3-packages/tree/master/circuits/cpp/src/aztec3/circuits/abis/public_kernel). - -## Circuit Overviews - -### Base Rollup Circuit - -The rollup providers (or sequencers - nomenclature is yet to be decided) pull up transactions from the pool to be rolled up. Each of these transactions is essentially a proof generated by the private kernel circuit including its public inputs. To accumulate several such transactions in a single L2 block, the rollup provider needs to aggregate the private kernel proofs. The base rollup circuit is meant to aggregate these private kernel proofs. In simple words, the rollup circuit validates that the private kernel circuit was correctly executed. - -In our design, we allow the rollup providers to only aggregate _two_ private kernel proofs at once. This would mean that if a rollup provider wishes to roll-up 1024 transactions in one L2 block, for example, he would need $\frac{1024}{2} = 512$ invocations of the base rollup circuit. This hard-limit on the number of private kernel proofs that one can aggregate is enable generating rollup proofs on commodity hardware, effectively reducing the entry-barrier for common users to become rollup providers. - -:::info -At a very high-level, the rollup circuits need to perform the following checks: - -1. Aggregate the inner proofs (most expensive part taking up appx 75% circuit size) -2. Merkle membership checks (second most expensive part taking up appx 15% circuit size) -3. Public input hashing using SHA-256 (third most expensive part, appx 10%, can blow up if you need to hash tons of public inputs) - -We have a limit on the first point: you can aggregate a maximum of two proofs per rollup circuit. We still need to decide if we wish to put any limits on the second step. Mike has an idea of splitting up the Merkle membership checks across multiple rollup circuits so that all of the Merkle membership computation doesn't need to be performed by a single circuit. Similarly, we need to ensure that a rollup circuit doesn't need to hash huge amounts of data in one stage. -::: - -:::warning -**Note**: For the first milestone, we do not include public function execution in our circuit design. -::: - -See pseudocode in [this diagram](https://miro.com/app/board/uXjVPlafJWM=/) for a deep dive into the Base Rollup Circuit's functionality. - -### Merge Rollup Circuit - -The base rollup proofs further need to be validated if they were executed correctly. The merge rollup circuit is supposed to verify that the base rollup proofs are correct. In principle, the design of the merge rollup circuit would be very similar to the base rollup circuit except the change in the ABIs. As with the base rollup circuit, every merge rollup circuit validates two base rollup proofs. - -Furthermore, we can use the same merge rollup circuit to verify two merge rollup proofs to further compress the proof validation. This leads to a formation of a tree-like structure to create an L2 block. - -See pseudocode in [this diagram](https://miro.com/app/board/uXjVPlafJWM=/) for a deep dive into the Merge Rollup Circuit's functionality. - -:::warning -**Note**: We might not need the merge rollup circuit for the offsite but its anyway going to be very similar to the base rollup circuit. -::: - -### Root Rollup Circuit - -The root rollup circuit is the final circuit execution layer before the proof is sent to L1 for on-chain verification. The root rollup circuit verifies that the final merge rollup circuit was correctly executed. The proof from the root rollup circuit is verified by the rollup contract on Ethereum. So effectively, verifying that one proof on-chain gives a final green flag to whatever number of transactions that were included in that particular L2 block. - -It is interesting to note that the root rollup circuit takes _one_ proof and outputs _one_ proof. The reason we do this is to switch the types of the proof: i.e. ultra-plonk/honk to standard-plonk. This is because standard-plonk proofs are cheaper to verify on-chain (in terms of gas costs). - -See pseudocode in [this diagram](https://miro.com/app/board/uXjVPlafJWM=/) for a deep dive into the Root Rollup Circuit's functionality. - -## Circuit Logic - -### Private Kernel Circuit Logic - -The private kernel circuit is recursive in that it will perform validation of a single function call, and then recursively verify its previous iteration along with the next function call. - -Below is a list of the private kernel circuit's high-level responsibilities: - -1. For the first iteration: - - **[M1.1]** Validate the signature of a signed tx object - - Validate the function in that tx object matches the one currently being processed -2. For all subsequent iterations: - - Pop an item off of the kernel's dynamic callstack - - Validate that this function matches the one currently being processed -3. Verify a 'previous' kernel circuit (mock for first iteration, always mocked for **[M1.1]**) -4. Verify the proof of execution for the function (or constructor **[M1.1]**) currently being processed -5. **[M1.1]** If this is a contract deployment, check the contract deployment logic - - _[After M1.1]_ Includes checks for private circuit execution logic -6. **[M1.1]** Generate `contract_address` and its nullifier (inserted in later circuit) -7. **[M1.1]** Generate `new_contract_data` which is the contract tree leaf preimage -8. Copy the current function's callstack into kernel's dynamic callstack -9. Validate the function data against `function_tree_root` - - Includes a membership check of the function leaf -10. Validate the contract data against `contract_tree_root` - - Includes a membership check of the contract leaf -11. Perform membership checks for commitments accessed by this function -12. Collect new commitments, nullifiers, contracts, and messages to L1 -13. Add recursion byproducts to `aggregation_object` -14. TODO: L1 messages -15. Section in progress... diff --git a/circuits/cpp/.clang-format b/circuits/cpp/.clang-format deleted file mode 100644 index 7e309b5090f..00000000000 --- a/circuits/cpp/.clang-format +++ /dev/null @@ -1,92 +0,0 @@ -Language: Cpp -BasedOnStyle: Google -ColumnLimit: 120 - -# Whitespace -IndentWidth: 4 -UseTab: Never -#LineEnding: LF -MaxEmptyLinesToKeep: 2 - -# Auto-insertions -#InsertNewlineAtEOF: true -#InsertTrailingCommas: true -#InsertBraces: true - -# Alignment -#ReferenceAlignment: Left -PointerAlignment: Left -#QualifierAlignment: Left # only in clang-format 14+ - -# Misc spacing/linebreaks -AccessModifierOffset: -2 -AllowShortFunctionsOnASingleLine: Inline -AllowShortIfStatementsOnASingleLine: Never -AlwaysBreakAfterReturnType: None -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakTemplateDeclarations: No -PenaltyReturnTypeOnItsOwnLine: 1000000 -BreakConstructorInitializers: BeforeComma - -# Includes -SortIncludes: true # Consider CaseSensitive in clang-format 13+ -IncludeBlocks: Regroup -IncludeCategories: - # 1. Special headers - - Regex: '"\(index\.hpp\)|\(init\.hpp\)"' - Priority: 1 - # 2. Headers in "" with no '/' (current dir). - - Regex: '"([A-Za-z0-9.\Q-_\E])+"' - Priority: 2 - SortPriority: 2 - # 2. Headers in "" that start with '../'. - - Regex: '"\.\./([A-Za-z0-9.\Q-_\E])+"' - Priority: 2 - SortPriority: 4 # same priority/group as 2, but sorted to bottom. - # 5. Aztec3 headers in "". - - Regex: '["<]aztec3/([A-Za-z0-9.\Q/-_\E])+[">]' - Priority: 5 - # 6. Barretenberg headers in "" - - Regex: '["<]barretenberg/.*[">]' - Priority: 6 - # 2. All other headers in "". - # Note: Must be below aztec3/barretenberg groups or it captures them too. - - Regex: '"([A-Za-z0-9.\Q/-_\E])+"' - Priority: 2 - SortPriority: 3 # same priority/group as 2, but sorted to middle. - # 6. Headers in <> with extension. - - Regex: '<([A-Za-z0-9\Q/-_\E])+\.[A-Za-z0-9.\Q/-_\E]>' - Priority: 7 - # 7. Headers in <> from specific external libraries. - - Regex: '<(gtest|placeHolderForOthers)>' - Priority: 8 - # 8. Headers in <> without extension. - - Regex: '<([A-Za-z0-9\Q/-_\E])+>' - Priority: 9 - -# Namespaces and using -FixNamespaceComments: true -NamespaceIndentation: None -SortUsingDeclarations: true # LexicographicNumeric - -# Bin packing -BinPackArguments: false -BinPackParameters: false - -# Braces -Cpp11BracedListStyle: false -#BreakBeforeBraces: Allman -BreakBeforeBraces: Custom -BraceWrapping: - AfterClass: false - AfterEnum: false - AfterFunction: true - AfterNamespace: false - AfterStruct: false - AfterUnion: false - AfterExternBlock: false - BeforeCatch: false - BeforeElse: false - SplitEmptyFunction: false - SplitEmptyRecord: false - SplitEmptyNamespace: false diff --git a/circuits/cpp/.clang-tidy b/circuits/cpp/.clang-tidy deleted file mode 100644 index cd140f4d0e6..00000000000 --- a/circuits/cpp/.clang-tidy +++ /dev/null @@ -1,212 +0,0 @@ -# Note there is some overlap between this file and .clangd -# .clangd has no concept of warnings versus errors, but since it -# won't actually fail/error (since its really just an LSP for -# showing issues in an editor), it is acceptable to treat most -# .clang-tidy warnings as .clangd errors. Also, some error codes -# with buggy-autofixes need to be omitted from checks in .clang-tidy -# but can be included in .clangd since it won't change code without -# a user action. -# -# .clang-tidy on the other hand will error in CI for any check that -# is flagged (not explicitly omitted after '*') in WarningsAsErrors. -# So, it needs to omit certain checks or keep them as warnings only -# if they are too strict. - -# TODO(AD): Picking a limited subset for now, pending a deeper dive into the performance issues. See #1152. -Checks: ' - clang-analyzer-apiModeling.Errno - clang-analyzer-apiModeling.StdCLibraryFunctions - clang-analyzer-apiModeling.TrustNonnull - clang-analyzer-apiModeling.TrustReturnsNonnull - clang-analyzer-apiModeling.google.GTest - clang-analyzer-apiModeling.llvm.CastValue - clang-analyzer-apiModeling.llvm.ReturnValue - clang-analyzer-core.CallAndMessage - clang-analyzer-core.CallAndMessageModeling - clang-analyzer-core.DivideZero - clang-analyzer-core.DynamicTypePropagation - clang-analyzer-core.NonNullParamChecker - clang-analyzer-core.NonnilStringConstants - clang-analyzer-core.NullDereference - clang-analyzer-core.StackAddrEscapeBase - clang-analyzer-core.StackAddressEscape - clang-analyzer-core.VLASize - clang-analyzer-core.builtin.BuiltinFunctions - clang-analyzer-core.builtin.NoReturnFunctions - clang-analyzer-core.uninitialized.ArraySubscript - clang-analyzer-core.uninitialized.Assign - clang-analyzer-core.uninitialized.Branch - clang-analyzer-core.uninitialized.CapturedBlockVariable - clang-analyzer-core.uninitialized.UndefReturn - clang-analyzer-cplusplus.InnerPointer - clang-analyzer-cplusplus.Move - clang-analyzer-cplusplus.NewDelete - clang-analyzer-cplusplus.PlacementNew - clang-analyzer-cplusplus.PureVirtualCall - clang-analyzer-cplusplus.SmartPtrModeling - clang-analyzer-cplusplus.StringChecker - clang-analyzer-cplusplus.VirtualCallModeling - clang-analyzer-deadcode.DeadStores - clang-analyzer-fuchsia.HandleChecker - clang-analyzer-nullability.NullPassedToNonnull - clang-analyzer-nullability.NullReturnedFromNonnull - clang-analyzer-nullability.NullabilityBase - clang-analyzer-nullability.NullableDereferenced - clang-analyzer-nullability.NullablePassedToNonnull - clang-analyzer-nullability.NullableReturnedFromNonnull - clang-analyzer-optin.cplusplus.UninitializedObject - clang-analyzer-optin.cplusplus.VirtualCall - clang-analyzer-optin.mpi.MPI-Checker - clang-analyzer-optin.osx.OSObjectCStyleCast - clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker - clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker - clang-analyzer-optin.performance.GCDAntipattern - clang-analyzer-optin.portability.UnixAPI - clang-analyzer-security.FloatLoopCounter - clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling - clang-analyzer-security.insecureAPI.SecuritySyntaxChecker - clang-analyzer-security.insecureAPI.UncheckedReturn - clang-analyzer-security.insecureAPI.bcmp - clang-analyzer-security.insecureAPI.bcopy - clang-analyzer-security.insecureAPI.bzero - clang-analyzer-security.insecureAPI.decodeValueOfObjCType - clang-analyzer-security.insecureAPI.getpw - clang-analyzer-security.insecureAPI.gets - clang-analyzer-security.insecureAPI.mkstemp - clang-analyzer-security.insecureAPI.mktemp - clang-analyzer-security.insecureAPI.rand - clang-analyzer-security.insecureAPI.strcpy - clang-analyzer-security.insecureAPI.vfork - clang-analyzer-unix.API - clang-analyzer-unix.DynamicMemoryModeling - clang-analyzer-unix.Malloc - clang-analyzer-unix.MallocSizeof - clang-analyzer-unix.MismatchedDeallocator - clang-analyzer-unix.Vfork - clang-analyzer-unix.cstring.BadSizeArg - clang-analyzer-unix.cstring.CStringModeling - clang-analyzer-unix.cstring.NullArg - clang-analyzer-valist.CopyToSelf - clang-analyzer-valist.Uninitialized - clang-analyzer-valist.Unterminated - clang-analyzer-valist.ValistBase - clang-analyzer-webkit.NoUncountedMemberChecker - clang-analyzer-webkit.RefCntblBaseVirtualDtor - clang-analyzer-webkit.UncountedLambdaCapturesChecker - cppcoreguidelines-avoid-c-arrays - cppcoreguidelines-avoid-goto - cppcoreguidelines-explicit-virtual-functions - cppcoreguidelines-init-variables - cppcoreguidelines-interfaces-global-init - cppcoreguidelines-macro-usage - cppcoreguidelines-narrowing-conversions - cppcoreguidelines-prefer-member-initializer - cppcoreguidelines-pro-type-const-cast - cppcoreguidelines-pro-type-static-cast-downcast - cppcoreguidelines-pro-type-union-access - cppcoreguidelines-pro-type-vararg - cppcoreguidelines-slicing - cppcoreguidelines-virtual-class-destructor - performance-faster-string-find - performance-for-range-copy - performance-implicit-conversion-in-loop - performance-inefficient-algorithm - performance-inefficient-string-concatenation - performance-inefficient-vector-operation - performance-move-const-arg - performance-move-constructor-init - performance-no-automatic-move - performance-no-int-to-ptr - performance-noexcept-move-constructor - performance-trivially-destructible - performance-type-promotion-in-math-fn - performance-unnecessary-copy-initialization - portability-restrict-system-includes - portability-simd-intrinsics - portability-std-allocator-const - -bugprone-unchecked-optional-access - -bugprone-unhandled-self-assignment - -clang-analyzer-core.UndefinedBinaryOperatorResult - -clang-analyzer-cplusplus.NewDeleteLeaks - -clang-analyzer-optin.performance.Padding - -cert-err58-cpp - -cert-oop54-cpp - -cppcoreguidelines-avoid-non-const-global-variables - -cppcoreguidelines-avoid-magic-numbers - -cppcoreguidelines-c-copy-assignment-signature - -cppcoreguidelines-no-malloc - -cppcoreguidelines-owning-memory - -cppcoreguidelines-pro-type-cstyle-cast - -cppcoreguidelines-pro-type-reinterpret-cast - -cppcoreguidelines-special-member-functions - -google-build-using-namespace - -google-global-names-in-headers - -google-readability-casting - -misc-definitions-in-headers - -misc-no-recursion - -misc-unconventional-assign-operator - -modernize-return-braced-init-list - -performance-unnecessary-value-param - -readability-function-cognitive-complexity - -readability-magic-numbers -' - -# We treat all warnings as errors. -WarningsAsErrors: '*' - -# Notes on specific Checks and WarningsAsErrors -# -# These checks rename our cbinds and consts that have `__` in the name: -# -bugprone-reserved-identifier, -# -cert-dcl37-c, -# -cert-dcl51-cpp, -# `any_of/all_of` loops are not objectively more readable: -# -readability-use-anyofallof, -# Will need to refactor our usage of `malloc/free` with `gsl::owner`: -# -cppcoreguidelines-owning-memory, -# Flags way too many functions: -# -bugprone-easily-swappable-parameters, -# We use anon namespaces to import types: -# -google-build-namespaces, -# -cert-dcl59-cpp, -# Not sure we want to use trailing return type: -# -modernize-use-trailing-return-type, -# Buggy in clang-tidy 15.0.6: -# -modernize-use-nodiscard, -# ^ TODO(david): re-enable if we move to newer clang version -# We use c-arrays in low-level code logic relating to c_bind: -# -modernize-avoid-c-arrays, -# This was changing code in ways that made it harder to follow: -# -modernize-pass-by-value, -# ^ TODO(david) we probably want to re-enable this one -# We like (a == true) in circuits: -# -readability-simplify-boolean-expr, -# We have a lot of one-letter variable names...: -# -readability-identifier-length, -# All of our tests use underscores in names: -# -google-readability-avoid-underscore-in-googletest-name, -# All of our circuit structs have non-private members: -# -misc-non-private-member-variables-in-classes, -# -cppcoreguidelines-non-private-member-variables-in-classes, -# We have many `for` loops that violate this part of the bounds safety profile -# -cppcoreguidelines-pro-bounds-constant-array-index, -# Many hits potential for false positives: -# -cppcoreguidelines-pro-type-member-init, -# Triggers on some tests that are not complex. We should re-enable this for tests: -# -readability-function-cognitive-complexity, -# Triggers for globals in tests and TEST macros -# -cert-err58-cpp, -# Useful but check is buggy in clang-tidy 15.0.6: -# -misc-const-correctness, -# ^ TODO(david): re-evaluate whether this one should be included here -# its auto-fixes are buggy -# if disabled, re-enable if fixed in newer clang version -# -# We should be able to fix: -# -google-build-using-namespace, # using whole::namespace; is bad -# -google-readability-todo, # the auto-fix for this inputs current user's name for all -# -cppcoreguidelines-avoid-magic-numbers, # we shouldn't use magic numbers! -# -readability-magic-numbers, - -HeaderFilterRegex: 'src/aztec3/' -FormatStyle: file diff --git a/circuits/cpp/.clang-tidy.slow b/circuits/cpp/.clang-tidy.slow deleted file mode 100644 index 60cbb30315f..00000000000 --- a/circuits/cpp/.clang-tidy.slow +++ /dev/null @@ -1,139 +0,0 @@ -# Disabled until #1152 is fully investigated (why this took 15 minutes in CI) - -# Note there is some overlap between this file and .clangd -# .clangd has no concept of warnings versus errors, but since it -# won't actually fail/error (since its really just an LSP for -# showing issues in an editor), it is acceptable to treat most -# .clang-tidy warnings as .clangd errors. Also, some error codes -# with buggy-autofixes need to be omitted from checks in .clang-tidy -# but can be included in .clangd since it won't change code without -# a user action. -# -# .clang-tidy on the other hand will error in CI for any check that -# is flagged (not explicitly omitted after '*') in WarningsAsErrors. -# So, it needs to omit certain checks or keep them as warnings only -# if they are too strict. - -Checks: ' - cert-*, - google-*, - cppcoreguidelines-*, - readability-*, - modernize-*, - bugprone-*, - misc-*, - performance-*, - clang-analyzer-*, - concurrency-*, - portability-*, - -bugprone-easily-swappable-parameters, - -bugprone-reserved-identifier, - -cppcoreguidelines-non-private-member-variables-in-classes, - -cppcoreguidelines-pro-bounds-constant-array-index, - -cppcoreguidelines-pro-bounds-pointer-arithmetic, - -cppcoreguidelines-pro-type-member-init, - -cert-dcl37-c, - -cert-dcl51-cpp, - -cert-dcl59-cpp, - -google-build-namespaces, - -google-readability-avoid-underscore-in-googletest-name, - -google-readability-todo, - -misc-non-private-member-variables-in-classes, - -modernize-avoid-c-arrays, - -modernize-pass-by-value, - -modernize-use-nodiscard, - -modernize-use-trailing-return-type, - -readability-identifier-length, - -readability-simplify-boolean-expr, - -readability-use-anyofallof, -' - -# We treat all warnings as errors except for these few. -# Some of these exceptions like 'google-build-using-namespace' -# we should be able to manually fix project-wide and then -# remove from the omissions list. -WarningsAsErrors: ' - *, - -bugprone-unchecked-optional-access, - -bugprone-unhandled-self-assignment, - -clang-analyzer-core.UndefinedBinaryOperatorResult, - -clang-analyzer-cplusplus.NewDeleteLeaks, - -clang-analyzer-optin.performance.Padding, - -cert-err58-cpp, - -cert-oop54-cpp, - -cppcoreguidelines-avoid-non-const-global-variables, - -cppcoreguidelines-avoid-magic-numbers, - -cppcoreguidelines-c-copy-assignment-signature, - -cppcoreguidelines-no-malloc, - -cppcoreguidelines-owning-memory, - -cppcoreguidelines-pro-type-cstyle-cast, - -cppcoreguidelines-pro-type-reinterpret-cast, - -cppcoreguidelines-special-member-functions, - -google-build-using-namespace, - -google-global-names-in-headers, - -google-readability-casting, - -misc-definitions-in-headers, - -misc-no-recursion, - -misc-unconventional-assign-operator, - -modernize-return-braced-init-list, - -performance-unnecessary-value-param, - -readability-function-cognitive-complexity, - -readability-magic-numbers, -' - -# Notes on specific Checks and WarningsAsErrors -# -# These checks rename our cbinds and consts that have `__` in the name: -# -bugprone-reserved-identifier, -# -cert-dcl37-c, -# -cert-dcl51-cpp, -# `any_of/all_of` loops are not objectively more readable: -# -readability-use-anyofallof, -# Will need to refactor our usage of `malloc/free` with `gsl::owner`: -# -cppcoreguidelines-owning-memory, -# Flags way too many functions: -# -bugprone-easily-swappable-parameters, -# We use anon namespaces to import types: -# -google-build-namespaces, -# -cert-dcl59-cpp, -# Not sure we want to use trailing return type: -# -modernize-use-trailing-return-type, -# Buggy in clang-tidy 15.0.6: -# -modernize-use-nodiscard, -# ^ TODO(david): re-enable if we move to newer clang version -# We use c-arrays in low-level code logic relating to c_bind: -# -modernize-avoid-c-arrays, -# This was changing code in ways that made it harder to follow: -# -modernize-pass-by-value, -# ^ TODO(david) we probably want to re-enable this one -# We like (a == true) in circuits: -# -readability-simplify-boolean-expr, -# We have a lot of one-letter variable names...: -# -readability-identifier-length, -# All of our tests use underscores in names: -# -google-readability-avoid-underscore-in-googletest-name, -# All of our circuit structs have non-private members: -# -misc-non-private-member-variables-in-classes, -# -cppcoreguidelines-non-private-member-variables-in-classes, -# We have many `for` loops that violate this part of the bounds safety profile -# -cppcoreguidelines-pro-bounds-constant-array-index, -# Many hits potential for false positives: -# -cppcoreguidelines-pro-type-member-init, -# Triggers on some tests that are not complex. We should re-enable this for tests: -# -readability-function-cognitive-complexity, -# Triggers for globals in tests and TEST macros -# -cert-err58-cpp, -# Useful but check is buggy in clang-tidy 15.0.6: -# -misc-const-correctness, -# ^ TODO(david): re-evaluate whether this one should be included here -# its auto-fixes are buggy -# if disabled, re-enable if fixed in newer clang version -# -# We should be able to fix: -# -google-build-using-namespace, # using whole::namespace; is bad -# -google-readability-todo, # the auto-fix for this inputs current user's name for all -# -cppcoreguidelines-avoid-magic-numbers, # we shouldn't use magic numbers! -# -readability-magic-numbers, - -HeaderFilterRegex: 'src/aztec3/' -FormatStyle: file diff --git a/circuits/cpp/.clangd b/circuits/cpp/.clangd deleted file mode 100644 index a2fd014d990..00000000000 --- a/circuits/cpp/.clangd +++ /dev/null @@ -1,73 +0,0 @@ -# Language Server Protocol for showing code problems -# and suggesting fixes in an editor. -# -# See .clang-tidy comments for more information. - -CompileFlags: # Tweak the parse settings - Remove: -fconstexpr-ops-limit=* ---- -# Applies all barretenberg source files -If: - PathMatch: [src/.*\.hpp, src/.*\.cpp, src/.*\.tcc, src/.*\.h] -Diagnostics: - # Checks whether we are including unused header files - # Note that some headers may be _implicitly_ used and still - # need to be included, so be careful before removing them. - UnusedIncludes: Strict - - # Static analysis configuration - ClangTidy: - Add: - - cert-* - - google-* - - cppcoreguidelines-* - - readability-* - - modernize-* - - bugprone-* - - misc-* - - performance-* - - clang-analyzer-* - - concurrency-* - - portability-* - Remove: - # Fixing this would be a lot of work. - - bugprone-easily-swappable-parameters - # These checks rename our cbinds and consts that have `__` in the name - - bugprone-reserved-identifier - # All of our circuit structs have non-private members - - cppcoreguidelines-non-private-member-variables-in-classes - # We have many `for` loops that violate this part of the bounds safety profile - - cppcoreguidelines-pro-bounds-constant-array-index - # These checks rename our cbinds and consts that have `__` in the name - - cert-dcl37-c - - cert-dcl51-cpp - # We use anon namespaces to import types - - cert-dcl59-cpp - # We use anon namespaces to import types - - google-build-namespaces - # Large diff; we often `use` an entire namespace - - google-readability-avoid-underscore-in-googletest-name - # All of our circuit structs have non-private members - - misc-non-private-member-variables-in-classes - # Huge diff. Not sure we want to use trailing return type - - modernize-use-trailing-return-type - # We like (a == true) in circuits - - readability-simplify-boolean-expr - # `any_of/all_of` loops are not objectively more readable - - readability-use-anyofallof - ---- # this divider is necessary -# Disable some checks for Google Test/Bench -If: - PathMatch: [src/.*\.test\.cpp, src/.*\.bench\.cpp] -Diagnostics: - ClangTidy: - # these checks get triggered by the Google macros - Remove: - # Triggers for globals in tests and TEST macros - - cert-err58-cpp - - cppcoreguidelines-avoid-non-const-global-variables - - cppcoreguidelines-owning-memory - - cppcoreguidelines-special-member-functions - # Triggers on some tests that are not complex - #- readability-function-cognitive-complexity \ No newline at end of file diff --git a/circuits/cpp/.gitignore b/circuits/cpp/.gitignore deleted file mode 100644 index 94b21237eb8..00000000000 --- a/circuits/cpp/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -.cache/ -build*/ -src/wasi-sdk-* -CMakeUserPresets.json - -# ctest log output dir -**/Testing/* \ No newline at end of file diff --git a/circuits/cpp/.rebuild_patterns b/circuits/cpp/.rebuild_patterns deleted file mode 100644 index d2edf385649..00000000000 --- a/circuits/cpp/.rebuild_patterns +++ /dev/null @@ -1,3 +0,0 @@ -^circuits/.*\.(cpp|cc|cxx|c\+\+|h|hpp|hxx|h\+\+|c|h|inl|inc|ipp|tpp|cmake)$ -^circuits/.*CMakeLists\.txt$ -^circuits/.*Dockerfile.*$ \ No newline at end of file diff --git a/circuits/cpp/CMakeLists.txt b/circuits/cpp/CMakeLists.txt deleted file mode 100644 index fb2b82d6278..00000000000 --- a/circuits/cpp/CMakeLists.txt +++ /dev/null @@ -1,145 +0,0 @@ -# aztec3 circuits package -# copyright 2019 Spilsbury Holdings Ltd - -cmake_minimum_required(VERSION 3.24) - -# Get the full path to barretenberg. This is helpful because the required -# relative path changes based on where in cmake the path is used. -# `BBERG_DIR` must be set before toolchain.cmake is imported because -# `BBERG_DIR` is used in toolchain.cmake to determine `WASI_SDK_PREFIX` -get_filename_component(BBERG_DIR ../barretenberg/cpp - REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") - -project( - Aztec3Circuits - DESCRIPTION "Project containing Aztec3 Circuits Infrastructure in C++." - VERSION 0.1.0 - LANGUAGES CXX C -) - -option(DISABLE_ASM "Disable custom assembly" OFF) -option(DISABLE_ADX "Disable ADX assembly variant" OFF) -option(MULTITHREADING "Enable multi-threading" ON) -option(TESTING "Build tests" ON) -option(ENABLE_ASAN "Address sanitizer for debugging tricky memory corruption" OFF) -option(BENCHMARKS "Build benchmarks" ON) -option(FUZZING "Build fuzzing harnesses" OFF) -option(DISABLE_TBB "Intel Thread Building Blocks" ON) -option(COVERAGE "Enable collecting coverage from tests" OFF) -option(ENABLE_HEAVY_TESTS "Enable heavy tests when collecting coverage" OFF) - -message(STATUS "Building barretenberg for UltraPlonk Composer.") - -if(ENABLE_ASAN) - add_compile_options(-fsanitize=address) - add_link_options(-fsanitize=address) -endif() - -if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "arm64") - message(STATUS "Compiling for ARM.") - set(ARM ON) - set(DISABLE_ASM ON) - set(DISABLE_ADX ON) - set(RUN_HAVE_STD_REGEX 0) - set(RUN_HAVE_POSIX_REGEX 0) - set(DISABLE_TBB 0) -endif() - -if(FUZZING) - add_definitions(-DFUZZING=1) - - if(DISABLE_CUSTOM_MUTATORS) - add_definitions(-DDISABLE_CUSTOM_MUTATORS=1) - endif() - - set(SANITIZER_OPTIONS "") - - if(ADDRESS_SANITIZER) - set(SANITIZER_OPTIONS ${SANITIZER_OPTIONS} -fsanitize=address) - endif() - - if(UNDEFINED_BEHAVIOUR_SANITIZER) - set(SANITIZER_OPTIONS ${SANITIZER_OPTIONS} -fsanitize=undefined -fno-sanitize=alignment) - endif() - - add_compile_options(-fsanitize=fuzzer-no-link ${SANITIZER_OPTIONS}) - - set(WASM OFF) - set(BENCHMARKS OFF) - set(MULTITHREADING OFF) - set(TESTING OFF) -endif() - -if(CMAKE_SYSTEM_PROCESSOR MATCHES "wasm32") - message(STATUS "Compiling for WebAssembly.") - set(WASM ON) - set(DISABLE_ASM ON) - set(MULTITHREADING OFF) - set(BENCHMARKS OFF) - set(DISABLE_TBB 1) - add_compile_definitions(_WASI_EMULATED_PROCESS_CLOCKS=1) -endif() - -set(CMAKE_C_STANDARD 11) -set(CMAKE_C_EXTENSIONS ON) -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED TRUE) -set(CMAKE_CXX_EXTENSIONS ON) - -if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "10") - message(WARNING "Clang <10 is not supported") - endif() -elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") - if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "10") - message(WARNING "GCC <10 is not supported") - endif() -else() - message(WARNING "Unsupported compiler, use Clang >10 or GCC >10") -endif() - -if(COVERAGE) - - # We've only set up LLVM coverage - if(NOT(CMAKE_CXX_COMPILER_ID MATCHES "Clang")) - message(FATAL_ERROR "Creating coverage is only available for clang") - endif() - - # Get major clang version - string(REPLACE "." ";" VERSION_LIST ${CMAKE_CXX_COMPILER_VERSION}) - list(GET VERSION_LIST 0 CLANG_VERSION_MAJOR) - - # Find llvm-profdata - set(PROFDATA_EXECUTABLE_NAME "llvm-profdata-${CLANG_VERSION_MAJOR}") - find_program(PROFDATA_EXECUTABLE ${PROFDATA_EXECUTABLE_NAME}) - if(PROFDATA_EXECUTABLE MATCHES "NOTFOUND") - message(FATAL_ERROR "Couldn't find ${PROFDATA_EXECUTABLE_NAME}") - endif() - - # Find llvm-cov - set(COV_EXECUTABLE_NAME "llvm-cov-${CLANG_VERSION_MAJOR}") - find_program(COV_EXECUTABLE ${COV_EXECUTABLE_NAME}) - if(COV_EXECUTABLE MATCHES "NOTFOUND") - message(FATAL_ERROR "Couldn't find ${COV_EXECUTABLE_NAME}") - endif() - - # Add profiling compile options and disable optimizations - add_compile_options(-fprofile-instr-generate -fcoverage-mapping -O0) - - # Add a custom target for creating the report - add_custom_target(create_full_coverage_report - COMMAND "${CMAKE_SOURCE_DIR}/scripts/collect_coverage_information.sh" ${PROFDATA_EXECUTABLE} ${COV_EXECUTABLE} - VERBATIM - ) -endif() - -include(cmake/build.cmake) -include(GNUInstallDirs) -include(cmake/arch.cmake) -include(cmake/threading.cmake) -include(cmake/gtest.cmake) -include(cmake/benchmark.cmake) -include(cmake/module.cmake) -include(cmake/msgpack.cmake) - -add_subdirectory(src) diff --git a/circuits/cpp/CMakePresets.json b/circuits/cpp/CMakePresets.json deleted file mode 100644 index 583fa90a9b2..00000000000 --- a/circuits/cpp/CMakePresets.json +++ /dev/null @@ -1,311 +0,0 @@ -{ - "version": 5, - "cmakeMinimumRequired": { - "major": 3, - "minor": 24, - "patch": 0 - }, - "configurePresets": [ - { - "name": "default", - "displayName": "Build with Clang", - "description": "Build with globally installed Clang", - "binaryDir": "build", - "generator": "Ninja", - "environment": { - "CC": "clang", - "CXX": "clang++", - "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" - }, - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release" - } - }, - { - "name": "homebrew", - "displayName": "Homebrew + Clang", - "description": "Build with Clang installed via Homebrew", - "inherits": "default", - "environment": { - "CC": "$env{BREW_PREFIX}/opt/llvm/bin/clang", - "CXX": "$env{BREW_PREFIX}/opt/llvm/bin/clang++", - "LDFLAGS": "-L$env{BREW_PREFIX}/opt/libomp/lib", - "CPPFLAGS": "-I$env{BREW_PREFIX}/opt/libomp/include" - } - }, - { - "name": "clang15", - "displayName": "Build with Clang-15", - "description": "Build with globally installed Clang-15", - "inherits": "default", - "environment": { - "CC": "clang-15", - "CXX": "clang++-15" - } - }, - { - "name": "clang15-assert", - "displayName": "Build with Clang-15 and assertions enabled", - "description": "Build with globally installed Clang-15 and assertions", - "inherits": "clang15", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "RelWithAssert" - } - }, - { - "name": "clang15-dbg", - "displayName": "Debugging build with Clang-15", - "description": "Build with globally installed Clang-15 in debug mode", - "inherits": "clang15", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug" - } - }, - { - "name": "clang16", - "displayName": "Build with Clang-16", - "description": "Build with globally installed Clang-16", - "inherits": "default", - "environment": { - "CC": "clang-16", - "CXX": "clang++-16" - } - }, - { - "name": "clang16-assert", - "displayName": "Build with Clang-16 and assertions enabled", - "description": "Build with globally installed Clang-16 and assertions", - "inherits": "clang16", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "RelWithAssert" - } - }, - { - "name": "clang16-dbg", - "displayName": "Debugging build with Clang-16", - "description": "Build with globally installed Clang-16 in debug mode", - "inherits": "clang16", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug" - } - }, - { - "name": "gcc", - "displayName": "Build with GCC", - "description": "Build with globally installed GCC", - "inherits": "default", - "environment": { - "CC": "gcc", - "CXX": "g++" - } - }, - { - "name": "gcc10", - "displayName": "Build with GCC-10", - "description": "Build with globally installed GCC-10", - "inherits": "default", - "environment": { - "CC": "gcc-10", - "CXX": "g++-10" - } - }, - { - "name": "bench", - "displayName": "Build benchmarks", - "description": "Build default preset but with a special benchmark directory", - "inherits": "default", - "binaryDir": "build-bench" - }, - { - "name": "fuzzing", - "displayName": "Build with fuzzing", - "description": "Build default preset but with fuzzing enabled", - "inherits": "default", - "binaryDir": "build-fuzzing", - "cacheVariables": { - "FUZZING": "ON" - } - }, - { - "name": "coverage", - "displayName": "Build with coverage", - "description": "Build default preset but with coverage enabled", - "inherits": "default", - "binaryDir": "build-coverage", - "cacheVariables": { - "COVERAGE": "ON", - "CMAKE_BUILD_TYPE": "Debug" - } - }, - { - "name": "wasm", - "displayName": "Build for WASM", - "description": "Build with a specific wasm-sdk to create wasm", - "binaryDir": "build-wasm", - "toolchainFile": "cmake/toolchains/wasm32-wasi.cmake", - "environment": { - "WASI_SDK_PREFIX": "${sourceDir}/barretenberg/cpp/src/wasi-sdk-20.0", - "CC": "$env{WASI_SDK_PREFIX}/bin/clang", - "CXX": "$env{WASI_SDK_PREFIX}/bin/clang++", - "AR": "$env{WASI_SDK_PREFIX}/bin/llvm-ar", - "RANLIB": "$env{WASI_SDK_PREFIX}/bin/llvm-ranlib" - }, - "cacheVariables": { - "CMAKE_SYSROOT": "$env{WASI_SDK_PREFIX}/share/wasi-sysroot", - "CMAKE_STAGING_PREFIX": "$env{WASI_SDK_PREFIX}/share/wasi-sysroot", - "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM": "NEVER", - "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY": "ONLY", - "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE": "ONLY", - "CMAKE_FIND_ROOT_PATH_MODE_PACKAGE": "ONLY", - "CMAKE_C_COMPILER_WORKS": "ON", - "CMAKE_CXX_COMPILER_WORKS": "ON", - "CMAKE_EXE_LINKER_FLAGS": "-O3", - "CMAKE_BUILD_TYPE": "Release" - } - }, - { - "name": "wasm-dbg", - "displayName": "Debugging build for WASM", - "description": "Build in debug mode with a specific wasm-sdk to create wasm", - "inherits": "wasm", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "CMAKE_EXE_LINKER_FLAGS": "" - } - } - ], - "buildPresets": [ - { - "name": "default", - "configurePreset": "default", - "inheritConfigureEnvironment": true, - "jobs": 0 - }, - { - "name": "homebrew", - "inherits": "default", - "configurePreset": "homebrew" - }, - { - "name": "clang15", - "inherits": "default", - "configurePreset": "clang15" - }, - { - "name": "clang15-dbg", - "inherits": "default", - "configurePreset": "clang15-dbg" - }, - { - "name": "clang16", - "inherits": "default", - "configurePreset": "clang16" - }, - { - "name": "clang16-dbg", - "inherits": "default", - "configurePreset": "clang16-dbg" - }, - { - "name": "gcc", - "inherits": "default", - "configurePreset": "gcc" - }, - { - "name": "gcc10", - "inherits": "default", - "configurePreset": "gcc10" - }, - { - "name": "bench", - "inherits": "default", - "configurePreset": "bench" - }, - { - "name": "fuzzing", - "inherits": "default", - "configurePreset": "fuzzing" - }, - { - "name": "coverage", - "inherits": "default", - "configurePreset": "coverage" - }, - { - "name": "wasm", - "configurePreset": "wasm", - "inheritConfigureEnvironment": true, - "jobs": 0 - }, - { - "name": "wasm-dbg", - "inherits": "wasm" - } - ], - "testPresets": [ - { - "name": "default", - "configurePreset": "default", - "inheritConfigureEnvironment": true - }, - { - "name": "homebrew", - "inherits": "default", - "configurePreset": "homebrew" - }, - { - "name": "clang15", - "inherits": "default", - "configurePreset": "clang15" - }, - { - "name": "clang15-dbg", - "inherits": "default", - "configurePreset": "clang15-dbg" - }, - { - "name": "clang16", - "inherits": "default", - "configurePreset": "clang16" - }, - { - "name": "clang16-dbg", - "inherits": "default", - "configurePreset": "clang16-dbg" - }, - { - "name": "gcc", - "inherits": "default", - "configurePreset": "gcc" - }, - { - "name": "gcc10", - "inherits": "default", - "configurePreset": "gcc10" - }, - { - "name": "bench", - "inherits": "default", - "configurePreset": "bench" - }, - { - "name": "fuzzing", - "inherits": "default", - "configurePreset": "fuzzing" - }, - { - "name": "coverage", - "inherits": "default", - "configurePreset": "coverage" - }, - { - "name": "wasm", - "configurePreset": "wasm", - "inheritConfigureEnvironment": true - }, - { - "name": "wasm-dbg", - "inherits": "wasm" - } - ] -} \ No newline at end of file diff --git a/circuits/cpp/barretenberg b/circuits/cpp/barretenberg deleted file mode 120000 index e9b54f1df3e..00000000000 --- a/circuits/cpp/barretenberg +++ /dev/null @@ -1 +0,0 @@ -../../barretenberg \ No newline at end of file diff --git a/circuits/cpp/bootstrap.sh b/circuits/cpp/bootstrap.sh deleted file mode 100755 index 440bf1e44c6..00000000000 --- a/circuits/cpp/bootstrap.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash -set -eu - -cd "$(dirname "$0")" - -CMD=${1:-} - -if [ -n "$CMD" ]; then - if [ "$CMD" = "clean" ]; then - git clean -fdx - exit 0 - else - echo "Unknown command: $CMD" - exit 1 - fi -fi - -rm -f build-wasm/CMakeCache.txt - -# Build WASM. -if [ -n "${WASM_DEBUG:-}" ] ; then - cmake --preset wasm-dbg - cmake --build --preset wasm-dbg --target aztec3-circuits.wasm -else - cmake --preset wasm - cmake --build --preset wasm --target aztec3-circuits.wasm -fi diff --git a/circuits/cpp/cmake/arch.cmake b/circuits/cpp/cmake/arch.cmake deleted file mode 100644 index 1812e8eb3ed..00000000000 --- a/circuits/cpp/cmake/arch.cmake +++ /dev/null @@ -1,10 +0,0 @@ -if(WASM) - # Disable SLP vectorization on WASM as it's brokenly slow. To give an idea, with this off it still takes - # 2m:18s to compile scalar_multiplication.cpp, and with it on I estimate it's 50-100 times longer. I never - # had the patience to wait it out... - add_compile_options(-fno-exceptions -fno-slp-vectorize) -endif() - -if(NOT WASM AND NOT APPLE AND NOT ARM) - add_compile_options(-march=skylake) -endif() diff --git a/circuits/cpp/cmake/benchmark.cmake b/circuits/cpp/cmake/benchmark.cmake deleted file mode 100644 index c8f90548d66..00000000000 --- a/circuits/cpp/cmake/benchmark.cmake +++ /dev/null @@ -1,25 +0,0 @@ -if(NOT TESTING) - set(BENCHMARKS OFF) -endif() - -if(BENCHMARKS) - include(FetchContent) - - FetchContent_Declare( - benchmark - GIT_REPOSITORY https://github.com/google/benchmark - GIT_TAG v1.7.1 - FIND_PACKAGE_ARGS - ) - - set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "Benchmark tests off") - set(BENCHMARK_ENABLE_INSTALL OFF CACHE BOOL "Benchmark installation off") - - FetchContent_MakeAvailable(benchmark) - if(NOT benchmark_FOUND) - # FetchContent_MakeAvailable calls FetchContent_Populate if `find_package` is unsuccessful - # so these variables will be available if we reach this case - set_property(DIRECTORY ${benchmark_SOURCE_DIR} PROPERTY EXCLUDE_FROM_ALL) - set_property(DIRECTORY ${benchmark_BINARY_DIR} PROPERTY EXCLUDE_FROM_ALL) - endif() -endif() diff --git a/circuits/cpp/cmake/build.cmake b/circuits/cpp/cmake/build.cmake deleted file mode 100644 index 3eb2eddd060..00000000000 --- a/circuits/cpp/cmake/build.cmake +++ /dev/null @@ -1,9 +0,0 @@ -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE) -endif() -message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") - -if(CMAKE_BUILD_TYPE STREQUAL "RelWithAssert") - add_compile_options(-O3) - remove_definitions(-DNDEBUG) -endif() \ No newline at end of file diff --git a/circuits/cpp/cmake/gtest.cmake b/circuits/cpp/cmake/gtest.cmake deleted file mode 100644 index e86bf49756e..00000000000 --- a/circuits/cpp/cmake/gtest.cmake +++ /dev/null @@ -1,51 +0,0 @@ -if(TESTING) - include(GoogleTest) - include(FetchContent) - - FetchContent_Declare( - GTest - GIT_REPOSITORY https://github.com/google/googletest.git - # Version 1.12.1 is not compatible with WASI-SDK 12 - GIT_TAG release-1.10.0 - FIND_PACKAGE_ARGS - ) - - set(BUILD_GMOCK OFF CACHE BOOL "Build with gMock disabled") - set(INSTALL_GTEST OFF CACHE BOOL "gTest installation disabled") - - FetchContent_MakeAvailable(GTest) - - if (NOT GTest_FOUND) - # FetchContent_MakeAvailable calls FetchContent_Populate if `find_package` is unsuccessful - # so these variables will be available if we reach this case - set_property(DIRECTORY ${gtest_SOURCE_DIR} PROPERTY EXCLUDE_FROM_ALL) - set_property(DIRECTORY ${gtest_BINARY_DIR} PROPERTY EXCLUDE_FROM_ALL) - - # Disable all warning when compiling gtest - target_compile_options( - gtest - PRIVATE - -w - ) - - if(WASM) - target_compile_definitions( - gtest - PRIVATE - -DGTEST_HAS_EXCEPTIONS=0 - -DGTEST_HAS_STREAM_REDIRECTION=0 - ) - endif() - - mark_as_advanced( - BUILD_GMOCK BUILD_GTEST BUILD_SHARED_LIBS - gmock_build_tests gtest_build_samples gtest_build_tests - gtest_disable_pthreads gtest_force_shared_crt gtest_hide_internal_symbols - ) - - add_library(GTest::gtest ALIAS gtest) - add_library(GTest::gtest_main ALIAS gtest_main) - endif() - - enable_testing() -endif() diff --git a/circuits/cpp/cmake/module.cmake b/circuits/cpp/cmake/module.cmake deleted file mode 100644 index 725220be58a..00000000000 --- a/circuits/cpp/cmake/module.cmake +++ /dev/null @@ -1,235 +0,0 @@ -# copyright 2020 Spilsbury Holdings -# -# usage: circuits_cmake_module(module_name [dependencies ...]) -# -# Scans for all .cpp files in a subdirectory, and creates a library named . -# Scans for all .test.cpp files in a subdirectory, and creates a gtest binary named _tests. -# Scans for all .bench.cpp files in a subdirectory, and creates a benchmark binary named _bench. -# -# We have to get a bit complicated here, due to the fact CMake will not parallelize the building of object files -# between dependent targets, due to the potential of post-build code generation steps etc. -# To work around this, we create "object libraries" containing the object files. -# Then we declare executables/libraries that are to be built from these object files. -# These assets will only be linked as their dependencies complete, but we can parallelize the compilation at least. - -function(circuits_cmake_module MODULE_NAME) - file(GLOB_RECURSE SOURCE_FILES *.cpp) - file(GLOB_RECURSE HEADER_FILES *.hpp *.tcc) - list(FILTER SOURCE_FILES EXCLUDE REGEX ".*\.(fuzzer|test|bench).cpp$") - - if(SOURCE_FILES) - add_library( - ${MODULE_NAME}_objects - OBJECT - ${SOURCE_FILES} - ) - list(APPEND lib_targets ${MODULE_NAME}_objects) - - add_library( - ${MODULE_NAME} - STATIC - $ - ) - - target_link_libraries( - ${MODULE_NAME} - PUBLIC - ${ARGN} - ${TBB_IMPORTED_TARGETS} - ) - list(APPEND lib_targets ${MODULE_NAME}) - - # enable msgpack downloading via dependency (solves race condition) - add_dependencies(${MODULE_NAME}_objects msgpack-c) - add_dependencies(${MODULE_NAME} msgpack-c) - - set(MODULE_LINK_NAME ${MODULE_NAME}) - endif() - - file(GLOB_RECURSE TEST_SOURCE_FILES *.test.cpp) - if(TESTING AND TEST_SOURCE_FILES) - add_library( - ${MODULE_NAME}_test_objects - OBJECT - ${TEST_SOURCE_FILES} - ) - list(APPEND lib_targets ${MODULE_NAME}_test_objects) - - target_link_libraries( - ${MODULE_NAME}_test_objects - PRIVATE - GTest::gtest - env - ${TBB_IMPORTED_TARGETS} - ) - - add_executable( - ${MODULE_NAME}_tests - $ - ) - list(APPEND exe_targets ${MODULE_NAME}_tests) - - if(WASM) - target_link_options( - ${MODULE_NAME}_tests - PRIVATE - -Wl,-z,stack-size=8388608 - ) - endif() - - if(CI) - target_compile_definitions( - ${MODULE_NAME}_test_objects - PRIVATE - -DCI=1 - ) - endif() - - if((COVERAGE AND NOT ENABLE_HEAVY_TESTS) OR (DISABLE_HEAVY_TESTS)) - # Heavy tests take hours when we are using profiling instrumentation - target_compile_definitions( - ${MODULE_NAME}_test_objects - PRIVATE - -DDISABLE_HEAVY_TESTS=1 - ) - endif() - - target_link_libraries( - ${MODULE_NAME}_tests - PRIVATE - ${MODULE_LINK_NAME} - ${ARGN} - GTest::gtest - GTest::gtest_main - env - ${TBB_IMPORTED_TARGETS} - ) - # enable msgpack downloading via dependency (solves race condition) - add_dependencies(${MODULE_NAME}_test_objects msgpack-c) - add_dependencies(${MODULE_NAME}_tests msgpack-c) - - if(NOT WASM AND NOT CI) - # If collecting coverage data, set profile - # For some reason processor affinity doesn't work, so the developer has to set it manually anyway - if(COVERAGE) - # Profile filename has to be dependent on some process characteristic, because ctest calls all tests individually and the profiles get overwritten - gtest_discover_tests(${MODULE_NAME}_tests - PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/profdata/${MODULE_NAME}.%p.profraw" - PROPERTIES PROCESSOR_AFFINITY ON - PROPERTIES PROCESSORS 16 - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) - else() - # Currently haven't found a way to easily wrap the calls in wasmtime when run from ctest. - # Needed to add `TEST_DISCOVERY_TIMEOUT` to work around: - # ``` - # Error running test executable. - # ... - # Result: Process terminated due to timeout - # ``` - gtest_discover_tests(${MODULE_NAME}_tests WORKING_DIRECTORY ${CMAKE_BINARY_DIR} PROPERTIES TEST_DISCOVERY_TIMEOUT 600) - endif() - endif() - - if(COVERAGE) - target_link_options( - ${MODULE_NAME}_tests - PRIVATE - -fprofile-instr-generate -fcoverage-mapping - ) - add_custom_target( - run_${MODULE_NAME}_tests - COMMAND mkdir -p ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/profdata - COMMAND LLVM_PROFILE_FILE=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/profdata/${MODULE_NAME}.%p.profraw ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${MODULE_NAME}_tests - BYPRODUCTS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/profdata/${MODULE_NAME}.profraw - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - DEPENDS ${MODULE_NAME}_tests - ) - add_custom_target( - generate_${MODULE_NAME}_tests_coverage - COMMAND ${PROFDATA_EXECUTABLE} merge -sparse ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/profdata/${MODULE_NAME}.profraw -o ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/profdata/${MODULE_NAME}.profdata - DEPENDS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/profdata/${MODULE_NAME}.profraw - BYPRODUCTS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/profdata/${MODULE_NAME}.profdata - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - ) - else() - add_custom_target( - run_${MODULE_NAME}_tests - COMMAND ${MODULE_NAME}_tests - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - ) - endif() - endif() - - file(GLOB_RECURSE FUZZERS_SOURCE_FILES *.fuzzer.cpp) - if(FUZZING AND FUZZERS_SOURCE_FILES) - foreach(FUZZER_SOURCE_FILE ${FUZZERS_SOURCE_FILES}) - get_filename_component(FUZZER_NAME_STEM ${FUZZER_SOURCE_FILE} NAME_WE) - add_executable( - ${MODULE_NAME}_${FUZZER_NAME_STEM}_fuzzer - ${FUZZER_SOURCE_FILE} - ) - list(APPEND exe_targets ${MODULE_NAME}_${FUZZER_NAME_STEM}_fuzzer) - - target_link_options( - ${MODULE_NAME}_${FUZZER_NAME_STEM}_fuzzer - PRIVATE - "-fsanitize=fuzzer" - ${SANITIZER_OPTIONS} - ) - - target_link_libraries( - ${MODULE_NAME}_${FUZZER_NAME_STEM}_fuzzer - PRIVATE - ${MODULE_LINK_NAME} - env - ) - # enable msgpack downloading via dependency (solves race condition) - add_dependencies(${MODULE_NAME}_${FUZZER_NAME_STEM}_fuzzer msgpack-c) - endforeach() - endif() - - file(GLOB_RECURSE BENCH_SOURCE_FILES *.bench.cpp) - if(BENCHMARKS AND BENCH_SOURCE_FILES) - add_library( - ${MODULE_NAME}_bench_objects - OBJECT - ${BENCH_SOURCE_FILES} - ) - list(APPEND lib_targets ${MODULE_NAME}_bench_objects) - - target_link_libraries( - ${MODULE_NAME}_bench_objects - PRIVATE - benchmark::benchmark - env - ${TBB_IMPORTED_TARGETS} - ) - - add_executable( - ${MODULE_NAME}_bench - $ - ) - list(APPEND exe_targets ${MODULE_NAME}_bench) - - target_link_libraries( - ${MODULE_NAME}_bench - PRIVATE - ${MODULE_LINK_NAME} - ${ARGN} - benchmark::benchmark - env - ${TBB_IMPORTED_TARGETS} - ) - - add_custom_target( - run_${MODULE_NAME}_bench - COMMAND ${MODULE_NAME}_bench - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - ) - add_dependencies(${MODULE_NAME}_bench_objects msgpack-c) - add_dependencies(${MODULE_NAME}_bench msgpack-c) - endif() - - set(${MODULE_NAME}_lib_targets ${lib_targets} PARENT_SCOPE) - set(${MODULE_NAME}_exe_targets ${exe_targets} PARENT_SCOPE) -endfunction() diff --git a/circuits/cpp/cmake/msgpack.cmake b/circuits/cpp/cmake/msgpack.cmake deleted file mode 100644 index 8ce70891552..00000000000 --- a/circuits/cpp/cmake/msgpack.cmake +++ /dev/null @@ -1,16 +0,0 @@ -include(ExternalProject) - -# External project: Download msgpack-c from GitHu -set(MSGPACK_PREFIX "${CMAKE_BINARY_DIR}/_deps/msgpack-c") -set(MSGPACK_INCLUDE "${MSGPACK_PREFIX}/src/msgpack-c/include") - -ExternalProject_Add( - msgpack-c - PREFIX ${MSGPACK_PREFIX} - GIT_REPOSITORY "https://github.com/AztecProtocol/msgpack-c.git" - GIT_TAG af447c28f0bafe761290a72754212436e530941b - CONFIGURE_COMMAND "" # No configure step - BUILD_COMMAND "" # No build step - INSTALL_COMMAND "" # No install step - UPDATE_COMMAND "" # No update step -) \ No newline at end of file diff --git a/circuits/cpp/cmake/threading.cmake b/circuits/cpp/cmake/threading.cmake deleted file mode 100644 index ff60f240a16..00000000000 --- a/circuits/cpp/cmake/threading.cmake +++ /dev/null @@ -1,37 +0,0 @@ -if(MULTITHREADING) - message(STATUS "Multithreading is enabled.") - add_compile_options(-pthread) - add_link_options(-pthread) - if(WASM) - add_compile_options(--target=wasm32-wasi-threads) - add_link_options(--target=wasm32-wasi-threads) - endif() - #add_compile_options(-fsanitize=thread) - #add_link_options(-fsanitize=thread) -else() - message(STATUS "Multithreading is disabled.") - add_definitions(-DNO_MULTITHREADING) - set(OMP_MULTITHREADING OFF) -endif() - -if(OMP_MULTITHREADING) - find_package(OpenMP REQUIRED) - message(STATUS "OMP multithreading is enabled.") - link_libraries(OpenMP::OpenMP_CXX) -else() - message(STATUS "OMP multithreading is disabled.") - add_definitions(-DNO_OMP_MULTITHREADING) -endif() - -if(DISABLE_TBB) - message(STATUS "Intel Thread Building Blocks is disabled.") - add_definitions(-DNO_TBB) -else() - find_package(TBB QUIET OPTIONAL_COMPONENTS tbb) - if(${TBB_FOUND}) - message(STATUS "Intel Thread Building Blocks is enabled.") - else() - message(STATUS "Could not locate TBB.") - add_definitions(-DNO_TBB) - endif() -endif() diff --git a/circuits/cpp/cmake/toolchains/aarch64-darwin.cmake b/circuits/cpp/cmake/toolchains/aarch64-darwin.cmake deleted file mode 100644 index 227680938b4..00000000000 --- a/circuits/cpp/cmake/toolchains/aarch64-darwin.cmake +++ /dev/null @@ -1,11 +0,0 @@ -set(CMAKE_SYSTEM_NAME Darwin) -set(CMAKE_SYSTEM_PROCESSOR aarch64) - -if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # Clang allows us to cross compile on Mac - # so we explicitly specify the arch to the compiler - # If you just select the arch toolchain and are on an - # x86_64, it will compile for x86_64 mac. - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch arm64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch arm64") -endif() diff --git a/circuits/cpp/cmake/toolchains/aarch64-linux.cmake b/circuits/cpp/cmake/toolchains/aarch64-linux.cmake deleted file mode 100644 index d79a26e90fd..00000000000 --- a/circuits/cpp/cmake/toolchains/aarch64-linux.cmake +++ /dev/null @@ -1,2 +0,0 @@ -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR aarch64) diff --git a/circuits/cpp/cmake/toolchains/i386-linux.cmake b/circuits/cpp/cmake/toolchains/i386-linux.cmake deleted file mode 100644 index db424698ee8..00000000000 --- a/circuits/cpp/cmake/toolchains/i386-linux.cmake +++ /dev/null @@ -1,7 +0,0 @@ -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR i386) - -add_compile_options("-m32") -add_link_options("-m32") -set(MULTITHREADING OFF) -add_definitions(-DDISABLE_SHENANIGANS=1) diff --git a/circuits/cpp/cmake/toolchains/wasm32-wasi.cmake b/circuits/cpp/cmake/toolchains/wasm32-wasi.cmake deleted file mode 100644 index 17e19376ed8..00000000000 --- a/circuits/cpp/cmake/toolchains/wasm32-wasi.cmake +++ /dev/null @@ -1,3 +0,0 @@ -set(CMAKE_SYSTEM_NAME Generic) -set(CMAKE_SYSTEM_VERSION 1) -set(CMAKE_SYSTEM_PROCESSOR wasm32) diff --git a/circuits/cpp/cmake/toolchains/x86_64-darwin.cmake b/circuits/cpp/cmake/toolchains/x86_64-darwin.cmake deleted file mode 100644 index 47b58dcc854..00000000000 --- a/circuits/cpp/cmake/toolchains/x86_64-darwin.cmake +++ /dev/null @@ -1,11 +0,0 @@ -set(CMAKE_SYSTEM_NAME Darwin) -set(CMAKE_SYSTEM_PROCESSOR x86_64) - -if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # Clang allows us to cross compile on Mac - # so we explicitly specify the arch to the compiler - # If you just select the x86_64 toolchain and are on an - # M1/arm64 mac, it will compile for arm64. - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch x86_64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch x86_64") -endif() diff --git a/circuits/cpp/cmake/toolchains/x86_64-linux.cmake b/circuits/cpp/cmake/toolchains/x86_64-linux.cmake deleted file mode 100644 index 69c1e6d234a..00000000000 --- a/circuits/cpp/cmake/toolchains/x86_64-linux.cmake +++ /dev/null @@ -1,2 +0,0 @@ -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR x86_64) diff --git a/circuits/cpp/format.sh b/circuits/cpp/format.sh deleted file mode 100755 index 54047bd6def..00000000000 --- a/circuits/cpp/format.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -set -eu - -if [ "${1:-}" == "staged" ]; then - echo Formatting circuits staged files... - for FILE in $(git diff-index --diff-filter=d --relative --cached --name-only HEAD | grep -e '\.\(cpp\|hpp\|tcc\)$'); do - clang-format -i $FILE - sed -i.bak 's/\r$//' $FILE && rm ${FILE}.bak - git add $FILE - done -elif [ -n "${1:-}" ]; then - for FILE in $(git diff-index --relative --name-only $1 | grep -e '\.\(cpp\|hpp\|tcc\)$'); do - clang-format -i $FILE - sed -i.bak 's/\r$//' $FILE && rm ${FILE}.bak - done -else - for FILE in $(find ./{src,barretenberg} -iname *.hpp -o -iname *.cpp -o -iname *.tcc | grep -v src/boost); do - clang-format -i $FILE - sed -i.bak 's/\r$//' $FILE && rm ${FILE}.bak - done -fi diff --git a/circuits/cpp/scripts/a3-tests b/circuits/cpp/scripts/a3-tests deleted file mode 100644 index ed332ef3457..00000000000 --- a/circuits/cpp/scripts/a3-tests +++ /dev/null @@ -1,4 +0,0 @@ -aztec3_circuits_abis_tests -aztec3_circuits_apps_tests -aztec3_circuits_kernel_tests -aztec3_circuits_rollup_tests \ No newline at end of file diff --git a/circuits/cpp/scripts/build_run_tests_docker_local b/circuits/cpp/scripts/build_run_tests_docker_local deleted file mode 100755 index f861fecbfa8..00000000000 --- a/circuits/cpp/scripts/build_run_tests_docker_local +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash -[ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace -set -eu - -# To be called only LOCALLY for testing WITH docker. -# Builds a docker image and runs tests in it. -# -# Run from circuits/cpp/ -# Example -# ./scripts/build_run_tests_docker_local 1 x86_64 glob -*.circuit* - -############################################################################### -# ARGS -############################################################################### -NUM_TRANSCRIPTS=$1 # integer (MANDATORY) -ARCH=$2 # x86_64 or wasm (MUST BE LOWERCASE) (MANDATORY) used in `run_tests_local` -# TESTS=$3 (MANDATORY) used in `run_tests_local` -# GTEST_FILTER=$4 (optional) used in `run_tests_local` -# *** See `run_tests_local` for the args forwarded to that script - -shift # arg1 (num transcripts) is not forwarded to `run_tests_local` - -# END ARGS -############################################################################### - -DOCKERFILE=dockerfiles/Dockerfile.${ARCH}-linux-clang-assert -IMAGE_URI=local-testing/circuits-${ARCH}-linux-clang-assert:latest - -# build docker image -time docker build -f $DOCKERFILE -t $IMAGE_URI . - -# run tests in docker image -RUN_ARGS="$@" # helper var necessary for some reason to pass all args to docker run -time docker run --rm -t $IMAGE_URI /bin/sh -c "\ - set -xe; \ - cd /usr/src/barretenberg/cpp/srs_db; \ - ln -sf /usr/src/barretenberg/cpp/srs_db /usr/src/circuits/cpp/srs_db; \ - ./download_ignition.sh $NUM_TRANSCRIPTS; \ - cd /usr/src/circuits/cpp; \ - export PATH=\$PATH:~/.wasmtime/bin/; \ - ./scripts/run_tests_local $RUN_ARGS;" diff --git a/circuits/cpp/scripts/collect_coverage_information.sh b/circuits/cpp/scripts/collect_coverage_information.sh deleted file mode 100755 index 45ad2764a22..00000000000 --- a/circuits/cpp/scripts/collect_coverage_information.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env bash - -# Check that the correct number of args have been provided -if [ $# -ne 2 ]; then - echo "Usage: $0 " - exit 1 -fi - -# Check that the llvm-profdata command exists -llvm_profdata_command="$1" -if ! command -v "$llvm_profdata_command" >/dev/null; then - echo "$llvm_profdata_command could not be found" - exit 1 -fi - -# Check that the llvm-cov command exists -llvm_cov_command="$2" -if ! command -v "$llvm_cov_command" >/dev/null; then - echo "$llvm_cov_command could not be found" - exit 1 -fi - -# Check for existence of test binaries -WORKING_DIRECTORY=$(pwd) -if [ ! -d "$WORKING_DIRECTORY/bin" ]; then - echo "No binary directory. Are you sure that you are in a build directory and you've compiled binaries?" - exit 1 -fi - -# Check for existence of profdata files, run make sure tests have been run and compiled with Debug and coverage flags enabled -if [ ! -d "$WORKING_DIRECTORY/bin/profdata" ]; then - echo "No profdata directory. Have you run any tests with profiling?" - exit 1 -fi - -# Find non empty profiles and store them in an array -declare -A non_empty_profiles -for profdata_file in $(ls "$WORKING_DIRECTORY/bin/profdata"); do - if [ -s "$WORKING_DIRECTORY/bin/profdata/$profdata_file" ]; then - non_empty_profiles["${profdata_file%%.*}"]=1 - fi -done -if [ ${#non_empty_profiles[@]} -eq 0 ]; then - echo "No profiles found" - exit 1 -fi - -# If there is one profile, output it into its coverate report into its own folder -if [ ${#non_empty_profiles[@]} -eq 1 ]; then - mkdir -p "$WORKING_DIRECTORY/merged_profdata/" - rm -f "$WORKING_DIRECTORY/merged_profdata/default.profdata" - $llvm_profdata_command merge -sparse "$WORKING_DIRECTORY/bin/profdata/${!non_empty_profiles[@]}."*.profraw -o "$WORKING_DIRECTORY/merged_profdata/default.profdata" - rm -rf "$WORKING_DIRECTORY/${non_empty_profiles[0]}_coverage_report" - mkdir "$WORKING_DIRECTORY/${non_empty_profiles[0]}_coverage_report" - $llvm_cov_command show -output-dir="$WORKING_DIRECTORY/${!non_empty_profiles[@]}_coverage_report" -format=html "$WORKING_DIRECTORY/bin/${!non_empty_profiles[@]}_tests" -instr-profile="$WORKING_DIRECTORY/merged_profdata/default.profdata" -ignore-filename-regex=".*_deps.*" -fi - -# If there are many reports, output all of the coverage reports into one folder -if [ ${#non_empty_profiles[@]} -gt 1 ]; then - mkdir -p "$WORKING_DIRECTORY/merged_profdata/" - rm -f "$WORKING_DIRECTORY/merged_profdata/default.profdata" - - # Merge related profdata files into one file named default.profdata - $llvm_profdata_command merge -sparse "$WORKING_DIRECTORY/bin/profdata/"*.profraw -o "$WORKING_DIRECTORY/merged_profdata/default.profdata" - additional_objects="" - for non_empty_profile_base in "${!non_empty_profiles[@]}"; do - additional_objects+="-object $WORKING_DIRECTORY/bin/${non_empty_profile_base}_tests " - done - object_string=${additional_objects#"-object"} - - # Output the coverage report into `all_tests_coverage_report` folder - rm -rf "$WORKING_DIRECTORY/all_tests_coverage_report" - mkdir "$WORKING_DIRECTORY/all_tests_coverage_report" - $llvm_cov_command show -output-dir="$WORKING_DIRECTORY/all_tests_coverage_report" -format=html $object_string -instr-profile="$WORKING_DIRECTORY/merged_profdata/default.profdata" -ignore-filename-regex=".*_deps.*" -fi \ No newline at end of file diff --git a/circuits/cpp/scripts/run_coverage b/circuits/cpp/scripts/run_coverage deleted file mode 100755 index ae40b20cda4..00000000000 --- a/circuits/cpp/scripts/run_coverage +++ /dev/null @@ -1,77 +0,0 @@ -#!bin/bash -[ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace -set -eu - -# To be called LOCALLY for testing WITHOUT docker. -# -# Contains core logic for collecting test coverage in the current environment. -# -# Run from circuits/cpp/ -# Example: -# ./scripts/run_coverage glob -# -# Running with the CLEAN environment variable set will delete the build-coverage folder and start again. -# Running with the CLEAR_COV environment variable set will clear existing vscode coverage data (lcov.info). -# -# This will create two outputs: lcov.info and an html coverage report in build-coverage/coverage_report -# -# Note: Assumes ignition SRS transcripts have already been downloaded - -# TESTS: -# 1. names of test executables to run -# - (like "aztec3_circuits_kernel_tests aztec3_circuits_abis_tests") -# 2. or "glob" (LOWERCASE) to run all built tests -# 3. or a file containing a list of test -TESTS=$1 - -# Set coverage build directory -BUILD_DIR="build-coverage" - -# If the clean file is set, wipe all existing coverage data -if [ -n "${CLEAN:-}" ]; then - echo "The CLEAN environment variable is set. Clearing existing coverage data." - rm -rf ./$BUILD_DIR || true -fi - -# Perform coverage build -echo "Setting cmake to run with preset coverage" -cmake -DUSE_TURBO=true --preset=coverage . - -# if TESTS is GLOB or empty, run all built tests -# if TESTS is a file, assume it contains a list of tests to run -# otherwise assume TESTS itself is a list of tests to run -if [ "$TESTS" = "glob" ] || [ -z "$TESTS" ]; then - echo " No test file specified. Building all test files." - TESTS=$(cat ./scripts/a3-tests) -elif [ -f "$TESTS" ]; then - TESTS=$(cat $TESTS | tr '\n' ' ') -fi - -# if just the CLEAR_COV env var is set then we will clear existing coveage report information -if [ -n "${CLEAR_COV:-}" ]; then - echo "The CLEAR_COV environment variable is set. Clearing existing coverage data." - rm ./$BUILD_DIR/lcov.info || true - rm ./$BUILD_DIR/merged_profdata/default.profdata || true - rm ./$BUILD_DIR/default.profraw || true - rm -rf ./$BUILD_DIR/bin/profdata || true -fi - -for BIN in $TESTS; do - echo "*** Building $BIN ***" - cmake --build --preset coverage --target $BIN -done - -echo "Testing $BIN" -echo "*** Collecting Profiling Information ***" -ctest --test-dir $BUILD_DIR || true # Ctest will fail here if there are unbuilt tests, but we would like to continue to generate reports -echo "Completed profiling" - -echo "*** Generating Coverage Reports ***" -cmake --build --preset coverage --target create_full_coverage_report - -echo "*** Generating VScode line coverage data ***" -for BIN in $TESTS; do - echo "Generating line coverage data for $BIN" - llvm-cov-15 export ./$BUILD_DIR/bin/$BIN --format=lcov -instr-profile="./$BUILD_DIR/merged_profdata/default.profdata" > $BUILD_DIR/lcov.info -done - diff --git a/circuits/cpp/scripts/run_tests b/circuits/cpp/scripts/run_tests deleted file mode 100755 index 62fbd90153b..00000000000 --- a/circuits/cpp/scripts/run_tests +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash -[ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace -set -eu - -# To be called from CI for testing with docker and AWS. -# Can't be called locally unless AWS credentials are set up. -# -# Call from config.yml -# Example: -# command: cond_spot_run_tests circuits-wasm-linux-clang-assert 1 wasm scripts/a3-tests -*.skip*:*.circuit* - - -############################################################################### -# ARGS -############################################################################### -NUM_TRANSCRIPTS=$1 # integer (MANDATORY) -ARCH=$2 # x86_64 or wasm (MUST BE LOWERCASE) (MANDATORY) used in `run_tests_local` -# TESTS=$3 (MANDATORY) used in `run_tests_local` -# GTEST_FILTER=$4 (optional) used in `run_tests_local` -# *** See `run_tests_local` for the args forwarded to that script - -shift # arg1 (num transcripts) is not forwarded to `run_tests_local` - -# END ARGS -############################################################################### - -$(aws ecr get-login --region us-east-2 --no-include-email) 2> /dev/null - -REPOSITORY="circuits-$ARCH-linux-clang-assert" -IMAGE_URI=$($(git rev-parse --show-toplevel)/build-system/scripts/calculate_image_uri $REPOSITORY) -$(git rev-parse --show-toplevel)/build-system/scripts/retry docker pull $IMAGE_URI - -# run tests in docker image -RUN_ARGS="$@" # helper var necessary for some reason to pass all args to docker run -time docker run --rm -t $IMAGE_URI /bin/sh -c "\ - set -xe; \ - mv /usr/src/barretenberg /usr/src/circuits/cpp/; \ - cd /usr/src/circuits/cpp/barretenberg/cpp/srs_db; \ - ./download_ignition.sh $NUM_TRANSCRIPTS; \ - cd /usr/src/circuits/cpp; \ - ln -sf /usr/src/circuits/cpp/barretenberg/cpp/srs_db /usr/src/circuits/cpp/srs_db; \ - export PATH=\$PATH:~/.wasmtime/bin/; \ - ./scripts/run_tests_local $RUN_ARGS;" diff --git a/circuits/cpp/scripts/run_tests_local b/circuits/cpp/scripts/run_tests_local deleted file mode 100755 index 4c12807414e..00000000000 --- a/circuits/cpp/scripts/run_tests_local +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env bash -[ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace -set -eu - -DIR="$(dirname "$0")" - -# To be called LOCALLY for testing WITHOUT docker. -# Also serves as a core/helper script called by -# `run_tests` and `build_run_tests_docker_local` -# when testing WITH docker. -# -# Contains core logic for running tests in the current environment. -# -# Run from circuits/cpp/ -# Example: -# ./scripts/run_tests_local x86_64 glob -*.circuit* -# -# Note: Assumes ignition SRS transcripts have already been downloaded - -############################################################################### -# ARGS -############################################################################### -# ARCH: x86_64 or wasm (MUST BE LOWERCASE) -ARCH=$1 -# TESTS: -# 1. names of test executables to run -# - (like "aztec3_circuits_kernel_tests aztec3_circuits_abis_tests") -# 2. or "glob" (LOWERCASE) to run all built tests -# 3. or a file containing a list of test -TESTS=$2 -# GTEST_FILTER: optional pattern like "*native*" to filter gtests -GTEST_FILTER=${3:-} - -# Shift away the args -shift -shift -if [ -n "$GTEST_FILTER" ]; then - shift -fi -# END ARGS -############################################################################### - -if [ "$ARCH" != "wasm" ]; then - # x86_64 / anything other than wasm - BUILD_DIR=$DIR/../build -else - BUILD_DIR=$DIR/../build-wasm -fi - -# if TESTS is GLOB or empty, run all built tests -# if TESTS is a file, assume it contains a list of tests to run -# otherwise assume TESTS itself is a list of tests to run -if [ "$TESTS" == "glob" ] || [ -z "$TESTS" ]; then - echo " No test file specified. Globbing $BUILD_DIR/bin for tests." - TESTS=$(cd $BUILD_DIR/bin && find -type f -executable | grep "test" | tr '\n' ' ') -elif [ -f "$TESTS" ]; then - TESTS=$(cat $TESTS | tr '\n' ' ') -fi - -echo "*** Running $ARCH tests${GTEST_FILTER:+ (with filter: $GTEST_FILTER)}: $TESTS ***" - -cd $BUILD_DIR; -for BIN in $TESTS; do - echo "Running tests from executable '$BIN'" - if [ "$ARCH" != "wasm" ]; then - # run test executables directly - # if gtest filter is non-empty, use it - # gtest filter is a command line arg to native executable - ./bin/$BIN ${GTEST_FILTER:+--gtest_filter=$GTEST_FILTER} $@ - else - # run test executables via wasmtime - # if gtest filter is non-empty, use it - # gtest filter is an env var to wasmtime - wasmtime --dir .. ./bin/$BIN --env ${GTEST_FILTER:+--env GTEST_FILTER=$GTEST_FILTER} --env GTEST_COLOR=1 - fi -done diff --git a/circuits/cpp/scripts/tidy.sh b/circuits/cpp/scripts/tidy.sh deleted file mode 100755 index 7faab2658c6..00000000000 --- a/circuits/cpp/scripts/tidy.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env bash -set -eu - -# Run clang-tidy on all C++ source files -# -# CMake must be configured for clang15 before running this script: -# cmake --preset clang15 -# -# Run examples (from circuits/cpp) -# ./scripts/tidy.sh -# or -# ./scripts/tidy.sh fix - -############################################################################### -# ARGS -############################################################################### -# FIX: or fix (MUST BE LOWERCASE) -# if 'fix', apply fixes to actual source file -# else, print warnings -FIX=$1 -# END ARGS -############################################################################### - -cmake --preset default -# Ensure we have downloaded msgpack headers -cmake --build --preset default --target msgpack-c -# CMake build dir which should contain `compile_commands.json` -BUILD_DIR=build -echo "*************************************************************************" -if [ "$FIX" == "fix" ]; then - echo "Tidy all source files - fix and format the files themselves" - FIX_OPT="-fix -format" -else - EXPORT_DIR=$BUILD_DIR/tidy-fixes - # Clean old tidy fixes - rm -f $EXPORT_DIR/* - mkdir -p $EXPORT_DIR - YAML_FILE=$EXPORT_DIR/tidy-all.yaml - - # run tidy on each source file and export fixes to yaml files - echo "Checking tidy on all source files and exporting fixes to directory: $EXPORT_DIR" - FIX_OPT="-export-fixes $YAML_FILE" - echo "To apply these fixes later, run the following from circuits/cpp:" - echo " clang-apply-replacements --format --style file $EXPORT_DIR" -fi - - -# find all C++ source files to tidy up -SOURCES=$(\ - find src/aztec3/ \ - -name *.cpp \ - -o -name *.hpp \ - -o -name *.cxx \ - -o -name *.hxx \ - -o -name *.tpp \ - -o -name *.cc \ - -o -name *.hh \ - -o -name *.c \ - -o -name *.h \ - | LC_ALL=C sort \ -) - -# MD5 of all source files before running clang-tidy -BEFORE_MD5=$( - for src in ${SOURCES[@]}; do - md5sum $src - done | md5sum) -echo "Before running clang-tidy, MD5 of all C++ files was: $BEFORE_MD5" -echo "*************************************************************************" - -# Need run-clang-tidy version 15, but it doesn't have a --version flag -RUN_TIDY=$(which run-clang-tidy-15 || which run-clang-tidy || which run-clang-tidy-mp-15) -# tidy all sources -$RUN_TIDY -p $BUILD_DIR $SOURCES $FIX_OPT -use-color || {\ - echo "Errors encountered when running clang-tidy!" && - echo "Check the output above before trying again." && \ - exit 1; -} - -echo "*************************************************************************" -if [ "$FIX" == "fix" ]; then - # MD5 of all source files after running clang-tidy - AFTER_MD5=$( - for src in ${SOURCES[@]}; do - md5sum $src - done | md5sum) - echo "AFTER running clang-tidy, MD5 of all C++ files was: $AFTER_MD5" - - echo "$BEFORE_MD5 ?= $AFTER_MD5" - if [ "$BEFORE_MD5" == "$AFTER_MD5" ]; then - echo "No tidying necessary!" - exit 0 - else - echo "WARNING: Some tidying was necessary!" - echo "If you are seeing this in CI, run the following" - echo "in circuits/cpp to tidy up the C++:" - echo " ./scripts/tidy.sh fix" - exit 1 - fi -else - echo "Reminder!" - echo "To apply these fixes later, run the following from circuits/cpp:" - echo " clang-apply-replacements --format --style file $EXPORT_DIR" -fi -echo "*************************************************************************" diff --git a/circuits/cpp/src/CMakeLists.txt b/circuits/cpp/src/CMakeLists.txt deleted file mode 100644 index a29ea8c7129..00000000000 --- a/circuits/cpp/src/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) - -add_compile_options(-Werror -Wall -Wextra -Wconversion -Wsign-conversion -Wno-deprecated -Wno-tautological-compare -Wfatal-errors) - -if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_compile_options(-fconstexpr-steps=100000000) - if(MEMORY_CHECKS) - message(STATUS "Compiling with memory checks.") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") - endif() -endif() - -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") - add_compile_options(-fconstexpr-ops-limit=100000000) -endif() - -include_directories(${CMAKE_SOURCE_DIR}/barretenberg/cpp/src) -include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${MSGPACK_INCLUDE}) - -# I feel this should be limited to ecc, however it's currently used in headers that go across libraries, -# and there currently isn't an easy way to inherit the DDISABLE_SHENANIGANS parameter. -if(DISABLE_ASM) - message(STATUS "Using fallback non-assembly methods for field multiplications.") - add_definitions(-DDISABLE_SHENANIGANS=1) -else() - message(STATUS "Using optimized assembly for field arithmetic.") -endif() - -add_subdirectory(aztec3) \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/CMakeLists.txt b/circuits/cpp/src/aztec3/CMakeLists.txt deleted file mode 100644 index 27ddfeda761..00000000000 --- a/circuits/cpp/src/aztec3/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -if (WASM) - link_directories(${CMAKE_SOURCE_DIR}/barretenberg/cpp/build-wasm/lib) -else() - link_directories(${CMAKE_SOURCE_DIR}/barretenberg/cpp/build/lib) -endif() - -add_subdirectory(circuits) -add_subdirectory(oracle) -add_subdirectory(dbs) -add_subdirectory(utils) - -if (WASM) - # We can't build a wasm module by just linking to the libraries as that produces, nothing. - # There are a couple of other ways to avoiding listing all the object files here and leveraging the dependency - # tree, but they come with the problem that they will import the 'env' object files. We explicitly want to avoid - # that as functions in 'env' should be implemented in JS itself. - # It turns out that just explicitly telling the wasm module which object files to include was easiest. - add_executable( - aztec3-circuits.wasm - $ - $ - $ - $ - ) - target_link_libraries(aztec3-circuits.wasm barretenberg wasi) - - target_link_options( - aztec3-circuits.wasm - PRIVATE - # TODO revisit implications of whole-archive - -nostartfiles -Wl,--whole-archive -Wl,--no-entry -Wl,--export-dynamic -Wl,--import-memory -Wl,--allow-undefined -Wl,--stack-first -Wl,-z,stack-size=1048576 - ) -endif() diff --git a/circuits/cpp/src/aztec3/circuits/CMakeLists.txt b/circuits/cpp/src/aztec3/circuits/CMakeLists.txt deleted file mode 100644 index ae3cfdda297..00000000000 --- a/circuits/cpp/src/aztec3/circuits/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -add_subdirectory(apps) -add_subdirectory(abis) -add_subdirectory(kernel) -add_subdirectory(rollup) -add_subdirectory(recursion) \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/.test.cpp b/circuits/cpp/src/aztec3/circuits/abis/.test.cpp deleted file mode 100644 index 757531113ef..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/.test.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include "index.hpp" -#include "previous_kernel_data.hpp" - -#include "aztec3/circuits/abis/combined_accumulated_data.hpp" - -#include - -#include - -namespace { -// Builder -using Builder = UltraCircuitBuilder; - -// Types -using CT = aztec3::utils::types::CircuitTypes; -using NT = aztec3::utils::types::NativeTypes; -} // namespace - -namespace aztec3::circuits::abis { - -class abi_tests : public ::testing::Test {}; - -TEST(abi_tests, msgpack_schema_smoke_test) -{ - // Just exercise these to make sure they don't error - // They will test for any bad serialization methods - msgpack_schema_to_string(CombinedAccumulatedData{}); - CombinedAccumulatedData cad; - EXPECT_EQ(msgpack::check_msgpack_method(cad), ""); -} - -TEST(abi_tests, native_read_write_call_context) -{ - CallContext const call_context = { - .msg_sender = 1, - .storage_contract_address = 2, - .portal_contract_address = 3, - .function_selector = { .value = 1 }, - .is_delegate_call = false, - .is_static_call = false, - .is_contract_deployment = false, - }; - - info("call_context: ", call_context); - - auto buffer = to_buffer(call_context); - auto call_context_2 = from_buffer>(buffer.data()); - - EXPECT_EQ(call_context, call_context_2); -} - -TEST(abi_tests, native_read_write_function_data) -{ - FunctionData const function_data = { - .selector = - { - .value = 11, - }, - .is_private = false, - .is_constructor = false, - }; - - info("function data: ", function_data); - - auto buffer = to_buffer(function_data); - auto function_data_2 = from_buffer>(buffer.data()); - - EXPECT_EQ(function_data, function_data_2); -} - -TEST(abi_tests, native_to_circuit_function_data) -{ - FunctionData const native_function_data = { - .selector = - { - .value = 11, - }, - .is_private = false, - .is_constructor = false, - }; - - info("function data: ", native_function_data); - - Builder builder = Builder(); - FunctionData const circuit_function_data = native_function_data.to_circuit_type(builder); - - info("function data: ", circuit_function_data); -} - -TEST(abi_tests, native_call_context) -{ - CallContext const call_context = { - .msg_sender = 10, - .storage_contract_address = 11, - .portal_contract_address = 12, - .function_selector = { .value = 1 }, - .is_delegate_call = false, - .is_static_call = false, - }; - - info("call context: ", call_context); -} - -TEST(abi_tests, native_to_circuit_call_context) -{ - CallContext const native_call_context = { - .msg_sender = 10, - .storage_contract_address = 11, - .portal_contract_address = 12, - .function_selector = { .value = 1 }, - .is_delegate_call = false, - .is_static_call = false, - }; - - info("call context: ", native_call_context); - - Builder builder = Builder(); - CallContext const circuit_call_context = native_call_context.to_circuit_type(builder); - - info("call context: ", circuit_call_context); -} - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/CMakeLists.txt b/circuits/cpp/src/aztec3/circuits/abis/CMakeLists.txt deleted file mode 100644 index 53fc0c72e0a..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -circuits_cmake_module( - aztec3_circuits_abis - barretenberg -) \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/README.md b/circuits/cpp/src/aztec3/circuits/abis/README.md deleted file mode 100644 index 1d6b1b23af5..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# aztec3::circuits::abis - -Contains all ABIs for use by: - -- Test app circuits -- Kernel circuits -- Rollup circuits - -All ABIs are generalized by an `NCT` template parameter (meaning `NativeOrCircuitTypes`). `NCT` can be either `aztec3::utils::types::NativeTypes` or `aztec3::utils::types::CircuitTypes` for some `Builder`. The idea being, there's a single implementation of every struct/class for native and circuit types. NativeType structs can be switched to CircuitType with the `to_circuit_type()` method. diff --git a/circuits/cpp/src/aztec3/circuits/abis/append_only_tree_snapshot.hpp b/circuits/cpp/src/aztec3/circuits/abis/append_only_tree_snapshot.hpp deleted file mode 100644 index 50ec136e492..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/append_only_tree_snapshot.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include - -namespace aztec3::circuits::abis { - -template struct AppendOnlyTreeSnapshot { - using fr = typename NCT::fr; - using uint32 = typename NCT::uint32; - - fr root = 0; - uint32 next_available_leaf_index; - MSGPACK_FIELDS(root, next_available_leaf_index); - - bool operator==(AppendOnlyTreeSnapshot const&) const = default; -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/block_header.hpp b/circuits/cpp/src/aztec3/circuits/abis/block_header.hpp deleted file mode 100644 index a843a94ff5b..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/block_header.hpp +++ /dev/null @@ -1,138 +0,0 @@ -#pragma once - -#include "aztec3/circuits/abis/append_only_tree_snapshot.hpp" -#include "aztec3/circuits/abis/global_variables.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct BlockHeader { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - // Private data - fr note_hash_tree_root = 0; - fr nullifier_tree_root = 0; - fr contract_tree_root = 0; - fr l1_to_l2_message_tree_root = 0; - fr archive_root = 0; - fr private_kernel_vk_tree_root = 0; // TODO: future enhancement - - // Public data - fr public_data_tree_root = 0; - fr global_variables_hash = 0; - - // for serialization, update with new fields - MSGPACK_FIELDS(note_hash_tree_root, - nullifier_tree_root, - contract_tree_root, - l1_to_l2_message_tree_root, - archive_root, - private_kernel_vk_tree_root, - public_data_tree_root, - global_variables_hash); - - boolean operator==(BlockHeader const& other) const - { - return note_hash_tree_root == other.note_hash_tree_root && nullifier_tree_root == other.nullifier_tree_root && - contract_tree_root == other.contract_tree_root && - l1_to_l2_message_tree_root == other.l1_to_l2_message_tree_root && archive_root == other.archive_root && - private_kernel_vk_tree_root == other.private_kernel_vk_tree_root && - public_data_tree_root == other.public_data_tree_root && - global_variables_hash == other.global_variables_hash; - }; - - template void assert_is_zero() - { - static_assert((std::is_same, NCT>::value)); - - note_hash_tree_root.assert_is_zero(); - nullifier_tree_root.assert_is_zero(); - contract_tree_root.assert_is_zero(); - l1_to_l2_message_tree_root.assert_is_zero(); - archive_root.assert_is_zero(); - private_kernel_vk_tree_root.assert_is_zero(); - public_data_tree_root.assert_is_zero(); - global_variables_hash.assert_is_zero(); - } - - template BlockHeader> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - BlockHeader> data = { - to_ct(note_hash_tree_root), to_ct(nullifier_tree_root), to_ct(contract_tree_root), - to_ct(l1_to_l2_message_tree_root), to_ct(archive_root), to_ct(private_kernel_vk_tree_root), - to_ct(public_data_tree_root), to_ct(global_variables_hash), - }; - - return data; - }; - - template BlockHeader to_native_type() const - { - static_assert(std::is_same, NCT>::value); - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - BlockHeader data = { - to_nt(note_hash_tree_root), to_nt(nullifier_tree_root), to_nt(contract_tree_root), - to_nt(l1_to_l2_message_tree_root), to_nt(archive_root), to_nt(private_kernel_vk_tree_root), - to_nt(public_data_tree_root), to_nt(global_variables_hash), - }; - - return data; - }; - - void set_public() - { - static_assert(!(std::is_same::value)); - - note_hash_tree_root.set_public(); - nullifier_tree_root.set_public(); - contract_tree_root.set_public(); - l1_to_l2_message_tree_root.set_public(); - archive_root.set_public(); - private_kernel_vk_tree_root.set_public(); - public_data_tree_root.set_public(); - global_variables_hash.set_public(); - } - - std::array to_array() const - { - return { note_hash_tree_root, - nullifier_tree_root, - contract_tree_root, - l1_to_l2_message_tree_root, - archive_root, // TODO(#3441) Note private_kernel_vk_tree_root, is not included yet as - // it is not present in noir, - public_data_tree_root, - global_variables_hash }; - } - - - fr hash() - { - return compute_block_hash(global_variables_hash, - note_hash_tree_root, - nullifier_tree_root, - contract_tree_root, - l1_to_l2_message_tree_root, - public_data_tree_root); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp b/circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp deleted file mode 100644 index 648cde0870d..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp +++ /dev/null @@ -1,588 +0,0 @@ -#include "c_bind.h" - -#include "call_stack_item.hpp" -#include "function_data.hpp" -#include "function_leaf_preimage.hpp" -#include "kernel_circuit_public_inputs.hpp" -#include "kernel_circuit_public_inputs_final.hpp" -#include "previous_kernel_data.hpp" -#include "private_circuit_public_inputs.hpp" -#include "tx_context.hpp" -#include "tx_request.hpp" -#include "private_kernel/private_kernel_inputs_inner.hpp" -#include "public_kernel/public_kernel_inputs.hpp" -#include "rollup/base/base_or_merge_rollup_public_inputs.hpp" -#include "rollup/base/base_rollup_inputs.hpp" -#include "rollup/root/root_rollup_inputs.hpp" -#include "rollup/root/root_rollup_public_inputs.hpp" - -#include "aztec3/circuits/abis/combined_accumulated_data.hpp" -#include "aztec3/circuits/abis/complete_address.hpp" -#include "aztec3/circuits/abis/final_accumulated_data.hpp" -#include "aztec3/circuits/abis/new_contract_data.hpp" -#include "aztec3/circuits/abis/packers.hpp" -#include "aztec3/circuits/abis/point.hpp" -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_init.hpp" -#include "aztec3/circuits/abis/tx_request.hpp" -#include "aztec3/circuits/abis/types.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace { - -using aztec3::circuits::compute_constructor_hash; -using aztec3::circuits::abis::CallStackItem; -using aztec3::circuits::abis::CompleteAddress; -using aztec3::circuits::abis::ConstantsPacker; -using aztec3::circuits::abis::FunctionData; -using aztec3::circuits::abis::FunctionLeafPreimage; -using aztec3::circuits::abis::GeneratorIndexPacker; -using aztec3::circuits::abis::NewContractData; -using aztec3::circuits::abis::Point; -using aztec3::circuits::abis::PrivateStateNoteGeneratorIndexPacker; -using aztec3::circuits::abis::PrivateStateTypePacker; -using aztec3::circuits::abis::StorageSlotGeneratorIndexPacker; -using aztec3::circuits::abis::TxContext; -using aztec3::circuits::abis::TxRequest; -using NT = aztec3::utils::types::NativeTypes; -using aztec3::circuits::abis::PrivateTypes; -using aztec3::circuits::abis::PublicTypes; - -// Cbind helper functions - -/** - * @brief Fill in zero-leaves to get a full tree's bottom layer. - * - * @details Given the a vector of nonzero leaves starting at the left, - * append zero leaves to that list until it represents a FULL set of leaves - * for a tree of the given height. - * **MODIFIES THE INPUT `leaves` REFERENCE!** - * - * @tparam TREE_HEIGHT height of the tree used to determine max leaves - * @param leaves the nonzero leaves of the tree starting at the left - * @param zero_leaf the leaf value to be used for any empty/unset leaves - */ -template void rightfill_with_zeroleaves(std::vector& leaves, NT::fr& zero_leaf) -{ - constexpr size_t max_leaves = 2 << (TREE_HEIGHT - 1); - // input cant exceed max leaves - // FIXME don't think asserts will show in wasm - ASSERT(leaves.size() <= max_leaves); - - // fill in input vector with zero-leaves - // to get a full bottom layer of the tree - leaves.insert(leaves.end(), max_leaves - leaves.size(), zero_leaf); -} - -} // namespace - -/** Copy this string to a bbmalloc'd buffer */ -static const char* bbmalloc_copy_string(const char* data, size_t len) -{ - char* output_copy = static_cast(bbmalloc(len + 1)); - memcpy(output_copy, data, len + 1); - return output_copy; -} - -/** - * For testing only. Take this object, write it to a buffer, then output it. */ -template static const char* as_string_output(uint8_t const* input_buf, uint32_t* size) -{ - using serialize::read; - T obj; - read(input_buf, obj); - std::ostringstream stream; - stream << obj; - std::string const str = stream.str(); - *size = static_cast(str.size()); - return bbmalloc_copy_string(str.c_str(), *size); -} - -/** - * For testing only. Take this object, serialize it to a buffer, then output it. */ -template static const char* as_serialized_output(uint8_t const* input_buf, uint32_t* size) -{ - using serialize::read; - T obj; - serialize::read(input_buf, obj); - std::vector stream; - serialize::write(stream, obj); - *size = static_cast(stream.size()); - return bbmalloc_copy_string(reinterpret_cast(stream.data()), *size); -} - -// WASM Cbinds -/** - * @brief Hashes a TX request. This is a WASM-export that can be called from Typescript. - * - * @details given a `uint8_t*` buffer representing a full TX request, - * read it into a `TxRequest` object, hash it to a `fr`, - * and serialize it to a `uint8_t*` output buffer - * - * @param tx_request_buf buffer of bytes containing all data needed to construct a TX request via `serialize::read()` - * @param output buffer that will contain the output which will be the hashed `TxRequest` - */ -WASM_EXPORT void abis__hash_tx_request(uint8_t const* tx_request_buf, uint8_t* output) -{ - TxRequest tx_request; - serialize::read(tx_request_buf, tx_request); - // TODO(dbanks12) consider using write() and serialize::read() instead of - // serialize to/from everywhere here and in test - NT::fr::serialize_to_buffer(tx_request.hash(), output); -} - -/** - * @brief Generates a function's "selector" from its "signature" using keccak256. - * This is a WASM-export that can be called from Typescript. - * - * @details given a `char const*` c-string representing a "function signature", - * hash using keccak and return its first 4 bytes (the "function selector") - * by copying them into the `output` buffer arg. This is a workalike of - * Ethereum/solidity's function selector computation.... - * Ethereum function selector is computed as follows: - * `uint8_t* hash = keccak256(const char* func_sig);` - * where func_sig does NOT include the trailing null character - * And the resulting cstring for "transfer(address,uint256)" is: - * `0xa9059cbb` - * The 0th to 3rd bytes make up the function selector like: - * where 0xa9 is hash[0], 05 is hash[1], 9c is hash[2], and bb is hash[3] - * - * @param func_sig_cstr c-string representing the function signature string like "transfer(uint256,address)" - * @param output buffer that will contain the output which will be 4-byte function selector - */ -WASM_EXPORT void abis__compute_function_selector(char const* func_sig_cstr, uint8_t* output) -{ - // hash the function signature using keccak256 - auto keccak_hash = ethash_keccak256(reinterpret_cast(func_sig_cstr), strlen(func_sig_cstr)); - // get a pointer to the start of the hash bytes - auto const* hash_bytes = reinterpret_cast(&keccak_hash.word64s[0]); - // get the correct number of bytes from the hash and copy into output buffer - std::copy_n(hash_bytes, aztec3::FUNCTION_SELECTOR_NUM_BYTES, output); -} - -/** - * @brief Hash verification key data. - * This is a WASM-export that can be called from Typescript. - * - * @details Pedersen hash VK to use later when computing function leaf - * or constructor hash. Return the serialized results in the `output` buffer. - * - * @param vk_data_buf buffer of bytes representing serialized verification_key_data - * @param output buffer that will contain the output. The serialized vk_hash. - */ -WASM_EXPORT void abis__hash_vk(uint8_t const* vk_data_buf, uint8_t* output) -{ - NT::VKData vk_data; - serialize::read(vk_data_buf, vk_data); - - NT::fr::serialize_to_buffer(vk_data.hash_native(), output); -} - -/** - * @brief Generates a function tree leaf from its preimage. - * This is a WASM-export that can be called from Typescript. - * - * @details given a `uint8_t const*` buffer representing a function leaf's preimage, - * construct a FunctionLeafPreimage instance, hash, and return the serialized results - * in the `output` buffer. - * - * @param function_leaf_preimage_buf a buffer of bytes representing the function leaf's preimage - * contents (`function_selector`, `is_private`, `vk_hash`, and `acir_hash`) - * @param output buffer that will contain the output. The hashed and serialized function leaf. - */ -WASM_EXPORT void abis__compute_function_leaf(uint8_t const* function_leaf_preimage_buf, uint8_t* output) -{ - FunctionLeafPreimage leaf_preimage; - serialize::read(function_leaf_preimage_buf, leaf_preimage); - leaf_preimage.hash(); - NT::fr::serialize_to_buffer(leaf_preimage.hash(), output); -} - -/** - * @brief Compute a function tree root from its nonzero leaves. - * This is a WASM-export that can be called from Typescript. - * - * @details given a serialized vector of nonzero function leaves, - * compute the corresponding tree's root and return the - * serialized results via `root_out` buffer. - * - * @param function_leaves_in input buffer representing a serialized vector of - * nonzero function leaves where each leaf is an `fr` starting at the left of the tree - * @param root_out buffer that will contain the serialized function tree root `fr`. - */ -WASM_EXPORT void abis__compute_function_tree_root(uint8_t const* function_leaves_in, uint8_t* root_out) -{ - std::vector leaves; - // fill in nonzero leaves to start - read(function_leaves_in, leaves); - // fill in zero leaves to complete tree - NT::fr zero_leaf = FunctionLeafPreimage().hash(); // hash of empty/0 preimage - rightfill_with_zeroleaves(leaves, zero_leaf); - - // compute the root of this complete tree, return - NT::fr const root = plonk::stdlib::merkle_tree::compute_tree_root_native(leaves); - - // serialize and return root - NT::fr::serialize_to_buffer(root, root_out); -} - -/** - * @brief Compute all of a function tree's nodes from its nonzero leaves. - * This is a WASM-export that can be called from Typescript. - * - * @details given a serialized vector of nonzero function leaves, - * compute ALL of the corresponding tree's nodes (including root) and return - * the serialized results via `tree_nodes_out` buffer. - * - * @param function_leaves_in input buffer representing a serialized vector of - * nonzero function leaves where each leaf is an `fr` starting at the left of the tree. - * @param tree_nodes_out buffer that will contain the serialized function tree. - * The 0th node is the bottom leftmost leaf. The last entry is the root. - */ -WASM_EXPORT void abis__compute_function_tree(uint8_t const* function_leaves_in, uint8_t* tree_nodes_out) -{ - std::vector leaves; - // fill in nonzero leaves to start - read(function_leaves_in, leaves); - // fill in zero leaves to complete tree - NT::fr zero_leaf = FunctionLeafPreimage().hash(); // hash of empty/0 preimage - rightfill_with_zeroleaves(leaves, zero_leaf); - - std::vector const tree = plonk::stdlib::merkle_tree::compute_tree_native(leaves); - - // serialize and return tree - write(tree_nodes_out, tree); -} - -/** - * @brief Hash some constructor info. - * This is a WASM-export that can be called from Typescript. - * - * @details Hash constructor info to use later when deriving/generating contract address: - * hash(function_signature_hash, args_hash, constructor_vk_hash) - * Return the serialized results in the `output` buffer. - * - * @param function_data_buf function data struct but as a buffer of bytes - * @param args_buf constructor args (array of fields) but as a buffer of bytes - * @param constructor_vk_hash_buf constructor vk hashed to a field but as a buffer of bytes - * @param output buffer that will contain the output. The serialized constructor_vk_hash. - */ -WASM_EXPORT void abis__hash_constructor(uint8_t const* function_data_buf, - uint8_t const* args_hash_buf, - uint8_t const* constructor_vk_hash_buf, - uint8_t* output) -{ - FunctionData function_data; - NT::fr args_hash; - NT::fr constructor_vk_hash; - - serialize::read(function_data_buf, function_data); - read(args_hash_buf, args_hash); - read(constructor_vk_hash_buf, constructor_vk_hash); - - NT::fr const constructor_hash = compute_constructor_hash(function_data, args_hash, constructor_vk_hash); - - NT::fr::serialize_to_buffer(constructor_hash, output); -} - -/** - * @brief Compute a complete address. - */ -CBIND(abis__compute_complete_address, aztec3::circuits::abis::CompleteAddress::compute); - -/** - * @brief Compute a contract address from deployer public key and partial address. - * This is a WASM-export that can be called from Typescript. - * - * @details Computes a contract address by hashing the deployers public key along with the previously computed partial - * address Return the serialized results in the `output` buffer. - * - * @param point_data_buf point data struct as a buffer of bytes - * @param partial_address_data_buf partial address - * @param output buffer that will contain the output. The serialized contract address. - */ -WASM_EXPORT void abis__compute_contract_address_from_partial(uint8_t const* point_data_buf, - uint8_t const* partial_address_data_buf, - uint8_t* output) -{ - Point deployer_public_key; - NT::fr partial_address; - - serialize::read(point_data_buf, deployer_public_key); - read(partial_address_data_buf, partial_address); - - NT::fr const contract_address = - aztec3::circuits::compute_contract_address_from_partial(deployer_public_key, partial_address); - - NT::fr::serialize_to_buffer(contract_address, output); -} - -/** - * @brief Hash args for a function call. - * - * @param args_buf array of args (fields), with the length on the first position - * @param output buffer that will contain the output - */ -WASM_EXPORT void abis__compute_var_args_hash(uint8_t const* args_buf, uint8_t* output) -{ - std::vector args; - read(args_buf, args); - NT::fr const args_hash = aztec3::circuits::compute_var_args_hash(args); - NT::fr::serialize_to_buffer(args_hash, output); -} - -/** - * @brief Generates a function tree leaf from its preimage. - * This is a WASM-export that can be called from Typescript. - * - * @details given a `uint8_t const*` buffer representing a function leaf's preimage, - * construct a NewContractData instance, hash, and return the serialized results - * in the `output` buffer. - * - * @param contract_leaf_preimage_buf a buffer of bytes representing the contract leaf's preimage - * contents (`contract_address`, `portal_contract_address`, `function_tree_root`) - * @param output buffer that will contain the output. The hashed and serialized contract leaf. - */ -WASM_EXPORT void abis__compute_contract_leaf(uint8_t const* contract_leaf_preimage_buf, uint8_t* output) -{ - NewContractData leaf_preimage; - serialize::read(contract_leaf_preimage_buf, leaf_preimage); - // as per the circuit implementation, if contract address == zero then return a zero leaf - auto to_write = leaf_preimage.hash(); - NT::fr::serialize_to_buffer(to_write, output); -} - -/** - * @brief Generates a commitment nonce, which will be used to create a unique commitment. - */ -CBIND(abis__compute_commitment_nonce, aztec3::circuits::compute_commitment_nonce); - -/** - * @brief Generates a unique commitment using a commitment nonce. - */ -CBIND(abis__compute_unique_commitment, aztec3::circuits::compute_unique_commitment); - -/** - * @brief Generates a siloed commitment tree leaf from the contract and the commitment. - */ -CBIND(abis__silo_commitment, aztec3::circuits::silo_commitment); - -/** - * @brief Generates a siloed nullifier from the contract and the nullifier. - */ -CBIND(abis__silo_nullifier, aztec3::circuits::silo_nullifier); - -/** - * @brief Computes the block hash from the block information. - * Globals is provided as a hash in this instance. - */ -CBIND(abis__compute_block_hash, aztec3::circuits::compute_block_hash); - -/** - * @brief Computes the block hash from the block information. - * The entire globals object is provided in this instance, rather than a hash as in above. - */ -CBIND(abis__compute_block_hash_with_globals, aztec3::circuits::compute_block_hash_with_globals); - -/** - * @brief Computes the hash of the global variables - */ -CBIND(abis__compute_globals_hash, aztec3::circuits::compute_globals_hash); - -/** - * @brief Compute the value to be inserted into the public data tree - */ -CBIND(abis__compute_public_data_tree_value, aztec3::circuits::compute_public_data_tree_value); - -/** - * @brief Compute the index for inserting a value into the public data tree - */ -CBIND(abis__compute_public_data_tree_index, aztec3::circuits::compute_public_data_tree_index); - -/** - * @brief Generates a signed tx request hash from it's pre-image - * This is a WASM-export that can be called from Typescript. - * - * @details given a `uint8_t const*` buffer representing a signed tx request's pre-image, - * construct a TxRequest instance, hash, and return the serialized results - * in the `output` buffer. - * - * @param tx_request_buf a buffer of bytes representing the signed tx request - * @param output buffer that will contain the output. The hashed and serialized signed tx request. - */ -WASM_EXPORT void abis__compute_transaction_hash(uint8_t const* tx_request_buf, uint8_t* output) -{ - TxRequest tx_request_preimage; - serialize::read(tx_request_buf, tx_request_preimage); - auto to_write = tx_request_preimage.hash(); - NT::fr::serialize_to_buffer(to_write, output); -} - -WASM_EXPORT void abis__compute_private_call_stack_item_hash(uint8_t const* call_stack_item_buf, uint8_t* output) -{ - CallStackItem call_stack_item; - serialize::read(call_stack_item_buf, call_stack_item); - NT::fr::serialize_to_buffer(call_stack_item.hash(), output); -} - -WASM_EXPORT void abis__compute_public_call_stack_item_hash(uint8_t const* call_stack_item_buf, uint8_t* output) -{ - CallStackItem call_stack_item; - serialize::read(call_stack_item_buf, call_stack_item); - NT::fr::serialize_to_buffer(get_call_stack_item_hash(call_stack_item), output); -} - -/** - * @brief Computes the hash of a message secret for use in l1 -> l2 messaging - * - * @param secret - * @param output - */ -WASM_EXPORT void abis__compute_message_secret_hash(uint8_t const* secret, uint8_t* output) -{ - NT::fr message_secret; - read(secret, message_secret); - auto secret_hash = NT::hash({ message_secret }, aztec3::GeneratorIndex::L1_TO_L2_MESSAGE_SECRET); - NT::fr::serialize_to_buffer(secret_hash, output); -} - -/* Typescript test helpers that call as_string_output() to stress serialization. - * Each of these take an object buffer, and a string size pointer. - * They return a string pointer (to be bbfree'd) and write to the string size pointer. */ -WASM_EXPORT const char* abis__test_roundtrip_serialize_tx_context(uint8_t const* tx_context_buf, uint32_t* size) -{ - return as_string_output>(tx_context_buf, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_tx_request(uint8_t const* tx_request_buf, uint32_t* size) -{ - return as_string_output>(tx_request_buf, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_call_context(uint8_t const* call_context_buf, uint32_t* size) -{ - return as_string_output>(call_context_buf, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_private_circuit_public_inputs( - uint8_t const* private_circuits_public_inputs_buf, uint32_t* size) -{ - return as_string_output>(private_circuits_public_inputs_buf, - size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_public_circuit_public_inputs( - uint8_t const* public_circuits_public_inputs_buf, uint32_t* size) -{ - return as_string_output>(public_circuits_public_inputs_buf, - size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_function_data(uint8_t const* function_data_buf, uint32_t* size) -{ - return as_string_output>(function_data_buf, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_base_rollup_inputs(uint8_t const* rollup_inputs_buf, - uint32_t* size) -{ - return as_string_output>(rollup_inputs_buf, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_previous_kernel_data(uint8_t const* kernel_data_buf, - uint32_t* size) -{ - return as_string_output>(kernel_data_buf, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_base_or_merge_rollup_public_inputs( - uint8_t const* rollup_inputs_buf, uint32_t* size) -{ - return as_string_output>(rollup_inputs_buf, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_reserialize_base_or_merge_rollup_public_inputs( - uint8_t const* rollup_inputs_buf, uint32_t* size) -{ - return as_serialized_output>(rollup_inputs_buf, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_root_rollup_inputs(uint8_t const* rollup_inputs_buf, - uint32_t* size) -{ - return as_string_output>(rollup_inputs_buf, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_root_rollup_public_inputs(uint8_t const* rollup_inputs_buf, - uint32_t* size) -{ - return as_string_output>(rollup_inputs_buf, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_reserialize_root_rollup_public_inputs(uint8_t const* rollup_inputs_buf, - uint32_t* size) -{ - return as_serialized_output>(rollup_inputs_buf, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_combined_accumulated_data(uint8_t const* input, uint32_t* size) -{ - return as_string_output>(input, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_final_accumulated_data(uint8_t const* input, uint32_t* size) -{ - return as_string_output>(input, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_signature(uint8_t const* input, uint32_t* size) -{ - return as_string_output(input, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_private_kernel_inputs_inner(uint8_t const* input, uint32_t* size) -{ - return as_string_output>(input, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_private_kernel_inputs_init(uint8_t const* input, uint32_t* size) -{ - return as_string_output>(input, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_kernel_circuit_public_inputs(uint8_t const* input, - uint32_t* size) -{ - return as_string_output>(input, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_kernel_circuit_public_inputs_final(uint8_t const* input, - uint32_t* size) -{ - return as_string_output>(input, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_public_kernel_inputs(uint8_t const* input, uint32_t* size) -{ - return as_string_output>(input, size); -} - -WASM_EXPORT const char* abis__test_roundtrip_serialize_function_leaf_preimage(uint8_t const* function_leaf_preimage_buf, - uint32_t* size) -{ - return as_string_output>(function_leaf_preimage_buf, size); -} - - -// When we return a packer from packers.hpp, we call its msgpack_pack method (as that is what is used -// internally in msgpack) and thus can get a JSON-like object of all our constants in Typescript. We explicitly do not -// want a schema here as our ConstantsPacker is not meant to be used in a Typescript function. (if it were, it would -// need to implement msgpack_schema, but as we handle it specially not much value). -CBIND_NOSCHEMA(get_circuit_constants, [] { return ConstantsPacker{}; }); -CBIND_NOSCHEMA(get_circuit_generator_index, [] { return GeneratorIndexPacker{}; }); -CBIND_NOSCHEMA(get_circuit_private_state_note_generator_index, [] { return PrivateStateNoteGeneratorIndexPacker{}; }); -CBIND_NOSCHEMA(get_circuit_storage_slot_generator_index, [] { return StorageSlotGeneratorIndexPacker{}; }); -CBIND_NOSCHEMA(get_circuit_private_state_type, [] { return PrivateStateTypePacker{}; }); diff --git a/circuits/cpp/src/aztec3/circuits/abis/c_bind.h b/circuits/cpp/src/aztec3/circuits/abis/c_bind.h deleted file mode 100644 index 49ebe515418..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/c_bind.h +++ /dev/null @@ -1,38 +0,0 @@ -#include - -#include -#include -#include - -WASM_EXPORT void abis__hash_tx_request(uint8_t const* tx_request_buf, uint8_t* output); - -WASM_EXPORT void abis__compute_function_selector(char const* func_sig_cstr, uint8_t* output); - -WASM_EXPORT void abis__compute_function_leaf(uint8_t const* function_leaf_preimage_buf, uint8_t* output); - -WASM_EXPORT void abis__compute_function_tree_root(uint8_t const* function_leaves_buf, uint8_t* output); - -WASM_EXPORT void abis__compute_function_tree(uint8_t const* function_leaves_buf, uint8_t* output); - -WASM_EXPORT void abis__hash_vk(uint8_t const* vk_data_buf, uint8_t* output); - -WASM_EXPORT void abis__hash_constructor(uint8_t const* func_data_buf, - uint8_t const* args_buf, - uint8_t const* constructor_vk_hash_buf, - uint8_t* output); - -CBIND_DECL(abis__compute_complete_address); - -CBIND_DECL(abis__compute_commitment_nonce); -CBIND_DECL(abis__compute_unique_commitment); -CBIND_DECL(abis__silo_commitment); -CBIND_DECL(abis__silo_nullifier); -CBIND_DECL(abis__compute_block_hash); -CBIND_DECL(abis__compute_block_hash_with_globals); -CBIND_DECL(abis__compute_globals_hash); - -WASM_EXPORT void abis__compute_message_secret_hash(uint8_t const* secret, uint8_t* output); -WASM_EXPORT void abis__compute_contract_leaf(uint8_t const* contract_leaf_preimage_buf, uint8_t* output); -WASM_EXPORT void abis__compute_transaction_hash(uint8_t const* tx_request_buf, uint8_t* output); -WASM_EXPORT void abis__compute_call_stack_item_hash(uint8_t const* call_stack_item_buf, uint8_t* output); -WASM_EXPORT void abis__compute_var_args_hash(uint8_t const* args_buf, uint8_t* output); \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/c_bind.test.cpp b/circuits/cpp/src/aztec3/circuits/abis/c_bind.test.cpp deleted file mode 100644 index ffd0217a836..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/c_bind.test.cpp +++ /dev/null @@ -1,338 +0,0 @@ -#include "c_bind.h" - -#include "function_leaf_preimage.hpp" -#include "tx_request.hpp" - -#include "aztec3/circuits/abis/complete_address.hpp" -#include "aztec3/circuits/abis/new_contract_data.hpp" -#include "aztec3/circuits/abis/tx_request.hpp" -#include "aztec3/circuits/hash.hpp" - -#include - -#include - -#include -#include - -namespace { - -using NT = aztec3::utils::types::NativeTypes; -using aztec3::circuits::abis::NewContractData; -// num_leaves = 2**h = 2<<(h-1) -// root layer does not count in height -constexpr size_t FUNCTION_TREE_NUM_LEAVES = 2 << (aztec3::FUNCTION_TREE_HEIGHT - 1); -// num_nodes = (2**(h+1))-1 = (2< std::string bytes_to_hex_str(std::array bytes) -{ - std::ostringstream stream; - for (const uint8_t& byte : bytes) { - stream << std::setw(2) << std::setfill('0') << std::hex << static_cast(byte); - } - return stream.str(); -} - -} // namespace - -namespace aztec3::circuits::abis { - -TEST(abi_tests, hash_tx_request) -{ - // Construct TxRequest with some randomized fields - TxRequest const tx_request = TxRequest{ - .origin = NT::fr::random_element(), - .function_data = FunctionData(), - .args_hash = NT::fr::random_element(), - .tx_context = TxContext(), - }; - - // Write the tx request to a buffer and - std::vector buf; - serialize::write(buf, tx_request); - - // create an output buffer for cbind hash results - std::array output = { 0 }; - // Make the c_bind call to hash the tx request - abis__hash_tx_request(buf.data(), output.data()); - - // Convert buffer to `fr` for comparison to in-test calculated hash - NT::fr const got_hash = NT::fr::serialize_from_buffer(output.data()); - - // Confirm cbind output == hash of tx request - EXPECT_EQ(got_hash, tx_request.hash()); -} - -TEST(abi_tests, compute_selector_transfer) -{ - const char* function_signature = "transfer(address,uint256)"; - - // create an output buffer for cbind selector results - std::array output = { 0 }; - // Make the c_bind call to compute the function selector via keccak256 - abis__compute_function_selector(function_signature, output.data()); - - // get the selector as a hex string - // compare against known good selector from solidity - // In solidity where selectors are 4 bytes it is a9059cbb - std::string const full_selector = "a9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b"; - EXPECT_EQ(bytes_to_hex_str(output), full_selector.substr(0, FUNCTION_SELECTOR_NUM_BYTES * 2)); -} - -TEST(abi_tests, compute_function_selector_transferFrom) -{ - const char* function_signature = "transferFrom(address,address,uint256)"; - - // create an output buffer for cbind selector results - std::array output = { 0 }; - // Make the c_bind call to compute the function selector via keccak256 - abis__compute_function_selector(function_signature, output.data()); - - // get the selector as a hex string - // compare against known good selector from solidity - std::string const full_selector = "23b872dd7302113369cda2901243429419bec145408fa8b352b3dd92b66c680b"; - EXPECT_EQ(bytes_to_hex_str(output), full_selector.substr(0, FUNCTION_SELECTOR_NUM_BYTES * 2)); -} - -TEST(abi_tests, hash_vk) -{ - // Initialize some random VK data - NT::VKData vk_data; - vk_data.circuit_type = static_cast(proof_system::CircuitType::ULTRA); - vk_data.circuit_size = static_cast(1) << (engine.get_random_uint8() >> 3); // must be a power of two - vk_data.num_public_inputs = engine.get_random_uint32(); - vk_data.commitments["test1"] = g1::element::random_element(); - vk_data.commitments["test2"] = g1::element::random_element(); - vk_data.commitments["foo1"] = g1::element::random_element(); - vk_data.commitments["foo2"] = g1::element::random_element(); - // Write the vk data to a bytes vector - std::vector vk_data_vec; - serialize::write(vk_data_vec, vk_data); - - // create an output buffer for cbind hash results - std::array output = { 0 }; - - // Make the c_bind call to hash the vk - abis__hash_vk(vk_data_vec.data(), output.data()); - - // Convert buffer to `fr` for comparison to in-test calculated hash - NT::fr const got_hash = NT::fr::serialize_from_buffer(output.data()); - - // Calculate the expected hash in-test - NT::fr const expected_hash = vk_data.hash_native(); - - // Confirm cbind output == expected hash - EXPECT_EQ(got_hash, expected_hash); -} - -TEST(abi_tests, compute_function_leaf) -{ - // Construct FunctionLeafPreimage with some randomized fields - auto const preimage = FunctionLeafPreimage{ - .selector = - { - .value = engine.get_random_uint32(), - }, - .is_private = static_cast(engine.get_random_uint8() & 1), - .vk_hash = NT::fr::random_element(), - .acir_hash = NT::fr::random_element(), - }; - - // Write the leaf preimage to a buffer - std::vector preimage_buf; - serialize::write(preimage_buf, preimage); - - std::array output = { 0 }; - abis__compute_function_leaf(preimage_buf.data(), output.data()); - - NT::fr const got_leaf = NT::fr::serialize_from_buffer(output.data()); - EXPECT_EQ(got_leaf, preimage.hash()); -} - -TEST(abi_tests, compute_function_tree_root) -{ - // randomize number of non-zero leaves such that `0 < num_nonzero_leaves <= FUNCTION_TREE_NUM_LEAVES` - uint8_t const num_nonzero_leaves = engine.get_random_uint8() % (FUNCTION_TREE_NUM_LEAVES + 1); - - // generate some random leaves - std::vector leaves_frs; - for (size_t l = 0; l < num_nonzero_leaves; l++) { - leaves_frs.push_back(NT::fr::random_element()); - } - // serialize the leaves to a buffer to pass to cbind - std::vector leaves_bytes_vec; - write(leaves_bytes_vec, leaves_frs); - - // call cbind and get output (root) - std::array output = { 0 }; - abis__compute_function_tree_root(leaves_bytes_vec.data(), output.data()); - NT::fr const got_root = NT::fr::serialize_from_buffer(output.data()); - - // compare cbind results with direct computation - - // add the zero leaves to the vector of fields and pass to barretenberg helper - NT::fr const zero_leaf = FunctionLeafPreimage().hash(); // hash of empty/0 preimage - for (size_t l = num_nonzero_leaves; l < FUNCTION_TREE_NUM_LEAVES; l++) { - leaves_frs.push_back(zero_leaf); - } - // compare results - EXPECT_EQ(got_root, plonk::stdlib::merkle_tree::compute_tree_root_native(leaves_frs)); -} - -TEST(abi_tests, compute_function_tree) -{ - // randomize number of non-zero leaves such that `0 < num_nonzero_leaves <= FUNCTION_TREE_NUM_LEAVES` - uint8_t const num_nonzero_leaves = engine.get_random_uint8() % (FUNCTION_TREE_NUM_LEAVES + 1); - - // generate some random leaves - std::vector leaves_frs; - for (size_t l = 0; l < num_nonzero_leaves; l++) { - leaves_frs.push_back(NT::fr::random_element()); - } - // serialize the leaves to a buffer to pass to cbind - std::vector leaves_bytes_vec; - write(leaves_bytes_vec, leaves_frs); - - // setup output buffer - // it must fit a uint32_t (for the vector length) - // plus all of the nodes `frs` in the tree - constexpr auto size_output_buf = sizeof(uint32_t) + (sizeof(NT::fr) * FUNCTION_TREE_NUM_NODES); - std::array output = { 0 }; - - // call cbind and get output (full tree root) - abis__compute_function_tree(leaves_bytes_vec.data(), output.data()); - // deserialize output to vector of frs representing all nodes in tree - std::vector got_tree; - uint8_t const* output_ptr = output.data(); - read(output_ptr, got_tree); - - // compare cbind results with direct computation - - // add the zero leaves to the vector of fields and pass to barretenberg helper - NT::fr const zero_leaf = FunctionLeafPreimage().hash(); // hash of empty/0 preimage - for (size_t l = num_nonzero_leaves; l < FUNCTION_TREE_NUM_LEAVES; l++) { - leaves_frs.push_back(zero_leaf); - } - - EXPECT_EQ(got_tree, plonk::stdlib::merkle_tree::compute_tree_native(leaves_frs)); -} - -TEST(abi_tests, hash_constructor) -{ - // Randomize required values - auto const func_data = FunctionData{ .selector = - { - .value = 10, - }, - .is_private = true, - .is_constructor = false }; - - NT::fr const args_hash = NT::fr::random_element(); - NT::fr const constructor_vk_hash = NT::fr::random_element(); - - // Write the function data and args to a buffer - std::vector func_data_buf; - serialize::write(func_data_buf, func_data); - - std::vector args_hash_buf; - write(args_hash_buf, args_hash); - - std::array constructor_vk_hash_buf = { 0 }; - NT::fr::serialize_to_buffer(constructor_vk_hash, constructor_vk_hash_buf.data()); - - // create an output buffer for cbind hash results - std::array output = { 0 }; - - // Make the c_bind call to hash the constructor values - abis__hash_constructor(func_data_buf.data(), args_hash_buf.data(), constructor_vk_hash_buf.data(), output.data()); - - // Convert buffer to `fr` for comparison to in-test calculated hash - NT::fr const got_hash = NT::fr::serialize_from_buffer(output.data()); - - // Calculate the expected hash in-test - NT::fr const expected_hash = - NT::hash({ func_data.hash(), args_hash, constructor_vk_hash }, aztec3::GeneratorIndex::CONSTRUCTOR); - - // Confirm cbind output == expected hash - EXPECT_EQ(got_hash, expected_hash); -} - -TEST(abi_tests, hash_var_args) -{ - // Initialize test data and write to buffer - std::vector const args(32, NT::fr::random_element()); - std::vector buf; - write(buf, args); - - // Prepare output buffer - std::array output = { 0 }; - - // Make the c_bind call to hash the constructor values - abis__compute_var_args_hash(buf.data(), output.data()); - - // Convert buffer to `fr` for comparison to in-test calculated hash - NT::fr const got_hash = NT::fr::serialize_from_buffer(output.data()); - - // Calculate the expected hash in-test - NT::fr const expected_hash = NT::hash(args, aztec3::GeneratorIndex::FUNCTION_ARGS); - - // Confirm cbind output == expected hash - EXPECT_EQ(got_hash, expected_hash); -} - -TEST(abi_tests, compute_contract_leaf) -{ - // Construct ContractLeafPreimage with some randomized fields - NewContractData const preimage = NewContractData{ - .contract_address = NT::fr::random_element(), - .portal_contract_address = NT::fr::random_element(), - .function_tree_root = NT::fr::random_element(), - }; - - // Write the leaf preimage to a buffer - std::vector preimage_buf; - serialize::write(preimage_buf, preimage); - - std::array output = { 0 }; - abis__compute_contract_leaf(preimage_buf.data(), output.data()); - - NT::fr const got_leaf = NT::fr::serialize_from_buffer(output.data()); - EXPECT_EQ(got_leaf, preimage.hash()); -} - -TEST(abi_tests, compute_transaction_hash) -{ - // Construct TxRequest with some randomized fields - TxRequest const tx_request = TxRequest{ - .origin = NT::fr::random_element(), - .function_data = FunctionData(), - .args_hash = NT::fr::random_element(), - .tx_context = TxContext(), - }; - - // Write the leaf preimage to a buffer - std::vector preimage_buf; - serialize::write(preimage_buf, tx_request); - - std::array output = { 0 }; - abis__compute_transaction_hash(preimage_buf.data(), output.data()); - - NT::fr const got_tx_hash = NT::fr::serialize_from_buffer(output.data()); - EXPECT_EQ(got_tx_hash, tx_request.hash()); -} - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/call_context.hpp b/circuits/cpp/src/aztec3/circuits/abis/call_context.hpp deleted file mode 100644 index fc50a3a562a..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/call_context.hpp +++ /dev/null @@ -1,127 +0,0 @@ -#pragma once - -#include "aztec3/circuits/abis/function_selector.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/msgpack_derived_equals.hpp" -#include "aztec3/utils/msgpack_derived_output.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct CallContext { - using address = typename NCT::address; - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - address msg_sender = 0; - address storage_contract_address = 0; - fr portal_contract_address = 0; - - FunctionSelector function_selector{}; - - boolean is_delegate_call = false; - boolean is_static_call = false; - boolean is_contract_deployment = false; - - // for serialization, update with new fields - MSGPACK_FIELDS(msg_sender, - storage_contract_address, - portal_contract_address, - function_selector, - is_delegate_call, - is_static_call, - is_contract_deployment); - boolean operator==(CallContext const& other) const - { - // we can't use =default with a custom boolean, but we can use a msgpack-derived utility - return utils::msgpack_derived_equals(*this, other); - }; - - template CallContext> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - CallContext> call_context = { - to_ct(msg_sender), - to_ct(storage_contract_address), - to_ct(portal_contract_address), - function_selector.to_circuit_type(builder), - to_ct(is_delegate_call), - to_ct(is_static_call), - to_ct(is_contract_deployment), - - }; - - return call_context; - }; - - template CallContext to_native_type() const - { - static_assert(std::is_same, NCT>::value); - auto to_native_type = [](T& e) { return e.template to_native_type(); }; - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - CallContext call_context = { - to_nt(msg_sender), - to_nt(storage_contract_address), - to_nt(portal_contract_address), - to_native_type(function_selector), - to_nt(is_delegate_call), - to_nt(is_static_call), - to_nt(is_contract_deployment), - }; - - return call_context; - }; - - fr hash() const - { - std::vector const inputs = { - msg_sender.to_field(), storage_contract_address.to_field(), - portal_contract_address, function_selector.to_field(), - fr(is_delegate_call), fr(is_static_call), - fr(is_contract_deployment), - }; - - return NCT::hash(inputs, GeneratorIndex::CALL_CONTEXT); - } - - template void assert_is_zero() - { - static_assert((std::is_same, NCT>::value)); - - msg_sender.to_field().assert_is_zero(); - storage_contract_address.to_field().assert_is_zero(); - portal_contract_address.assert_is_zero(); - function_selector.to_field().assert_is_zero(); - fr(is_delegate_call).assert_is_zero(); - fr(is_static_call).assert_is_zero(); - fr(is_contract_deployment).assert_is_zero(); - } - - void set_public() - { - static_assert(!(std::is_same::value)); - - msg_sender.to_field().set_public(); - storage_contract_address.to_field().set_public(); - portal_contract_address.set_public(); - function_selector.set_public(); - fr(is_delegate_call).set_public(); - fr(is_static_call).set_public(); - fr(is_contract_deployment).set_public(); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/call_stack_item.hpp b/circuits/cpp/src/aztec3/circuits/abis/call_stack_item.hpp deleted file mode 100644 index f964abe594a..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/call_stack_item.hpp +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once -#include "function_data.hpp" -#include "kernel_circuit_public_inputs.hpp" -#include "private_circuit_public_inputs.hpp" -#include "public_circuit_public_inputs.hpp" - -#include "aztec3/circuits/abis/types.hpp" -#include "aztec3/utils/msgpack_derived_equals.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template typename PrivatePublic> struct CallStackItem { - using address = typename NCT::address; - using boolean = typename NCT::boolean; - using fr = typename NCT::fr; - - // This is the _actual_ contract address relating to where this function's code resides in the - // contract tree. Regardless of whether this is a call or delegatecall, this - // `contract_address` _does not change_. Amongst other things, it's used as a lookup for - // getting the correct code from the tree. There is a separate `storage_contract_address` - // within a CallStackItem which varies depending on whether this is a call or delegatecall. - address contract_address = 0; - FunctionData function_data{}; - typename PrivatePublic::AppCircuitPublicInputs public_inputs{}; - // True if this call stack item represents a request to execute a function rather than a - // fulfilled execution. Used when enqueuing calls from private to public functions. - boolean is_execution_request = false; - - // for serialization, update with new fields - MSGPACK_FIELDS(contract_address, function_data, public_inputs, is_execution_request); - // for schema serialization - void msgpack_schema(auto& packer) const - { - packer.pack_with_name(PrivatePublic::schema_name + std::string("CallStackItem"), *this); // NOLINT - } - boolean operator==(CallContext const& other) const - { - // we can't use =default with a custom boolean, but we can use a msgpack-derived utility - return utils::msgpack_derived_equals(*this, other); - }; - - template - CallStackItem, PrivatePublic> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - CallStackItem, PrivatePublic> call_stack_item = { - to_ct(contract_address), - function_data.to_circuit_type(builder), - public_inputs.to_circuit_type(builder), - to_ct(is_execution_request), - }; - - return call_stack_item; - }; - - fr hash() const - { - const std::vector inputs = { - contract_address.to_field(), - function_data.hash(), - public_inputs.hash(), - }; - - // NOLINTNEXTLINE(misc-const-correctness) - fr call_stack_item_hash = NCT::hash(inputs, GeneratorIndex::CALL_STACK_ITEM); - - return call_stack_item_hash; - } -}; - -// Returns a copy of this call stack item where all result-related fields are zeroed out. -inline CallStackItem as_execution_request( - CallStackItem const& call_stack_item) -{ - return { - .contract_address = call_stack_item.contract_address, - .function_data = call_stack_item.function_data, - .public_inputs = { - .call_context = call_stack_item.public_inputs.call_context, - .args_hash = call_stack_item.public_inputs.args_hash, - }, - .is_execution_request = call_stack_item.is_execution_request, - }; -}; - -// Returns the hash of a call stack item, or if the call stack item represents an execution request, -// zeroes out all fields but those related to the request (contract, function data, call context, args) -// and then hashes the item. Implemented only for native types for now. -inline fr get_call_stack_item_hash(abis::CallStackItem const& call_stack_item) -{ - auto const& preimage = - call_stack_item.is_execution_request ? as_execution_request(call_stack_item) : call_stack_item; - return preimage.hash(); -} - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/combined_accumulated_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/combined_accumulated_data.hpp deleted file mode 100644 index e3e2800a69c..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/combined_accumulated_data.hpp +++ /dev/null @@ -1,230 +0,0 @@ -#pragma once -#include "new_contract_data.hpp" -#include "optionally_revealed_data.hpp" -#include "public_data_read.hpp" -#include "public_data_update_request.hpp" - -#include "aztec3/circuits/abis/membership_witness.hpp" -#include "aztec3/circuits/abis/read_request_membership_witness.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -#include -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct CombinedAccumulatedData { - using fr = typename NCT::fr; - using uint32 = typename NCT::uint32; - using boolean = typename NCT::boolean; - using AggregationObject = typename NCT::AggregationObject; - - AggregationObject aggregation_object{}; - - std::array read_requests{}; - - std::array new_commitments{}; - std::array new_nullifiers{}; - std::array nullified_commitments{}; - // For pending nullifiers, we have: - // nullifiedCommitments[j] != 0 <==> newNullifiers[j] nullifies nullifiedCommitments[j] - - std::array private_call_stack{}; - std::array public_call_stack{}; - std::array new_l2_to_l1_msgs{}; - - std::array encrypted_logs_hash{}; - std::array unencrypted_logs_hash{}; - - // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the - // variable-length data. - fr encrypted_log_preimages_length = 0; - fr unencrypted_log_preimages_length = 0; - - std::array, MAX_NEW_CONTRACTS_PER_TX> new_contracts{}; - - std::array, MAX_OPTIONALLY_REVEALED_DATA_LENGTH_PER_TX> optionally_revealed_data{}; - - std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX> public_data_update_requests{}; - std::array, MAX_PUBLIC_DATA_READS_PER_TX> public_data_reads{}; - - // for serialization, update with new fields - MSGPACK_FIELDS(aggregation_object, - read_requests, - new_commitments, - new_nullifiers, - nullified_commitments, - private_call_stack, - public_call_stack, - new_l2_to_l1_msgs, - encrypted_logs_hash, - unencrypted_logs_hash, - encrypted_log_preimages_length, - unencrypted_log_preimages_length, - new_contracts, - optionally_revealed_data, - public_data_update_requests, - public_data_reads); - boolean operator==(CombinedAccumulatedData const& other) const - { - return msgpack_derived_equals(*this, other); - }; - - template CombinedAccumulatedData> to_circuit_type(Builder& builder) const - { - typedef CircuitTypes CT; - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(builder); }; - - CombinedAccumulatedData acc_data = { - typename CT::AggregationObject{ - to_ct(aggregation_object.P0), - to_ct(aggregation_object.P1), - to_ct(aggregation_object.public_inputs), - aggregation_object.proof_witness_indices, - aggregation_object.has_data, - }, - - to_ct(read_requests), - - to_ct(new_commitments), - to_ct(new_nullifiers), - to_ct(nullified_commitments), - - to_ct(private_call_stack), - to_ct(public_call_stack), - to_ct(new_l2_to_l1_msgs), - - to_ct(encrypted_logs_hash), - to_ct(unencrypted_logs_hash), - - to_ct(encrypted_log_preimages_length), - to_ct(unencrypted_log_preimages_length), - - map(new_contracts, to_circuit_type), - map(optionally_revealed_data, to_circuit_type), - map(public_data_update_requests, to_circuit_type), - map(public_data_reads, to_circuit_type), - }; - - return acc_data; - }; - - template CombinedAccumulatedData to_native_type() const - { - static_assert(std::is_same, NCT>::value); - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - auto to_native_type = [](T& e) { return e.template to_native_type(); }; - - CombinedAccumulatedData acc_data = { - typename NativeTypes::AggregationObject{ - to_nt(aggregation_object.P0), - to_nt(aggregation_object.P1), - to_nt(aggregation_object.public_inputs), - aggregation_object.proof_witness_indices, - aggregation_object.has_data, - }, - - to_nt(read_requests), - - to_nt(new_commitments), - to_nt(new_nullifiers), - to_nt(nullified_commitments), - - to_nt(private_call_stack), - to_nt(public_call_stack), - to_nt(new_l2_to_l1_msgs), - - to_nt(encrypted_logs_hash), - to_nt(unencrypted_logs_hash), - - to_nt(encrypted_log_preimages_length), - to_nt(unencrypted_log_preimages_length), - - map(new_contracts, to_native_type), - map(optionally_revealed_data, to_native_type), - map(public_data_update_requests, to_native_type), - map(public_data_reads, to_native_type), - }; - return acc_data; - } - - void set_public() - { - static_assert(!(std::is_same::value)); - - aggregation_object.add_proof_outputs_as_public_inputs(); - - set_array_public(read_requests); - - set_array_public(new_commitments); - set_array_public(new_nullifiers); - set_array_public(nullified_commitments); - - set_array_public(private_call_stack); - set_array_public(public_call_stack); - set_array_public(new_l2_to_l1_msgs); - - set_array_public(encrypted_logs_hash); - set_array_public(unencrypted_logs_hash); - - set_array_public(new_contracts); - set_array_public(optionally_revealed_data); - set_array_public(public_data_update_requests); - set_array_public(public_data_reads); - } - - template void set_array_public(std::array& arr) - { - static_assert(!(std::is_same::value)); - for (T& e : arr) { - fr(e).set_public(); - } - } - - template void set_array_public(std::array, SIZE>& arr) - { - static_assert(!(std::is_same::value)); - for (auto& e : arr) { - e.set_public(); - } - } - - template void set_array_public(std::array, SIZE>& arr) - { - static_assert(!(std::is_same::value)); - for (auto& e : arr) { - e.set_public(); - } - } - - template void set_array_public(std::array, SIZE>& arr) - { - static_assert(!(std::is_same::value)); - for (auto& e : arr) { - e.set_public(); - } - } - - template void set_array_public(std::array, SIZE>& arr) - { - static_assert(!(std::is_same::value)); - for (auto& e : arr) { - e.set_public(); - } - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/combined_constant_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/combined_constant_data.hpp deleted file mode 100644 index 21d2aef29b4..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/combined_constant_data.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include "tx_context.hpp" - -#include "aztec3/circuits/abis/block_header.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::circuits::abis::BlockHeader; -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct CombinedConstantData { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - BlockHeader block_header{}; - TxContext tx_context{}; - - // for serialization: update up with new fields - MSGPACK_FIELDS(block_header, tx_context); - boolean operator==(CombinedConstantData const& other) const - { - return msgpack_derived_equals(*this, other); - } - - template CombinedConstantData> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - CombinedConstantData> constant_data = { - block_header.to_circuit_type(builder), - tx_context.to_circuit_type(builder), - }; - - return constant_data; - }; - - template CombinedConstantData to_native_type() const - { - static_assert(std::is_same, NCT>::value); - - auto to_native_type = [](T& e) { return e.template to_native_type(); }; - - CombinedConstantData constant_data = { - to_native_type(block_header), - to_native_type(tx_context), - }; - - return constant_data; - }; - - void set_public() - { - static_assert(!(std::is_same::value)); - - block_header.set_public(); - tx_context.set_public(); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/complete_address.hpp b/circuits/cpp/src/aztec3/circuits/abis/complete_address.hpp deleted file mode 100644 index e8bc16eb76e..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/complete_address.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#pragma once -#include "aztec3/circuits/abis/coordinate.hpp" -#include "aztec3/circuits/abis/point.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::circuits::compute_partial_address; -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct CompleteAddress { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - typename NCT::address address; - Point public_key; - fr partial_address; - - // for serialization, update with new fields - MSGPACK_FIELDS(address, public_key, partial_address); - bool operator==(CompleteAddress const&) const = default; - - template CompleteAddress> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - CompleteAddress> complete_address = { to_ct(address), - to_ct(public_key), - to_ct(partial_address) }; - - return complete_address; - }; - - template CompleteAddress to_native_type() const - { - static_assert((std::is_same, NCT>::value)); - - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - CompleteAddress complete_address = { to_nt(address), to_nt(public_key), to_nt(partial_address) }; - - return complete_address; - }; - - void set_public() - { - static_assert(!(std::is_same::value)); - - address.set_public(); - public_key.set_public(); - partial_address.set_public(); - } - - void assert_is_zero() - { - static_assert(!(std::is_same::value)); - - address.assert_is_zero(); - public_key.assert_is_zero(); - partial_address.assert_is_zero(); - } - - static CompleteAddress compute(Point const& point, - typename NCT::fr const& contract_address_salt, - typename NCT::fr const& function_tree_root, - typename NCT::fr const& constructor_hash) - { - using fr = typename NCT::fr; - - const fr partial_address = - compute_partial_address(contract_address_salt, function_tree_root, constructor_hash); - - CompleteAddress complete_address; - complete_address.address = compute_contract_address_from_partial(point, partial_address); - complete_address.public_key = point; - complete_address.partial_address = partial_address; - - return complete_address; - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/contract_deployment_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/contract_deployment_data.hpp deleted file mode 100644 index f351d5bfe9b..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/contract_deployment_data.hpp +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once -#include "aztec3/circuits/abis/point.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct ContractDeploymentData { - using address = typename NCT::address; - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - Point deployer_public_key; - fr constructor_vk_hash = 0; - fr function_tree_root = 0; - fr contract_address_salt = 0; - address portal_contract_address = 0; - - // for serialization: update up with new fields - MSGPACK_FIELDS( - deployer_public_key, constructor_vk_hash, function_tree_root, contract_address_salt, portal_contract_address); - - boolean operator==(ContractDeploymentData const& other) const - { - return deployer_public_key == other.deployer_public_key && constructor_vk_hash == other.constructor_vk_hash && - function_tree_root == other.function_tree_root && contract_address_salt == other.contract_address_salt && - portal_contract_address == other.portal_contract_address; - }; - - template ContractDeploymentData> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - ContractDeploymentData> data = { - deployer_public_key.to_circuit_type(builder), - to_ct(constructor_vk_hash), - to_ct(function_tree_root), - to_ct(contract_address_salt), - to_ct(portal_contract_address), - }; - - return data; - }; - - template ContractDeploymentData to_native_type() const - { - static_assert(std::is_same, NCT>::value); - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - auto to_native_type = [](T& e) { return e.template to_native_type(); }; - - ContractDeploymentData call_context = { - to_native_type(deployer_public_key), to_nt(constructor_vk_hash), to_nt(function_tree_root), - to_nt(contract_address_salt), to_nt(portal_contract_address), - }; - - return call_context; - }; - - template void assert_is_zero() - { - static_assert((std::is_same, NCT>::value)); - - deployer_public_key.assert_is_zero(); - constructor_vk_hash.assert_is_zero(); - function_tree_root.assert_is_zero(); - contract_address_salt.assert_is_zero(); - portal_contract_address.to_field().assert_is_zero(); - } - - void set_public() - { - static_assert(!(std::is_same::value)); - - deployer_public_key.set_public(); - constructor_vk_hash.set_public(); - function_tree_root.set_public(); - contract_address_salt.set_public(); - portal_contract_address.to_field().set_public(); - } - - fr hash() const - { - std::vector const inputs = { - deployer_public_key.x, deployer_public_key.y, constructor_vk_hash, - function_tree_root, contract_address_salt, portal_contract_address.to_field(), - }; - - return NCT::hash(inputs, GeneratorIndex::CONTRACT_DEPLOYMENT_DATA); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/contract_storage_read.hpp b/circuits/cpp/src/aztec3/circuits/abis/contract_storage_read.hpp deleted file mode 100644 index 0748759a494..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/contract_storage_read.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using plonk::stdlib::witness_t; - -template struct ContractStorageRead { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - fr storage_slot = 0; - fr current_value = 0; - - // for serialization, update with new fields - MSGPACK_FIELDS(storage_slot, current_value); - bool operator==(ContractStorageRead const&) const = default; - - template ContractStorageRead> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - ContractStorageRead> contract_storage_read = { - to_ct(storage_slot), - to_ct(current_value), - }; - - return contract_storage_read; - }; - - template ContractStorageRead to_native_type() const - { - static_assert((std::is_same, NCT>::value)); - - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - ContractStorageRead contract_storage_read = { - to_nt(storage_slot), - to_nt(current_value), - }; - - return contract_storage_read; - }; - - fr hash() const - { - std::vector const inputs = { - storage_slot, - current_value, - }; - - return NCT::hash(inputs, GeneratorIndex::PUBLIC_DATA_READ); - } - - void set_public() - { - static_assert(!(std::is_same::value)); - - storage_slot.set_public(); - current_value.set_public(); - } - - boolean is_empty() const { return storage_slot == 0; } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/contract_storage_update_request.hpp b/circuits/cpp/src/aztec3/circuits/abis/contract_storage_update_request.hpp deleted file mode 100644 index ea0e66df800..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/contract_storage_update_request.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once -#include "aztec3/utils/msgpack_derived_output.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using plonk::stdlib::witness_t; - -template struct ContractStorageUpdateRequest { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - fr storage_slot = 0; - fr old_value = 0; - fr new_value = 0; - - // for serialization, update with new fields - MSGPACK_FIELDS(storage_slot, old_value, new_value); - bool operator==(ContractStorageUpdateRequest const&) const = default; - template - ContractStorageUpdateRequest> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - ContractStorageUpdateRequest> update_request = { - to_ct(storage_slot), - to_ct(old_value), - to_ct(new_value), - }; - - return update_request; - }; - - template ContractStorageUpdateRequest to_native_type() const - { - static_assert((std::is_same, NCT>::value)); - - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - ContractStorageUpdateRequest update_request = { - to_nt(storage_slot), - to_nt(old_value), - to_nt(new_value), - }; - - return update_request; - }; - - fr hash() const - { - std::vector const inputs = { - storage_slot, - old_value, - new_value, - }; - - return NCT::hash(inputs, GeneratorIndex::PUBLIC_DATA_UPDATE_REQUEST); - } - - void set_public() - { - static_assert(!(std::is_same::value)); - - storage_slot.set_public(); - old_value.set_public(); - new_value.set_public(); - } - - boolean is_empty() const { return storage_slot == 0; } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/coordinate.hpp b/circuits/cpp/src/aztec3/circuits/abis/coordinate.hpp deleted file mode 100644 index 446ab45628d..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/coordinate.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::GeneratorIndex; -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct Coordinate { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - std::array fields; - - // for serialization, update with new fields - MSGPACK_FIELDS(fields); - bool operator==(Coordinate const&) const = default; - - template Coordinate> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - Coordinate> coordinate = { - to_ct(fields), - }; - - return coordinate; - }; - - template Coordinate to_native_type() const - { - static_assert((std::is_same, NCT>::value)); - - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - Coordinate coordinate = { - to_nt(fields), - }; - - return coordinate; - }; - - void set_public() - { - static_assert(!(std::is_same::value)); - - fields[0].set_public(); - fields[1].set_public(); - } - - void assert_is_zero() - { - static_assert(!(std::is_same::value)); - - fields[0].assert_is_zero(); - fields[1].assert_is_zero(); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/final_accumulated_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/final_accumulated_data.hpp deleted file mode 100644 index 9aba003e806..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/final_accumulated_data.hpp +++ /dev/null @@ -1,194 +0,0 @@ -#pragma once -#include "new_contract_data.hpp" -#include "optionally_revealed_data.hpp" -#include "public_data_read.hpp" -#include "public_data_update_request.hpp" - -#include "aztec3/circuits/abis/membership_witness.hpp" -#include "aztec3/circuits/abis/read_request_membership_witness.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -#include -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct FinalAccumulatedData { - using fr = typename NCT::fr; - using uint32 = typename NCT::uint32; - using boolean = typename NCT::boolean; - using AggregationObject = typename NCT::AggregationObject; - - AggregationObject aggregation_object{}; - - std::array new_commitments{}; - std::array new_nullifiers{}; - std::array nullified_commitments{}; - // For pending nullifiers, we have: - // nullifiedCommitments[j] != 0 <==> newNullifiers[j] nullifies nullifiedCommitments[j] - - std::array private_call_stack{}; - std::array public_call_stack{}; - std::array new_l2_to_l1_msgs{}; - - std::array encrypted_logs_hash{}; - std::array unencrypted_logs_hash{}; - - // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the - // variable-length data. - fr encrypted_log_preimages_length = 0; - fr unencrypted_log_preimages_length = 0; - - std::array, MAX_NEW_CONTRACTS_PER_TX> new_contracts{}; - - std::array, MAX_OPTIONALLY_REVEALED_DATA_LENGTH_PER_TX> optionally_revealed_data{}; - - // for serialization, update with new fields - MSGPACK_FIELDS(aggregation_object, - new_commitments, - new_nullifiers, - nullified_commitments, - private_call_stack, - public_call_stack, - new_l2_to_l1_msgs, - encrypted_logs_hash, - unencrypted_logs_hash, - encrypted_log_preimages_length, - unencrypted_log_preimages_length, - new_contracts, - optionally_revealed_data); - boolean operator==(FinalAccumulatedData const& other) const - { - return msgpack_derived_equals(*this, other); - }; - - template FinalAccumulatedData> to_circuit_type(Builder& builder) const - { - typedef CircuitTypes CT; - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(builder); }; - - FinalAccumulatedData acc_data = { - typename CT::AggregationObject{ - to_ct(aggregation_object.P0), - to_ct(aggregation_object.P1), - to_ct(aggregation_object.public_inputs), - aggregation_object.proof_witness_indices, - aggregation_object.has_data, - }, - - to_ct(new_commitments), - to_ct(new_nullifiers), - to_ct(nullified_commitments), - - to_ct(private_call_stack), - to_ct(public_call_stack), - to_ct(new_l2_to_l1_msgs), - - to_ct(encrypted_logs_hash), - to_ct(unencrypted_logs_hash), - - to_ct(encrypted_log_preimages_length), - to_ct(unencrypted_log_preimages_length), - - map(new_contracts, to_circuit_type), - map(optionally_revealed_data, to_circuit_type), - }; - - return acc_data; - }; - - template FinalAccumulatedData to_native_type() const - { - static_assert(std::is_same, NCT>::value); - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - auto to_native_type = [](T& e) { return e.template to_native_type(); }; - - FinalAccumulatedData acc_data = { - typename NativeTypes::AggregationObject{ - to_nt(aggregation_object.P0), - to_nt(aggregation_object.P1), - to_nt(aggregation_object.public_inputs), - aggregation_object.proof_witness_indices, - aggregation_object.has_data, - }, - - to_nt(new_commitments), - to_nt(new_nullifiers), - to_nt(nullified_commitments), - - to_nt(private_call_stack), - to_nt(public_call_stack), - to_nt(new_l2_to_l1_msgs), - - to_nt(encrypted_logs_hash), - to_nt(unencrypted_logs_hash), - - to_nt(encrypted_log_preimages_length), - to_nt(unencrypted_log_preimages_length), - - map(new_contracts, to_native_type), - map(optionally_revealed_data, to_native_type), - }; - return acc_data; - } - - void set_public() - { - static_assert(!(std::is_same::value)); - - aggregation_object.add_proof_outputs_as_public_inputs(); - - set_array_public(new_commitments); - set_array_public(new_nullifiers); - set_array_public(nullified_commitments); - - set_array_public(private_call_stack); - set_array_public(public_call_stack); - set_array_public(new_l2_to_l1_msgs); - - set_array_public(encrypted_logs_hash); - set_array_public(unencrypted_logs_hash); - - set_array_public(new_contracts); - set_array_public(optionally_revealed_data); - } - - template void set_array_public(std::array& arr) - { - static_assert(!(std::is_same::value)); - for (T& e : arr) { - fr(e).set_public(); - } - } - - template void set_array_public(std::array, SIZE>& arr) - { - static_assert(!(std::is_same::value)); - for (auto& e : arr) { - e.set_public(); - } - } - - template void set_array_public(std::array, SIZE>& arr) - { - static_assert(!(std::is_same::value)); - for (auto& e : arr) { - e.set_public(); - } - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/function_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/function_data.hpp deleted file mode 100644 index 784aa4691d0..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/function_data.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once - -#include "aztec3/circuits/abis/function_selector.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -namespace aztec3::circuits::abis { - -// using plonk::stdlib::witness_t; -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct FunctionData { - using uint32 = typename NCT::uint32; - using boolean = typename NCT::boolean; - using fr = typename NCT::fr; - - FunctionSelector selector; - boolean is_internal = false; - boolean is_private = false; - boolean is_constructor = false; - - MSGPACK_FIELDS(selector, is_internal, is_private, is_constructor); - - boolean operator==(FunctionData const& other) const - { - return selector == other.selector && is_internal == other.is_internal && is_private == other.is_private && - is_constructor == other.is_constructor; - }; - - template FunctionData> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - FunctionData> function_data = { - selector.to_circuit_type(builder), - to_ct(is_internal), - to_ct(is_private), - to_ct(is_constructor), - }; - - return function_data; - }; - - template FunctionData to_native_type() const - { - static_assert(std::is_same, NCT>::value); - auto to_native_type = [](T& e) { return e.template to_native_type(); }; - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - FunctionData function_data = { - to_native_type(selector), - to_nt(is_internal), - to_nt(is_private), - to_nt(is_constructor), - }; - - return function_data; - }; - - void set_public() - { - static_assert(!(std::is_same::value)); - - selector.set_public(); - fr(is_internal).set_public(); - fr(is_private).set_public(); - fr(is_constructor).set_public(); - } - - // TODO: this can all be packed into 1 field element, so this `hash` function should just return that field element. - fr hash() const - { - std::vector const inputs = { - fr(selector.value), - fr(is_internal), - fr(is_private), - fr(is_constructor), - }; - - return NCT::hash(inputs, GeneratorIndex::FUNCTION_DATA); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/function_leaf_preimage.hpp b/circuits/cpp/src/aztec3/circuits/abis/function_leaf_preimage.hpp deleted file mode 100644 index f1461cea4b5..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/function_leaf_preimage.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#pragma once - -#include "aztec3/circuits/abis/function_selector.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -/** - * @brief A struct representing the "preimage" of a function tree leaf. - * Templated on NativeTypes/CircuitTypes. - * - * @details A FunctionLeafPreimage contains: - * - `selector` keccak hash of function signature truncated to NUM_FUNCTION_SELECTOR_BYTES - * - `is_private` boolean flag - * - `vk_hash` pedersen hash of the function verification key - * - `acir_hash` hash of the function's acir bytecode - * This struct includes a `hash()` function for computing its pedersen compression. - * There are also static functions for: - * - converting preimages between native/circuit types - * - serializing and deserializing preimages - * - writing a preimage to an ostream - */ -template struct FunctionLeafPreimage { - using boolean = typename NCT::boolean; - using fr = typename NCT::fr; - using uint32 = typename NCT::uint32; - - FunctionSelector selector = {}; - boolean is_internal = false; - boolean is_private = false; - fr vk_hash = 0; - fr acir_hash = 0; - - // For serialization, update with new fields - MSGPACK_FIELDS(selector, is_internal, is_private, vk_hash, acir_hash); - - boolean operator==(FunctionLeafPreimage const& other) const - { - return selector == other.selector && is_internal == other.is_internal && is_private == other.is_private && - vk_hash == other.vk_hash && acir_hash == other.acir_hash; - }; - - template FunctionLeafPreimage> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - FunctionLeafPreimage> preimage = { - selector.to_circuit_type(builder), to_ct(is_internal), to_ct(is_private), to_ct(vk_hash), to_ct(acir_hash), - }; - - return preimage; - }; - - template FunctionLeafPreimage to_native_type() const - { - static_assert(std::is_same, NCT>::value); - auto to_native_type = [](T& e) { return e.template to_native_type(); }; - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - FunctionLeafPreimage preimage = { - to_native_type(selector), to_nt(is_internal), to_nt(is_private), to_nt(vk_hash), to_nt(acir_hash), - }; - - return preimage; - }; - - void set_public() - { - static_assert(!(std::is_same::value)); - - selector.set_public(); - fr(is_internal).set_public(); - fr(is_private).set_public(); - vk_hash.set_public(); - acir_hash.set_public(); - } - - fr hash() const - { - std::vector const inputs = { - selector.value, fr(is_internal), fr(is_private), vk_hash, acir_hash, - }; - return NCT::hash(inputs, GeneratorIndex::FUNCTION_LEAF); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/function_selector.hpp b/circuits/cpp/src/aztec3/circuits/abis/function_selector.hpp deleted file mode 100644 index 6506b9a40cd..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/function_selector.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include "barretenberg/serialize/msgpack.hpp" - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct FunctionSelector { - using uint32 = typename NCT::uint32; - using boolean = typename NCT::boolean; - using fr = typename NCT::fr; - - uint32 value; // e.g. 1st 4-bytes of abi-encoding of function. - - MSGPACK_FIELDS(value); - - boolean operator==(FunctionSelector const& other) const { return value == other.value; }; - - template FunctionSelector> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - FunctionSelector> selector = { - to_ct(value), - }; - - return selector; - }; - - template FunctionSelector to_native_type() const - { - static_assert(std::is_same, NCT>::value); - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - FunctionSelector selector = { - to_nt(value), - }; - - return selector; - }; - - fr to_field() const { return fr(value); } - - void set_public() - { - static_assert(!(std::is_same::value)); - - fr(value).set_public(); - } -}; - -} // namespace aztec3::circuits::abis \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/global_variables.hpp b/circuits/cpp/src/aztec3/circuits/abis/global_variables.hpp deleted file mode 100644 index 79442dfed58..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/global_variables.hpp +++ /dev/null @@ -1,88 +0,0 @@ -#pragma once -#include "function_data.hpp" -#include "tx_context.hpp" - -#include "aztec3/utils/array.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct GlobalVariables { - using address = typename NCT::address; - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - fr chain_id = 0; - fr version = 0; - fr block_number = 0; - fr timestamp = 0; - - // For serialization, update with new fields - MSGPACK_FIELDS(chain_id, version, block_number, timestamp); - - boolean operator==(GlobalVariables const& other) const - { - return chain_id == other.chain_id && version == other.version && block_number == other.block_number && - timestamp == other.timestamp; - }; - - /** - * @brief Returns an object containing all global variables set to zero. - * - * @return GlobalVariables - */ - static GlobalVariables empty() - { - GlobalVariables globals = { 0, 0, 0, 0 }; - return globals; - } - - template GlobalVariables> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(builder); }; - - GlobalVariables> globals = { - to_ct(chain_id), - to_ct(version), - to_ct(block_number), - to_ct(timestamp), - }; - - return globals; - }; - - - fr hash() const - { - std::vector inputs; - inputs.push_back(chain_id); - inputs.push_back(version); - inputs.push_back(block_number); - inputs.push_back(timestamp); - - return NCT::hash(inputs, GeneratorIndex::GLOBAL_VARIABLES); - } - - void set_public() - { - static_assert(!(std::is_same::value)); - - chain_id.set_public(); - version.set_public(); - block_number.set_public(); - timestamp.set_public(); - } -}; // namespace aztec3::circuits::abis - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/index.hpp b/circuits/cpp/src/aztec3/circuits/abis/index.hpp deleted file mode 100644 index dc500bbe9a7..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/index.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "call_context.hpp" -#include "call_stack_item.hpp" -#include "contract_storage_read.hpp" -#include "contract_storage_update_request.hpp" -#include "function_data.hpp" -#include "private_circuit_public_inputs.hpp" \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/kernel_circuit_public_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/kernel_circuit_public_inputs.hpp deleted file mode 100644 index d14a11eb796..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/kernel_circuit_public_inputs.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once -#include "combined_accumulated_data.hpp" -#include "combined_constant_data.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct KernelCircuitPublicInputs { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - CombinedAccumulatedData end{}; - CombinedConstantData constants{}; - - boolean is_private = true; // TODO: might need to instantiate from witness! - - // for serialization, update with new fields - MSGPACK_FIELDS(end, constants, is_private); - - boolean operator==(KernelCircuitPublicInputs const& other) const - { - return msgpack_derived_equals(*this, other); - }; - - template KernelCircuitPublicInputs> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - KernelCircuitPublicInputs> private_inputs = { - end.to_circuit_type(builder), - constants.to_circuit_type(builder), - - to_ct(is_private), - }; - - return private_inputs; - }; - - template KernelCircuitPublicInputs to_native_type() const - { - static_assert(std::is_same, NCT>::value); - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - auto to_native_type = [](T& e) { return e.template to_native_type(); }; - - KernelCircuitPublicInputs pis = { - to_native_type(end), - to_native_type(constants), - - to_nt(is_private), - }; - - return pis; - }; - - void set_public() - { - static_assert(!(std::is_same::value)); - - end.set_public(); - constants.set_public(); - - fr(is_private).set_public(); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/kernel_circuit_public_inputs_final.hpp b/circuits/cpp/src/aztec3/circuits/abis/kernel_circuit_public_inputs_final.hpp deleted file mode 100644 index 90ce25eedd2..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/kernel_circuit_public_inputs_final.hpp +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once -#include "combined_constant_data.hpp" -#include "final_accumulated_data.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct KernelCircuitPublicInputsFinal { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - FinalAccumulatedData end{}; - CombinedConstantData constants{}; - - boolean is_private = true; // TODO: might need to instantiate from witness! - - // for serialization, update with new fields - MSGPACK_FIELDS(end, constants, is_private); - - boolean operator==(KernelCircuitPublicInputsFinal const& other) const - { - return msgpack_derived_equals(*this, other); - } - - template - KernelCircuitPublicInputsFinal> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - KernelCircuitPublicInputsFinal> private_inputs = { - end.to_circuit_type(builder), - constants.to_circuit_type(builder), - - to_ct(is_private), - }; - - return private_inputs; - }; - - template KernelCircuitPublicInputsFinal to_native_type() const - { - static_assert(std::is_same, NCT>::value); - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - auto to_native_type = [](T& e) { return e.template to_native_type(); }; - - KernelCircuitPublicInputsFinal pis = { - to_native_type(end), - to_native_type(constants), - - to_nt(is_private), - }; - - return pis; - }; - - void set_public() - { - static_assert(!(std::is_same::value)); - - end.set_public(); - constants.set_public(); - - fr(is_private).set_public(); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/membership_witness.hpp b/circuits/cpp/src/aztec3/circuits/abis/membership_witness.hpp deleted file mode 100644 index 45ad4680b2d..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/membership_witness.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once - -#include "aztec3/utils/array.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" - -namespace aztec3::circuits::abis { - -using aztec3::utils::is_array_empty; -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct MembershipWitness { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - fr leaf_index = 0; - std::array sibling_path{}; - - MSGPACK_FIELDS(leaf_index, sibling_path); - // for schema serialization - void msgpack_schema(auto& packer) const { packer.pack_with_name("MembershipWitness" + std::to_string(N), *this); } - boolean operator==(MembershipWitness const& other) const - { - return leaf_index == other.leaf_index && sibling_path == other.sibling_path; - }; - - template MembershipWitness, N> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - MembershipWitness, N> witness = { - to_ct(leaf_index), - map(sibling_path, to_ct), - }; - - return witness; - } - - template MembershipWitness to_native_type() const - { - static_assert((std::is_same, NCT>::value)); - - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - MembershipWitness witness = { - to_nt(leaf_index), - map(sibling_path, to_nt), - }; - - return witness; - } - - void set_public() - { - static_assert(!(std::is_same::value)); - - leaf_index.set_public(); - for (fr const& e : sibling_path) { - e.set_public(); - } - } - - boolean is_empty() const { return aztec3::utils::is_empty(leaf_index) && is_array_empty(sibling_path); } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/new_contract_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/new_contract_data.hpp deleted file mode 100644 index 4933e7716ce..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/new_contract_data.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once - -#include "aztec3/constants.hpp" -#include "aztec3/utils/msgpack_derived_equals.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct NewContractData { - using address = typename NCT::address; - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - address contract_address = 0; - address portal_contract_address = 0; - fr function_tree_root = 0; - // for serialization, update with new fields - MSGPACK_FIELDS(contract_address, portal_contract_address, function_tree_root); - - boolean operator==(NewContractData const& other) const - { - // we can't use =default with a custom boolean, but we can use a msgpack-derived utility - return utils::msgpack_derived_equals(*this, other); - }; - - template NewContractData> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - NewContractData> new_contract_data = { to_ct(contract_address), - to_ct(portal_contract_address), - to_ct(function_tree_root) }; - - return new_contract_data; - }; - - template NewContractData to_native_type() const - { - static_assert(std::is_same, NCT>::value); - - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - NewContractData new_contract_data = { to_nt(contract_address), - to_nt(portal_contract_address), - to_nt(function_tree_root) }; - - return new_contract_data; - }; - - boolean is_empty() const - { - return ((contract_address.to_field().is_zero()) && (portal_contract_address.to_field().is_zero()) && - (function_tree_root.is_zero())); - } - - void set_public() - { - static_assert(!(std::is_same::value)); - - contract_address.to_field().set_public(); - portal_contract_address.to_field().set_public(); - function_tree_root.set_public(); - } - - fr hash() const - { - // as per the circuit implementation, if contract address == zero then return a zero leaf - if (is_empty()) { - return fr::zero(); - } - std::vector const inputs = { - fr(contract_address), - fr(portal_contract_address), - fr(function_tree_root), - }; - - return NCT::hash(inputs, GeneratorIndex::CONTRACT_LEAF); - } - - void conditional_select(const boolean& condition, const NewContractData& other) - { - contract_address = address::conditional_assign(condition, other.contract_address, contract_address); - portal_contract_address = - address::conditional_assign(condition, other.portal_contract_address, portal_contract_address); - function_tree_root = fr::conditional_assign(condition, other.function_tree_root, function_tree_root); - } -}; - -template using ContractLeafPreimage = NewContractData; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/optionally_revealed_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/optionally_revealed_data.hpp deleted file mode 100644 index 41e118d6049..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/optionally_revealed_data.hpp +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once -#include "function_data.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct OptionallyRevealedData { - using address = typename NCT::address; - using boolean = typename NCT::boolean; - using fr = typename NCT::fr; - - fr call_stack_item_hash = 0; - FunctionData function_data{}; - fr vk_hash = 0; - address portal_contract_address = 0; - boolean pay_fee_from_l1 = false; - boolean pay_fee_from_public_l2 = false; - boolean called_from_l1 = false; - boolean called_from_public_l2 = false; - - // for serialization: update up with new fields - MSGPACK_FIELDS(call_stack_item_hash, - function_data, - vk_hash, - portal_contract_address, - pay_fee_from_l1, - pay_fee_from_public_l2, - called_from_l1, - called_from_public_l2); - boolean operator==(OptionallyRevealedData const& other) const - { - return call_stack_item_hash == other.call_stack_item_hash && function_data == other.function_data && - vk_hash == other.vk_hash && portal_contract_address == other.portal_contract_address && - pay_fee_from_l1 == other.pay_fee_from_l1 && pay_fee_from_public_l2 == other.pay_fee_from_public_l2 && - called_from_l1 == other.called_from_l1 && called_from_public_l2 == other.called_from_public_l2; - }; - - template OptionallyRevealedData> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - OptionallyRevealedData> data = { - to_ct(call_stack_item_hash), - function_data.to_circuit_type(builder), - to_ct(vk_hash), - to_ct(portal_contract_address), - to_ct(pay_fee_from_l1), - to_ct(pay_fee_from_public_l2), - to_ct(called_from_l1), - to_ct(called_from_public_l2), - }; - - return data; - }; - - template OptionallyRevealedData to_native_type() const - { - static_assert(std::is_same, NCT>::value); - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - auto to_native_type = [](T& e) { return e.template to_native_type(); }; - - OptionallyRevealedData data = { - to_nt(call_stack_item_hash), to_native_type(function_data), to_nt(vk_hash), - to_nt(portal_contract_address), to_nt(pay_fee_from_l1), to_nt(pay_fee_from_public_l2), - to_nt(called_from_l1), to_nt(called_from_public_l2), - }; - - return data; - }; - - void set_public() - { - static_assert(!(std::is_same::value)); - - call_stack_item_hash.set_public(); - function_data.set_public(); - vk_hash.set_public(); - portal_contract_address.to_field().set_public(); - fr(pay_fee_from_l1).set_public(); - fr(pay_fee_from_public_l2).set_public(); - fr(called_from_l1).set_public(); - fr(called_from_public_l2).set_public(); - } - - template void set_array_public(std::array& arr) - { - static_assert(!(std::is_same::value)); - for (T& e : arr) { - fr(e).set_public(); - } - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/packers.hpp b/circuits/cpp/src/aztec3/circuits/abis/packers.hpp deleted file mode 100644 index 45291c516ac..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/packers.hpp +++ /dev/null @@ -1,230 +0,0 @@ -#pragma once -#include "msgpack/v3/adaptor/detail/cpp11_define_map_decl.hpp" - -#include "aztec3/constants.hpp" - -#include "barretenberg/serialize/msgpack_impl/name_value_pair_macro.hpp" - -namespace aztec3::circuits::abis { - -// Represents constants during serialization (only) -struct ConstantsPacker { - template void msgpack_pack(Packer& packer) const - { - auto pack = [&](auto&... args) { - msgpack::type::define_map{ args... }.msgpack_pack(packer); - }; - - // Note: NVP macro can handle up to 30 arguments so we call it multiple times here. If adding a new constant - // add it to the last call or introduce a new one if the last call is already "full". - pack(NVP(ARGS_LENGTH, - RETURN_VALUES_LENGTH, - MAX_NEW_COMMITMENTS_PER_CALL, - MAX_NEW_NULLIFIERS_PER_CALL, - MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - MAX_NEW_L2_TO_L1_MSGS_PER_CALL, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, - MAX_PUBLIC_DATA_READS_PER_CALL, - MAX_READ_REQUESTS_PER_CALL, - MAX_NEW_COMMITMENTS_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, - MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_PUBLIC_DATA_READS_PER_TX, - MAX_NEW_CONTRACTS_PER_TX, - MAX_OPTIONALLY_REVEALED_DATA_LENGTH_PER_TX, - MAX_READ_REQUESTS_PER_TX), - NVP(NUM_ENCRYPTED_LOGS_HASHES_PER_TX, - NUM_UNENCRYPTED_LOGS_HASHES_PER_TX, - NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, - KERNELS_PER_BASE_ROLLUP, - MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP, - MAX_PUBLIC_DATA_READS_PER_BASE_ROLLUP, - VK_TREE_HEIGHT, - FUNCTION_TREE_HEIGHT, - CONTRACT_TREE_HEIGHT, - NOTE_HASH_TREE_HEIGHT, - PUBLIC_DATA_TREE_HEIGHT, - NULLIFIER_TREE_HEIGHT, - L1_TO_L2_MSG_TREE_HEIGHT, - ROLLUP_VK_TREE_HEIGHT, - CONTRACT_SUBTREE_HEIGHT, - CONTRACT_SUBTREE_SIBLING_PATH_LENGTH, - NOTE_HASH_SUBTREE_HEIGHT, - NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, - NULLIFIER_SUBTREE_HEIGHT, - ARCHIVE_HEIGHT, - NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, - L1_TO_L2_MSG_SUBTREE_HEIGHT), - NVP(L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, - FUNCTION_SELECTOR_NUM_BYTES, - MAPPING_SLOT_PEDERSEN_SEPARATOR, - NUM_FIELDS_PER_SHA256, - L1_TO_L2_MESSAGE_LENGTH, - L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH, - MAX_NOTE_FIELDS_LENGTH, - GET_NOTE_ORACLE_RETURN_LENGTH, - MAX_NOTES_PER_PAGE, - VIEW_NOTE_ORACLE_RETURN_LENGTH, - CALL_CONTEXT_LENGTH, - BLOCK_HEADER_LENGTH, - FUNCTION_DATA_LENGTH, - CONTRACT_DEPLOYMENT_DATA_LENGTH, - PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, - CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH, - CONTRACT_STORAGE_READ_LENGTH, - PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, - GET_NOTES_ORACLE_RETURN_LENGTH, - EMPTY_NULLIFIED_COMMITMENT), - NVP(CALL_PRIVATE_FUNCTION_RETURN_SIZE, - PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH, - PRIVATE_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH, - KERNELS_PER_BASE_ROLLUP, - COMMITMENTS_NUM_BYTES_PER_BASE_ROLLUP, - NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP, - PUBLIC_DATA_WRITES_NUM_BYTES_PER_BASE_ROLLUP, - CONTRACTS_NUM_BYTES_PER_BASE_ROLLUP, - CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP, - CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP_UNPADDED, - L2_TO_L1_MSGS_NUM_BYTES_PER_BASE_ROLLUP, - LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP)); // <-- Add names of new constants here - } -}; - -struct GeneratorIndexPacker { - template void msgpack_pack(Packer& packer) const - { - auto pack = [&](auto&... args) { - msgpack::type::define_map{ args... }.msgpack_pack(packer); - }; - - int COMMITMENT = GeneratorIndex::COMMITMENT; - int COMMITMENT_NONCE = GeneratorIndex::COMMITMENT_NONCE; - int UNIQUE_COMMITMENT = GeneratorIndex::UNIQUE_COMMITMENT; - int SILOED_COMMITMENT = GeneratorIndex::SILOED_COMMITMENT; - int NULLIFIER = GeneratorIndex::NULLIFIER; - int INITIALIZATION_NULLIFIER = GeneratorIndex::INITIALIZATION_NULLIFIER; - int OUTER_NULLIFIER = GeneratorIndex::OUTER_NULLIFIER; - int PUBLIC_DATA_READ = GeneratorIndex::PUBLIC_DATA_READ; - int PUBLIC_DATA_UPDATE_REQUEST = GeneratorIndex::PUBLIC_DATA_UPDATE_REQUEST; - int FUNCTION_DATA = GeneratorIndex::FUNCTION_DATA; - int FUNCTION_LEAF = GeneratorIndex::FUNCTION_LEAF; - int CONTRACT_DEPLOYMENT_DATA = GeneratorIndex::CONTRACT_DEPLOYMENT_DATA; - int CONSTRUCTOR = GeneratorIndex::CONSTRUCTOR; - int CONSTRUCTOR_ARGS = GeneratorIndex::CONSTRUCTOR_ARGS; - int CONTRACT_ADDRESS = GeneratorIndex::CONTRACT_ADDRESS; - int CONTRACT_LEAF = GeneratorIndex::CONTRACT_LEAF; - int CALL_CONTEXT = GeneratorIndex::CALL_CONTEXT; - int CALL_STACK_ITEM = GeneratorIndex::CALL_STACK_ITEM; - int CALL_STACK_ITEM_2 = GeneratorIndex::CALL_STACK_ITEM_2; - int L1_TO_L2_MESSAGE_SECRET = GeneratorIndex::L1_TO_L2_MESSAGE_SECRET; - int L2_TO_L1_MSG = GeneratorIndex::L2_TO_L1_MSG; - int TX_CONTEXT = GeneratorIndex::TX_CONTEXT; - int PUBLIC_LEAF_INDEX = GeneratorIndex::PUBLIC_LEAF_INDEX; - int PUBLIC_DATA_LEAF = GeneratorIndex::PUBLIC_DATA_LEAF; - int SIGNED_TX_REQUEST = GeneratorIndex::SIGNED_TX_REQUEST; - int GLOBAL_VARIABLES = GeneratorIndex::GLOBAL_VARIABLES; - int PARTIAL_ADDRESS = GeneratorIndex::PARTIAL_ADDRESS; - int BLOCK_HASH = GeneratorIndex::BLOCK_HASH; - int SIDE_EFFECT = GeneratorIndex::SIDE_EFFECT; - int TX_REQUEST = GeneratorIndex::TX_REQUEST; - int SIGNATURE_PAYLOAD = GeneratorIndex::SIGNATURE_PAYLOAD; - int VK = GeneratorIndex::VK; - int PRIVATE_CIRCUIT_PUBLIC_INPUTS = GeneratorIndex::PRIVATE_CIRCUIT_PUBLIC_INPUTS; - int PUBLIC_CIRCUIT_PUBLIC_INPUTS = GeneratorIndex::PUBLIC_CIRCUIT_PUBLIC_INPUTS; - int FUNCTION_ARGS = GeneratorIndex::FUNCTION_ARGS; - - - // Note: NVP macro can handle up to 20 arguments so we call it multiple times here. If adding a new constant - // add it to the last call or introduce a new one if the last call is already "full". - pack(NVP(COMMITMENT, - COMMITMENT_NONCE, - UNIQUE_COMMITMENT, - SILOED_COMMITMENT, - NULLIFIER, - INITIALIZATION_NULLIFIER, - OUTER_NULLIFIER, - PUBLIC_DATA_READ, - PUBLIC_DATA_UPDATE_REQUEST, - FUNCTION_DATA, - FUNCTION_LEAF, - CONTRACT_DEPLOYMENT_DATA, - CONSTRUCTOR, - CONSTRUCTOR_ARGS, - CONTRACT_ADDRESS, - CONTRACT_LEAF, - CALL_CONTEXT, - CALL_STACK_ITEM, - CALL_STACK_ITEM_2, - L1_TO_L2_MESSAGE_SECRET), - NVP(L2_TO_L1_MSG, - TX_CONTEXT, - PUBLIC_LEAF_INDEX, - PUBLIC_DATA_LEAF, - SIGNED_TX_REQUEST, - GLOBAL_VARIABLES, - PARTIAL_ADDRESS, - BLOCK_HASH, - SIDE_EFFECT, - TX_REQUEST, - SIGNATURE_PAYLOAD, - VK, - PRIVATE_CIRCUIT_PUBLIC_INPUTS, - PUBLIC_CIRCUIT_PUBLIC_INPUTS, - FUNCTION_ARGS)); - } -}; - -struct StorageSlotGeneratorIndexPacker { - template void msgpack_pack(Packer& packer) const - { - auto pack = [&](auto&... args) { - msgpack::type::define_map{ args... }.msgpack_pack(packer); - }; - - int BASE_SLOT = StorageSlotGeneratorIndex::BASE_SLOT; - int MAPPING_SLOT = StorageSlotGeneratorIndex::MAPPING_SLOT; - int MAPPING_SLOT_PLACEHOLDER = StorageSlotGeneratorIndex::MAPPING_SLOT_PLACEHOLDER; - - pack(NVP(BASE_SLOT, MAPPING_SLOT, MAPPING_SLOT_PLACEHOLDER)); - } -}; - -struct PrivateStateNoteGeneratorIndexPacker { - template void msgpack_pack(Packer& packer) const - { - auto pack = [&](auto&... args) { - msgpack::type::define_map{ args... }.msgpack_pack(packer); - }; - - int VALUE = PrivateStateNoteGeneratorIndex::VALUE; - int OWNER = PrivateStateNoteGeneratorIndex::OWNER; - int CREATOR = PrivateStateNoteGeneratorIndex::CREATOR; - int SALT = PrivateStateNoteGeneratorIndex::SALT; - int NONCE = PrivateStateNoteGeneratorIndex::NONCE; - int MEMO = PrivateStateNoteGeneratorIndex::MEMO; - int IS_DUMMY = PrivateStateNoteGeneratorIndex::IS_DUMMY; - - pack(NVP(VALUE, OWNER, CREATOR, SALT, NONCE, MEMO, IS_DUMMY)); - } -}; - -struct PrivateStateTypePacker { - template void msgpack_pack(Packer& packer) const - { - auto pack = [&](auto&... args) { - msgpack::type::define_map{ args... }.msgpack_pack(packer); - }; - - int PARTITIONED = PrivateStateType::PARTITIONED; - int WHOLE = PrivateStateType::WHOLE; - - pack(NVP(PARTITIONED, WHOLE)); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/point.hpp b/circuits/cpp/src/aztec3/circuits/abis/point.hpp deleted file mode 100644 index ec0bf26b478..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/point.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once -#include "aztec3/circuits/abis/coordinate.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::GeneratorIndex; -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct Point { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - fr x; - fr y; - - // for serialization, update with new fields - MSGPACK_FIELDS(x, y); - bool operator==(Point const&) const = default; - - template Point> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - Point> point = { to_ct(x), to_ct(y) }; - - return point; - }; - - template Point to_native_type() const - { - static_assert((std::is_same, NCT>::value)); - - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - Point point = { to_nt(x), to_nt(y) }; - - return point; - }; - - void set_public() - { - static_assert(!(std::is_same::value)); - - x.set_public(); - y.set_public(); - } - - void assert_is_zero() - { - static_assert(!(std::is_same::value)); - - x.assert_is_zero(); - y.assert_is_zero(); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/previous_kernel_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/previous_kernel_data.hpp deleted file mode 100644 index 588738eb076..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/previous_kernel_data.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -// @todo Naming should not be previous. Annoying. -template struct PreviousKernelData { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - using VK = typename NCT::VK; - using uint32 = typename NCT::uint32; - - KernelCircuitPublicInputs public_inputs{}; // TODO: not needed as already contained in proof? - NativeTypes::Proof proof{}; // TODO: how to express proof as native/circuit type when it gets used as a buffer? - std::shared_ptr vk; - - // TODO: this index and path are meant to be those of a leaf within the tree of _kernel circuit_ vks; not the tree - // of functions within the contract tree. - uint32 vk_index = 0; - std::array vk_path{}; - - // for serialization, update with new fields - MSGPACK_FIELDS(public_inputs, proof, vk, vk_index, vk_path); - boolean operator==(PreviousKernelData const& other) const - { - // WARNING: proof not checked! - return public_inputs == other.public_inputs && - // proof == other.proof && - vk == other.vk && vk_index == other.vk_index && vk_path == other.vk_path; - }; - - // WARNING: the `proof` does NOT get converted! - template PreviousKernelData> to_circuit_type(Builder& builder) const - { - typedef CircuitTypes CT; - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - PreviousKernelData> data = { - public_inputs.to_circuit_type(builder), - proof, // Notice: not converted! Stays as native. - CT::VK::from_witness(&builder, vk), - to_ct(vk_index), - to_ct(vk_path), - }; - - return data; - }; - -}; // namespace aztec3::circuits::abis::private_kernel - -template inline void read(B& buf, verification_key& key) -{ - using serialize::read; - // TODO(AD): We read this as if it were verification_key_data. - // TODO(AD): This seems like it could be rethought. - verification_key_data data; - read(buf, data); - key = verification_key{ std::move(data), barretenberg::srs::get_crs_factory()->get_verifier_crs() }; -} - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_circuit_public_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/private_circuit_public_inputs.hpp deleted file mode 100644 index c10e84c6d17..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/private_circuit_public_inputs.hpp +++ /dev/null @@ -1,691 +0,0 @@ -#pragma once - -#include "call_context.hpp" -#include "contract_deployment_data.hpp" - -#include "aztec3/circuits/abis/block_header.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using plonk::stdlib::witness_t; - -template class PrivateCircuitPublicInputs { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - public: - CallContext call_context{}; - - fr args_hash = 0; - std::array return_values{}; - - std::array read_requests{}; - - std::array new_commitments{}; - std::array new_nullifiers{}; - std::array nullified_commitments{}; - - std::array private_call_stack{}; - std::array public_call_stack{}; - std::array new_l2_to_l1_msgs{}; - - std::array encrypted_logs_hash{}; - std::array unencrypted_logs_hash{}; - - // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the - // variable-length data. - fr encrypted_log_preimages_length = 0; - fr unencrypted_log_preimages_length = 0; - - BlockHeader block_header{}; - - ContractDeploymentData contract_deployment_data{}; - - fr chain_id = 0; - fr version = 0; - - // For serialization, update with new fields - MSGPACK_FIELDS(call_context, - args_hash, - return_values, - read_requests, - new_commitments, - new_nullifiers, - nullified_commitments, - private_call_stack, - public_call_stack, - new_l2_to_l1_msgs, - encrypted_logs_hash, - unencrypted_logs_hash, - encrypted_log_preimages_length, - unencrypted_log_preimages_length, - block_header, - contract_deployment_data, - chain_id, - version); - - boolean operator==(PrivateCircuitPublicInputs const& other) const - { - return call_context == other.call_context && args_hash == other.args_hash && - return_values == other.return_values && read_requests == other.read_requests && - new_commitments == other.new_commitments && - new_nullifiers == other.new_nullifiers && nullified_commitments == other.nullified_commitments && - private_call_stack == other.private_call_stack && public_call_stack == other.public_call_stack && - new_l2_to_l1_msgs == other.new_l2_to_l1_msgs && encrypted_logs_hash == other.encrypted_logs_hash && - unencrypted_logs_hash == other.unencrypted_logs_hash && - encrypted_log_preimages_length == other.encrypted_log_preimages_length && - unencrypted_log_preimages_length == other.unencrypted_log_preimages_length && - block_header == other.block_header && contract_deployment_data == other.contract_deployment_data && - chain_id == other.chain_id && version == other.version; - }; - - template - PrivateCircuitPublicInputs> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(builder); }; - - PrivateCircuitPublicInputs> pis = { - to_circuit_type(call_context), - - to_ct(args_hash), - to_ct(return_values), - - to_ct(read_requests), - - to_ct(new_commitments), - to_ct(new_nullifiers), - to_ct(nullified_commitments), - - to_ct(private_call_stack), - to_ct(public_call_stack), - to_ct(new_l2_to_l1_msgs), - - to_ct(encrypted_logs_hash), - to_ct(unencrypted_logs_hash), - - to_ct(encrypted_log_preimages_length), - to_ct(unencrypted_log_preimages_length), - - to_circuit_type(block_header), - - to_circuit_type(contract_deployment_data), - - to_ct(chain_id), - to_ct(version), - }; - - return pis; - }; - - template PrivateCircuitPublicInputs to_native_type() const - { - static_assert(std::is_same, NCT>::value); - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - auto to_native_type = [](T& e) { return e.template to_native_type(); }; - - PrivateCircuitPublicInputs pis = { - to_native_type(call_context), - - to_nt(args_hash), - to_nt(return_values), - - to_nt(read_requests), - - to_nt(new_commitments), - to_nt(new_nullifiers), - to_nt(nullified_commitments), - - to_nt(private_call_stack), - to_nt(public_call_stack), - to_nt(new_l2_to_l1_msgs), - - to_nt(encrypted_logs_hash), - to_nt(unencrypted_logs_hash), - - to_nt(encrypted_log_preimages_length), - to_nt(unencrypted_log_preimages_length), - - to_native_type(block_header), - - to_native_type(contract_deployment_data), - - to_nt(chain_id), - to_nt(version), - }; - - return pis; - }; - - fr hash() const - { - // auto to_hashes = [](const T& e) { return e.hash(); }; - - std::vector inputs; - - inputs.push_back(call_context.hash()); - - inputs.push_back(args_hash); - spread_arr_into_vec(return_values, inputs); - - spread_arr_into_vec(read_requests, inputs); - - spread_arr_into_vec(new_commitments, inputs); - spread_arr_into_vec(new_nullifiers, inputs); - spread_arr_into_vec(nullified_commitments, inputs); - - spread_arr_into_vec(private_call_stack, inputs); - spread_arr_into_vec(public_call_stack, inputs); - spread_arr_into_vec(new_l2_to_l1_msgs, inputs); - - spread_arr_into_vec(encrypted_logs_hash, inputs); - spread_arr_into_vec(unencrypted_logs_hash, inputs); - - inputs.push_back(encrypted_log_preimages_length); - inputs.push_back(unencrypted_log_preimages_length); - - spread_arr_into_vec(block_header.to_array(), inputs); - - inputs.push_back(contract_deployment_data.hash()); - - inputs.push_back(chain_id); - inputs.push_back(version); - - if (inputs.size() != PRIVATE_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH) { - throw_or_abort("Incorrect number of input fields when hashing PrivateCircuitPublicInputs"); - } - return NCT::hash(inputs, GeneratorIndex::PRIVATE_CIRCUIT_PUBLIC_INPUTS); - } - - template void spread_arr_into_vec(std::array const& arr, std::vector& vec) const - { - const auto arr_size = sizeof(arr) / sizeof(fr); - vec.insert(vec.end(), arr.data(), arr.data() + arr_size); - } -}; - -// It's been extremely useful for all members here to be std::optional. It allows test app circuits to be very -// quickly drafted without worrying about any of the public inputs which aren't relevant to that circuit. Any values -// which aren't set by the circuit can then be safely set to zero when calling `set_public` (by checking for -// std::nullopt) -template class OptionalPrivateCircuitPublicInputs { - using fr = typename NCT::fr; - using opt_fr = typename std::optional; - - public: - std::optional> call_context; - - opt_fr args_hash; - std::array return_values; - - std::array read_requests; - - std::array new_commitments; - std::array new_nullifiers; - std::array nullified_commitments; - - std::array private_call_stack; - std::array public_call_stack; - std::array new_l2_to_l1_msgs; - - std::array encrypted_logs_hash; - std::array unencrypted_logs_hash; - - opt_fr encrypted_log_preimages_length; - opt_fr unencrypted_log_preimages_length; - - std::optional> block_header; - - std::optional> contract_deployment_data; - - opt_fr chain_id; - opt_fr version; - - // For serialization, update with new fields - MSGPACK_FIELDS(call_context, - args_hash, - return_values, - read_requests, - new_commitments, - new_nullifiers, - nullified_commitments, - private_call_stack, - public_call_stack, - new_l2_to_l1_msgs, - encrypted_logs_hash, - unencrypted_logs_hash, - encrypted_log_preimages_length, - unencrypted_log_preimages_length, - block_header, - contract_deployment_data, - chain_id, - version); - - OptionalPrivateCircuitPublicInputs() = default; - - OptionalPrivateCircuitPublicInputs( - std::optional> const& call_context, - - opt_fr const& args_hash, - std::array const& return_values, - - std::array const& read_requests, - - std::array const& new_commitments, - std::array const& new_nullifiers, - std::array const& nullified_commitments, - - std::array const& private_call_stack, - std::array const& public_call_stack, - std::array const& new_l2_to_l1_msgs, - - std::array const& encrypted_logs_hash, - std::array const& unencrypted_logs_hash, - - opt_fr const& encrypted_log_preimages_length, - opt_fr const& unencrypted_log_preimages_length, - - std::optional> const& block_header, - - std::optional> const& contract_deployment_data, - - opt_fr const& chain_id, - opt_fr const& version) - : call_context(call_context) - , args_hash(args_hash) - , return_values(return_values) - , read_requests(read_requests) - , new_commitments(new_commitments) - , new_nullifiers(new_nullifiers) - , nullified_commitments(nullified_commitments) - , private_call_stack(private_call_stack) - , public_call_stack(public_call_stack) - , new_l2_to_l1_msgs(new_l2_to_l1_msgs) - , encrypted_logs_hash(encrypted_logs_hash) - , unencrypted_logs_hash(unencrypted_logs_hash) - , encrypted_log_preimages_length(encrypted_log_preimages_length) - , unencrypted_log_preimages_length(unencrypted_log_preimages_length) - , block_header(block_header) - , contract_deployment_data(contract_deployment_data) - , chain_id(chain_id) - , version(version){}; - - bool operator==(OptionalPrivateCircuitPublicInputs const&) const = default; - - static OptionalPrivateCircuitPublicInputs create() - { - auto new_inputs = OptionalPrivateCircuitPublicInputs(); - - new_inputs.call_context = std::nullopt; - - new_inputs.args_hash = std::nullopt; - new_inputs.return_values.fill(std::nullopt); - - new_inputs.read_requests.fill(std::nullopt); - - new_inputs.new_commitments.fill(std::nullopt); - new_inputs.new_nullifiers.fill(std::nullopt); - new_inputs.nullified_commitments.fill(std::nullopt); - - new_inputs.private_call_stack.fill(std::nullopt); - new_inputs.public_call_stack.fill(std::nullopt); - new_inputs.new_l2_to_l1_msgs.fill(std::nullopt); - - new_inputs.encrypted_logs_hash.fill(std::nullopt); - new_inputs.unencrypted_logs_hash.fill(std::nullopt); - - new_inputs.encrypted_log_preimages_length = std::nullopt; - new_inputs.unencrypted_log_preimages_length = std::nullopt; - - new_inputs.block_header = std::nullopt; - - new_inputs.contract_deployment_data = std::nullopt; - - new_inputs.chain_id = std::nullopt; - new_inputs.version = std::nullopt; - - return new_inputs; - }; - - void set_commitments(std::vector commitments) - { - if (commitments.size() > new_commitments.size()) { - throw_or_abort("Too many commitments for the number supported by the public inputs ABI."); - } - for (size_t i = 0; i < commitments.size(); ++i) { - new_commitments[i] = commitments[i]; - } - } - - void set_nullifiers(std::vector nullifiers) - { - if (nullifiers.size() > new_nullifiers.size()) { - throw_or_abort("Too many commitments for the number supported by the public inputs ABI."); - } - for (size_t i = 0; i < nullifiers.size(); ++i) { - new_nullifiers[i] = nullifiers[i]; - } - } - - void set_nullified_commitments(std::vector input_nullified_commitments) - { - if (input_nullified_commitments.size() > nullified_commitments.size()) { - throw_or_abort("Too many commitments nullified for the number supported by the public inputs ABI."); - } - for (size_t i = 0; i < input_nullified_commitments.size(); ++i) { - nullified_commitments[i] = input_nullified_commitments[i]; - } - } - - template void make_unused_inputs_zero(Builder& builder) - { - static_assert((std::is_same, NCT>::value)); - - make_unused_element_zero(builder, call_context); - - make_unused_element_zero(builder, args_hash); - make_unused_array_elements_zero(builder, return_values); - - make_unused_array_elements_zero(builder, read_requests); - - make_unused_array_elements_zero(builder, new_commitments); - make_unused_array_elements_zero(builder, new_nullifiers); - make_unused_array_elements_zero(builder, nullified_commitments); - - make_unused_array_elements_zero(builder, private_call_stack); - make_unused_array_elements_zero(builder, public_call_stack); - make_unused_array_elements_zero(builder, new_l2_to_l1_msgs); - - make_unused_array_elements_zero(builder, encrypted_logs_hash); - make_unused_array_elements_zero(builder, unencrypted_logs_hash); - - make_unused_element_zero(builder, encrypted_log_preimages_length); - make_unused_element_zero(builder, unencrypted_log_preimages_length); - - make_unused_element_zero(builder, block_header); - - make_unused_element_zero(builder, contract_deployment_data); - - make_unused_element_zero(builder, chain_id); - make_unused_element_zero(builder, version); - - all_elements_populated = true; - } - - template void set_public(Builder& builder) - { - static_assert(!(std::is_same::value)); - - make_unused_inputs_zero(builder); - - // Optional members are guaranteed to be nonempty from here. - - (*call_context).set_public(); - - (*args_hash).set_public(); - set_array_public(return_values); - - set_array_public(read_requests); - - set_array_public(new_commitments); - set_array_public(new_nullifiers); - set_array_public(nullified_commitments); - - set_array_public(private_call_stack); - set_array_public(public_call_stack); - set_array_public(new_l2_to_l1_msgs); - - set_array_public(encrypted_logs_hash); - set_array_public(unencrypted_logs_hash); - - (*encrypted_log_preimages_length).set_public(); - (*unencrypted_log_preimages_length).set_public(); - - (*block_header).set_public(); - - (*contract_deployment_data).set_public(); - - (*chain_id).set_public(); - (*version).set_public(); - } - - template - OptionalPrivateCircuitPublicInputs> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - auto to_circuit_type = [&](auto& e) { - return e ? std::make_optional((*e).to_circuit_type(builder)) : std::nullopt; - }; - - OptionalPrivateCircuitPublicInputs> pis = { - to_circuit_type(call_context), - - to_ct(args_hash), - to_ct(return_values), - - to_ct(read_requests), - - to_ct(new_commitments), - to_ct(new_nullifiers), - to_ct(nullified_commitments), - - to_ct(private_call_stack), - to_ct(public_call_stack), - to_ct(new_l2_to_l1_msgs), - - to_ct(encrypted_logs_hash), - to_ct(unencrypted_logs_hash), - - to_ct(encrypted_log_preimages_length), - to_ct(unencrypted_log_preimages_length), - - to_circuit_type(block_header), - - to_circuit_type(contract_deployment_data), - - to_ct(chain_id), - to_ct(version), - }; - - return pis; - }; - - template OptionalPrivateCircuitPublicInputs to_native_type() const - { - static_assert(std::is_same, NCT>::value); - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - auto to_native_type = [](const std::optional& e) { - return e ? std::make_optional((*e).template to_native_type()) : std::nullopt; - }; - // auto to_native_type = [&](T& e) { return e.to_native_type(); }; - - OptionalPrivateCircuitPublicInputs pis = { to_native_type(call_context), - - to_nt(args_hash), - to_nt(return_values), - - to_nt(read_requests), - - to_nt(new_commitments), - to_nt(new_nullifiers), - to_nt(nullified_commitments), - - to_nt(private_call_stack), - to_nt(public_call_stack), - to_nt(new_l2_to_l1_msgs), - - to_nt(encrypted_logs_hash), - to_nt(unencrypted_logs_hash), - - to_nt(encrypted_log_preimages_length), - to_nt(unencrypted_log_preimages_length), - - to_native_type(block_header), - - to_native_type(contract_deployment_data), - - to_nt(chain_id), - to_nt(version) }; - - return pis; - }; - - fr hash() const - { - // auto to_hashes = [](const std::optional& e) { - // if (!e) { - // throw_or_abort("Value is nullopt"); - // } - // return (*e).hash(); - // }; - - std::vector inputs; - - inputs.push_back((*call_context).hash()); - - inputs.push_back(*args_hash); - spread_arr_opt_into_vec(return_values, inputs); - - spread_arr_opt_into_vec(read_requests, inputs); - - spread_arr_opt_into_vec(new_commitments, inputs); - spread_arr_opt_into_vec(new_nullifiers, inputs); - spread_arr_opt_into_vec(nullified_commitments, inputs); - - spread_arr_opt_into_vec(private_call_stack, inputs); - spread_arr_opt_into_vec(public_call_stack, inputs); - spread_arr_opt_into_vec(new_l2_to_l1_msgs, inputs); - - spread_arr_into_vec(encrypted_logs_hash, inputs); - spread_arr_into_vec(unencrypted_logs_hash, inputs); - - inputs.push_back(*encrypted_log_preimages_length); - inputs.push_back(*unencrypted_log_preimages_length); - - spread_arr_opt_into_vec((*block_header).to_array(), inputs); - - inputs.push_back((*contract_deployment_data).hash()); - - inputs.push_back(*chain_id); - inputs.push_back(*version); - - return NCT::hash(inputs, GeneratorIndex::PRIVATE_CIRCUIT_PUBLIC_INPUTS); - } - - // We can remove optionality when using the inputs in a kernel or rollup circuit, for ease of use. - PrivateCircuitPublicInputs remove_optionality() const - { - auto get_value = [&](auto& e) { return e.value(); }; - - return PrivateCircuitPublicInputs{ - .call_context = call_context.value(), - - .args_hash = args_hash.value(), - .return_values = map(return_values, get_value), - - .read_requests = map(read_requests, get_value), - - .new_commitments = map(new_commitments, get_value), - .new_nullifiers = map(new_nullifiers, get_value), - .nullified_commitments = map(nullified_commitments, get_value), - - .private_call_stack = map(private_call_stack, get_value), - .public_call_stack = map(public_call_stack, get_value), - .new_l2_to_l1_msgs = map(new_l2_to_l1_msgs, get_value), - - .encrypted_logs_hash = map(encrypted_logs_hash, get_value), - .unencrypted_logs_hash = map(unencrypted_logs_hash, get_value), - - .encrypted_log_preimages_length = encrypted_log_preimages_length.value(), - .unencrypted_log_preimages_length = unencrypted_log_preimages_length.value(), - - .block_header = block_header.value(), - - .contract_deployment_data = contract_deployment_data.value(), - - .chain_id = chain_id.value(), - .version = version.value(), - }; - } - - private: - bool all_elements_populated = false; - - template - void spread_arr_opt_into_vec(std::array, SIZE> const& arr, std::vector& vec) const - { - auto get_opt_value = [](const std::optional& e) { - if (!e) { - throw_or_abort("Value is nullopt"); - } - return *e; - }; - - std::array arr_values = map(arr, get_opt_value); - const auto arr_size = sizeof(arr_values) / sizeof(fr); - vec.insert(vec.end(), arr_values.data(), arr_values.data() + arr_size); - } - - template void spread_arr_into_vec(std::array const& arr, std::vector& vec) const - { - const auto arr_size = sizeof(arr) / sizeof(fr); - vec.insert(vec.end(), arr.data(), arr.data() + arr_size); - } - - template - void make_unused_array_elements_zero(Builder& builder, std::array, SIZE>& arr) - { - static_assert((std::is_same, NCT>::value)); - - for (std::optional& e : arr) { - make_unused_element_zero(builder, e); - } - } - - template void make_unused_element_zero(Builder& builder, std::optional& element) - { - static_assert((std::is_same, NCT>::value)); - - if (!element) { - element = - T(witness_t(&builder, 0)); // convert the nullopt value to a circuit witness value of `0` - fr(*element).assert_is_zero(); - } - } - - // ABIStruct is a template for any of the structs in the abis/ dir. E.g. ExecutedCallback, CallbackStackItem. - template class ABIStruct> - void make_unused_element_zero(Builder& builder, std::optional>>& element) - { - static_assert((std::is_same, NCT>::value)); - - if (!element) { - element = ABIStruct().to_circuit_type( - builder); // convert the nullopt value to a circuit witness value of `0` - (*element).template assert_is_zero(); - } - } - - // Make sure this is only called by functions which have implemented a "CT only" check. - template void set_array_public(std::array, SIZE>& arr) - { - for (std::optional& e : arr) { - fr(*e).set_public(); - } - } -}; -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/call_context_reconciliation_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/private_kernel/call_context_reconciliation_data.hpp deleted file mode 100644 index 7889c49b641..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/call_context_reconciliation_data.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// #pragma once - -// #include "../call_context.hpp" - -// #include "aztec3/utils/types/native_types.hpp" -// #include "aztec3/utils/types/circuit_types.hpp" -// #include "aztec3/utils/types/convert.hpp" - -// #include - -// namespace aztec3::circuits::abis::private_kernel { - -// using plonk::stdlib::witness_t; -// using aztec3::utils::types::CircuitTypes; -// using aztec3::utils::types::NativeTypes; -// using std::is_same; - -// template struct CallContextReconciliationData { -// typedef typename NCT::fr fr; - -// /** -// * This class needs an explanation... -// * -// */ -// std::array, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL> private_call_contexts; -// std::array private_counterparts; - -// std::array, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL> public_call_contexts; -// std::array public_counterparts; - -// // std::array contract_deployment_call_stack; - -// std::array, MAX_NEW_L2_TO_L1_MSGS_PER_CALL> l1_call_contexts; -// std::array l1_counterparts; // TODO: this is probably wrong. - -// template -// CallContextReconciliationData> to_circuit_type(Builder& builder) const -// { -// static_assert((std::is_same::value)); - -// // Capture the circuit builder: -// auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; -// auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(builder); }; - -// CallContextReconciliationData> data = { - -// map(private_call_contexts, to_circuit_type), to_ct(private_counterparts), - -// map(public_call_contexts, to_circuit_type), to_ct(public_counterparts), - -// map(l1_call_contexts, to_circuit_type), to_ct(l1_counterparts), -// }; - -// return data; -// }; -// }; - -// } // namespace aztec3::circuits::abis::private_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/globals.hpp b/circuits/cpp/src/aztec3/circuits/abis/private_kernel/globals.hpp deleted file mode 100644 index c0dddfa2d65..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/globals.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis::private_kernel { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct Globals { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - fr min_timestamp = 0; - - boolean operator==(Globals const& other) const { return min_timestamp == other.min_timestamp; }; - - template Globals> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - Globals> global_data = { to_ct(min_timestamp) }; - - return global_data; - }; - - void set_public() - { - static_assert(!(std::is_same::value)); - - min_timestamp.set_public(); - } -}; - -} // namespace aztec3::circuits::abis::private_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_call_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_call_data.hpp deleted file mode 100644 index 5ad120dfdf5..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_call_data.hpp +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once - -#include "call_context_reconciliation_data.hpp" -#include "../call_stack_item.hpp" -#include "../read_request_membership_witness.hpp" -#include "../types.hpp" - -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis::private_kernel { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct PrivateCallData { - using address = typename NCT::address; - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - using VK = typename NCT::VK; - - CallStackItem call_stack_item{}; - - std::array, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL> private_call_stack_preimages{}; - - // std::array, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL> - // public_call_stack_preimages; - - NativeTypes::Proof proof{}; // TODO: how to express proof as native/circuit type when it gets used as a buffer? - std::shared_ptr vk; - - MembershipWitness function_leaf_membership_witness{}; - MembershipWitness contract_leaf_membership_witness{}; - - std::array, MAX_READ_REQUESTS_PER_CALL> - read_request_membership_witnesses{}; - - fr portal_contract_address = 0; // an ETH address - fr acir_hash = 0; - - // For serialization, update with new fields - MSGPACK_FIELDS(call_stack_item, - private_call_stack_preimages, - proof, - vk, - function_leaf_membership_witness, - contract_leaf_membership_witness, - read_request_membership_witnesses, - portal_contract_address, - acir_hash); - - boolean operator==(PrivateCallData const& other) const - { - // WARNING: proof skipped! - return call_stack_item == other.call_stack_item && - private_call_stack_preimages == other.private_call_stack_preimages && vk == other.vk && - function_leaf_membership_witness == other.function_leaf_membership_witness && - contract_leaf_membership_witness == other.contract_leaf_membership_witness && - read_request_membership_witnesses == other.read_request_membership_witnesses && - portal_contract_address == other.portal_contract_address && acir_hash == other.acir_hash; - }; - - // WARNING: the `proof` does NOT get converted! (because the current implementation of `verify_proof` takes a proof - // of native bytes; any conversion to circuit types happens within the `verify_proof` function) - template PrivateCallData> to_circuit_type(Builder& builder) const - { - typedef CircuitTypes CT; - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(builder); }; - - PrivateCallData> data = { - to_circuit_type(call_stack_item), - - map(private_call_stack_preimages, to_circuit_type), - - proof, // Notice: not converted! Stays as native. This is because of how the verify_proof function - // currently works. - CT::VK::from_witness(&builder, vk), - - to_circuit_type(function_leaf_membership_witness), - to_circuit_type(contract_leaf_membership_witness), - - aztec3::utils::types::to_ct>( - builder, read_request_membership_witnesses), - - to_ct(portal_contract_address), - to_ct(acir_hash), - }; - - return data; - }; -}; // namespace aztec3::circuits::abis::private_kernel - -} // namespace aztec3::circuits::abis::private_kernel diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_kernel_inputs_init.hpp b/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_kernel_inputs_init.hpp deleted file mode 100644 index d21935e3217..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_kernel_inputs_init.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include "private_call_data.hpp" -#include "../tx_request.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -namespace aztec3::circuits::abis::private_kernel { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct PrivateKernelInputsInit { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - TxRequest tx_request{}; - PrivateCallData private_call{}; - - // For serialization, update with new fields - MSGPACK_FIELDS(tx_request, private_call); - boolean operator==(PrivateKernelInputsInit const& other) const - { - return msgpack_derived_equals(*this, other); - }; - - template PrivateKernelInputsInit> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - PrivateKernelInputsInit> private_inputs = { - // TODO to_ct(signature), - tx_request.to_circuit_type(builder), - private_call.to_circuit_type(builder), - }; - - return private_inputs; - }; -}; - -} // namespace aztec3::circuits::abis::private_kernel diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_kernel_inputs_inner.hpp b/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_kernel_inputs_inner.hpp deleted file mode 100644 index d6b5217bbfa..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_kernel_inputs_inner.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "private_call_data.hpp" -#include "../previous_kernel_data.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis::private_kernel { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct PrivateKernelInputsInner { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - PreviousKernelData previous_kernel{}; - PrivateCallData private_call{}; - - // For serialization, update with new fields - MSGPACK_FIELDS(previous_kernel, private_call); - boolean operator==(PrivateKernelInputsInner const& other) const - { - return msgpack_derived_equals(*this, other); - }; - - template PrivateKernelInputsInner> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - PrivateKernelInputsInner> private_inputs = { - previous_kernel.to_circuit_type(builder), - private_call.to_circuit_type(builder), - }; - - return private_inputs; - }; -}; - -} // namespace aztec3::circuits::abis::private_kernel diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_kernel_inputs_ordering.hpp b/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_kernel_inputs_ordering.hpp deleted file mode 100644 index 2cfd6d2b643..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_kernel_inputs_ordering.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include "private_call_data.hpp" -#include "../previous_kernel_data.hpp" - -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis::private_kernel { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct PrivateKernelInputsOrdering { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - PreviousKernelData previous_kernel{}; - - std::array read_commitment_hints{}; - std::array nullifier_commitment_hints{}; - - // For serialization, update with new fields - MSGPACK_FIELDS(previous_kernel, read_commitment_hints, nullifier_commitment_hints); - boolean operator==(PrivateKernelInputsOrdering const& other) const - { - return msgpack_derived_equals(*this, other); - }; - - template - PrivateKernelInputsOrdering> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - PrivateKernelInputsOrdering> private_inputs = { - previous_kernel.to_circuit_type(builder), - read_commitment_hints.to_circuit_type(builder), - nullifier_commitment_hints.to_circuit_type(builder), - }; - - return private_inputs; - }; -}; - -} // namespace aztec3::circuits::abis::private_kernel diff --git a/circuits/cpp/src/aztec3/circuits/abis/public_circuit_public_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/public_circuit_public_inputs.hpp deleted file mode 100644 index 6548b93a28d..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/public_circuit_public_inputs.hpp +++ /dev/null @@ -1,140 +0,0 @@ -#pragma once - -#include "call_context.hpp" -#include "contract_storage_read.hpp" -#include "contract_storage_update_request.hpp" -#include "../../constants.hpp" - -#include "aztec3/circuits/abis/block_header.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include "barretenberg/common/throw_or_abort.hpp" -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct PublicCircuitPublicInputs { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - using address = typename NCT::address; - - CallContext call_context{}; - - fr args_hash = 0; - std::array return_values{}; - - std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL> - contract_storage_update_requests{}; - std::array, MAX_PUBLIC_DATA_READS_PER_CALL> contract_storage_reads{}; - - std::array public_call_stack{}; - std::array new_commitments{}; - std::array new_nullifiers{}; - std::array new_l2_to_l1_msgs{}; - - std::array unencrypted_logs_hash{}; - - // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the - // variable-length data. - fr unencrypted_log_preimages_length = 0; - - BlockHeader block_header{}; - - address prover_address{}; - - // for serialization, update with new fields - MSGPACK_FIELDS(call_context, - args_hash, - return_values, - contract_storage_update_requests, - contract_storage_reads, - public_call_stack, - new_commitments, - new_nullifiers, - new_l2_to_l1_msgs, - unencrypted_logs_hash, - unencrypted_log_preimages_length, - block_header, - prover_address); - - boolean operator==(PublicCircuitPublicInputs const& other) const - { - return msgpack_derived_equals(*this, other); - } - - template PublicCircuitPublicInputs> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(builder); }; - - PublicCircuitPublicInputs> pis = { - .call_context = to_circuit_type(call_context), - - .args_hash = to_ct(args_hash), - .return_values = to_ct(return_values), - - .contract_storage_update_requests = map(contract_storage_update_requests, to_circuit_type), - .contract_storage_reads = map(contract_storage_reads, to_circuit_type), - - .public_call_stack = to_ct(public_call_stack), - .new_commitments = to_ct(new_commitments), - .new_nullifiers = to_ct(new_nullifiers), - .new_l2_to_l1_msgs = to_ct(new_l2_to_l1_msgs), - - .unencrypted_logs_hash = to_ct(unencrypted_logs_hash), - .unencrypted_log_preimages_length = to_ct(unencrypted_log_preimages_length), - - .block_header = to_ct(block_header), - - .prover_address = to_ct(prover_address), - }; - - return pis; - }; - - fr hash() const - { - auto to_hashes = [](const T& e) { return e.hash(); }; - - std::vector inputs; - - inputs.push_back(call_context.hash()); - - inputs.push_back(args_hash); - spread_arr_into_vec(return_values, inputs); - - spread_arr_into_vec(map(contract_storage_update_requests, to_hashes), inputs); - spread_arr_into_vec(map(contract_storage_reads, to_hashes), inputs); - - spread_arr_into_vec(public_call_stack, inputs); - spread_arr_into_vec(new_commitments, inputs); - spread_arr_into_vec(new_nullifiers, inputs); - spread_arr_into_vec(new_l2_to_l1_msgs, inputs); - - spread_arr_into_vec(unencrypted_logs_hash, inputs); - inputs.push_back(unencrypted_log_preimages_length); - - spread_arr_into_vec(block_header.to_array(), inputs); - inputs.push_back(prover_address); - - if (inputs.size() != PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH) { - throw_or_abort("Incorrect number of input fields when hashing PublicCircuitPublicInputs"); - } - return NCT::hash(inputs, GeneratorIndex::PUBLIC_CIRCUIT_PUBLIC_INPUTS); - } - - template void spread_arr_into_vec(std::array const& arr, std::vector& vec) const - { - const auto arr_size = sizeof(arr) / sizeof(fr); - vec.insert(vec.end(), arr.data(), arr.data() + arr_size); - } -}; // namespace aztec3::circuits::abis - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/public_data_read.hpp b/circuits/cpp/src/aztec3/circuits/abis/public_data_read.hpp deleted file mode 100644 index d95ed30160a..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/public_data_read.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::GeneratorIndex; -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct PublicDataRead { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - fr leaf_index = 0; - fr value = 0; - - // for serialization, update with new fields - MSGPACK_FIELDS(leaf_index, value); - bool operator==(PublicDataRead const&) const = default; - - template PublicDataRead> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - PublicDataRead> read = { - to_ct(leaf_index), - to_ct(value), - }; - - return read; - }; - - template PublicDataRead to_native_type() const - { - static_assert((std::is_same, NCT>::value)); - - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - PublicDataRead read = { - to_nt(leaf_index), - to_nt(value), - }; - - return read; - }; - - fr hash() const - { - std::vector inputs = { - leaf_index, - value, - }; - - return NCT::hash(inputs, GeneratorIndex::PUBLIC_DATA_READ); - } - - void set_public() - { - static_assert(!(std::is_same::value)); - - leaf_index.set_public(); - value.set_public(); - } - - boolean is_empty() const { return leaf_index == 0; } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/public_data_update_request.hpp b/circuits/cpp/src/aztec3/circuits/abis/public_data_update_request.hpp deleted file mode 100644 index 2d70484d232..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/public_data_update_request.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::GeneratorIndex; -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct PublicDataUpdateRequest { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - fr leaf_index = 0; - fr old_value = 0; - fr new_value = 0; - - // for serialization, update with new fields - MSGPACK_FIELDS(leaf_index, old_value, new_value); - bool operator==(PublicDataUpdateRequest const&) const = default; - - template PublicDataUpdateRequest> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - PublicDataUpdateRequest> update_request = { - to_ct(leaf_index), - to_ct(old_value), - to_ct(new_value), - }; - - return update_request; - }; - - template PublicDataUpdateRequest to_native_type() const - { - static_assert((std::is_same, NCT>::value)); - - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - PublicDataUpdateRequest update_request = { - to_nt(leaf_index), - to_nt(old_value), - to_nt(new_value), - }; - - return update_request; - }; - - fr hash() const - { - std::vector inputs = { - leaf_index, - old_value, - new_value, - }; - - return NCT::hash(inputs, GeneratorIndex::PUBLIC_DATA_UPDATE_REQUEST); - } - - void set_public() - { - static_assert(!(std::is_same::value)); - - leaf_index.set_public(); - old_value.set_public(); - new_value.set_public(); - } - - boolean is_empty() const { return leaf_index == 0; } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/public_kernel/public_call_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/public_kernel/public_call_data.hpp deleted file mode 100644 index 46ae4286599..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/public_kernel/public_call_data.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once - -#include "../call_stack_item.hpp" -#include "../types.hpp" - -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis::public_kernel { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct PublicCallData { - using address = typename NCT::address; - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - using VK = typename NCT::VK; - - CallStackItem call_stack_item{}; - - std::array, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL> public_call_stack_preimages{}; - - NativeTypes::Proof proof{}; // TODO: how to express proof as native/circuit type when it gets used as a buffer? - - fr portal_contract_address = 0; // an ETH address - fr bytecode_hash = 0; - - // for serialization, update with new fields - MSGPACK_FIELDS(call_stack_item, public_call_stack_preimages, proof, portal_contract_address, bytecode_hash); - boolean operator==(PublicCallData const& other) const - { - // WARNING: proof skipped! - return call_stack_item == other.call_stack_item && - public_call_stack_preimages == other.public_call_stack_preimages && - portal_contract_address == other.portal_contract_address && bytecode_hash == other.bytecode_hash; - }; - - // WARNING: the `proof` does NOT get converted! (because the current implementation of `verify_proof` takes a proof - // of native bytes; any conversion to circuit types happens within the `verify_proof` function) - template PublicCallData> to_circuit_type(Builder& builder) const - { - // typedef CircuitTypes CT; - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(builder); }; - - PublicCallData> data = { - call_stack_item.to_circuit_type(builder), - - map(public_call_stack_preimages, to_circuit_type), - - proof, // Notice: not converted! Stays as native. This is because of how the verify_proof function - // currently works. - // CT::VK::from_witness(&builder, vk), - - // to_circuit_type(function_leaf_membership_witness), - // to_circuit_type(contract_leaf_membership_witness), - - to_ct(portal_contract_address), - to_ct(bytecode_hash), - }; - - return data; - }; -}; - -} // namespace aztec3::circuits::abis::public_kernel diff --git a/circuits/cpp/src/aztec3/circuits/abis/public_kernel/public_kernel_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/public_kernel/public_kernel_inputs.hpp deleted file mode 100644 index d4119747c80..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/public_kernel/public_kernel_inputs.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "public_call_data.hpp" -#include "../previous_kernel_data.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis::public_kernel { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct PublicKernelInputs { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - PreviousKernelData previous_kernel{}; - PublicCallData public_call{}; - - // for serialization, update with new fields - MSGPACK_FIELDS(previous_kernel, public_call); - boolean operator==(PublicKernelInputs const& other) const - { - return previous_kernel == other.previous_kernel && public_call == other.public_call; - }; - - template PublicKernelInputs> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - PublicKernelInputs> public_kernel_inputs = { - previous_kernel.to_circuit_type(builder), - public_call.to_circuit_type(builder), - }; - - return public_kernel_inputs; - }; -}; - -} // namespace aztec3::circuits::abis::public_kernel diff --git a/circuits/cpp/src/aztec3/circuits/abis/read_request_membership_witness.hpp b/circuits/cpp/src/aztec3/circuits/abis/read_request_membership_witness.hpp deleted file mode 100644 index e63e60a9837..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/read_request_membership_witness.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#include "aztec3/circuits/abis/membership_witness.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -/** - * A ReadRequestMembershipWitness is similar to a MembershipWitness but includes - * some additional fields used to direct the kernel regarding whether a read is transient - * and if so which commitment it corresponds to. - */ -template struct ReadRequestMembershipWitness { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - fr leaf_index = 0; - std::array sibling_path{}; - boolean is_transient = false; // whether or not the read request corresponds to a pending commitment - // In case we change the default to true, we have to adapt is_empty() method - fr hint_to_commitment = 0; // hint to point kernel to the commitment this rr corresponds to - - // For serialization, update with new fields - MSGPACK_FIELDS(leaf_index, sibling_path, is_transient, hint_to_commitment); - - boolean operator==(ReadRequestMembershipWitness const& other) const - { - return leaf_index == other.leaf_index && sibling_path == other.sibling_path && - is_transient == other.is_transient && hint_to_commitment == other.hint_to_commitment; - }; - - template - ReadRequestMembershipWitness, N> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - ReadRequestMembershipWitness, N> witness = { - to_ct(leaf_index), to_ct(sibling_path), to_ct(is_transient), to_ct(hint_to_commitment) - }; - - return witness; - } - - template ReadRequestMembershipWitness to_native_type() const - { - static_assert((std::is_same, NCT>::value)); - - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - ReadRequestMembershipWitness witness = { - to_nt(leaf_index), map(sibling_path, to_nt), to_nt(is_transient), to_nt(hint_to_commitment) - }; - - return witness; - } - - - void set_public() - { - static_assert(!(std::is_same::value)); - - leaf_index.set_public(); - for (fr const& e : sibling_path) { - e.set_public(); - } - - fr(is_transient).set_public(); - hint_to_commitment.set_public(); - } - - // Deliberately consider a transient read request membership witness as non-empty. - boolean is_empty() const - { - return aztec3::utils::is_empty(leaf_index) && is_array_empty(sibling_path) && !is_transient && - aztec3::utils::is_empty(hint_to_commitment); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp deleted file mode 100644 index 342acd3808c..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include "../../append_only_tree_snapshot.hpp" -#include "../constant_rollup_data.hpp" - -#include "aztec3/constants.hpp" - -namespace aztec3::circuits::abis { - - -const uint32_t BASE_ROLLUP_TYPE = 0; -const uint32_t MERGE_ROLLUP_TYPE = 1; - -template struct BaseOrMergeRollupPublicInputs { - using fr = typename NCT::fr; - using AggregationObject = typename NCT::AggregationObject; - using boolean = typename NCT::boolean; - - uint32_t rollup_type; - // subtree height is always 0 for base. - // so that we always pass-in two base/merge circuits of the same height into the next level of recursion - fr rollup_subtree_height; - - AggregationObject end_aggregation_object; - ConstantRollupData constants; - - AppendOnlyTreeSnapshot start_note_hash_tree_snapshot; - AppendOnlyTreeSnapshot end_note_hash_tree_snapshot; - - AppendOnlyTreeSnapshot start_nullifier_tree_snapshot; - AppendOnlyTreeSnapshot end_nullifier_tree_snapshot; - - AppendOnlyTreeSnapshot start_contract_tree_snapshot; - AppendOnlyTreeSnapshot end_contract_tree_snapshot; - - fr start_public_data_tree_root; - fr end_public_data_tree_root; - - // We hash public inputs to make them constant-sized (to then be unpacked on-chain) - std::array calldata_hash; - - // For serialization, update with new fields - MSGPACK_FIELDS(rollup_type, - rollup_subtree_height, - end_aggregation_object, - constants, - start_note_hash_tree_snapshot, - end_note_hash_tree_snapshot, - start_nullifier_tree_snapshot, - end_nullifier_tree_snapshot, - start_contract_tree_snapshot, - end_contract_tree_snapshot, - start_public_data_tree_root, - end_public_data_tree_root, - calldata_hash); - boolean operator==(BaseOrMergeRollupPublicInputs const& other) const - { - return msgpack_derived_equals(*this, other); - }; -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_rollup_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_rollup_inputs.hpp deleted file mode 100644 index c50cb0e5572..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_rollup_inputs.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once -#include "../../append_only_tree_snapshot.hpp" -#include "../../membership_witness.hpp" -#include "../../previous_kernel_data.hpp" -#include "../constant_rollup_data.hpp" -#include "../nullifier_leaf_preimage.hpp" - -#include "aztec3/constants.hpp" - -#include - -namespace aztec3::circuits::abis { - -template struct BaseRollupInputs { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - std::array, KERNELS_PER_BASE_ROLLUP> kernel_data{}; - - AppendOnlyTreeSnapshot start_note_hash_tree_snapshot{}; - AppendOnlyTreeSnapshot start_nullifier_tree_snapshot{}; - AppendOnlyTreeSnapshot start_contract_tree_snapshot{}; - fr start_public_data_tree_root{}; - AppendOnlyTreeSnapshot start_archive_snapshot{}; - - std::array, MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP> low_nullifier_leaf_preimages{}; - std::array, MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP> - low_nullifier_membership_witness{}; - - // For inserting the new subtrees into their respective trees: - // Note: the insertion leaf index can be derived from the above snapshots' `next_available_leaf_index` values. - std::array new_commitments_subtree_sibling_path{}; - std::array new_nullifiers_subtree_sibling_path{}; - std::array new_contracts_subtree_sibling_path{}; - std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP> - new_public_data_update_requests_sibling_paths{}; - std::array, MAX_PUBLIC_DATA_READS_PER_BASE_ROLLUP> - new_public_data_reads_sibling_paths{}; - - std::array, KERNELS_PER_BASE_ROLLUP> archive_root_membership_witnesses{}; - - ConstantRollupData constants{}; - - // for serialization, update with new fields - MSGPACK_FIELDS(kernel_data, - start_note_hash_tree_snapshot, - start_nullifier_tree_snapshot, - start_contract_tree_snapshot, - start_public_data_tree_root, - start_archive_snapshot, - low_nullifier_leaf_preimages, - low_nullifier_membership_witness, - new_commitments_subtree_sibling_path, - new_nullifiers_subtree_sibling_path, - new_contracts_subtree_sibling_path, - new_public_data_update_requests_sibling_paths, - new_public_data_reads_sibling_paths, - archive_root_membership_witnesses, - constants); - - boolean operator==(BaseRollupInputs const& other) const - { - return msgpack_derived_equals(*this, other); - }; -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/constant_rollup_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/constant_rollup_data.hpp deleted file mode 100644 index e77d45a492f..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/constant_rollup_data.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include "../append_only_tree_snapshot.hpp" -#include "../global_variables.hpp" - -#include - -namespace aztec3::circuits::abis { - -template struct ConstantRollupData { - using fr = typename NCT::fr; - - // The very latest roots as at the very beginning of the entire rollup: - AppendOnlyTreeSnapshot start_archive_snapshot{}; - - // Some members of this struct tbd: - fr private_kernel_vk_tree_root = 0; - fr public_kernel_vk_tree_root = 0; - fr base_rollup_vk_hash = 0; - fr merge_rollup_vk_hash = 0; - - GlobalVariables global_variables{}; - - MSGPACK_FIELDS(start_archive_snapshot, - private_kernel_vk_tree_root, - public_kernel_vk_tree_root, - base_rollup_vk_hash, - merge_rollup_vk_hash, - global_variables); - - bool operator==(ConstantRollupData const&) const = default; -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/merge/merge_rollup_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/merge/merge_rollup_inputs.hpp deleted file mode 100644 index bf1c30dc291..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/merge/merge_rollup_inputs.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -#include "aztec3/circuits/abis/rollup/merge/previous_rollup_data.hpp" - -#include - -namespace aztec3::circuits::abis { - -template struct MergeRollupInputs { - std::array, 2> previous_rollup_data; - - // For serialization, update with new fields - MSGPACK_FIELDS(previous_rollup_data); - bool operator==(MergeRollupInputs const&) const = default; -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/merge/previous_rollup_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/merge/previous_rollup_data.hpp deleted file mode 100644 index 53b2de8ce62..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/merge/previous_rollup_data.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include "aztec3/circuits/abis/membership_witness.hpp" -#include "aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::NativeTypes; - -template struct PreviousRollupData { - BaseOrMergeRollupPublicInputs base_or_merge_rollup_public_inputs; - - NativeTypes::Proof proof; - std::shared_ptr vk; - NativeTypes::uint32 vk_index = 0; - MembershipWitness vk_sibling_path; - - // For serialization, update with new fields - MSGPACK_FIELDS(base_or_merge_rollup_public_inputs, proof, vk, vk_index, vk_sibling_path); - - bool operator==(PreviousRollupData const&) const = default; -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/nullifier_leaf_preimage.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/nullifier_leaf_preimage.hpp deleted file mode 100644 index 0f4af4ad921..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/nullifier_leaf_preimage.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "aztec3/utils/types/circuit_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using std::is_same; - -template struct NullifierLeafPreimage { - using fr = typename NCT::fr; - using uint32 = typename NCT::uint32; - - fr leaf_value = 0; - fr next_value = 0; - uint32 next_index; - - MSGPACK_FIELDS(leaf_value, next_value, next_index); - bool operator==(NullifierLeafPreimage const&) const = default; - - bool is_empty() const { return leaf_value.is_zero() && next_index == 0 && next_value.is_zero(); } - - fr hash() const - { - return is_empty() ? fr::zero() : stdlib::merkle_tree::hash_native({ leaf_value, next_index, next_value }); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp deleted file mode 100644 index ce1993e6194..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp +++ /dev/null @@ -1,41 +0,0 @@ - - -#pragma once -#include "aztec3/circuits/abis/append_only_tree_snapshot.hpp" -#include "aztec3/circuits/abis/rollup/merge/previous_rollup_data.hpp" -#include "aztec3/constants.hpp" - -#include - -namespace aztec3::circuits::abis { - -// TODO: The copy constructor for this struct may throw memory access out of bounds -// Hit when running aztec3-packages/yarn-project/circuits.js/src/rollup/rollup_wasm_wrapper.test.ts."calls -// root_rollup__sim" -template struct RootRollupInputs { - using fr = typename NCT::fr; - - // All below are shared between the base and merge rollups - std::array, 2> previous_rollup_data{}; - - // inputs required to process l1 to l2 messages - std::array new_l1_to_l2_messages{}; - std::array new_l1_to_l2_message_tree_root_sibling_path{}; - - AppendOnlyTreeSnapshot start_l1_to_l2_message_tree_snapshot{}; - - // inputs required to add the block hash - AppendOnlyTreeSnapshot start_archive_snapshot{}; - std::array new_archive_sibling_path{}; - - // For serialization, update with new fields - MSGPACK_FIELDS(previous_rollup_data, - new_l1_to_l2_messages, - new_l1_to_l2_message_tree_root_sibling_path, - start_l1_to_l2_message_tree_snapshot, - start_archive_snapshot, - new_archive_sibling_path); - bool operator==(RootRollupInputs const&) const = default; -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp deleted file mode 100644 index bf2525c27d8..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp +++ /dev/null @@ -1,128 +0,0 @@ -#pragma once - -#include "aztec3/circuits/abis/append_only_tree_snapshot.hpp" -#include "aztec3/circuits/abis/global_variables.hpp" -#include "aztec3/constants.hpp" - -#include - -#include - -namespace aztec3::circuits::abis { - -template struct RootRollupPublicInputs { - using fr = typename NCT::fr; - using AggregationObject = typename NCT::AggregationObject; - - // All below are shared between the base and merge rollups - AggregationObject end_aggregation_object{}; - - GlobalVariables global_variables{}; - - AppendOnlyTreeSnapshot start_note_hash_tree_snapshot{}; - AppendOnlyTreeSnapshot end_note_hash_tree_snapshot{}; - - AppendOnlyTreeSnapshot start_nullifier_tree_snapshot{}; - AppendOnlyTreeSnapshot end_nullifier_tree_snapshot{}; - - AppendOnlyTreeSnapshot start_contract_tree_snapshot{}; - AppendOnlyTreeSnapshot end_contract_tree_snapshot{}; - - fr start_public_data_tree_root{}; - fr end_public_data_tree_root{}; - - AppendOnlyTreeSnapshot start_tree_of_historical_note_hash_tree_roots_snapshot{}; - AppendOnlyTreeSnapshot end_tree_of_historical_note_hash_tree_roots_snapshot{}; - - AppendOnlyTreeSnapshot start_tree_of_historical_contract_tree_roots_snapshot{}; - AppendOnlyTreeSnapshot end_tree_of_historical_contract_tree_roots_snapshot{}; - - AppendOnlyTreeSnapshot start_l1_to_l2_message_tree_snapshot{}; - AppendOnlyTreeSnapshot end_l1_to_l2_message_tree_snapshot{}; - - AppendOnlyTreeSnapshot start_tree_of_historical_l1_to_l2_message_tree_roots_snapshot{}; - AppendOnlyTreeSnapshot end_tree_of_historical_l1_to_l2_message_tree_roots_snapshot{}; - - AppendOnlyTreeSnapshot start_archive_snapshot{}; - AppendOnlyTreeSnapshot end_archive_snapshot{}; - - std::array calldata_hash{}; - std::array l1_to_l2_messages_hash{}; - - // For serialization, update with new fields - MSGPACK_FIELDS(end_aggregation_object, - global_variables, - start_note_hash_tree_snapshot, - end_note_hash_tree_snapshot, - start_nullifier_tree_snapshot, - end_nullifier_tree_snapshot, - start_contract_tree_snapshot, - end_contract_tree_snapshot, - start_public_data_tree_root, - end_public_data_tree_root, - start_tree_of_historical_note_hash_tree_roots_snapshot, - end_tree_of_historical_note_hash_tree_roots_snapshot, - start_tree_of_historical_contract_tree_roots_snapshot, - end_tree_of_historical_contract_tree_roots_snapshot, - start_l1_to_l2_message_tree_snapshot, - end_l1_to_l2_message_tree_snapshot, - start_tree_of_historical_l1_to_l2_message_tree_roots_snapshot, - end_tree_of_historical_l1_to_l2_message_tree_roots_snapshot, - start_archive_snapshot, - end_archive_snapshot, - calldata_hash, - l1_to_l2_messages_hash); - - bool operator==(RootRollupPublicInputs const&) const = default; - - fr hash() const - { - std::vector buf; - - write(&buf, global_variables); - write(buf, start_note_hash_tree_snapshot); - write(buf, start_nullifier_tree_snapshot); - write(buf, start_contract_tree_snapshot); - write(buf, start_tree_of_historical_note_hash_tree_roots_snapshot); - write(buf, start_tree_of_historical_contract_tree_roots_snapshot); - write(buf, start_public_data_tree_root); - write(buf, start_l1_to_l2_message_tree_snapshot); - write(buf, start_tree_of_historical_l1_to_l2_message_tree_roots_snapshot); - write(buf, start_archive_snapshot); - write(buf, end_note_hash_tree_snapshot); - write(buf, end_nullifier_tree_snapshot); - write(buf, end_contract_tree_snapshot); - write(buf, end_tree_of_historical_note_hash_tree_roots_snapshot); - write(buf, end_tree_of_historical_contract_tree_roots_snapshot); - write(buf, end_public_data_tree_root); - write(buf, end_l1_to_l2_message_tree_snapshot); - write(buf, end_tree_of_historical_l1_to_l2_message_tree_roots_snapshot); - write(buf, end_archive_snapshot); - - // Stitching calldata hash together - auto high_buffer = calldata_hash[0].to_buffer(); - auto low_buffer = calldata_hash[1].to_buffer(); - - for (uint8_t i = 0; i < 16; i++) { - buf.push_back(high_buffer[16 + i]); - } - for (uint8_t i = 0; i < 16; i++) { - buf.push_back(low_buffer[16 + i]); - } - - // Stitch l1_to_l2_messages_hash - auto high_buffer_m = l1_to_l2_messages_hash[0].to_buffer(); - auto low_buffer_m = l1_to_l2_messages_hash[1].to_buffer(); - - for (uint8_t i = 0; i < 16; i++) { - buf.push_back(high_buffer_m[16 + i]); - } - for (uint8_t i = 0; i < 16; i++) { - buf.push_back(low_buffer_m[16 + i]); - } - - return sha256::sha256_to_field(buf); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/tx_context.hpp b/circuits/cpp/src/aztec3/circuits/abis/tx_context.hpp deleted file mode 100644 index 278c8dc2ce0..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/tx_context.hpp +++ /dev/null @@ -1,108 +0,0 @@ -#pragma once -#include "contract_deployment_data.hpp" -#include "function_data.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct TxContext { - using address = typename NCT::address; - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - boolean is_fee_payment_tx = false; - boolean is_rebate_payment_tx = false; - boolean is_contract_deployment_tx = false; - - ContractDeploymentData contract_deployment_data{}; - - fr chain_id = 0; - fr version = 0; - - // for serialization: update up with new fields - MSGPACK_FIELDS(is_fee_payment_tx, - is_rebate_payment_tx, - is_contract_deployment_tx, - contract_deployment_data, - chain_id, - version); - boolean operator==(TxContext const& other) const - { - return is_fee_payment_tx == other.is_fee_payment_tx && is_rebate_payment_tx == other.is_rebate_payment_tx && - is_contract_deployment_tx == other.is_contract_deployment_tx && - contract_deployment_data == other.contract_deployment_data && chain_id == other.chain_id && - version == other.version; - }; - - template TxContext> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - // auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(builder); }; - - TxContext> tx_context = { - to_ct(is_fee_payment_tx), - to_ct(is_rebate_payment_tx), - to_ct(is_contract_deployment_tx), - contract_deployment_data.to_circuit_type(builder), - to_ct(chain_id), - to_ct(version), - }; - - return tx_context; - }; - - template TxContext to_native_type() const - { - static_assert(std::is_same, NCT>::value); - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - auto to_native_type = [](T& e) { return e.template to_native_type(); }; - - TxContext tx_context = { to_nt(is_fee_payment_tx), - to_nt(is_rebate_payment_tx), - to_nt(is_contract_deployment_tx), - to_native_type(contract_deployment_data), - to_nt(chain_id), - to_nt(version) }; - - return tx_context; - }; - - void set_public() - { - static_assert(!(std::is_same::value)); - - fr(is_fee_payment_tx).set_public(); - fr(is_rebate_payment_tx).set_public(); - fr(is_contract_deployment_tx).set_public(); - contract_deployment_data.set_public(); - chain_id.set_public(); - version.set_public(); - } - - fr hash() const - { - std::vector const inputs = { - fr(is_fee_payment_tx), - fr(is_rebate_payment_tx), - fr(is_contract_deployment_tx), - contract_deployment_data.hash(), - chain_id, - version, - }; - - return NCT::hash(inputs, GeneratorIndex::TX_CONTEXT); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/tx_request.hpp b/circuits/cpp/src/aztec3/circuits/abis/tx_request.hpp deleted file mode 100644 index c6682bf59c9..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/tx_request.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once -#include "function_data.hpp" -#include "tx_context.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::abis { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct TxRequest { - using address = typename NCT::address; - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - address origin = 0; - FunctionData function_data{}; - fr args_hash = 0; - TxContext tx_context{}; - - // For serialization, update with new fields - MSGPACK_FIELDS(origin, function_data, args_hash, tx_context); - boolean operator==(TxContext const& other) const - { - return origin == other.origin && function_data == other.function_data && args_hash == other.args && - tx_context == other.tx_context; - }; - - template TxRequest> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(builder); }; - - TxRequest> tx_request = { - to_ct(origin), - to_circuit_type(function_data), - to_ct(args_hash), - to_circuit_type(tx_context), - }; - - return tx_request; - }; - - fr hash() const - { - std::vector inputs; - inputs.push_back(fr(origin)); - inputs.push_back(function_data.hash()); - inputs.push_back(args_hash); - inputs.push_back(tx_context.hash()); - - return NCT::hash(inputs, GeneratorIndex::TX_REQUEST); - } -}; - -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/types.hpp b/circuits/cpp/src/aztec3/circuits/abis/types.hpp deleted file mode 100644 index e0601e48fc0..00000000000 --- a/circuits/cpp/src/aztec3/circuits/abis/types.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include "private_circuit_public_inputs.hpp" -#include "public_circuit_public_inputs.hpp" - -#include - -namespace aztec3::circuits::abis { - -template struct PrivateTypes { - using AppCircuitPublicInputs = PrivateCircuitPublicInputs; - // used in schema serialization - static constexpr char schema_name[] = "Private"; // NOLINT -}; - -template struct PublicTypes { - using AppCircuitPublicInputs = PublicCircuitPublicInputs; - // used in schema serialization - static constexpr char schema_name[] = "Public"; // NOLINT -}; -} // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/apps/.test.cpp b/circuits/cpp/src/aztec3/circuits/apps/.test.cpp deleted file mode 100644 index de490d5fd4e..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/.test.cpp +++ /dev/null @@ -1,383 +0,0 @@ - -#include - -// #include "utxo_state_var.hpp" - -#include "contract.hpp" -#include "function_execution_context.hpp" -#include "oracle_wrapper.hpp" -#include "notes/default_private_note/note.hpp" -#include "notes/default_private_note/note_preimage.hpp" -#include "notes/default_singleton_private_note/note.hpp" -#include "notes/default_singleton_private_note/note_preimage.hpp" -#include "notes/note_interface.hpp" -#include "state_vars/field_state_var.hpp" -#include "state_vars/mapping_state_var.hpp" -#include "state_vars/utxo_set_state_var.hpp" -#include "state_vars/utxo_state_var.hpp" - -#include "aztec3/oracle/oracle.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace { -// Builder -using C = UltraCircuitBuilder; - -// Types -using CT = aztec3::utils::types::CircuitTypes; -using NT = aztec3::utils::types::NativeTypes; -using aztec3::utils::types::to_ct; - -// exec_ctx -// using aztec3::circuits::apps::FunctionExecutionContext; - -// Contract -using Contract = aztec3::circuits::apps::Contract; - -// Oracle -using DB = aztec3::oracle::FakeDB; -using aztec3::oracle::NativeOracle; -using OracleWrapper = aztec3::circuits::apps::OracleWrapperInterface; - -// StateVars -using aztec3::circuits::apps::state_vars::FieldStateVar; -using aztec3::circuits::apps::state_vars::MappingStateVar; -using aztec3::circuits::apps::state_vars::UTXOSetStateVar; -using aztec3::circuits::apps::state_vars::UTXOStateVar; - - -using aztec3::circuits::apps::notes::DefaultPrivateNote; - -using aztec3::circuits::apps::notes::DefaultSingletonPrivateNote; - -// State variables -// Get rid of ugly `Builder` template arg from our state var types: -template using Mapping = MappingStateVar; -template using UTXO = UTXOStateVar; -template using UTXOSet = UTXOSetStateVar; - -using Field = FieldStateVar; -} // namespace - -namespace aztec3::circuits::apps { - -class state_var_tests : public ::testing::Test { - protected: - static NativeOracle get_test_native_oracle(DB& db) - { - const NT::address contract_address = 12345; - const NT::fr msg_sender_private_key = 123456789; - const NT::address msg_sender = NT::fr( - uint256_t(0x01071e9a23e0f7edULL, 0x5d77b35d1830fa3eULL, 0xc6ba3660bb1f0c0bULL, 0x2ef9f7f09867fd6eULL)); - - FunctionData const function_data{ - .selector = - { - .value = 1, // TODO: deduce this from the contract, somehow. - }, - .is_private = true, - .is_constructor = false, - }; - - CallContext const call_context{ .msg_sender = msg_sender, - .storage_contract_address = contract_address, - .portal_contract_address = 0, - .is_delegate_call = false, - .is_static_call = false, - .is_contract_deployment = false }; - - return NativeOracle(db, contract_address, function_data, call_context, msg_sender_private_key); - }; -}; - -TEST_F(state_var_tests, circuit_mapping) -{ - // TODO: currently, we can't hide all of this boilerplate in a test fixture function, because each of these classes - // contains a reference to earlier-declared classes... so we'd end up with classes containing dangling references, - // if all this stuff were to be declared in a setup function's scope. - // We could instead store shared_ptrs in every class...? - C builder = C(); - DB db; - NativeOracle native_oracle = get_test_native_oracle(db); - OracleWrapper oracle_wrapper = OracleWrapper(builder, native_oracle); - FunctionExecutionContext exec_ctx(builder, oracle_wrapper); - - // TODO: - // Interestingly, if I scope the below, the debugger works, but running the test via the command line fails. This is - // because all pointers to the contract which are stored in other classes become dangling pointers, because contract - // would go out of scope immediately... so the declaration of this contract and any pointers probably all need to be - // shared_ptr eventually. - // { - - // I'm not entirely sure why we need to prepend `::` to `Contract`, to get to the unnamed namespace's declaration of - // `Contract` above... - ::Contract contract("TestContract"); - exec_ctx.register_contract(&contract); - - contract.declare_state_var("my_mapping"); - // } - - Mapping my_mapping(&exec_ctx, "my_mapping"); - - my_mapping[5] = to_ct(builder, NT::fr(5)); - - // info("my_mapping[5]: ", my_mapping[5]); - // info("my_mapping[5].start_slot: ", my_mapping[5].start_slot); - // info("my_mapping[5].storage_slot_point: ", my_mapping[5].storage_slot_point); -} - -TEST_F(state_var_tests, circuit_mapping_within_mapping) -{ - C builder = C(); - DB db; - NativeOracle native_oracle = get_test_native_oracle(db); - OracleWrapper oracle_wrapper = OracleWrapper(builder, native_oracle); - FunctionExecutionContext exec_ctx(builder, oracle_wrapper); - - // { - ::Contract contract("TestContract"); - exec_ctx.register_contract(&contract); - - contract.declare_state_var("my_mapping"); - // } - - Mapping> my_mapping(&exec_ctx, "my_mapping"); - - my_mapping[5][6] = 7; - - info(my_mapping[5][6].state_var_name, ": ", my_mapping[5][6]); -} - -TEST_F(state_var_tests, circuit_partial_mapping) -{ - C builder = C(); - DB db; - NativeOracle native_oracle = get_test_native_oracle(db); - OracleWrapper oracle_wrapper = OracleWrapper(builder, native_oracle); - FunctionExecutionContext exec_ctx(builder, oracle_wrapper); - - // { - ::Contract contract("TestContract"); - exec_ctx.register_contract(&contract); - - contract.declare_state_var("my_mapping"); - // } - - Mapping> my_mapping(&exec_ctx, "my_mapping"); - - my_mapping["?"][6] = 7; - - info(my_mapping["?"][6].state_var_name, ": ", my_mapping["?"][6]); -} - -TEST_F(state_var_tests, circuit_utxo_of_default_private_note_fr) -{ - C builder = C(); - DB db; - NativeOracle native_oracle = get_test_native_oracle(db); - OracleWrapper oracle_wrapper = OracleWrapper(builder, native_oracle); - FunctionExecutionContext exec_ctx(builder, oracle_wrapper); - - ::Contract contract("TestContract"); - exec_ctx.register_contract(&contract); - - contract.declare_state_var("my_utxo"); - - // FUNCTION: - - using Note = DefaultPrivateNote; - - UTXO my_utxo(&exec_ctx, "my_utxo"); - - const auto& msg_sender = oracle_wrapper.get_msg_sender(); - - Note old_note = my_utxo.get({ .owner = msg_sender }); - - old_note.remove(); - - CT::fr const old_value = *(old_note.get_preimage().value); - - CT::fr new_value = old_value + 5; - - my_utxo.insert({ .value = new_value, // - .owner = msg_sender, - .creator_address = msg_sender, - .memo = 1234 }); - - exec_ctx.finalize(); - - // Here, we test that the shared_ptr of a note, stored within the exec_ctx, works. TODO: put this in its own little - // test, instead of this ever-growing beast test. - auto new_note_pointers = exec_ctx.get_new_notes(); - std::shared_ptr const debug_note = std::dynamic_pointer_cast(new_note_pointers[0]); - // info("new_note_pointers: ", new_note_pointers); - // info("*(new_note_pointers[0]): ", debug_note->get_preimage()); - - auto new_nullifiers = exec_ctx.get_new_nullifiers(); - // info("new_nullifiers: ", new_nullifiers); -} - -TEST_F(state_var_tests, circuit_utxo_set_of_default_private_notes_fr) -{ - C builder = C(); - DB db; - NativeOracle native_oracle = get_test_native_oracle(db); - OracleWrapper oracle_wrapper = OracleWrapper(builder, native_oracle); - FunctionExecutionContext exec_ctx(builder, oracle_wrapper); - - // bool sort(NT::uint256 i, NT::uint256 j) - // { - // return (i < j); - // }; - - ::Contract contract("TestContract"); - exec_ctx.register_contract(&contract); - - contract.declare_state_var("balances"); - - // FUNCTION: - - using Note = DefaultPrivateNote; - - UTXOSet balances(&exec_ctx, "balances"); - - // Imagine these were passed into the function as args: - CT::fr const amount = 5; - CT::address to_address = 765976; - - const auto& msg_sender = oracle_wrapper.get_msg_sender(); - - std::vector old_balance_notes = balances.get(2, { .owner = msg_sender }); - - CT::fr const old_value_1 = *(old_balance_notes[0].get_preimage().value); - CT::fr const old_value_2 = *(old_balance_notes[1].get_preimage().value); - - old_balance_notes[0].remove(); - old_balance_notes[1].remove(); - - // MISSING: overflow & underflow checks, but I can't be bothered with safe_uint or range checks yet. - - CT::fr new_value = (old_value_1 + old_value_2) - amount; - - balances.insert({ - .value = new_value, - .owner = to_address, - .creator_address = msg_sender, - .memo = 1234, - }); - - exec_ctx.finalize(); - - // Here, we test that the shared_ptr of a note, stored within the exec_ctx, works. TODO: put this in its own little - // test, instead of this ever-growing beast test. - auto new_note_pointers = exec_ctx.get_new_notes(); - std::shared_ptr const debug_note = std::dynamic_pointer_cast(new_note_pointers[0]); - // info("new_note_pointers: ", new_note_pointers); - // info("*(new_note_pointers[0]): ", debug_note->get_preimage()); - - auto new_nullifiers = exec_ctx.get_new_nullifiers(); - // info("new_nullifiers: ", new_nullifiers); -} - -TEST_F(state_var_tests, circuit_initialize_utxo_of_default_singleton_private_note_fr) -{ - C builder = C(); - DB db; - NativeOracle native_oracle = get_test_native_oracle(db); - OracleWrapper oracle_wrapper = OracleWrapper(builder, native_oracle); - FunctionExecutionContext exec_ctx(builder, oracle_wrapper); - - ::Contract contract("TestContract"); - exec_ctx.register_contract(&contract); - - contract.declare_state_var("my_utxo"); - - // FUNCTION: - - // This time we use a slightly different Note type, which is tailored towards singleton UTXO use-cases. In - // particular, it copes with the distinction between initialization of the UTXO, vs future modification of the UTXO. - using Note = DefaultSingletonPrivateNote; - - UTXO my_utxo(&exec_ctx, "my_utxo"); - - // We hard-code the address of the person who may initialize the state in the 'contract's bytecode' (i.e. as a - // selector value). (Number chosen to match msg_sender of tests). - const CT::address unique_person_who_may_initialize = - NT::uint256(0x01071e9a23e0f7edULL, 0x5d77b35d1830fa3eULL, 0xc6ba3660bb1f0c0bULL, 0x2ef9f7f09867fd6eULL); - - unique_person_who_may_initialize.assert_equal(oracle_wrapper.get_msg_sender()); - - // The person who may initialize the note might be different from the person who's actually given the note to own. - // (E.g. the caller of this function might be the deployer of the contract, who is initializing notes on behalf of - // other users) - CT::address owner_of_initialized_note = 888888; - - my_utxo.initialize({ .value = 100, .owner = owner_of_initialized_note }); - - exec_ctx.finalize(); - - // Here, we test that the shared_ptr of a note, stored within the exec_ctx, works. TODO: put this in its own little - // test, instead of this ever-growing beast test. - auto new_note_pointers = exec_ctx.get_new_notes(); - std::shared_ptr const debug_note = std::dynamic_pointer_cast(new_note_pointers[0]); - // info("new_note_pointers: ", new_note_pointers); - // info("*(new_note_pointers[0]): ", debug_note->get_preimage()); - - auto new_nullifiers = exec_ctx.get_new_nullifiers(); - // info("new_nullifiers: ", new_nullifiers); -} - -TEST_F(state_var_tests, circuit_modify_utxo_of_default_singleton_private_note_fr) -{ - C builder = C(); - DB db; - NativeOracle native_oracle = get_test_native_oracle(db); - OracleWrapper oracle_wrapper = OracleWrapper(builder, native_oracle); - FunctionExecutionContext exec_ctx(builder, oracle_wrapper); - - ::Contract contract("TestContract"); - exec_ctx.register_contract(&contract); - - contract.declare_state_var("my_utxo"); - - // FUNCTION: - - // This time we use a slightly different Note type, which is tailored towards singleton UTXO use-cases. In - // particular, it copes with the distinction between initialization of the UTXO, vs future modification of the UTXO. - using Note = DefaultSingletonPrivateNote; - - UTXO my_utxo(&exec_ctx, "my_utxo"); - - const auto& msg_sender = oracle_wrapper.get_msg_sender(); - - Note old_note = my_utxo.get({ .owner = msg_sender }); - - old_note.remove(); - - CT::fr const old_value = *(old_note.get_preimage().value); - - CT::fr new_value = old_value + 5; - - my_utxo.insert({ - .value = new_value, // - .owner = msg_sender, - }); - - exec_ctx.finalize(); - - // Here, we test that the shared_ptr of a note, stored within the exec_ctx, works. TODO: put this in its own little - // test, instead of this ever-growing beast test. - auto new_note_pointers = exec_ctx.get_new_notes(); - std::shared_ptr const debug_note = std::dynamic_pointer_cast(new_note_pointers[0]); - // info("new_note_pointers: ", new_note_pointers); - // info("*(new_note_pointers[0]): ", debug_note->get_preimage()); - - auto new_nullifiers = exec_ctx.get_new_nullifiers(); - // info("new_nullifiers: ", new_nullifiers); -} - -} // namespace aztec3::circuits::apps \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/CMakeLists.txt b/circuits/cpp/src/aztec3/circuits/apps/CMakeLists.txt deleted file mode 100644 index 59a9a8ad289..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -circuits_cmake_module( - aztec3_circuits_apps - barretenberg -) \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/README.md b/circuits/cpp/src/aztec3/circuits/apps/README.md deleted file mode 100644 index d323b199f28..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# aztec3::circuits::apps - -All code in this dir is for: -- Demonstrating how our users' (developers) apps will need to be written, in terms of: - - Public inputs - - Syntax for State Variables & UTXOs - - Function calls -- To help illustrate ideas to the Noir team -- To allow test app circuits to be mocked-up as quickly and easily as possible, for use in the Kernel & Rollup circuits. - - - - -utxo_state_var.insert(note_preimage) - ↓ -Opcodes.UTXO_SSTORE (this=state_var*, note_preimage) - ↓ -exec_ctx got from state_var->exec_ctx -new_note = Note(state_var, new_note_preimage) <- could be done in state_var -exec_ctx->new_notes.push_back(new_note) -NO VISITOR CALLED - - - -utxo_state_var.get(NotePreimage advice) - ↓ -Opcodes.UTXO_LOAD (this=state_var*, advice) - ↓ -oracle got from state_var->exec_ctx->oracle -storage_slot_point got from state_var->storage_slot_point -Grab note_preimages and paths from DB -new_note = Note(state_var, note_preimage) -Compare against advice -- VISITOR CALLED: new_note.constrain_against_advice(advice) -Membership checks (and other checks) -- VISITOR CALLED: new_note.get_commitment() -return new_note - - - -note.remove() - ↓ -Opcodes.UTXO_NULL (state_var*, *this=note) - ↓ -exec_ctx got from state_var->exec_ctx -- VISITOR CALLED: - - nullifier = note.compute_nullifier() <- could be done in state_var -exec_ctx->new_nullifiers.push_back(nullifier) - - - -utxo_state_var.initialize(note_preimage) - ↓ -Opcodes.UTXO_SSTORE (this=state_var*, note_preimage) - ↓ -exec_ctx got from state_var->exec_ctx -new_note = Note(state_var, new_note_preimage) -exec_ctx->new_notes.push_back(new_note) -NO VISITOR CALLED \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/contract.hpp b/circuits/cpp/src/aztec3/circuits/apps/contract.hpp deleted file mode 100644 index cfb880a96cc..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/contract.hpp +++ /dev/null @@ -1,103 +0,0 @@ -#pragma once - -#include "function_declaration.hpp" - -#include "aztec3/circuits/abis/function_data.hpp" - -#include - -namespace aztec3::circuits::apps { - -using aztec3::circuits::abis::FunctionData; - -using NT = aztec3::utils::types::NativeTypes; - -// template class FunctionExecutionContext; - -template class Contract { - using fr = typename NCT::fr; - using uint32 = typename NCT::uint32; - - public: - const std::string contract_name; - - fr state_var_counter = 0; - - std::vector state_var_names; - - std::map start_slots_by_state_var_name; - - std::map> function_datas; - - std::map> imported_contracts; - - explicit Contract(std::string const& contract_name) : contract_name(contract_name) - { - // exec_ctx.register_contract(this); - } - - void set_functions(std::vector> const& functions); - - void import_contracts(std::vector>> import_declarations); - - Contract& get_imported_contract(std::string const& name) - { - if (!imported_contracts.contains(name)) { - throw_or_abort("No contract with that name imported"); - } - return imported_contracts[name]; - } - - // TODO: return some Function class which has a `call` method... - // FunctionData get_function(std::string name) { return function_data[name]; } - - FunctionData get_function_data_by_name(std::string const& name); - - // TODO: maybe also declare a type at this stage, so the correct type can be checked-for when the StateVar type is - // created within the function. - /** - * Note: this simply tracks the 'start' storage slots of each state variable at the 'contract scope level'. - * TODO: maybe we can just keep a vector of names and query the start slot with index_of(), instead. - */ - void declare_state_var(std::string const& state_var_name) - { - push_new_state_var_name(state_var_name); - start_slots_by_state_var_name[state_var_name] = state_var_counter; - // state_var_counter++; - state_var_counter++; - ASSERT(state_var_counter == state_var_names.size()); - }; - - fr& get_start_slot(std::string const& state_var_name) - { - if (!start_slots_by_state_var_name.contains(state_var_name)) { - throw_or_abort("Name '" + state_var_name + "' not found. Use `declare_state_var`."); - } - return start_slots_by_state_var_name.at(state_var_name); - }; - - private: - // Prevents an infinite loop if two contracts import each other. - bool already_imported; - - void push_new_state_var_name(std::string const& state_var_name) - { - if (index_of(state_var_names, state_var_name) == -1) { - state_var_names.push_back(state_var_name); - - return; - } - throw_or_abort("name already exists"); - } -}; - -} // namespace aztec3::circuits::apps - -// Importing in this way (rather than explicit instantiation of a template class at the bottom of a .cpp file) preserves -// the following: -// - We retain implicit instantiation of templates. -// - We don't implement method definitions in this file, to avoid a circular dependency with -// function_execution_context.hpp. -// TODO: things have changed since initially importing this .tpp file - maybe a conventional .cpp file is possible now -// instead... -#include "contract.tpp" \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/contract.tpp b/circuits/cpp/src/aztec3/circuits/apps/contract.tpp deleted file mode 100644 index 0496fb90dfa..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/contract.tpp +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once - -#include "function_declaration.hpp" -#include "function_execution_context.hpp" - -#include "aztec3/circuits/abis/function_data.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/convert.hpp" - -#include - -namespace aztec3::circuits::apps { - -using NT = aztec3::utils::types::NativeTypes; -using aztec3::circuits::abis::FunctionData; -using aztec3::circuits::abis::FunctionSelector; - -template void Contract::set_functions(std::vector> const& functions) -{ - for (uint32_t i = 0; i < functions.size(); ++i) { - const auto& function = functions[i]; - if (function_datas.contains(function.name)) { - throw_or_abort("Name already exists"); - } - function_datas[function.name] = FunctionData{ - .selector = - { - .value = static_cast(i), - }, - .is_private = function.is_private, - .is_constructor = function.is_constructor, - }; - } -}; - -template -void Contract::import_contracts(std::vector>> const import_declarations) -{ - // Prevents an infinite loop if two contracts import each-other. - if (already_imported) { - return; - } - - for (uint32_t i = 0; i < import_declarations.size(); ++i) { - const std::pair>& decl = import_declarations[i]; - if (imported_contracts.contains(decl.first)) { - throw_or_abort("Name already exists"); - } - imported_contracts.insert(decl); - } - already_imported = true; -} - -// TODO: return some Function class which has a `call` method... -// FunctionData get_function(std::string name) { return function_data[name]; } - -template FunctionData Contract::get_function_data_by_name(std::string const& name) -{ - if (!function_datas.contains(name)) { - throw_or_abort("function data not found"); - } - return function_datas[name]; -} - -} // namespace aztec3::circuits::apps \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/function_declaration.hpp b/circuits/cpp/src/aztec3/circuits/apps/function_declaration.hpp deleted file mode 100644 index 20266e2e9f8..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/function_declaration.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::apps { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using plonk::stdlib::witness_t; - -// This exists just so that designated initializers can be used when passing this info to a function, for readability. -template struct FunctionDeclaration { - using boolean = typename NCT::boolean; - - std::string name; - boolean is_private = false; - boolean is_constructor = false; -}; - -} // namespace aztec3::circuits::apps \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/function_execution_context.hpp b/circuits/cpp/src/aztec3/circuits/apps/function_execution_context.hpp deleted file mode 100644 index 172e17d13c1..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/function_execution_context.hpp +++ /dev/null @@ -1,336 +0,0 @@ -#pragma once - -#include "contract.hpp" -#include "oracle_wrapper.hpp" -#include "notes/note_interface.hpp" -#include "opcodes/opcodes.hpp" - -#include "aztec3/circuits/abis/call_stack_item.hpp" -#include "aztec3/circuits/abis/function_data.hpp" -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/types.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/convert.hpp" - -#include - -namespace aztec3::circuits::apps { - -using aztec3::circuits::abis::CallStackItem; -using aztec3::circuits::abis::FunctionData; -using aztec3::circuits::abis::OptionalPrivateCircuitPublicInputs; -using aztec3::circuits::abis::PrivateCircuitPublicInputs; -using aztec3::circuits::abis::PrivateTypes; - -using aztec3::circuits::apps::notes::NoteInterface; -using aztec3::circuits::apps::opcodes::Opcodes; - -using plonk::stdlib::array_push; - -using aztec3::utils::types::CircuitTypes; -using plonk::stdlib::witness_t; -using NT = aztec3::utils::types::NativeTypes; -using aztec3::utils::types::to_ct; -using aztec3::utils::types::to_nt; - -template class FunctionExecutionContext { - using NT = NativeTypes; - using CT = CircuitTypes; - using fr = typename CT::fr; - using address = typename CT::address; - - // We restrict only the opcodes to be able to push to the private members of the exec_ctx. - // This will just help us build better separation of concerns. - friend class Opcodes; - - public: - Builder& builder; - OracleWrapperInterface& oracle; - - Contract* contract = nullptr; - - std::array>, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL> - nested_private_call_exec_ctxs; - - // TODO: make this private! - OptionalPrivateCircuitPublicInputs private_circuit_public_inputs{}; - - private: - std::vector>> new_notes; - std::vector new_commitments; - - // Nullifier preimages can be got from the corresponding Note that they nullify. - std::vector>> nullified_notes; - std::vector new_nullifiers; - std::vector nullified_commitments; - - PrivateCircuitPublicInputs final_private_circuit_public_inputs{}; - - bool is_finalized = false; - - public: - FunctionExecutionContext(Builder& builder, OracleWrapperInterface& oracle) - : builder(builder) - , oracle(oracle) - , private_circuit_public_inputs(OptionalPrivateCircuitPublicInputs::create()) - { - private_circuit_public_inputs.call_context = oracle.get_call_context(); - private_circuit_public_inputs.contract_deployment_data = oracle.get_contract_deployment_data(); - } - - void register_contract(Contract* contract) - { - if (this->contract != nullptr) { - throw_or_abort("A contract is already assigned to this FunctionExecutionContext"); - } - this->contract = contract; - } - - // TODO: consider making this a debug-only method. - // Not a reference, because we won't want to allow unsafe access. Hmmm, except it's a vector of pointers, so one can - // still modify the pointers... But at least the original vector isn't being pushed-to or deleted-from. - std::vector>> get_new_notes() { return new_notes; } - - std::vector get_new_nullifiers() { return new_nullifiers; } - - void push_new_note(NoteInterface* const note_ptr) { new_notes.push_back(note_ptr); } - - void push_newly_nullified_note(NoteInterface* note_ptr) { nullified_notes.push_back(note_ptr); } - - PrivateCircuitPublicInputs get_final_private_circuit_public_inputs() - { - // For safety, only return this if the circuit is complete. - if (!is_finalized) { - throw_or_abort("You need to call exec_ctx.finalize() in your circuit first."); - } - return final_private_circuit_public_inputs; - } - - /** - * @brief Get the call_stack_item representing `this` exec_ctx's function call. - */ - CallStackItem get_call_stack_item() - { - const NT::address& actual_contract_address = oracle.native_oracle.get_actual_contract_address(); - const FunctionData& function_data = oracle.native_oracle.get_function_data(); - - return CallStackItem{ - .contract_address = actual_contract_address, - .function_data = function_data, - .public_inputs = get_final_private_circuit_public_inputs(), - }; - } - - /** - * @brief Get the call_stack_items of any nested function calls made by this exec_ctx's function. - */ - std::array, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL> get_private_call_stack_items() - { - std::array, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL> result; - - for (size_t i = 0; i < result.size(); ++i) { - auto& nested_exec_ctx = nested_private_call_exec_ctxs[i]; - if (nested_exec_ctx != nullptr) { - const NT::address& actual_contract_address = - nested_exec_ctx->oracle.native_oracle.get_actual_contract_address(); - const FunctionData& function_data = nested_exec_ctx->oracle.native_oracle.get_function_data(); - - result[i] = CallStackItem{ - .contract_address = actual_contract_address, - .function_data = function_data, - .public_inputs = nested_exec_ctx->get_final_private_circuit_public_inputs(), - }; - } - } - - // TODO: do we need to instantiate-with-zeros the structs at the unused indices of `result`? - - return result; - } - - /** - * @brief Allows a call to be made to a function of another contract - * - * TODO: maybe we want to move some of the code that's in this function into a method in the Opcodes class. Although - * that class was really shoehorned into existence, and is a bit bleurgh. - */ - std::array call( - address const& f_contract_address, - std::string const& f_name, - std::function&, std::vector)> f, - std::vector const& args) - { - // Convert function name to bytes and use the first 4 bytes as the function encoding, for now: - std::vector f_name_bytes(f_name.begin(), f_name.end()); - std::vector f_encoding_bytes(f_name_bytes.begin(), f_name_bytes.begin() + 4); - uint32_t f_encoding = 0; - memcpy(&f_encoding, f_encoding_bytes.data(), sizeof(f_encoding)); - - fr f_encoding_ct = fr(f_encoding); - // Important Note: we MUST constrain this function_selector value against a fixed selector value. Without the - // below line, an attacker could pass any f_encoding as a witness. - f_encoding_ct.convert_constant_to_fixed_witness(&builder); - - /// @dev The above constraining could alternatively be achieved as follows: - // fr alternative_f_encoding_ct = fr(to_ct(builder, f_encoding)); - // alternative_f_encoding_ct.fix_witness(); - - const FunctionData f_function_data_ct{ - // Note: we MUST - .selector = - { - .value = f_encoding_ct, - }, - .is_private = true, - .is_constructor = false, - }; - - const CallContext f_call_context_ct{ - .msg_sender = oracle.get_this_contract_address(), // the sender is `this` contract! - .storage_contract_address = f_contract_address, - .portal_contract_address = 0, // TODO - .function_selector = f_function_data_ct.selector, - .is_delegate_call = false, - .is_static_call = false, - .is_contract_deployment = false, - }; - - NativeOracle f_oracle(oracle.native_oracle.db, - f_contract_address.get_value(), - f_function_data_ct.template to_native_type(), - f_call_context_ct.template to_native_type(), - oracle.get_msg_sender_private_key() - .get_value() // TODO: consider whether a nested function should even be able to - // access a private key, given that the call is now coming from a - // contract (which cannot own a secret), rather than a human. - ); - - Builder f_builder = Builder(); - - OracleWrapperInterface f_oracle_wrapper(f_builder, f_oracle); - - // We need an exec_ctx reference which won't go out of scope, so we store a shared_ptr to the newly-created - // exec_ctx in `this` exec_ctx. - auto f_exec_ctx = std::make_shared>(f_builder, f_oracle_wrapper); - - array_push(nested_private_call_exec_ctxs, f_exec_ctx); - - auto native_args = to_nt(args); - - // This calls the function `f`, passing the arguments shown. - // The f_exec_ctx will be populated with all the information about that function's execution. - std::apply(f, std::forward_as_tuple(*f_exec_ctx, native_args)); - - // Remember: the data held in the f_exec_ctc was built with a different builder than that - // of `this` exec_ctx. So we only allow ourselves to get the native types, so that we can consciously declare - // circuit types for `this` exec_ctx using `this->builder`. - auto f_public_inputs_nt = f_exec_ctx->get_final_private_circuit_public_inputs(); - - // Since we've made a call to another function, we now need to push a call_stack_item_hash to `this` function's - // private call stack. - // Note: we need to constrain some of `this` circuit's variables against f's public inputs: - // - args - // - return_values - // - call_context (TODO: maybe this only needs to be done in the kernel circuit). - auto f_public_inputs_ct = f_public_inputs_nt.to_circuit_type(builder); - - // Constrain that the arguments of the executed function match those we expect: - auto args_hash_ct = compute_var_args_hash(args); - args_hash_ct.assert_equal(f_public_inputs_ct.args_hash); - - CallStackItem const f_call_stack_item_ct{ - .contract_address = f_contract_address, - .function_data = f_function_data_ct, - .public_inputs = f_public_inputs_ct, - }; - - auto call_stack_item_hash = f_call_stack_item_ct.hash(); - - array_push(private_circuit_public_inputs.private_call_stack, call_stack_item_hash); - - // The return values are implicitly constrained by being returned as circuit types from this method, for - // further use in the circuit. Note: ALL elements of the return_values array MUST be constrained, even if - // they're placeholder zeroes. - return f_public_inputs_ct.return_values; - } - - /** - * @brief This is an important optimization, to save on the number of emitted nullifiers. - * - * A nullifier is ideal to serve as a nonce for a new note commitment, because its uniqueness is enforced by the - * Rollup circuit. But we won't know how many non-dummy nullifiers we have at our disposal (to inject into - * commitments) until the end of the function. - * - * Or to put it another way, at the time we want to create a new commitment (during a function's execution), we - * would need a nonce. We could certainly query the `exec_ctx` for any nullifiers which have already been created - * earlier in this function's execution, and we could use one of those. But there might not-yet have been any - * nullifiers created within the function. Now, at that point, we _could_ generate a dummy nullifier and use that as - * a nonce. But that uses up a precious slot in the circuit's nullifiers array (part of the circuit's public inputs - * abi). And it might be the case that later in the function, a load of non-dummy nullifiers get created. So as an - * optimization, it would be better if we could use _those_ nullifiers, so as to minimize dummy values in the - * circuit's public inputs. - * - * And so, we provide the option here of deferring the injection of nonces into note_preimages (and hence deferring - * the computation of each new note commitment) until the very end of the function's execution, when we know how - * many non-dummy nullifiers we have to play with. If we find this circuit is creating more new commitments than new - * nullifiers, we can generate some dummy nullifiers at this stage to make up the difference. - * - * Note: Using a nullifier as a nonce is a very common and widely-applicable pattern. So much so that it feels - * acceptable to have this function execute regardless of the underlying Note types being used by the circuit. - * - * Note: It's up to the implementer of a custom Note type to decide how a nonce is derived, via the `set_nonce() - * override` method dictated by the NoteInterface. - * - * Note: Not all custom Note types will need a nonce of this kind in their NotePreimage. But they can simply - * implement an empty body in the `set_nonce() override`. - * - * TODO: Might need some refactoring. Roles between: Opcodes modifying exec_ctx members; and the exec_ctx directly - * modifying its members, are somewhat blurred at the moment. - */ - void finalize_utxos() - { - // Copy some vectors, as we can't control whether they'll be pushed-to further, when we call Note methods. - auto new_nullifiers_copy = new_nullifiers; - - size_t used_nullifiers_count = 0; - fr next_nullifier; - std::vector new_nonces; - - // This is almost a visitor pattern. Call methods on each note. The note will choose what to do. - for (size_t i = 0; i < new_notes.size(); ++i) { - NoteInterface& note = *new_notes[i]; - - if (note.needs_nonce()) { - const bool next_nullifier_available = new_nullifiers_copy.size() > used_nullifiers_count; - - if (next_nullifier_available) { - next_nullifier = new_nullifiers_copy[used_nullifiers_count++]; - note.set_nonce(next_nullifier); - } else { - const fr new_nonce = note.generate_nonce(); - new_nonces.push_back(new_nonce); - } - } - - new_commitments.push_back(note.get_commitment()); - } - - // Push new_nonces to the end of new_nullifiers: - std::copy(new_nonces.begin(), new_nonces.end(), std::back_inserter(new_nullifiers)); - } - - void finalize() - { - finalize_utxos(); - private_circuit_public_inputs.set_commitments(new_commitments); - private_circuit_public_inputs.set_nullifiers(new_nullifiers); - private_circuit_public_inputs.set_nullified_commitments(nullified_commitments); - private_circuit_public_inputs.set_public(builder); - final_private_circuit_public_inputs = - private_circuit_public_inputs.remove_optionality().template to_native_type(); - is_finalized = true; - } -}; - -} // namespace aztec3::circuits::apps diff --git a/circuits/cpp/src/aztec3/circuits/apps/notes/default_private_note/note.hpp b/circuits/cpp/src/aztec3/circuits/apps/notes/default_private_note/note.hpp deleted file mode 100644 index 6c2837c5447..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/notes/default_private_note/note.hpp +++ /dev/null @@ -1,130 +0,0 @@ -#pragma once - -#include "note_preimage.hpp" -#include "nullifier_preimage.hpp" -#include "../note_interface.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -// Forward-declare from this namespace in particular: -namespace aztec3::circuits::apps::state_vars { -template class StateVar; -} // namespace aztec3::circuits::apps::state_vars - -namespace aztec3::circuits::apps::notes { - -using aztec3::circuits::apps::state_vars::StateVar; // Don't #include it! - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template class DefaultPrivateNote : public NoteInterface { - public: - using CT = CircuitTypes; - using fr = typename CT::fr; - using grumpkin_point = typename CT::grumpkin_point; - using address = typename CT::address; - using boolean = typename CT::boolean; - - using NotePreimage = DefaultPrivateNotePreimage, ValueType>; - using NullifierPreimage = DefaultPrivateNoteNullifierPreimage>; - - - StateVar* state_var; - - private: - std::optional commitment; - std::optional nullifier; - std::optional partial_commitment; - - NotePreimage note_preimage; - std::optional nullifier_preimage; - - public: - DefaultPrivateNote(StateVar* state_var, NotePreimage note_preimage) - : state_var(state_var), note_preimage(note_preimage){}; - - ~DefaultPrivateNote() override = default; - - // OVERRIDE METHODS: - - void remove() override; - - fr get_commitment() override - { - if (commitment) { - return *commitment; - } - return compute_commitment(); - }; - - fr get_nullifier() override - { - if (nullifier) { - return *nullifier; - } - return compute_nullifier(); - }; - - // grumpkin_point get_partial_commitment() override const - // { - // if (!partial_commitment) { - // throw_or_abort( - // "No partial_commitment exists for this note. Are you sure you haven't accidentally created a " - // "complete commitment?"); - // } - // return *partial_commitment; - // }; - - void constrain_against_advice(NoteInterface const& advice_note) override; - - bool needs_nonce() override; - - void set_nonce(fr const& nonce) override; - - fr generate_nonce() override; - - fr get_initialization_nullifier() override - { - throw_or_abort( - "DefaultPrivateNote does not support initialization. Maybe use DefaultSingletonPrivateNote instead?"); - }; - - fr get_initialization_commitment() override - { - throw_or_abort( - "DefaultPrivateNote does not support initialization. Maybe use DefaultSingletonPrivateNote instead?"); - }; - - // CUSTOM METHODS - - auto& get_oracle(); - - grumpkin_point compute_partial_commitment(); - - fr compute_dummy_nullifier(); - - static fr compute_nullifier(fr const& commitment, - fr const& owner_private_key, - boolean const& is_dummy_commitment = false); - - NotePreimage& get_preimage() { return note_preimage; }; - - private: - fr compute_commitment(); - fr compute_nullifier(); - - bool is_partial_preimage() const; - bool is_partial_storage_slot() const; - bool is_partial() const; -}; - -} // namespace aztec3::circuits::apps::notes - -// Importing in this way (rather than explicit instantiation of a template class at the bottom of a .cpp file) preserves -// the following: -// - We retain implicit instantiation of templates. -// - We don't implement method definitions in this file, to avoid a circular dependency with the state_var files (which -// are forward-declared in this file). -#include "note.tpp" \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/notes/default_private_note/note.tpp b/circuits/cpp/src/aztec3/circuits/apps/notes/default_private_note/note.tpp deleted file mode 100644 index 67a71a529bf..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/notes/default_private_note/note.tpp +++ /dev/null @@ -1,195 +0,0 @@ -#include "note_preimage.hpp" -#include "nullifier_preimage.hpp" -#include "../../opcodes/opcodes.hpp" -#include "../../oracle_wrapper.hpp" -#include "../../state_vars/state_var_base.hpp" -#include "../note_interface.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace { -using aztec3::circuits::apps::opcodes::Opcodes; -using aztec3::circuits::apps::state_vars::StateVar; -} // namespace - -namespace aztec3::circuits::apps::notes { - -using aztec3::GeneratorIndex; -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using plonk::stdlib::witness_t; - -template void DefaultPrivateNote::remove() -{ - Opcodes::UTXO_NULL(state_var, *this); -} - -template auto& DefaultPrivateNote::get_oracle() -{ - return state_var->exec_ctx->oracle; -} - -template bool DefaultPrivateNote::is_partial_preimage() const -{ - const auto& [value, owner, creator_address, memo, salt, nonce, _] = note_preimage; - - return (!value || !owner || !creator_address || !memo || !salt || !nonce); -} - -template bool DefaultPrivateNote::is_partial_storage_slot() const -{ - return state_var->is_partial_slot; -} - -template bool DefaultPrivateNote::is_partial() const -{ - return is_partial_preimage() || is_partial_storage_slot(); -} - -template -typename CircuitTypes::fr DefaultPrivateNote::compute_commitment() -{ - if (commitment.has_value()) { - return *commitment; - } - - grumpkin_point const storage_slot_point = state_var->storage_slot_point; - - if (!note_preimage.salt) { - note_preimage.salt = get_oracle().generate_random_element(); - } - - const auto& [value, owner, creator_address, memo, salt, nonce, is_dummy] = note_preimage; - - const grumpkin_point commitment_point = - storage_slot_point + CT::commit( - { - *value, /*PrivateStateNoteGeneratorIndex::VALUE*/ - (*owner).to_field(), /*PrivateStateNoteGeneratorIndex::OWNER*/ - (*creator_address).to_field(), /*PrivateStateNoteGeneratorIndex::CREATOR*/ - *memo, /*PrivateStateNoteGeneratorIndex::MEMO*/ - *salt, /*PrivateStateNoteGeneratorIndex::SALT*/ - *nonce, /*PrivateStateNoteGeneratorIndex::NONCE*/ - is_dummy, /*PrivateStateNoteGeneratorIndex::IS_DUMMY*/ - }, - GeneratorIndex::COMMITMENT); - - commitment = commitment_point.x; - - return *commitment; -} - -template -typename CircuitTypes::fr DefaultPrivateNote::compute_nullifier() -{ - if (is_partial()) { - throw_or_abort("Can't nullify a partial note."); - } - if (nullifier && nullifier_preimage) { - return *nullifier; - } - if (!commitment) { - compute_commitment(); - } - - fr const& owner_private_key = get_oracle().get_msg_sender_private_key(); - - nullifier = - DefaultPrivateNote::compute_nullifier(*commitment, owner_private_key, note_preimage.is_dummy); - nullifier_preimage = { - *commitment, - owner_private_key, - note_preimage.is_dummy, - }; - return *nullifier; -}; - -template -typename CircuitTypes::fr DefaultPrivateNote::compute_dummy_nullifier() -{ - auto& oracle = get_oracle(); - fr const dummy_commitment = oracle.generate_random_element(); - fr const& owner_private_key = oracle.get_msg_sender_private_key(); - const boolean is_dummy_commitment = true; - - return DefaultPrivateNote::compute_nullifier(dummy_commitment, owner_private_key, is_dummy_commitment); -}; - -template -typename CircuitTypes::fr DefaultPrivateNote::compute_nullifier(fr const& commitment, - fr const& owner_private_key, - boolean const& is_dummy_commitment) -{ - const std::vector hash_inputs{ - commitment, - owner_private_key, - is_dummy_commitment, - }; - - // We compress the hash_inputs with Pedersen, because that's cheaper (constraint-wise) than compressing - // the data directly with Blake2s in the next step. - const fr compressed_inputs = CT::hash(hash_inputs, GeneratorIndex::NULLIFIER); - - // Blake2s hash the compressed result. Without this it's possible to leak info from the pedersen - // compression. - /** E.g. we can extract a representation of the hashed_pk: - * Paraphrasing, if: - * nullifier = note_comm * G1 + hashed_pk * G2 + is_dummy_note * G3 - * Then an observer can derive hashed_pk * G2 = nullifier - note_comm * G1 - is_dummy_note * G3 - * They can derive this for every tx, to link which txs are being sent by the same user. - * Notably, at the point someone withdraws, the observer would be able to connect `hashed_pk * G2` with a - * specific eth address. - */ - auto blake_input = typename CT::byte_array(compressed_inputs); - auto blake_result = CT::blake2s(blake_input); - return fr(blake_result); -}; - -template -void DefaultPrivateNote::constrain_against_advice(NoteInterface const& advice_note) -{ - // Cast from a ref to the base (interface) type to a ref to this derived type: - const auto& advice_note_ref = dynamic_cast&>(advice_note); - - auto assert_equal = [](std::optional& this_member, std::optional const& advice_member) { - if (advice_member) { - (*this_member).assert_equal(*advice_member); - } - }; - - const auto& advice_preimage = advice_note_ref.note_preimage; - auto& this_preimage = note_preimage; - - assert_equal(this_preimage.value, advice_preimage.value); - assert_equal(this_preimage.owner, advice_preimage.owner); - assert_equal(this_preimage.creator_address, advice_preimage.creator_address); - assert_equal(this_preimage.memo, advice_preimage.memo); - assert_equal(this_preimage.salt, advice_preimage.salt); - assert_equal(this_preimage.nonce, advice_preimage.nonce); -} - -template bool DefaultPrivateNote::needs_nonce() -{ - return !note_preimage.nonce; -} - -template -void DefaultPrivateNote::set_nonce(typename CircuitTypes::fr const& nonce) -{ - ASSERT(!note_preimage.nonce); - note_preimage.nonce = nonce; -}; - -template -typename CircuitTypes::fr DefaultPrivateNote::generate_nonce() -{ - ASSERT(!note_preimage.nonce); - note_preimage.nonce = compute_dummy_nullifier(); - return *(note_preimage.nonce); -}; - -} // namespace aztec3::circuits::apps::notes \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/notes/default_private_note/note_preimage.hpp b/circuits/cpp/src/aztec3/circuits/apps/notes/default_private_note/note_preimage.hpp deleted file mode 100644 index e93eb00e0bb..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/notes/default_private_note/note_preimage.hpp +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::apps::notes { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct DefaultPrivateNotePreimage { - using fr = typename NCT::fr; - using address = typename NCT::address; - using boolean = typename NCT::boolean; - - // No custom constructors so that designated initializers can be used (for readability of test circuits). - - std::optional value; - std::optional
owner; - std::optional
creator_address; - std::optional memo; // numerical representation of a string - - std::optional salt; - std::optional nonce; - - boolean is_dummy = false; - // For serialization, update with new fields - MSGPACK_FIELDS(value, owner, creator_address, memo, salt, nonce, is_dummy); - - bool operator==(DefaultPrivateNotePreimage const&) const = default; - - template auto to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - // Depending on whether the _circuit_ type version of `V` is from the stdlib, or some custom type, the - // conversion method will be different. - const bool has_to_circuit_type = requires(V v) { v.to_circuit_type(); }; - const bool has_to_ct = requires(V v) { to_ct(v); }; - - // To avoid messy template arguments in the calling code, we use a lambda function with `auto` return type to - // avoid explicitly having to state the circuit type for `V`. - auto circuit_value = [&]() -> auto - { - if constexpr (has_to_circuit_type) { - return value.to_circuit_type(); - } else if (has_to_ct) { - return to_ct(value); - } else { - throw_or_abort("Can't convert Value to circuit type"); - } - } - (); - - // When this method is called, this class must be templated over native types. We can avoid templating over the - // circuit types (for the return values) (in order to make the calling syntax cleaner) with the below `decltype` - // deduction of the _circuit_ version of template type `V`. - DefaultPrivateNotePreimage, typename decltype(circuit_value)::value_type> preimage = { - circuit_value, to_ct(owner), to_ct(creator_address), to_ct(memo), - to_ct(salt), to_ct(nonce), to_ct(is_dummy), - }; - - return preimage; - }; - - template auto to_native_type() const - { - static_assert(!std::is_same::value); - - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - // See `to_circuit_type()` for explanation of this code. - const bool has_to_native_type = requires(V v) { v.to_native_type(); }; - const bool has_to_nt = requires(V v) { to_nt(v); }; - - auto native_value = [&]() -> auto - { - if constexpr (has_to_native_type) { - return value.to_native_type(); - } else if (has_to_nt) { - return to_nt(value); - } else { - throw_or_abort("Can't convert Value to native type"); - } - } - (); - - DefaultPrivateNotePreimage preimage = { - native_value, to_nt(owner), to_nt(creator_address), to_nt(memo), to_nt(salt), to_nt(nonce), to_nt(is_dummy), - }; - - return preimage; - }; -}; - -} // namespace aztec3::circuits::apps::notes diff --git a/circuits/cpp/src/aztec3/circuits/apps/notes/default_private_note/nullifier_preimage.hpp b/circuits/cpp/src/aztec3/circuits/apps/notes/default_private_note/nullifier_preimage.hpp deleted file mode 100644 index 9cf6fb9ac3b..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/notes/default_private_note/nullifier_preimage.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::apps::notes { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct DefaultPrivateNoteNullifierPreimage { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - fr commitment; - fr owner_private_key; - boolean is_dummy = false; - // For serialization, update with new fields - MSGPACK_FIELDS(commitment, owner_private_key, is_dummy); - - bool operator==(DefaultPrivateNoteNullifierPreimage const&) const = default; - - template - DefaultPrivateNoteNullifierPreimage> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - DefaultPrivateNoteNullifierPreimage> preimage = { - to_ct(commitment), - to_ct(owner_private_key), - to_ct(is_dummy), - }; - - return preimage; - }; -}; - -} // namespace aztec3::circuits::apps::notes diff --git a/circuits/cpp/src/aztec3/circuits/apps/notes/default_singleton_private_note/note.hpp b/circuits/cpp/src/aztec3/circuits/apps/notes/default_singleton_private_note/note.hpp deleted file mode 100644 index df09571661c..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/notes/default_singleton_private_note/note.hpp +++ /dev/null @@ -1,111 +0,0 @@ -#pragma once - -#include "note_preimage.hpp" -#include "nullifier_preimage.hpp" -#include "../note_interface.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -// Forward-declare from this namespace in particular: -namespace aztec3::circuits::apps::state_vars { -template class StateVar; -} // namespace aztec3::circuits::apps::state_vars - -namespace aztec3::circuits::apps::notes { - -using aztec3::circuits::apps::state_vars::StateVar; // Don't #include it! - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template class DefaultSingletonPrivateNote : public NoteInterface { - public: - using CT = CircuitTypes; - using fr = typename CT::fr; - using grumpkin_point = typename CT::grumpkin_point; - using address = typename CT::address; - using boolean = typename CT::boolean; - - using NotePreimage = DefaultSingletonPrivateNotePreimage, ValueType>; - using NullifierPreimage = DefaultSingletonPrivateNoteNullifierPreimage>; - - - StateVar* state_var; - - private: - std::optional commitment; - std::optional nullifier; - - NotePreimage note_preimage; - std::optional nullifier_preimage; - - public: - DefaultSingletonPrivateNote(StateVar* state_var, NotePreimage note_preimage) - : state_var(state_var), note_preimage(note_preimage){}; - - ~DefaultSingletonPrivateNote() override = default; - - // OVERRIDE METHODS: - - void remove() override; - - fr get_commitment() override - { - if (commitment) { - return *commitment; - } - return compute_commitment(); - }; - - fr get_nullifier() override - { - if (nullifier) { - return *nullifier; - } - return compute_nullifier(); - }; - - void constrain_against_advice(NoteInterface const& advice_note) override; - - bool needs_nonce() override; - - void set_nonce(fr const& nonce) override; - - fr generate_nonce() override; - - fr get_initialization_nullifier() override; - - fr get_initialization_commitment() override; - - // CUSTOM METHODS - - auto& get_oracle(); - - grumpkin_point compute_partial_commitment(); - - fr compute_dummy_nullifier(); - - static fr compute_nullifier(fr const& commitment, - fr const& owner_private_key, - boolean const& is_dummy_commitment = false); - - NotePreimage& get_preimage() { return note_preimage; }; - - private: - fr compute_commitment(); - fr compute_nullifier(); - - bool is_partial_preimage() const; - bool is_partial_storage_slot() const; - bool is_partial() const; -}; - -} // namespace aztec3::circuits::apps::notes - -// Importing in this way (rather than explicit instantiation of a template class at the bottom of a .cpp file) preserves -// the following: -// - We retain implicit instantiation of templates. -// - We don't implement method definitions in this file, to avoid a circular dependency with the state_var files (which -// are forward-declared in this file). -#include "note.tpp" \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/notes/default_singleton_private_note/note.tpp b/circuits/cpp/src/aztec3/circuits/apps/notes/default_singleton_private_note/note.tpp deleted file mode 100644 index 1f9b44822bf..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/notes/default_singleton_private_note/note.tpp +++ /dev/null @@ -1,251 +0,0 @@ -#include "note_preimage.hpp" -#include "nullifier_preimage.hpp" -#include "../../opcodes/opcodes.hpp" -#include "../../oracle_wrapper.hpp" -#include "../../state_vars/state_var_base.hpp" -#include "../note_interface.hpp" - -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace { -using aztec3::circuits::apps::opcodes::Opcodes; -using aztec3::circuits::apps::state_vars::StateVar; -} // namespace - -namespace aztec3::circuits::apps::notes { - -using aztec3::GeneratorIndex; - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using plonk::stdlib::witness_t; - -template void DefaultSingletonPrivateNote::remove() -{ - Opcodes::UTXO_NULL(state_var, *this); -} - -template auto& DefaultSingletonPrivateNote::get_oracle() -{ - return state_var->exec_ctx->oracle; -} - -template bool DefaultSingletonPrivateNote::is_partial_preimage() const -{ - const auto& [value, owner, salt, nonce] = note_preimage; - - return (!value || !owner || !salt || !nonce); -} - -template bool DefaultSingletonPrivateNote::is_partial_storage_slot() const -{ - return state_var->is_partial_slot; -} - -template bool DefaultSingletonPrivateNote::is_partial() const -{ - return is_partial_preimage() || is_partial_storage_slot(); -} - -template -typename CircuitTypes::fr DefaultSingletonPrivateNote::compute_commitment() -{ - if (commitment.has_value()) { - return *commitment; - } - - grumpkin_point const storage_slot_point = state_var->storage_slot_point; - - if (!note_preimage.salt) { - note_preimage.salt = get_oracle().generate_random_element(); - } - - const auto& [value, owner, salt, nonce] = note_preimage; - - const grumpkin_point commitment_point = - storage_slot_point + CT::commit( - { - *value, /*PrivateStateNoteGeneratorIndex::VALUE*/ - (*owner).to_field(), /*PrivateStateNoteGeneratorIndex::OWNER*/ - *salt, /*PrivateStateNoteGeneratorIndex::SALT*/ - *nonce, /*PrivateStateNoteGeneratorIndex::NONCE*/ - }, - GeneratorIndex::COMMITMENT); - - commitment = commitment_point.x; - - return *commitment; -} - -template -typename CircuitTypes::fr DefaultSingletonPrivateNote::compute_nullifier() -{ - if (is_partial()) { - throw_or_abort("Can't nullify a partial note."); - } - if (nullifier && nullifier_preimage) { - return *nullifier; - } - if (!commitment) { - compute_commitment(); - } - - fr const& owner_private_key = get_oracle().get_msg_sender_private_key(); - - nullifier = DefaultSingletonPrivateNote::compute_nullifier(*commitment, owner_private_key); - nullifier_preimage = { - *commitment, - owner_private_key, - }; - return *nullifier; -}; - -template -typename CircuitTypes::fr DefaultSingletonPrivateNote::compute_dummy_nullifier() -{ - auto& oracle = get_oracle(); - fr const dummy_commitment = oracle.generate_random_element(); - fr const& owner_private_key = oracle.get_msg_sender_private_key(); - const boolean is_dummy_commitment = true; - - return DefaultSingletonPrivateNote::compute_nullifier( - dummy_commitment, owner_private_key, is_dummy_commitment); -}; - -template -typename CircuitTypes::fr DefaultSingletonPrivateNote::compute_nullifier( - fr const& commitment, fr const& owner_private_key, boolean const& is_dummy_commitment) -{ - const std::vector hash_inputs{ - commitment, - owner_private_key, - is_dummy_commitment, - }; - - // We compress the hash_inputs with Pedersen, because that's cheaper (constraint-wise) than compressing - // the data directly with Blake2s in the next step. - const fr compressed_inputs = CT::hash(hash_inputs, GeneratorIndex::NULLIFIER); - - // Blake2s hash the compressed result. Without this it's possible to leak info from the pedersen - // compression. - /** E.g. we can extract a representation of the hashed_pk: - * Paraphrasing, if: - * nullifier = note_comm * G1 + hashed_pk * G2 + is_dummy_note * G3 - * Then an observer can derive hashed_pk * G2 = nullifier - note_comm * G1 - is_dummy_note * G3 - * They can derive this for every tx, to link which txs are being sent by the same user. - * Notably, at the point someone withdraws, the observer would be able to connect `hashed_pk * G2` with a - * specific eth address. - */ - auto blake_input = typename CT::byte_array(compressed_inputs); - auto blake_result = CT::blake2s(blake_input); - return fr(blake_result); -}; - -template -void DefaultSingletonPrivateNote::constrain_against_advice(NoteInterface const& advice_note) -{ - // Cast from a ref to the base (interface) type to a ref to this derived type: - const auto& advice_note_ref = dynamic_cast&>(advice_note); - - auto assert_equal = [](std::optional& this_member, std::optional const& advice_member) { - if (advice_member) { - (*this_member).assert_equal(*advice_member); - } - }; - - const auto& advice_preimage = advice_note_ref.note_preimage; - auto& this_preimage = note_preimage; - - assert_equal(this_preimage.value, advice_preimage.value); - assert_equal(this_preimage.owner, advice_preimage.owner); - assert_equal(this_preimage.salt, advice_preimage.salt); - assert_equal(this_preimage.nonce, advice_preimage.nonce); -} - -template bool DefaultSingletonPrivateNote::needs_nonce() -{ - return !note_preimage.nonce; -} - -template -void DefaultSingletonPrivateNote::set_nonce(typename CircuitTypes::fr const& nonce) -{ - ASSERT(!note_preimage.nonce); - note_preimage.nonce = nonce; -}; - -template -typename CircuitTypes::fr DefaultSingletonPrivateNote::generate_nonce() -{ - ASSERT(!note_preimage.nonce); - note_preimage.nonce = compute_dummy_nullifier(); - return *(note_preimage.nonce); -}; - -template -typename CircuitTypes::fr DefaultSingletonPrivateNote::get_initialization_nullifier() -{ - auto& oracle = get_oracle(); - - const fr& owner_private_key = oracle.get_msg_sender_private_key(); - - // We prevent this storage slot from even being initialized again: - auto& storage_slot_point = state_var->storage_slot_point; - - const std::vector hash_inputs{ - storage_slot_point.x, - storage_slot_point.y, - }; - - const bool is_dummy = false; - - // We compress the hash_inputs with Pedersen, because that's cheap. - const fr compressed_storage_slot_point = CT::hash(hash_inputs, GeneratorIndex::INITIALIZATION_NULLIFIER); - - // For now, we piggy-back on the regular nullifier function. - return DefaultSingletonPrivateNote::compute_nullifier( - compressed_storage_slot_point, owner_private_key, is_dummy); -}; - -template -typename CircuitTypes::fr DefaultSingletonPrivateNote::get_initialization_commitment() -{ - /** - * TODO: Get rid of this temporary fix of including owner_private_key while computing the initialization commitment. - * Details: We need to add the initialization commitment value to the `nullified_commitments`. - * In this case, since the actual note data is not yet available, we compute the initialization nullifier as: - * null = hash(compressed_storage_slot, owner_private_key, false) - * - * Thus, the initialization commitment here is `compressed_storage_slot`. But since the storage slot is not a real - * circuit variable, `compressed_storage_slot` would be a circuit constant. The compiler doesn't allow us - * to make a circuit constant as a public input of the circuit, it just crashes at runtime. - * To avoid this, we compute the initial commitment as: - * comm = hash(storage_slot_point.x, storage_slot_point.y, owner_private_key) - * - * This makes the initial commitment a "real" circuit variable. - */ - auto& oracle = get_oracle(); - - const fr& owner_private_key = oracle.get_msg_sender_private_key(); - - // We prevent this storage slot from even being initialized again: - auto& storage_slot_point = state_var->storage_slot_point; - - const std::vector hash_inputs{ - storage_slot_point.x, - storage_slot_point.y, - owner_private_key, - }; - - // We compress the hash_inputs with Pedersen, because that's cheap. - fr compressed_storage_slot_point = CT::hash(hash_inputs, GeneratorIndex::INITIALIZATION_NULLIFIER); - - return compressed_storage_slot_point; -}; - -} // namespace aztec3::circuits::apps::notes \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/notes/default_singleton_private_note/note_preimage.hpp b/circuits/cpp/src/aztec3/circuits/apps/notes/default_singleton_private_note/note_preimage.hpp deleted file mode 100644 index 852897c4ac8..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/notes/default_singleton_private_note/note_preimage.hpp +++ /dev/null @@ -1,106 +0,0 @@ -#pragma once - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::apps::notes { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct DefaultSingletonPrivateNotePreimage { - using fr = typename NCT::fr; - using grumpkin_point = typename NCT::grumpkin_point; - using address = typename NCT::address; - using boolean = typename NCT::boolean; - - // No custom constructors so that designated initializers can be used (for readability of test circuits). - - std::optional value; - std::optional
owner; - - std::optional salt; - std::optional nonce; - - // For serialization, update with new fields - MSGPACK_FIELDS(value, owner, salt, nonce); - - bool operator==(DefaultSingletonPrivateNotePreimage const&) const = default; - - template auto to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - // Depending on whether the _circuit_ type version of `V` is from the stdlib, or some custom type, the - // conversion method will be different. - const bool has_to_circuit_type = requires(V v) { v.to_circuit_type(); }; - const bool has_to_ct = requires(V v) { to_ct(v); }; - - // To avoid messy template arguments in the calling code, we use a lambda function with `auto` return type to - // avoid explicitly having to state the circuit type for `V`. - auto circuit_value = [&]() -> auto - { - if constexpr (has_to_circuit_type) { - return value.to_circuit_type(); - } else if (has_to_ct) { - return to_ct(value); - } else { - throw_or_abort("Can't convert Value to circuit type"); - } - } - (); - - // When this method is called, this class must be templated over native types. We can avoid templating over the - // circuit types (for the return values) (in order to make the calling syntax cleaner) with the below `decltype` - // deduction of the _circuit_ version of template type `V`. - DefaultSingletonPrivateNotePreimage, typename decltype(circuit_value)::value_type> - preimage = { - circuit_value, - to_ct(owner), - to_ct(salt), - to_ct(nonce), - }; - - return preimage; - }; - - template auto to_native_type() const - { - static_assert(!std::is_same::value); - - auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - - // See `to_circuit_type()` for explanation of this code. - const bool has_to_native_type = requires(V v) { v.to_native_type(); }; - const bool has_to_nt = requires(V v) { to_nt(v); }; - - auto native_value = [&]() -> auto - { - if constexpr (has_to_native_type) { - return value.to_native_type(); - } else if (has_to_nt) { - return to_nt(value); - } else { - throw_or_abort("Can't convert Value to native type"); - } - } - (); - - DefaultSingletonPrivateNotePreimage preimage = { - native_value, - to_nt(owner), - to_nt(salt), - to_nt(nonce), - }; - - return preimage; - }; -}; - -} // namespace aztec3::circuits::apps::notes diff --git a/circuits/cpp/src/aztec3/circuits/apps/notes/default_singleton_private_note/nullifier_preimage.hpp b/circuits/cpp/src/aztec3/circuits/apps/notes/default_singleton_private_note/nullifier_preimage.hpp deleted file mode 100644 index f73cd42560d..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/notes/default_singleton_private_note/nullifier_preimage.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::apps::notes { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -template struct DefaultSingletonPrivateNoteNullifierPreimage { - using fr = typename NCT::fr; - using boolean = typename NCT::boolean; - - fr commitment; - fr owner_private_key; - boolean is_dummy = false; - - // For serialization, update with new fields - MSGPACK_FIELDS(commitment, owner_private_key, is_dummy); - - bool operator==(DefaultSingletonPrivateNoteNullifierPreimage const&) const = default; - - template - DefaultSingletonPrivateNoteNullifierPreimage> to_circuit_type(Builder& builder) const - { - static_assert((std::is_same::value)); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - DefaultSingletonPrivateNoteNullifierPreimage> preimage = { - to_ct(commitment), - to_ct(owner_private_key), - to_ct(is_dummy), - }; - - return preimage; - }; -}; - -} // namespace aztec3::circuits::apps::notes diff --git a/circuits/cpp/src/aztec3/circuits/apps/notes/note_interface.hpp b/circuits/cpp/src/aztec3/circuits/apps/notes/note_interface.hpp deleted file mode 100644 index f9bfb3c7e94..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/notes/note_interface.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include "aztec3/utils/types/circuit_types.hpp" - -namespace aztec3::circuits::apps::notes { - -using aztec3::utils::types::CircuitTypes; - -/** - * Note: The methods in this interface must be implemented by the derived Note types, even if such note types don't - * require such functions. - * - * It's essentially a visitor pattern. The Opcodes and UTXOStateVar types can call all of these - * methods on any Note, and the Note must choose whether to compute something, or whether to throw, for each method. - */ -template class NoteInterface { - public: - using CT = CircuitTypes; - using fr = typename CT::fr; - using grumpkin_point = typename CT::grumpkin_point; - using address = typename CT::address; - using boolean = typename CT::boolean; - - // Destructor explicitly made virtual, to ensure that the destructor of the derived class is called if the derived - // object is deleted through a pointer to this base class. (In many places in the code, files handle - // `NoteInterface*` pointers instead of the derived class). - virtual ~NoteInterface() = default; - - // TODO: maybe rather than have this be a pure interface, we should have a constructor and the `state_var*` and - // `note_preimage` members here (although that would require a NotePreimage template param). - // This is all because the Opcodes actually _assume_ a particular constructor layout for each Note, as well as - // _assume_ those two data members are always present. Having said that, there's still no way to actually enforce a - // constructor function data of a derived class. - - virtual void remove() = 0; - - virtual fr get_commitment() = 0; - - virtual fr get_nullifier() = 0; - - virtual fr get_initialization_nullifier() = 0; - - virtual fr get_initialization_commitment() = 0; - - virtual void constrain_against_advice(NoteInterface const& advice_note) = 0; - - virtual bool needs_nonce() = 0; - - virtual void set_nonce(fr const& nonce) = 0; - - virtual fr generate_nonce() = 0; -}; - -} // namespace aztec3::circuits::apps::notes \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/opcodes/opcodes.hpp b/circuits/cpp/src/aztec3/circuits/apps/opcodes/opcodes.hpp deleted file mode 100644 index ca2bef912fd..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/opcodes/opcodes.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::apps::state_vars { -template class StateVar; -template class UTXOStateVar; -template class UTXOSetStateVar; -} // namespace aztec3::circuits::apps::state_vars - -namespace aztec3::circuits::apps::opcodes { - -using aztec3::circuits::apps::state_vars::StateVar; // Don't #include it! -using aztec3::circuits::apps::state_vars::UTXOSetStateVar; // Don't #include it! -using aztec3::circuits::apps::state_vars::UTXOStateVar; // Don't #include it! - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using plonk::stdlib::witness_t; - -/** - * @brief - These static methods are a suggestion for what ACIR++ 'Opcodes' might do. They can get - * data from an oracle. They can apply constraints to that data. And they are the only class allowed to push data to the - * execution context. - * Separating out this functionality into a separate `Opcodes` class, like this, was trickier than - * just writing this stuff directly in the `Note` or `FunctionExecutionContext` classes, but hopefully the separation is - * sensible. - * - * TODO: Any oracle access or exec_ctx access should go through this class? - */ -template class Opcodes { - public: - using CT = CircuitTypes; - using address = typename CT::address; - - /** - * @brief - * - Load a singleton UTXOSLoadDatum from the Private Client's DB - * - Generate constraints to prove its existence in the tree - * - Validate the data - */ - template - static Note UTXO_SLOAD(UTXOStateVar* utxo_state_var, typename Note::NotePreimage const& advice); - - /** - * @brief - * - Load a subset of `UTXOSLoadDatum`s (which belong to a particular UTXOSetStateVar), from the Private Client's DB - * - Generate constraints to prove each datum's existence in the tree - * - Validate the data - */ - template static std::vector UTXO_SLOAD(UTXOSetStateVar* utxo_set_state_var, - size_t const& num_notes, - typename Note::NotePreimage const& advice); - - /** - * @brief Compute and push a new nullifier to the public inputs of this exec_ctx. - */ - template static void UTXO_NULL(StateVar* state_var, Note& note_to_nullify); - - /** - * @brief Compute and push a new commitment to the public inputs of this exec_ctx, BUT ALSO compute and produce an - * initialization nullifier, to prevent this note from being initialized again in the future. - */ - template static void UTXO_INIT(StateVar* state_var, Note& note_to_initialize); - - /** - * @brief Compute and push a new commitment to the public inputs of this exec_ctx. - */ - template - static void UTXO_SSTORE(StateVar* state_var, typename Note::NotePreimage new_note_preimage); -}; - -} // namespace aztec3::circuits::apps::opcodes - -// Importing in this way (rather than explicit instantiation of a template class at the bottom of a .cpp file) preserves -// the following: -// - We retain implicit instantiation of templates. -// - We don't implement method definitions in this file, to avoid a circular dependency with the state_var files (which -// are forward-declared in this file). -#include "opcodes.tpp" diff --git a/circuits/cpp/src/aztec3/circuits/apps/opcodes/opcodes.tpp b/circuits/cpp/src/aztec3/circuits/apps/opcodes/opcodes.tpp deleted file mode 100644 index 25c8c81a860..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/opcodes/opcodes.tpp +++ /dev/null @@ -1,153 +0,0 @@ -#pragma once - -#include "../state_vars/state_var_base.hpp" -#include "../state_vars/utxo_set_state_var.hpp" -#include "../state_vars/utxo_state_var.hpp" -#include "../function_execution_context.hpp" -#include "../utxo_datum.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace { -// Declared here, so that `opcodes.hpp` doesn't see it; thereby preventing circular dependencies. -using aztec3::circuits::apps::state_vars::StateVar; -using aztec3::circuits::apps::state_vars::UTXOSetStateVar; -using aztec3::circuits::apps::state_vars::UTXOStateVar; -} // namespace - -namespace aztec3::circuits::apps::opcodes { - -using aztec3::circuits::apps::FunctionExecutionContext; - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using plonk::stdlib::witness_t; - -template template -Note Opcodes::UTXO_SLOAD(UTXOStateVar* utxo_state_var, - typename Note::NotePreimage const& advice) -{ - auto& oracle = utxo_state_var->exec_ctx->oracle; - - typename CT::grumpkin_point const& storage_slot_point = utxo_state_var->storage_slot_point; - - // Retrieve UTXO witness datum from the DB: - UTXOSLoadDatum const utxo_datum = - oracle.template get_utxo_sload_datum(storage_slot_point, advice); - - Note new_note{ utxo_state_var, utxo_datum.preimage }; - Note advice_note{ utxo_state_var, advice }; - - new_note.constrain_against_advice(advice_note); - - // TODO: hard-code or calculate the correct commitment in the FakeDB stub, so that the returned data passes this - // check. - // Commenting-out this check for now, so the proof verifies. - // info("calculated commitment: ", new_note.get_commitment()); - // info("retrieved commitment: ", utxo_datum.commitment); - // new_note.get_commitment().assert_equal(utxo_datum.commitment, "UTXO_SLOAD: bad commitment"); - - oracle.get_contract_address().assert_equal(utxo_datum.contract_address, "UTXO_SLOAD: bad contract address"); - - // TODO within this function: - // - Merkle Membership Check using the contract_address, utxo_datum.{sibling_path, leaf_index, - // historical_note_hash_tree_root} - - return new_note; -}; - -template template -std::vector Opcodes::UTXO_SLOAD(UTXOSetStateVar* utxo_set_state_var, - size_t const& num_notes, - typename Note::NotePreimage const& advice) -{ - auto& oracle = utxo_set_state_var->exec_ctx->oracle; - - typename CT::grumpkin_point const& storage_slot_point = utxo_set_state_var->storage_slot_point; - - // Retrieve multiple UTXO witness datum's from the DB: - std::vector> utxo_data = - oracle.template get_utxo_sload_data(storage_slot_point, num_notes, advice); - - // Rely on the oracle to pad the data set with dummies, if there aren't enough notes in the DB. - ASSERT(utxo_data.size() == num_notes); - - std::vector new_notes; - - for (size_t i = 0; i < num_notes; i++) { - auto& utxo_datum = utxo_data[i]; - Note new_note{ utxo_set_state_var, utxo_datum.preimage }; - Note advice_note{ utxo_set_state_var, advice }; - - new_note.constrain_against_advice(advice_note); - - // TODO: hard-code or calculate the correct commitment in the FakeDB stub, so that the returned data passes this - // check. - // Commenting-out this check for now, so the proof verifies. - // info("calculated commitment: ", new_note.get_commitment()); - // info("retrieved commitment: ", utxo_datum.commitment); - // new_note.get_commitment().assert_equal(utxo_datum.commitment, "UTXO_SLOAD: bad commitment"); - - oracle.get_contract_address().assert_equal(utxo_datum.contract_address, "UTXO_SLOAD: bad contract address"); - - // TODO within this function: - // - Merkle Membership Check using the contract_address, utxo_datum.{sibling_path, leaf_index, - // historical_note_hash_tree_root} - - new_notes.push_back(new_note); - } - - return new_notes; -}; - -template template -void Opcodes::UTXO_NULL(StateVar* state_var, Note& note_to_nullify) -{ - typename CT::fr const nullifier = note_to_nullify.get_nullifier(); - typename CT::fr const nullified_note_commitment = note_to_nullify.get_commitment(); - - auto& exec_ctx = state_var->exec_ctx; - - exec_ctx->new_nullifiers.push_back(nullifier); - exec_ctx->nullified_commitments.push_back(nullified_note_commitment); - - std::shared_ptr const nullified_note_ptr = std::make_shared(note_to_nullify); - - exec_ctx->nullified_notes.push_back(nullified_note_ptr); -}; - -template template -void Opcodes::UTXO_INIT(StateVar* state_var, Note& note_to_initialize) -{ - typename CT::fr const init_nullifier = note_to_initialize.get_initialization_nullifier(); - typename CT::fr const init_commitment = note_to_initialize.get_initialization_commitment(); - - auto& exec_ctx = state_var->exec_ctx; - - exec_ctx->new_nullifiers.push_back(init_nullifier); - exec_ctx->nullified_commitments.push_back(init_commitment); - - std::shared_ptr const init_note_ptr = std::make_shared(note_to_initialize); - - // TODO: consider whether this should actually be pushed-to... - exec_ctx->nullified_notes.push_back(init_note_ptr); - - exec_ctx->new_notes.push_back(init_note_ptr); -}; - -template template -void Opcodes::UTXO_SSTORE(StateVar* state_var, typename Note::NotePreimage new_note_preimage) -{ - auto& exec_ctx = state_var->exec_ctx; - - // Make a shared pointer, so we don't end up with a dangling pointer in the exec_ctx when this `new_note` - // immediately goes out of scope. - std::shared_ptr const new_note_ptr = std::make_shared(state_var, new_note_preimage); - - exec_ctx->new_notes.push_back(new_note_ptr); -}; - -} // namespace aztec3::circuits::apps::opcodes diff --git a/circuits/cpp/src/aztec3/circuits/apps/oracle_wrapper.hpp b/circuits/cpp/src/aztec3/circuits/apps/oracle_wrapper.hpp deleted file mode 100644 index 5e30857ad2c..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/oracle_wrapper.hpp +++ /dev/null @@ -1,133 +0,0 @@ -#pragma once - -#include "aztec3/circuits/abis/call_context.hpp" -#include "aztec3/circuits/abis/contract_deployment_data.hpp" -#include "aztec3/oracle/oracle.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::apps { - -using NT = aztec3::utils::types::NativeTypes; -using aztec3::circuits::abis::CallContext; -using aztec3::circuits::abis::ContractDeploymentData; -using aztec3::oracle::NativeOracle; -using aztec3::utils::types::CircuitTypes; - -/** - * The main purpose of this wrapper is to: - * - cache values which have been already given by the oracle previously during this execution; - * - convert Native types (returned by the oracle) into circuit types, using the builder instance. - * Note: Insecure circuits could be built if the same value is queried twice from the oracle (since a malicious prover - * could provide two different witnesses for a single thing). The Native oracle will throw if you try a double-query of - * certain information. - */ -template class OracleWrapperInterface { - using CT = CircuitTypes; - using fr = typename CT::fr; - using grumpkin_point = typename CT::grumpkin_point; - using address = typename CT::address; - - public: - Builder& builder; - NativeOracle& native_oracle; - - // Initialize from Native. - // Used when initializing for a user's first call. - OracleWrapperInterface(Builder& builder, NativeOracle& native_oracle) - : builder(builder), native_oracle(native_oracle){}; - - fr& get_msg_sender_private_key() - { - if (msg_sender_private_key) { - return *msg_sender_private_key; - } - msg_sender_private_key = aztec3::utils::types::to_ct(builder, native_oracle.get_msg_sender_private_key()); - validate_msg_sender_private_key(); - return *msg_sender_private_key; - }; - - address get_contract_address() { return get_call_context().storage_contract_address; }; - - CallContext& get_call_context() - { - if (call_context) { - return *call_context; - } - call_context = native_oracle.get_call_context().to_circuit_type(builder); - return *call_context; - }; - - ContractDeploymentData& get_contract_deployment_data() - { - if (contract_deployment_data) { - return *contract_deployment_data; - } - contract_deployment_data = native_oracle.get_contract_deployment_data().to_circuit_type(builder); - return *contract_deployment_data; - }; - - address& get_msg_sender() { return get_call_context().msg_sender; }; - - address& get_this_contract_address() { return get_call_context().storage_contract_address; }; - - address& get_tx_origin() { return get_call_context().tx_origin; }; - - fr generate_salt() const { return aztec3::utils::types::to_ct(builder, native_oracle.generate_salt()); } - - fr generate_random_element() const - { - return aztec3::utils::types::to_ct(builder, native_oracle.generate_random_element()); - } - - template - auto get_utxo_sload_datum(grumpkin_point const& storage_slot_point, NotePreimage const& advice) - { - auto native_storage_slot_point = aztec3::utils::types::to_nt(storage_slot_point); - - auto native_advice = advice.template to_native_type(); - - auto native_utxo_sload_datum = native_oracle.get_utxo_sload_datum(native_storage_slot_point, native_advice); - - return native_utxo_sload_datum.to_circuit_type(builder); - } - - template auto get_utxo_sload_data(grumpkin_point const& storage_slot_point, - size_t const& num_notes, - NotePreimage const& advice) - { - auto native_storage_slot_point = aztec3::utils::types::to_nt(storage_slot_point); - - auto native_advice = advice.template to_native_type(); - - auto native_utxo_sload_data = - native_oracle.get_utxo_sload_data(native_storage_slot_point, num_notes, native_advice); - - auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(builder); }; - - return map(native_utxo_sload_data, to_circuit_type); - } - - private: - std::optional> call_context; - std::optional> contract_deployment_data; - std::optional msg_sender_private_key; - - void validate_msg_sender_private_key() - { - const address msg_sender = get_msg_sender(); - const address derived_msg_sender = address::derive_from_private_key(*msg_sender_private_key); - msg_sender.assert_equal(derived_msg_sender, - format("msg_sender validation failed.\nmsg_sender_private_key: ", - msg_sender_private_key, - "\nPurported msg_sender: ", - msg_sender, - "\nDerived msg_sender: ", - derived_msg_sender)); - } -}; - -} // namespace aztec3::circuits::apps \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/private_state.test.cpp b/circuits/cpp/src/aztec3/circuits/apps/private_state.test.cpp deleted file mode 100644 index 4584d1d145e..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/private_state.test.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// #include "index.hpp" - -// // #include "aztec3/constants.hpp" -// -// #include -// #include - -// namespace aztec3::circuits::apps { - -// namespace { -// using Builder = aztec3::utils::types:plonk::stdlib::types::Builder; -// using CT = aztec3::utils::types::CircuitTypes; -// using NT = aztec3::utils::types::NativeTypes; -// // using plonk::stdlib::pedersen; -// } // namespace - -// class private_state_tests : public ::testing::Test {}; - -// // TEST(private_state_tests, test_native_private_state) -// // { -// // StateFactory state_factory("MyContract"); -// // PrivateStateVar x = state_factory.declare_private_state_var("x"); - -// // PrivateStateVar native_private_state = PrivateStateVar(x); - -// // auto buffer = to_buffer(native_private_state); - -// // auto native_private_state_2 = from_buffer>(buffer.data()); - -// // EXPECT_EQ(native_private_state, native_private_state_2); -// // } - -// // TEST(private_state_tests, test_create_private_state) -// // { -// // StateFactory state_factory("MyContract"); - -// // state_factory.declare_private_state_var("balances", { "asset_id", "owner" }); - -// // state_factory.declare_private_state_var("x"); - -// // // info("state_factory: ", state_factory); -// // } - -// // TEST(private_state_tests, test_native_private_state_note_preimage) -// // { -// // StateFactory state_factory("MyContract"); -// // PrivateStateVar x = state_factory.declare_private_state_var("x"); - -// // PrivateStateNotePreimage native_preimage = { -// // .value = 2, -// // .owner = 3, -// // .creator_address = NT::address(4), -// // .salt = 5, -// // .nonce = 6, -// // .memo = 7, -// // }; - -// // auto buffer = to_buffer(native_preimage); - -// // auto native_preimage_2 = from_buffer>(buffer.data()); - -// // EXPECT_EQ(native_preimage, native_preimage_2); -// // } - -// // TEST(private_state_tests, test_native_private_state_note_preimage_mapping) -// // { -// // StateFactory state_factory("MyContract"); -// // PrivateStateVar x = state_factory.declare_private_state_var("x", { "mapping_key_name_1", -// "mapping_key_name_2" -// // }); - -// // PrivateStateNotePreimage native_preimage = { -// // .mapping_key_values_by_key_name = std::map>({ { "mapping_key_name_2", 5 } -// }), -// // .value = 2, -// // .owner = 3, -// // .creator_address = NT::address(4), -// // .salt = 5, -// // .nonce = 6, -// // .memo = 7, -// // }; - -// // auto buffer = to_buffer(native_preimage); - -// // auto native_preimage_2 = from_buffer>(buffer.data()); - -// // EXPECT_EQ(native_preimage, native_preimage_2); -// // } - -// // TEST(private_state_tests, test_native_private_state_note_mapping) -// // { -// // StateFactory state_factory("MyContract"); -// // PrivateStateVar x = state_factory.declare_private_state_var("x", { "mapping_key_name_1", -// "mapping_key_name_2" -// // }); - -// // PrivateStateNotePreimage private_state_preimage = { -// // .mapping_key_values_by_key_name = std::map>({ { "mapping_key_name_2", 5 } -// }), -// // .value = 2, -// // .owner = 3, -// // .creator_address = NT::address(4), -// // .salt = 5, -// // .nonce = 6, -// // .memo = 7, -// // }; - -// // PrivateStateNote private_state_note = PrivateStateNote(x, private_state_preimage); - -// // auto buffer = to_buffer(private_state_note); - -// // auto private_state_note_2 = from_buffer>(buffer.data()); - -// // EXPECT_EQ(private_state_note, private_state_note_2); -// // } - -// /// TODO: figure out how to catch and test errors in gtest. - -// } // namespace aztec3::circuits::apps \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/state_vars/field_state_var.hpp b/circuits/cpp/src/aztec3/circuits/apps/state_vars/field_state_var.hpp deleted file mode 100644 index 6345f4cb8e5..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/state_vars/field_state_var.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include "state_var_base.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -namespace aztec3::circuits::apps::state_vars { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -// TODO: we can probably generalize this to be a PrimitiveStateVar for any stdlib primitive. -template class FieldStateVar : public StateVar { - public: - using CT = CircuitTypes; - using NT = NativeTypes; - using fr = typename CT::fr; - using grumpkin_point = typename CT::grumpkin_point; - - fr value = 0; - - FieldStateVar& operator=(fr&& other) - { - value = other; - return *this; - } - - FieldStateVar() = default; - - // Instantiate a top-level var: - FieldStateVar(FunctionExecutionContext* exec_ctx, std::string const& state_var_name, fr const& start_slot) - : StateVar(exec_ctx, state_var_name, start_slot){}; - - // Instantiate a var nested within a container: - FieldStateVar(FunctionExecutionContext* exec_ctx, - std::string const& state_var_name, - grumpkin_point const& storage_slot_point, - size_t level_of_container_nesting, - bool is_partial_slot) - : StateVar( - exec_ctx, state_var_name, storage_slot_point, level_of_container_nesting, is_partial_slot){}; - - bool operator==(FieldStateVar const&) const = default; -}; - -template inline std::ostream& operator<<(std::ostream& os, FieldStateVar const& v) -{ - return os << v.value; -} - -} // namespace aztec3::circuits::apps::state_vars diff --git a/circuits/cpp/src/aztec3/circuits/apps/state_vars/mapping_state_var.hpp b/circuits/cpp/src/aztec3/circuits/apps/state_vars/mapping_state_var.hpp deleted file mode 100644 index 1add53261f8..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/state_vars/mapping_state_var.hpp +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include "state_var_base.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -// Forward-declare from this namespace in particular: -namespace aztec3::circuits::apps { -template class FunctionExecutionContext; -} - -namespace aztec3::circuits::apps::state_vars { - -using aztec3::circuits::apps::FunctionExecutionContext; // Don't #include it! - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -/** - * @tparam V - the value type being mapped-to by this mapping. - * - * Note: we restrict mapping _keys_ to always be a `field` type. This is to allow storage_slot_points to be computed - * more easily (it was difficult enough to get working). You'll notice, therefore, that there's no Key template type; - * only a value template type (`V`). Adding a Key template type could be a future enhancement. - */ -template class MappingStateVar : public StateVar { - public: - using CT = CircuitTypes; - using NT = NativeTypes; - using fr = typename CT::fr; - using grumpkin_point = typename CT::grumpkin_point; - - // native_storage_slot.x => value cache, to prevent creating constraints with each `at()` call. - std::map value_cache; - - MappingStateVar() = default; - - // Instantiate a top-level mapping: - MappingStateVar(FunctionExecutionContext* exec_ctx, std::string const& state_var_name) - : StateVar(exec_ctx, state_var_name){}; - - // Instantiate a nested mapping (within some other container). - // Note: we assume this is called by some other StateVar, and the params have been computed correctly. - // TODO: we could specify a set of `friend` classes which may access this method, to make this assumption more - // explicit. - MappingStateVar(FunctionExecutionContext* exec_ctx, - std::string const& state_var_name, - grumpkin_point const& storage_slot_point, - size_t level_of_container_nesting, - bool is_partial_slot) - : StateVar( - exec_ctx, state_var_name, storage_slot_point, level_of_container_nesting, is_partial_slot){}; - - bool operator==(MappingStateVar const&) const = default; - - V& operator[](std::optional const& key) { return this->at(key); }; - V& operator[](std::string const& question_mark) - { - ASSERT(question_mark == "?"); - return this->at(std::nullopt); - }; - - V& at(std::optional const& key); - - static std::tuple compute_slot_point_at_mapping_key(NT::fr const& start_slot, - std::optional const& key); - - std::tuple compute_slot_point_at_mapping_key(std::optional const& key); -}; - -} // namespace aztec3::circuits::apps::state_vars - -// Importing in this way (rather than explicit instantiation of a template class at the bottom of a .cpp file) preserves -// the following: -// - We retain implicit instantiation of templates. -// - We don't implement method definitions in this file, to avoid a circular dependency with -// function_execution_context.hpp. -#include "mapping_state_var.tpp" diff --git a/circuits/cpp/src/aztec3/circuits/apps/state_vars/mapping_state_var.tpp b/circuits/cpp/src/aztec3/circuits/apps/state_vars/mapping_state_var.tpp deleted file mode 100644 index 43b3c22a382..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/state_vars/mapping_state_var.tpp +++ /dev/null @@ -1,129 +0,0 @@ -#pragma once - -// #include "oracle_wrapper.hpp" -// #include "private_state_note.hpp" -// #include "private_state_note_preimage.hpp" -// #include "private_state_operand.hpp" - -#include "../function_execution_context.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace { -using aztec3::circuits::apps::FunctionExecutionContext; -} // namespace - -namespace aztec3::circuits::apps::state_vars { - - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -// Fr: start_slot -// -// mapping(fr => V): -// level of nesting = 1 -// start_slot_point = start_slot * A -// at(k1).slot = start_slot_point + k1 * B -// -// mapping(fr => mapping(fr => T)): -// level_of_nesting = 2 -// start_slot_point becomes: prev_start_slot_point + k1 * B -// at(k2).slot = new_start_slot_point + k2 * C - -template -std::tuple MappingStateVar::compute_slot_point_at_mapping_key( - NT::fr const& start_slot, std::optional const& key) -{ - bool const is_partial_slot = false; - - std::vector inputs; - - // TODO: compare (in a test) this little calc against calling `compute_start_slot_point`. - inputs.emplace_back(start_slot); - - if (key) { - inputs.emplace_back(*key); - } else { - // If this mapping key has no mapping_key_value (std::nullopt), then we must be partially committing and - // omitting this mapping key from that partial commitment. - // So use a placeholder generator for this mapping key, to signify "this mapping key is missing". - // Note: we can't just commit to a value of `0` for this mapping key, since `0` is a valid value to - // commit to, and so "missing" is distinguished as follows. - inputs.emplace_back(NativeTypes::fr(1)); - } - - return std::make_tuple(NativeTypes::commit(inputs, StorageSlotGeneratorIndex::MAPPING_SLOT), is_partial_slot); -} - -template -std::tuple::grumpkin_point, bool> MappingStateVar:: - compute_slot_point_at_mapping_key(std::optional const& key) -{ - bool is_partial_slot = false; - - std::vector inputs; - - inputs.push_back(this->start_slot); - - if (key) { - inputs.push_back(*key); - } else { - // If this mapping key has no mapping_key_value (std::nullopt), then we must be partially committing and - // omitting this mapping key from that partial commitment. - // So use a placeholder generator for this mapping key, to signify "this mapping key is missing". - // Note: we can't just commit to a value of `0` for this mapping key, since `0` is a valid value to - // commit to, and so "missing" is distinguished as follows. - inputs.push_back(fr(1)); - is_partial_slot = true; - } - - return std::make_tuple(CT::commit(inputs, StorageSlotGeneratorIndex::MAPPING_SLOT), is_partial_slot); -} - -template V& MappingStateVar::at(std::optional const& key) -{ - // First calculate natively and check to see if we've already calculated this state's slot and stored it in the - // cache, so we don't create unnecessary circuit gates: - - std::optional native_key; - if (!key) { - native_key = std::nullopt; - } else { - native_key = static_cast((*key).get_value()); - } - - bool is_partial_slot = false; - NativeTypes::grumpkin_point native_new_slot_point; - std::tie(native_new_slot_point, is_partial_slot) = - MappingStateVar::compute_slot_point_at_mapping_key(this->start_slot.get_value(), native_key); - NativeTypes::fr const native_lookup = native_new_slot_point.x; - - // Check cache - if (this->value_cache.contains(native_lookup)) { - return this->value_cache[native_lookup]; - } - - // Create gates: - grumpkin_point new_slot_point; - std::tie(new_slot_point, is_partial_slot) = compute_slot_point_at_mapping_key(key); - NativeTypes::fr const lookup = new_slot_point.x.get_value(); - - if (lookup != native_lookup) { - throw_or_abort("Expected lookup calcs to be equal!"); - } - - std::string const value_name = this->state_var_name + (key ? format("[", *key, "]").c_str() : "[?]"); - - V value = V(this->exec_ctx, value_name, new_slot_point, this->level_of_container_nesting + 1, is_partial_slot); - - this->value_cache[lookup] = value; - - return this->value_cache[lookup]; -} - -}; // namespace aztec3::circuits::apps::state_vars diff --git a/circuits/cpp/src/aztec3/circuits/apps/state_vars/state_var_base.hpp b/circuits/cpp/src/aztec3/circuits/apps/state_vars/state_var_base.hpp deleted file mode 100644 index 0bead2a69c3..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/state_vars/state_var_base.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -// Forward-declare from this namespace in particular: -namespace aztec3::circuits::apps { -template class FunctionExecutionContext; -} - -namespace aztec3::circuits::apps::state_vars { - -using aztec3::circuits::apps::FunctionExecutionContext; // Don't #include it! - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -/** - * @brief StateVar is a base class from which contract state variables are derived. Its main purpose is deriving storage - * slots, and generating constraints for those slot derivations, in a protocol-consistent way, regardless of the app - * being written. - */ -template class StateVar { - public: - using CT = CircuitTypes; - using NT = NativeTypes; - using fr = typename CT::fr; - using grumpkin_point = typename CT::grumpkin_point; - - // The execution context of the function currently being executed. - FunctionExecutionContext* exec_ctx; - - // Must match the name of a state which has been declared to the `Contract`. - std::string state_var_name; - - // The `start slot` of the state variable is the slot which is assigned to this particular state by the `Contract`, - // based on the ordering of declarations of the _names_ of states. For container types (mappings/arrays/structs), - // the state variable might be able to access multiple storage slots. The start slot is the 'starting point' for - // deriving such slots. - fr start_slot = 0; - - // The 'storage slot point' of the state variable. Having a _point_ for every storage slot allows for - // partial-commitment functionality. - // I.e. we can generate placeholder storage slots, which can be partially-committed to in one function, and then - // completed in some future function, once the mapping keys or array indices at which we'd like to store the data - // are known in future. Aztec Connect does something similar (the `asset_id` of the output value note isn't known - // until later, so is partially committed-to). - grumpkin_point storage_slot_point; - - // In order to calculate the correct storage_slot_point, we need to know how many containers - // we're nested inside, so that we can find the correct Pedersen generator. - size_t level_of_container_nesting = 0; - - // Optionally informs custom notes whether they should commit or partially-commit to this state. - bool is_partial_slot = false; - - StateVar() = default; - - // Instantiate a top-level state: - StateVar(FunctionExecutionContext* exec_ctx, std::string const& state_var_name); - - // Instantiate a state nested within a container: - StateVar( - FunctionExecutionContext* exec_ctx, - std::string const& state_var_name, - grumpkin_point const& storage_slot_point, // the parent always calculates the storage_slot_point of its child. - size_t level_of_container_nesting, // the parent always calculates the level of nesting of its child. - bool is_partial_slot = false) - : exec_ctx(exec_ctx) - , state_var_name(state_var_name) - , storage_slot_point(storage_slot_point) - , level_of_container_nesting(level_of_container_nesting) - , is_partial_slot(is_partial_slot){}; - - bool operator==(StateVar const&) const = default; - - StateVar operator=(StateVar const& other) - { - this->exec_ctx = other.exec_ctx; - this->state_var_name = other.state_var_name; - this->start_slot = other.start_slot; - this->storage_slot_point = other.storage_slot_point; - this->level_of_container_nesting = other.level_of_container_nesting; - this->is_partial_slot = other.is_partial_slot; - return *this; - } - - private: - grumpkin_point compute_slot_point(); -}; - -} // namespace aztec3::circuits::apps::state_vars - -// Importing in this way (rather than explicit instantiation of a template class at the bottom of a .cpp file) preserves -// the following: -// - We retain implicit instantiation of templates. -// - We avoid circular dependencies with function_execution_context.hpp -#include "state_var_base.tpp" diff --git a/circuits/cpp/src/aztec3/circuits/apps/state_vars/state_var_base.tpp b/circuits/cpp/src/aztec3/circuits/apps/state_vars/state_var_base.tpp deleted file mode 100644 index f1448192827..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/state_vars/state_var_base.tpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "../function_execution_context.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" - -#include - -namespace { -using aztec3::circuits::apps::FunctionExecutionContext; -} - -namespace aztec3::circuits::apps::state_vars { - -using aztec3::utils::types::CircuitTypes; - -template -StateVar::StateVar(FunctionExecutionContext* exec_ctx, std::string const& state_var_name) - : exec_ctx(exec_ctx), state_var_name(state_var_name) -{ - // NOLINTBEGIN(cppcoreguidelines-prefer-member-initializer) - // this ^ linter rule breaks things here here - start_slot = exec_ctx->contract->get_start_slot(state_var_name); - storage_slot_point = compute_slot_point(); - // NOLINTEND(cppcoreguidelines-prefer-member-initializer) -} - -template typename CircuitTypes::grumpkin_point StateVar::compute_slot_point() -{ - ASSERT(level_of_container_nesting == 0); - return CT::commit({ start_slot }, { StorageSlotGeneratorIndex::BASE_SLOT }); -} - -// template class PrivateStateVar; - -}; // namespace aztec3::circuits::apps::state_vars diff --git a/circuits/cpp/src/aztec3/circuits/apps/state_vars/utxo_set_state_var.hpp b/circuits/cpp/src/aztec3/circuits/apps/state_vars/utxo_set_state_var.hpp deleted file mode 100644 index 69121dba555..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/state_vars/utxo_set_state_var.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#include "state_var_base.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -// Forward-declare from this namespace in particular: -namespace aztec3::circuits::apps { -template class FunctionExecutionContext; -} - -namespace aztec3::circuits::apps::state_vars { - -using aztec3::circuits::apps::FunctionExecutionContext; // Don't #include it! - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -/** - * @brief - A derived StateVar which represents an unordered set of UTXOs which live in the UTXO tree. - * Notice the `get` and `insert` methods for this StateVar, which interact with the UTXO tree opcodes. - * - * @tparam Note - A UTXO state variable always acts on notes and note preimages. We allow for custom Note types to be - * designed. The Note type must implement the NoteInterface. TODO: maybe explicitly have this class act on the - * NoteInterface type, rather than a template type. - */ -template class UTXOSetStateVar : public StateVar { - public: - using CT = CircuitTypes; - using NT = NativeTypes; - using fr = typename CT::fr; - using grumpkin_point = typename CT::grumpkin_point; - - using NotePreimage = typename Note::NotePreimage; - - UTXOSetStateVar() = default; - - // Instantiate a top-level var: - UTXOSetStateVar(FunctionExecutionContext* exec_ctx, std::string const& state_var_name) - : StateVar(exec_ctx, state_var_name){}; - - // Instantiate a var nested within a container: - UTXOSetStateVar(FunctionExecutionContext* exec_ctx, - std::string const& state_var_name, - grumpkin_point const& storage_slot_point, - size_t level_of_container_nesting, - bool is_partial_slot) - : StateVar( - exec_ctx, state_var_name, storage_slot_point, level_of_container_nesting, is_partial_slot){}; - - /** - * @param advice - For NotePreimages, we allow 'advice' to be given, so that the correct DB entry is - * chosen. - * E.g. so that the `owner` can be specified. - */ - std::vector get(size_t const& num_notes, NotePreimage const& advice); - - void insert(NotePreimage new_note_preimage); -}; - -} // namespace aztec3::circuits::apps::state_vars - -#include "utxo_set_state_var.tpp" \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/state_vars/utxo_set_state_var.tpp b/circuits/cpp/src/aztec3/circuits/apps/state_vars/utxo_set_state_var.tpp deleted file mode 100644 index 4f289777f2e..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/state_vars/utxo_set_state_var.tpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "../opcodes/opcodes.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -namespace { -using aztec3::circuits::apps::opcodes::Opcodes; -} // namespace - -namespace aztec3::circuits::apps::state_vars { - -template -std::vector UTXOSetStateVar::get(size_t const& num_notes, - typename Note::NotePreimage const& advice) -{ - return Opcodes::template UTXO_SLOAD(this, num_notes, advice); -}; - -template -void UTXOSetStateVar::insert(typename Note::NotePreimage new_note_preimage) -{ - return Opcodes::template UTXO_SSTORE(this, new_note_preimage); -}; - -} // namespace aztec3::circuits::apps::state_vars \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/state_vars/utxo_state_var.hpp b/circuits/cpp/src/aztec3/circuits/apps/state_vars/utxo_state_var.hpp deleted file mode 100644 index 48f5bba3f46..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/state_vars/utxo_state_var.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include "state_var_base.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -// Forward-declare from this namespace in particular: -namespace aztec3::circuits::apps { -template class FunctionExecutionContext; -} - -namespace aztec3::circuits::apps::state_vars { - -using aztec3::circuits::apps::FunctionExecutionContext; // Don't #include it! - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; - -/** - * @brief - A derived StateVar which represents a singleton UTXO type. I.e. a state which can only ever have at-most ONE - * non-nullified UTXO in the tree at any time. Notice the `get` and `insert` methods for this StateVar, which interact - * with the UTXO tree opcodes. - * - * @tparam Note - A UTXO state variable always acts on notes and note preimages. We allow for custom Note types to be - * designed. The Note type must implement the NoteInterface. TODO: maybe explicitly have this class act on the - * NoteInterface type, rather than a template type. - */ -template class UTXOStateVar : public StateVar { - public: - using CT = CircuitTypes; - using NT = NativeTypes; - using fr = typename CT::fr; - using grumpkin_point = typename CT::grumpkin_point; - using address = typename CT::address; - - using NotePreimage = typename Note::NotePreimage; - - UTXOStateVar() = default; - - // Instantiate a top-level var: - UTXOStateVar(FunctionExecutionContext* exec_ctx, std::string const& state_var_name) - : StateVar(exec_ctx, state_var_name){}; - - // Instantiate a var nested within a container: - UTXOStateVar(FunctionExecutionContext* exec_ctx, - std::string const& state_var_name, - grumpkin_point const& storage_slot_point, - size_t level_of_container_nesting, - bool is_partial_slot) - : StateVar( - exec_ctx, state_var_name, storage_slot_point, level_of_container_nesting, is_partial_slot){}; - - /** - * @param advice - For NotePreimages, we allow 'advice' to be given, so that the correct DB entry is - * chosen. - * E.g. so that the `owner` can be specified. - */ - Note get(NotePreimage const& advice); - - /** - * @brief For singleton UTXOs, there's a distinction between initializing and modifying in future. See here: - * https://discourse.aztec.network/t/utxo-syntax-2-initializing-singleton-utxos/47. So we include this method for - * singleton UTXO types. - */ - void initialize(NotePreimage new_note_preimage); - - void insert(NotePreimage new_note_preimage); -}; - -} // namespace aztec3::circuits::apps::state_vars - -#include "utxo_state_var.tpp" \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/state_vars/utxo_state_var.tpp b/circuits/cpp/src/aztec3/circuits/apps/state_vars/utxo_state_var.tpp deleted file mode 100644 index 68842792702..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/state_vars/utxo_state_var.tpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include "../opcodes/opcodes.hpp" - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -namespace { -using aztec3::circuits::apps::opcodes::Opcodes; -} // namespace - -namespace aztec3::circuits::apps::state_vars { - -template -Note UTXOStateVar::get(typename Note::NotePreimage const& advice) -{ - return Opcodes::template UTXO_SLOAD(this, advice); -}; - -template -void UTXOStateVar::initialize(typename Note::NotePreimage new_note_preimage) -{ - Note new_note{ this, new_note_preimage }; - Opcodes::template UTXO_INIT(this, new_note); -}; - -template -void UTXOStateVar::insert(typename Note::NotePreimage new_note_preimage) -{ - Opcodes::template UTXO_SSTORE(this, new_note_preimage); -}; - -} // namespace aztec3::circuits::apps::state_vars \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/basic_contract_deployment/basic_contract_deployment.cpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/basic_contract_deployment/basic_contract_deployment.cpp deleted file mode 100644 index 5a9e39fe27f..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/basic_contract_deployment/basic_contract_deployment.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "basic_contract_deployment.hpp" - -#include "contract.hpp" - -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/hash.hpp" - -namespace aztec3::circuits::apps::test_apps::basic_contract_deployment { - -using aztec3::circuits::abis::OptionalPrivateCircuitPublicInputs; - -OptionalPrivateCircuitPublicInputs constructor(FunctionExecutionContext& exec_ctx, std::vector const& args) -{ - /**************************************************************** - * PREAMBLE - ****************************************************************/ - - // Make the exec_ctx aware of the contract's layout. - Contract contract = init_contract(); - exec_ctx.register_contract(&contract); - - // Convert params into circuit types: - auto& builder = exec_ctx.builder; - - CT::fr const arg0 = to_ct(builder, args[0]); - CT::fr const arg1 = to_ct(builder, args[1]); - CT::fr const arg2 = to_ct(builder, args[2]); - - auto& oracle = exec_ctx.oracle; - const CT::address msg_sender = oracle.get_msg_sender(); - - /**************************************************************** - * BODY - ****************************************************************/ - // SKIPPED - - /**************************************************************** - * CLEANUP - ****************************************************************/ - - // Push args to the public inputs. - // TODO: don't give function direct access to the exec_ctx? - auto& public_inputs = exec_ctx.private_circuit_public_inputs; - public_inputs.args_hash = compute_var_args_hash({ arg0, arg1, arg2 }); - - exec_ctx.finalize(); - - // info("public inputs: ", public_inputs); - - return public_inputs.to_native_type(); -} - -} // namespace aztec3::circuits::apps::test_apps::basic_contract_deployment diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/basic_contract_deployment/basic_contract_deployment.hpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/basic_contract_deployment/basic_contract_deployment.hpp deleted file mode 100644 index e478e4d997f..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/basic_contract_deployment/basic_contract_deployment.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "init.hpp" - -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/apps/function_execution_context.hpp" - -namespace aztec3::circuits::apps::test_apps::basic_contract_deployment { - -using aztec3::circuits::abis::OptionalPrivateCircuitPublicInputs; - -OptionalPrivateCircuitPublicInputs constructor(FunctionExecutionContext& exec_ctx, std::vector const& args); - -} // namespace aztec3::circuits::apps::test_apps::basic_contract_deployment \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/basic_contract_deployment/contract.hpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/basic_contract_deployment/contract.hpp deleted file mode 100644 index 11e110731ea..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/basic_contract_deployment/contract.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "contract.hpp" -#include "init.hpp" - -#include "aztec3/circuits/apps/contract.hpp" -#include "aztec3/circuits/apps/function_declaration.hpp" - -namespace aztec3::circuits::apps::test_apps::basic_contract_deployment { - -inline Contract init_contract() -{ - Contract contract("BasicContractDeployment"); - - // Solely used for assigning vk indices. - contract.set_functions({ - { .name = "constructor", .is_private = true, .is_constructor = true }, - }); - - return contract; -} - -} // namespace aztec3::circuits::apps::test_apps::basic_contract_deployment \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/basic_contract_deployment/init.hpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/basic_contract_deployment/init.hpp deleted file mode 100644 index 4b193f601d7..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/basic_contract_deployment/init.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include "aztec3/circuits/apps/contract.hpp" -#include "aztec3/circuits/apps/function_execution_context.hpp" -#include "aztec3/circuits/apps/notes/default_private_note/note.hpp" -#include "aztec3/circuits/apps/oracle_wrapper.hpp" -#include "aztec3/circuits/apps/state_vars/mapping_state_var.hpp" -#include "aztec3/circuits/apps/state_vars/utxo_set_state_var.hpp" -#include "aztec3/oracle/oracle.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -namespace aztec3::circuits::apps::test_apps::basic_contract_deployment { - -// Builder -using C = UltraCircuitBuilder; - -// Native and circuit types -using CT = aztec3::utils::types::CircuitTypes; -using NT = aztec3::utils::types::NativeTypes; - -// Database types -using DB = oracle::FakeDB; -using oracle::NativeOracle; -using OracleWrapper = apps::OracleWrapperInterface; - -using Contract = apps::Contract; -using FunctionExecutionContext = apps::FunctionExecutionContext; - -using aztec3::utils::types::to_ct; - -// StateVars -using apps::state_vars::MappingStateVar; -using apps::state_vars::UTXOSetStateVar; - -// Get rid of ugly `Builder` template arg from our state var types: -template using Mapping = MappingStateVar; -template using UTXOSet = UTXOSetStateVar; - -using DefaultNote = apps::notes::DefaultPrivateNote; - -} // namespace aztec3::circuits::apps::test_apps::basic_contract_deployment \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/.test.cpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/.test.cpp deleted file mode 100644 index 0bae9fc9f21..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/.test.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "index.hpp" - -#include - -#include - -namespace aztec3::circuits::apps::test_apps::escrow { - -class escrow_tests : public ::testing::Test { - protected: - static NativeOracle get_test_native_oracle(DB& db) - { - const NT::address contract_address = 12345; - const NT::fr msg_sender_private_key = 123456789; - const NT::address msg_sender = NT::fr( - uint256_t(0x01071e9a23e0f7edULL, 0x5d77b35d1830fa3eULL, 0xc6ba3660bb1f0c0bULL, 0x2ef9f7f09867fd6eULL)); - - FunctionData const function_data{ - .selector = - { - .value = 1, // TODO: deduce this from the contract, somehow. - }, - .is_private = true, - .is_constructor = false, - }; - - CallContext const call_context{ - .msg_sender = msg_sender, - .storage_contract_address = contract_address, - .portal_contract_address = 0, - .function_selector = function_data.selector, - .is_delegate_call = false, - .is_static_call = false, - .is_contract_deployment = false, - }; - - return NativeOracle(db, contract_address, function_data, call_context, msg_sender_private_key); - }; -}; - -TEST_F(escrow_tests, circuit_deposit) -{ - // TODO: currently, we can't hide all of this boilerplate in a test fixture function, because each of these classes - // contains a reference to earlier-declared classes... so we'd end up with classes containing dangling references, - // if all this stuff were to be declared in a setup function's scope. - // We could instead store shared_ptrs in every class...? - C builder = C(); - DB db; - NativeOracle native_oracle = get_test_native_oracle(db); - OracleWrapper oracle_wrapper = OracleWrapper(builder, native_oracle); - FunctionExecutionContext exec_ctx(builder, oracle_wrapper); - - auto amount = NT::fr(5); - auto asset_id = NT::fr(1); - auto memo = NT::fr(999); - - auto result = deposit(exec_ctx, { amount, asset_id, memo }); - info("result: ", result); - - // info("witness: ", builder.witness); - // info("constant variables: ", builder.constant_variables); - // info("variables: ", builder.variables); - info("failed?: ", builder.failed()); - info("err: ", builder.err()); - info("n: ", builder.num_gates); -} - -TEST_F(escrow_tests, circuit_transfer) -{ - C builder = C(); - DB db; - NativeOracle native_oracle = get_test_native_oracle(db); - OracleWrapper oracle_wrapper = OracleWrapper(builder, native_oracle); - FunctionExecutionContext exec_ctx(builder, oracle_wrapper); - - auto amount = NT::fr(5); - auto to = NT::address(657756); - auto asset_id = NT::fr(1); - auto memo = NT::fr(999); - auto reveal_msg_sender_to_recipient = true; - auto fee = NT::fr(2); - - transfer(exec_ctx, amount, to, asset_id, memo, reveal_msg_sender_to_recipient, fee); - - // info("witness: ", builder.witness); - // info("constant variables: ", builder.constant_variables); - // info("variables: ", builder.variables); - info("failed?: ", builder.failed()); - info("err: ", builder.err()); - info("n: ", builder.num_gates); -} - -TEST_F(escrow_tests, circuit_withdraw) -{ - C builder = C(); - DB db; - NativeOracle native_oracle = get_test_native_oracle(db); - OracleWrapper oracle_wrapper = OracleWrapper(builder, native_oracle); - FunctionExecutionContext exec_ctx(builder, oracle_wrapper); - - auto amount = NT::fr(5); - auto asset_id = NT::fr(1); - auto memo = NT::fr(999); - auto l1_withdrawal_address = NT::fr(657756); - auto fee = NT::fr(2); - - withdraw(exec_ctx, amount, asset_id, memo, l1_withdrawal_address, fee); - - // info("witness: ", builder.witness); - // info("constant variables: ", builder.constant_variables); - // info("variables: ", builder.variables); - info("failed?: ", builder.failed()); - info("err: ", builder.err()); - info("n: ", builder.num_gates); -} - -} // namespace aztec3::circuits::apps::test_apps::escrow \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/README.md b/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/README.md deleted file mode 100644 index 85bb977feed..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# test_apps::escrow - -zk-money functionality in an Aztec3 setting. \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/contract.hpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/contract.hpp deleted file mode 100644 index 2aa577eafbb..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/contract.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "init.hpp" - -#include "aztec3/circuits/apps/contract.hpp" -#include "aztec3/circuits/apps/function_declaration.hpp" - -namespace aztec3::circuits::apps::test_apps::escrow { - -inline Contract init_contract() -{ - Contract contract("Escrow"); - - contract.declare_state_var("balances"); - - // Solely used for assigning vk indices. - contract.set_functions({ - { .name = "deposit", .is_private = true }, - { .name = "transfer", .is_private = true }, - { .name = "withdraw", .is_private = true }, - }); - - return contract; -} - -} // namespace aztec3::circuits::apps::test_apps::escrow \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/deposit.cpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/deposit.cpp deleted file mode 100644 index 61703be8a8c..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/deposit.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "deposit.hpp" - -#include "contract.hpp" - -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/apps/function_execution_context.hpp" -#include "aztec3/circuits/hash.hpp" - -namespace aztec3::circuits::apps::test_apps::escrow { - -using aztec3::circuits::abis::OptionalPrivateCircuitPublicInputs; - -OptionalPrivateCircuitPublicInputs deposit(FunctionExecutionContext& exec_ctx, std::vector const& args) -{ - /**************************************************************** - * PREAMBLE - ****************************************************************/ - - // Make the exec_ctx aware of the contract's layout. - Contract contract = init_contract(); - exec_ctx.register_contract(&contract); - - // Convert params into circuit types: - auto& builder = exec_ctx.builder; - - CT::fr amount = to_ct(builder, args[0]); - CT::fr asset_id = to_ct(builder, args[1]); - CT::fr memo = to_ct(builder, args[2]); - - auto& oracle = exec_ctx.oracle; - const CT::address msg_sender = oracle.get_msg_sender(); - - /**************************************************************** - * BODY - ****************************************************************/ - - // Syntactic sugar for a state variable: - // Note: these Mappings always map-from a field type (because it was complicated enough!!!) - // mapping(asset_id => mapping(owner => UTXOSet< >)) balances; - Mapping>> balances(&exec_ctx, "balances"); - - balances[asset_id][msg_sender.to_field()].insert({ - .value = amount, - .owner = msg_sender, - .creator_address = msg_sender, - .memo = memo, - }); - - /**************************************************************** - * CLEANUP - ****************************************************************/ - - // Push args to the public inputs. - // TODO: don't give function direct access to the exec_ctx? - auto& public_inputs = exec_ctx.private_circuit_public_inputs; - public_inputs.args_hash = compute_var_args_hash({ amount, asset_id, memo }); - - exec_ctx.finalize(); - - // info("public inputs: ", public_inputs); - - return public_inputs.to_native_type(); - // TODO: also return note preimages and nullifier preimages. - // TODO: or, we'll be collecting this data in the exec_ctx. -}; - -} // namespace aztec3::circuits::apps::test_apps::escrow \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/deposit.hpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/deposit.hpp deleted file mode 100644 index 326cef2c0dd..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/deposit.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "init.hpp" - -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/apps/function_execution_context.hpp" - -namespace aztec3::circuits::apps::test_apps::escrow { - -using aztec3::circuits::abis::OptionalPrivateCircuitPublicInputs; - -OptionalPrivateCircuitPublicInputs deposit(FunctionExecutionContext& exec_ctx, std::vector const& args); - -} // namespace aztec3::circuits::apps::test_apps::escrow \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/index.hpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/index.hpp deleted file mode 100644 index ff3c61046c1..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/index.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "contract.hpp" -#include "deposit.hpp" -#include "init.hpp" -#include "transfer.hpp" -#include "withdraw.hpp" \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/init.hpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/init.hpp deleted file mode 100644 index 30d5da1dbbc..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/init.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include "aztec3/circuits/apps/contract.hpp" -#include "aztec3/circuits/apps/function_execution_context.hpp" -#include "aztec3/circuits/apps/notes/default_private_note/note.hpp" -#include "aztec3/circuits/apps/oracle_wrapper.hpp" -#include "aztec3/circuits/apps/state_vars/mapping_state_var.hpp" -#include "aztec3/circuits/apps/state_vars/utxo_set_state_var.hpp" -#include "aztec3/oracle/oracle.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -namespace aztec3::circuits::apps::test_apps::escrow { - -// Builder -using C = UltraCircuitBuilder; - -// Native and circuit types -using CT = aztec3::utils::types::CircuitTypes; -using NT = aztec3::utils::types::NativeTypes; - -// Database types -using DB = oracle::FakeDB; -using oracle::NativeOracle; -using OracleWrapper = apps::OracleWrapperInterface; - -using Contract = apps::Contract; -using FunctionExecutionContext = apps::FunctionExecutionContext; - -using aztec3::utils::types::to_ct; - -// StateVars -using apps::state_vars::MappingStateVar; -using apps::state_vars::UTXOSetStateVar; - -// Get rid of ugly `Builder` template arg from our state var types: -template using Mapping = MappingStateVar; -template using UTXOSet = UTXOSetStateVar; - -using DefaultNote = apps::notes::DefaultPrivateNote; - -} // namespace aztec3::circuits::apps::test_apps::escrow \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/transfer.cpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/transfer.cpp deleted file mode 100644 index 08809a8e4e2..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/transfer.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include "transfer.hpp" - -#include "contract.hpp" - -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/hash.hpp" - -namespace aztec3::circuits::apps::test_apps::escrow { - -using aztec3::circuits::abis::OptionalPrivateCircuitPublicInputs; - -OptionalPrivateCircuitPublicInputs transfer(FunctionExecutionContext& exec_ctx, - NT::fr const& _amount, - NT::address const& _to, - NT::fr const& _asset_id, - NT::fr const& _memo, - NT::boolean const& _reveal_msg_sender_to_recipient, - NT::fr const& _fee) -{ - /**************************************************************** - * Initialization - ****************************************************************/ - - // Make the exec_ctx aware of the contract's layout. - Contract contract = init_contract(); - exec_ctx.register_contract(&contract); - - // Convert arguments into circuit types: - auto& builder = exec_ctx.builder; - - CT::fr amount = to_ct(builder, _amount); - CT::address to = to_ct(builder, _to); - CT::fr asset_id = to_ct(builder, _asset_id); - CT::fr memo = to_ct(builder, _memo); - CT::boolean const reveal_msg_sender_to_recipient = to_ct(builder, _reveal_msg_sender_to_recipient); - CT::fr const fee = to_ct(builder, _fee); - - /**************************************************************** - * Get States & Globals used by the function - ****************************************************************/ - - auto& oracle = exec_ctx.oracle; - CT::address msg_sender = oracle.get_msg_sender(); - - // Syntactic sugar for a state variable: - // Note: these Mappings always map-from a field type (because it was complicated enough!!!) - // mapping(asset_id => mapping(owner => UTXOSet< >)) balances; - Mapping>> balances(&exec_ctx, "balances"); - - /**************************************************************** - * BODY - ****************************************************************/ - - CT::address creator_address = - CT::address::conditional_assign(reveal_msg_sender_to_recipient, msg_sender, CT::address(0)); - - // TODO: sort & filter functions! - std::vector old_balance_notes = - balances[asset_id][msg_sender.to_field()].get(2, { .owner = msg_sender }); - - CT::fr const old_value_1 = *(old_balance_notes[0].get_preimage().value); - CT::fr const old_value_2 = *(old_balance_notes[1].get_preimage().value); - - // MISSING: overflow & underflow checks, but I can't be bothered with safe_uint or range checks yet. - CT::fr change = (old_value_1 + old_value_2) - (amount + fee); - - old_balance_notes[0].remove(); - old_balance_notes[1].remove(); - - // Send amount to `to` address. - balances[asset_id][to.to_field()].insert({ - .value = amount, - .owner = to, - .creator_address = creator_address, - .memo = memo, - }); - - // Return change to sender: - balances[asset_id][msg_sender.to_field()].insert({ - .value = change, - .owner = msg_sender, - .creator_address = msg_sender, - .memo = memo, - }); - - /**************************************************************** - * CLEANUP - ****************************************************************/ - - // Push args to the public inputs. - auto& public_inputs = exec_ctx.private_circuit_public_inputs; - public_inputs.args_hash = compute_var_args_hash( - { amount, to.to_field(), asset_id, memo, CT::fr(reveal_msg_sender_to_recipient), fee }); - - /// TODO: merkle membership check - // public_inputs.historical_note_hash_tree_root - - exec_ctx.finalize(); - - // info("public inputs: ", public_inputs); - - return public_inputs.to_native_type(); -}; - -} // namespace aztec3::circuits::apps::test_apps::escrow \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/transfer.hpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/transfer.hpp deleted file mode 100644 index 444f5052ea4..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/transfer.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "init.hpp" - -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/apps/function_execution_context.hpp" - -namespace aztec3::circuits::apps::test_apps::escrow { - -using aztec3::circuits::abis::OptionalPrivateCircuitPublicInputs; - -OptionalPrivateCircuitPublicInputs transfer(FunctionExecutionContext& exec_ctx, - NT::fr const& _amount, - NT::address const& _to, - NT::fr const& _asset_id, - NT::fr const& _memo, - NT::boolean const& _reveal_msg_sender_to_recipient, - NT::fr const& _fee); - -} // namespace aztec3::circuits::apps::test_apps::escrow \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/withdraw.cpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/withdraw.cpp deleted file mode 100644 index d61fcceed27..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/withdraw.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "withdraw.hpp" - -#include "contract.hpp" - -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/hash.hpp" - -namespace aztec3::circuits::apps::test_apps::escrow { - -using aztec3::circuits::abis::OptionalPrivateCircuitPublicInputs; - -OptionalPrivateCircuitPublicInputs withdraw(FunctionExecutionContext& exec_ctx, - NT::fr const& _amount, - NT::fr const& _asset_id, - NT::fr const& _memo, - NT::fr const& _l1_withdrawal_address, - NT::fr const& _fee) -{ - /**************************************************************** - * Initialization - ****************************************************************/ - - // Make the exec_ctx aware of the contract's layout. - Contract contract = init_contract(); - exec_ctx.register_contract(&contract); - - // Convert arguments into circuit types: - auto& builder = exec_ctx.builder; - - CT::fr const amount = to_ct(builder, _amount); - CT::fr asset_id = to_ct(builder, _asset_id); - CT::fr memo = to_ct(builder, _memo); - CT::fr const l1_withdrawal_address = to_ct(builder, _l1_withdrawal_address); - CT::fr const fee = to_ct(builder, _fee); - - /**************************************************************** - * Get States & Globals used by the function - ****************************************************************/ - - auto& oracle = exec_ctx.oracle; - CT::address msg_sender = oracle.get_msg_sender(); - - // Syntactic sugar for a state variable: - // Note: these Mappings always map-from a field type (because it was complicated enough!!!) - // mapping(asset_id => mapping(owner => UTXOSet< >)) balances; - Mapping>> balances(&exec_ctx, "balances"); - - /**************************************************************** - * BODY - ****************************************************************/ - - // TODO: sort & filter functions! - std::vector old_balance_notes = - balances[asset_id][msg_sender.to_field()].get(2, { .owner = msg_sender }); - - CT::fr const old_value_1 = *(old_balance_notes[0].get_preimage().value); - CT::fr const old_value_2 = *(old_balance_notes[1].get_preimage().value); - - // MISSING: overflow & underflow checks, but I can't be bothered with safe_uint or range checks yet. - CT::fr change = (old_value_1 + old_value_2) - (amount + fee); - - old_balance_notes[0].remove(); - old_balance_notes[1].remove(); - - // Return change to self: - balances[asset_id][msg_sender.to_field()].insert({ - .value = change, - .owner = msg_sender, - .creator_address = msg_sender, - .memo = memo, - }); - - // auto& l1_withdraw_function = contract.get_l1_function("withdraw"); - - // TODO: this doesn't do anything at the moment: - // l1_withdraw_function.call({ asset_id, amount, msg_sender.to_field() }); - - /**************************************************************** - * CLEANUP - ****************************************************************/ - - // Push args to the public inputs. - auto& public_inputs = exec_ctx.private_circuit_public_inputs; - public_inputs.args_hash = compute_var_args_hash({ amount, asset_id, memo, l1_withdrawal_address, fee }); - - exec_ctx.finalize(); - - /// TODO: merkle membership check - // public_inputs.historical_note_hash_tree_root - - // info("public inputs: ", public_inputs); - - return public_inputs.to_native_type(); -}; - -} // namespace aztec3::circuits::apps::test_apps::escrow \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/withdraw.hpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/withdraw.hpp deleted file mode 100644 index 666e9db417e..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/escrow/withdraw.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "init.hpp" - -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/apps/function_execution_context.hpp" - -namespace aztec3::circuits::apps::test_apps::escrow { - -using aztec3::circuits::abis::OptionalPrivateCircuitPublicInputs; - -OptionalPrivateCircuitPublicInputs withdraw(FunctionExecutionContext& exec_ctx, - NT::fr const& _amount, - NT::fr const& _asset_id, - NT::fr const& _memo, - NT::fr const& _l1_withdrawal_address, - NT::fr const& _fee); - -} // namespace aztec3::circuits::apps::test_apps::escrow \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/.test.cpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/.test.cpp deleted file mode 100644 index df1d4e060ea..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/.test.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "index.hpp" - -#include "aztec3/circuits/abis/call_context.hpp" -#include "aztec3/circuits/abis/function_data.hpp" - -#include - -#include - -namespace aztec3::circuits::apps::test_apps::private_to_private_function_call { - -class private_to_private_function_call_tests : public ::testing::Test {}; - -TEST(private_to_private_function_call_tests, circuit_private_to_private_function_call) -{ - C fn1_builder = C(); - DB db; - - const NT::address contract_address = 12345; - const NT::fr msg_sender_private_key = 123456789; - const NT::address msg_sender = - uint256_t(0x01071e9a23e0f7edULL, 0x5d77b35d1830fa3eULL, 0xc6ba3660bb1f0c0bULL, 0x2ef9f7f09867fd6eULL); - - const FunctionData function_data{ - .selector = - { - .value = 1, // TODO: deduce this from the contract, somehow. - }, - .is_private = true, - .is_constructor = false, - }; - - const CallContext call_context{ - .msg_sender = msg_sender, - .storage_contract_address = contract_address, - .portal_contract_address = 0, - .function_selector = function_data.selector, - .is_delegate_call = false, - .is_static_call = false, - .is_contract_deployment = false, - }; - - NativeOracle fn1_oracle = NativeOracle(db, contract_address, function_data, call_context, msg_sender_private_key); - OracleWrapper fn1_oracle_wrapper = OracleWrapper(fn1_builder, fn1_oracle); - - FunctionExecutionContext fn1_exec_ctx(fn1_builder, fn1_oracle_wrapper); - - auto a = NT::fr(111); - auto b = NT::fr(222); - auto c = NT::fr(333); - - function_1_1(fn1_exec_ctx, { a, b, c, 0, 0, 0, 0, 0 }); - - const auto& function_1_1_public_inputs = fn1_exec_ctx.get_final_private_circuit_public_inputs(); - - info("function_1_1_public_inputs: ", function_1_1_public_inputs); - - // info("witness: ", fn1_builder.witness); - // info("constant variables: ", fn1_builder.constant_variables); - // info("variables: ", fn1_builder.variables); - info("failed?: ", fn1_builder.failed()); - info("err: ", fn1_builder.err()); - info("n: ", fn1_builder.num_gates); -} - -} // namespace aztec3::circuits::apps::test_apps::private_to_private_function_call \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/README.md b/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/README.md deleted file mode 100644 index 34550188adf..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/README.md +++ /dev/null @@ -1,2 +0,0 @@ -Unfinished example directory. -Not worth reading yet. \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/contract.hpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/contract.hpp deleted file mode 100644 index 4d62ff38fda..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/contract.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include "init.hpp" - -#include "aztec3/circuits/apps/contract.hpp" -#include "aztec3/circuits/apps/function_declaration.hpp" -#include "aztec3/circuits/apps/function_execution_context.hpp" - -namespace aztec3::circuits::apps::test_apps::private_to_private_function_call { - -Contract init_contract_2(); - -inline Contract init_contract_1() -{ - Contract contract_1("contract_1"); - - contract_1.declare_state_var("x"); - - // Solely used for assigning vk indices. - contract_1.set_functions({ - { .name = "function_1_1", .is_private = true }, - }); - - contract_1.import_contracts({ std::make_pair("contract_2", init_contract_2()) }); - - return contract_1; -} - -inline Contract init_contract_2() -{ - Contract contract_2("contract_2"); - - contract_2.declare_state_var("y"); - - // Solely used for assigning vk indices. - contract_2.set_functions({ - { .name = "function_2_1", .is_private = true }, - }); - - return contract_2; -} - -} // namespace aztec3::circuits::apps::test_apps::private_to_private_function_call \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/function_1_1.cpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/function_1_1.cpp deleted file mode 100644 index 53c8c0db1e7..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/function_1_1.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "function_1_1.hpp" - -#include "contract.hpp" -#include "function_2_1.hpp" - -#include "aztec3/circuits/apps/function_execution_context.hpp" -#include "aztec3/circuits/hash.hpp" - -namespace aztec3::circuits::apps::test_apps::private_to_private_function_call { - -void function_1_1(FunctionExecutionContext& exec_ctx, std::vector const& _args) -{ - /**************************************************************** - * Initialization - ****************************************************************/ - - // Make the exec_ctx aware of the contract's layout. - Contract contract_1 = init_contract_1(); - exec_ctx.register_contract(&contract_1); - - // Convert arguments into circuit types: - auto& builder = exec_ctx.builder; - const auto a = to_ct(builder, _args[0]); - const auto b = to_ct(builder, _args[1]); - const auto c = to_ct(builder, _args[2]); - - /**************************************************************** - * Get States & Globals used by the function - ****************************************************************/ - - auto& oracle = exec_ctx.oracle; - - CT::address msg_sender = oracle.get_msg_sender(); - - // Syntactic sugar for declaring a state variable: - UTXO x(&exec_ctx, "x"); - - /**************************************************************** - * BODY - ****************************************************************/ - - // Hard-coded to match tests. - const CT::address unique_person_who_may_initialize = - NT::uint256(0x01071e9a23e0f7edULL, 0x5d77b35d1830fa3eULL, 0xc6ba3660bb1f0c0bULL, 0x2ef9f7f09867fd6eULL); - - unique_person_who_may_initialize.assert_equal(msg_sender); - - /** - * Now we want to call an external function of another smart contract. - * What I've written below is a bit of a hack. - * In reality what we'll need from Noir++ is syntax which hides all of the boilerplate I write below. - * Also, I _know_ where all the code for `function_2_1` is, so I've taken a big shortcut and #included - * `function_2_1.hpp`. This won't be the way we'll fetch bytecode in practice. In practice, we might only learn the - * contract address at runtime, and hence we'll have to fetch some acir bytecode at runtime from a DB and execute - * that in a simulator (e.g. the ACVM). This is where all this noddy C++ example code that I'm writing falls short. - * But hopefully this code still serves as a useful example of how the public inputs of a private function should be - * computed. - */ - // auto function_2_1 = contract_1.get_function("function_2_1"); - const CT::address fn_2_1_contract_address = 23456; - - // TODO: this can probably be tidied up. - auto return_values = - exec_ctx.call(fn_2_1_contract_address, - "function_2_1", - std::function)>(function_2_1), - { a, b, c, 0, 0, 0, 0, 0 }); - - // Use the return value in some way, just for fun: - x.initialize({ - .value = return_values[0], - .owner = msg_sender, - }); - - /**************************************************************** - * CLEANUP - ****************************************************************/ - - // Push args to the public inputs. - auto& public_inputs = exec_ctx.private_circuit_public_inputs; - public_inputs.args_hash = compute_var_args_hash({ a, b, c }); - - exec_ctx.finalize(); -}; - -} // namespace aztec3::circuits::apps::test_apps::private_to_private_function_call \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/function_1_1.hpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/function_1_1.hpp deleted file mode 100644 index 3119a4263b9..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/function_1_1.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "init.hpp" - -#include "aztec3/circuits/apps/function_execution_context.hpp" - -namespace aztec3::circuits::apps::test_apps::private_to_private_function_call { - -void function_1_1(FunctionExecutionContext& exec_ctx, std::vector const& _args); - -} // namespace aztec3::circuits::apps::test_apps::private_to_private_function_call \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/function_2_1.cpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/function_2_1.cpp deleted file mode 100644 index ba26b494b80..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/function_2_1.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "function_2_1.hpp" - -#include "contract.hpp" - -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/hash.hpp" - -namespace aztec3::circuits::apps::test_apps::private_to_private_function_call { - - -void function_2_1(FunctionExecutionContext& exec_ctx, std::vector const& _args) -{ - /**************************************************************** - * Initialization - ****************************************************************/ - - // Make the exec_ctx aware of the contract's layout. - Contract contract_2 = init_contract_2(); - exec_ctx.register_contract(&contract_2); - - // Convert arguments into circuit types: - auto& builder = exec_ctx.builder; - const auto a = to_ct(builder, _args[0]); - const auto b = to_ct(builder, _args[1]); - const auto c = to_ct(builder, _args[2]); - - /**************************************************************** - * Get States & Globals used by the function - ****************************************************************/ - - auto& oracle = exec_ctx.oracle; - - CT::address msg_sender = oracle.get_msg_sender(); - - // Syntactic sugar for declaring a state variable: - UTXO y(&exec_ctx, "y"); - - /**************************************************************** - * BODY - ****************************************************************/ - - auto product = a * b * c; - - CT::address const unique_person_who_may_initialize = 999999; - - unique_person_who_may_initialize.assert_equal(msg_sender); - - y.initialize({ - .value = product, - .owner = msg_sender, - }); - // TODO: how to initialize a UTXO if it's part of a nested function call, because the msg_sender will be a contract - // address (currently the unique_initializer_address is asserted to be the msg_sender). - - /**************************************************************** - * CLEANUP - ****************************************************************/ - - // Push args to the public inputs. - - auto& public_inputs = exec_ctx.private_circuit_public_inputs; - public_inputs.args_hash = compute_var_args_hash({ a, b, c }); - - public_inputs.return_values[0] = product; - - exec_ctx.finalize(); - - // info("public inputs: ", public_inputs); - - // TODO: also return note preimages and nullifier preimages. -}; - -} // namespace aztec3::circuits::apps::test_apps::private_to_private_function_call \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/function_2_1.hpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/function_2_1.hpp deleted file mode 100644 index e363e100b62..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/function_2_1.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "init.hpp" - -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" - -namespace aztec3::circuits::apps::test_apps::private_to_private_function_call { - -using aztec3::circuits::abis::OptionalPrivateCircuitPublicInputs; - -void function_2_1(FunctionExecutionContext& exec_ctx, std::vector const& _args); - -} // namespace aztec3::circuits::apps::test_apps::private_to_private_function_call \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/index.hpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/index.hpp deleted file mode 100644 index 80035d4a71c..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/index.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#include "contract.hpp" -#include "function_1_1.hpp" -#include "function_2_1.hpp" -#include "init.hpp" \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/init.hpp b/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/init.hpp deleted file mode 100644 index 7f2e42a70a4..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/test_apps/private_to_private_function_call/init.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "aztec3/circuits/apps/contract.hpp" -#include "aztec3/circuits/apps/function_execution_context.hpp" -#include "aztec3/circuits/apps/notes/default_singleton_private_note/note.hpp" -#include "aztec3/circuits/apps/oracle_wrapper.hpp" -#include "aztec3/circuits/apps/state_vars/utxo_state_var.hpp" -#include "aztec3/oracle/oracle.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -namespace aztec3::circuits::apps::test_apps::private_to_private_function_call { - -// Builder -using C = UltraCircuitBuilder; - -// Native and circuit types -using CT = aztec3::utils::types::CircuitTypes; -using NT = aztec3::utils::types::NativeTypes; - -// Database types -using DB = oracle::FakeDB; -using oracle::NativeOracle; -using OracleWrapper = OracleWrapperInterface; - -using Contract = apps::Contract; -using FunctionExecutionContext = apps::FunctionExecutionContext; - -using aztec3::utils::types::to_ct; - -// StateVars -using apps::state_vars::UTXOStateVar; - -// Get rid of ugly `Builder` template arg from our state var types: -template using UTXO = UTXOStateVar; - -using Note = apps::notes::DefaultSingletonPrivateNote; - -} // namespace aztec3::circuits::apps::test_apps::private_to_private_function_call \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/utxo_datum.hpp b/circuits/cpp/src/aztec3/circuits/apps/utxo_datum.hpp deleted file mode 100644 index c13bd18527b..00000000000 --- a/circuits/cpp/src/aztec3/circuits/apps/utxo_datum.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::apps { - -using aztec3::utils::types::CircuitTypes; -using aztec3::utils::types::NativeTypes; -using plonk::stdlib::witness_t; - -/** - * @tparam NCT - NativeTypes or CircuitTypes - * @tparam NotePreimage - */ -template struct UTXOSLoadDatum { - using fr = typename NCT::fr; - using address = typename NCT::address; - using uint32 = typename NCT::uint32; - - fr commitment = 0; - address contract_address = 0; - NotePreimage preimage{}; - - std::vector sibling_path; - uint32 leaf_index; - fr historical_note_hash_tree_root = 0; - - template auto to_circuit_type(Builder& builder) const - { - static_assert(std::is_same::value); - - // Capture the circuit builder: - auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; - - auto preimage_ct = preimage.to_circuit_type(builder); - - UTXOSLoadDatum, decltype(preimage_ct)> datum = { - to_ct(commitment), to_ct(contract_address), preimage_ct, - to_ct(sibling_path), to_ct(leaf_index), to_ct(historical_note_hash_tree_root), - }; - - return datum; - }; -}; - -} // namespace aztec3::circuits::apps diff --git a/circuits/cpp/src/aztec3/circuits/hash.hpp b/circuits/cpp/src/aztec3/circuits/hash.hpp deleted file mode 100644 index 241271f1925..00000000000 --- a/circuits/cpp/src/aztec3/circuits/hash.hpp +++ /dev/null @@ -1,458 +0,0 @@ -#pragma once - -#include "aztec3/circuits/abis/function_data.hpp" -#include "aztec3/circuits/abis/function_leaf_preimage.hpp" -#include "aztec3/circuits/abis/function_selector.hpp" -#include "aztec3/circuits/abis/global_variables.hpp" -#include "aztec3/circuits/abis/new_contract_data.hpp" -#include "aztec3/circuits/abis/point.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/circuit_errors.hpp" - -#include - -#include -#include - -namespace aztec3::circuits { - -using abis::FunctionData; -using abis::FunctionSelector; -using abis::Point; -using aztec3::circuits::abis::ContractLeafPreimage; -using aztec3::circuits::abis::FunctionLeafPreimage; -using MemoryStore = proof_system::plonk::stdlib::merkle_tree::MemoryStore; -using MerkleTree = proof_system::plonk::stdlib::merkle_tree::MerkleTree; - -template typename NCT::fr compute_var_args_hash(std::vector const& args) -{ - auto const MAX_ARGS = 32; - if (args.size() > MAX_ARGS) { - throw_or_abort("Too many arguments in call to compute_var_args_hash"); - } - return NCT::hash(args, FUNCTION_ARGS); -} - -template typename NCT::fr compute_constructor_hash(FunctionData const& function_data, - typename NCT::fr const& args_hash, - typename NCT::fr const& constructor_vk_hash) -{ - using fr = typename NCT::fr; - - fr const function_data_hash = function_data.hash(); - - std::vector const inputs = { - function_data_hash, - args_hash, - constructor_vk_hash, - }; - - return NCT::hash(inputs, aztec3::GeneratorIndex::CONSTRUCTOR); -} - -template typename NCT::fr compute_partial_address(typename NCT::fr const& contract_address_salt, - typename NCT::fr const& function_tree_root, - typename NCT::fr const& constructor_hash) -{ - std::vector const inputs = { - typename NCT::fr(0), typename NCT::fr(0), contract_address_salt, function_tree_root, constructor_hash, - }; - return NCT::hash(inputs, aztec3::GeneratorIndex::PARTIAL_ADDRESS); -} - -template -typename NCT::address compute_contract_address_from_partial(Point const& point, - typename NCT::fr const& partial_address) -{ - std::vector const inputs = { - point.x, - point.y, - partial_address, - }; - return { NCT::hash(inputs, aztec3::GeneratorIndex::CONTRACT_ADDRESS) }; -} - -template typename NCT::fr compute_commitment_nonce(typename NCT::fr const& first_nullifier, - typename NCT::fr const& commitment_index) -{ - using fr = typename NCT::fr; - - std::vector const inputs = { - first_nullifier, - commitment_index, - }; - - return NCT::hash(inputs, aztec3::GeneratorIndex::COMMITMENT_NONCE); -} - -template typename NCT::fr silo_commitment(typename NCT::address const& contract_address, - typename NCT::fr const& inner_commitment) -{ - using fr = typename NCT::fr; - - std::vector const inputs = { - contract_address.to_field(), - inner_commitment, - }; - - return NCT::hash(inputs, aztec3::GeneratorIndex::SILOED_COMMITMENT); -} - -template -typename NCT::fr compute_unique_commitment(typename NCT::fr nonce, typename NCT::fr siloed_commitment) -{ - using fr = typename NCT::fr; - - std::vector const inputs = { - nonce, - siloed_commitment, - }; - - return NCT::hash(inputs, aztec3::GeneratorIndex::UNIQUE_COMMITMENT); -} - -template -typename NCT::fr silo_nullifier(typename NCT::address const& contract_address, typename NCT::fr nullifier) -{ - using fr = typename NCT::fr; - - std::vector const inputs = { - contract_address.to_field(), - nullifier, - }; - - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1475): use hash here (everywhere?) - return NCT::hash(inputs, aztec3::GeneratorIndex::OUTER_NULLIFIER); -} - - -template typename NCT::fr compute_block_hash(typename NCT::fr const& globals_hash, - typename NCT::fr const& note_hash_tree_root, - typename NCT::fr const& nullifier_tree_root, - typename NCT::fr const& contract_tree_root, - typename NCT::fr const& l1_to_l2_message_tree_root, - typename NCT::fr const& public_data_tree_root) -{ - using fr = typename NCT::fr; - - std::vector const inputs = { - globals_hash, note_hash_tree_root, nullifier_tree_root, - contract_tree_root, l1_to_l2_message_tree_root, public_data_tree_root, - }; - - return NCT::hash(inputs, aztec3::GeneratorIndex::BLOCK_HASH); -} - -template -typename NCT::fr compute_block_hash_with_globals(abis::GlobalVariables const& globals, - typename NCT::fr const& note_hash_tree_root, - typename NCT::fr const& nullifier_tree_root, - typename NCT::fr const& contract_tree_root, - typename NCT::fr const& l1_to_l2_message_tree_root, - typename NCT::fr const& public_data_tree_root) -{ - using fr = typename NCT::fr; - - std::vector const inputs = { - globals.hash(), note_hash_tree_root, nullifier_tree_root, - contract_tree_root, l1_to_l2_message_tree_root, public_data_tree_root, - }; - - return NCT::hash(inputs, aztec3::GeneratorIndex::BLOCK_HASH); -} - -template typename NCT::fr compute_globals_hash(abis::GlobalVariables const& globals) -{ - return globals.hash(); -} - -/** - * @brief Calculate the Merkle tree root from the sibling path and leaf. - * - * @details The leaf is hashed with its sibling, and then the result is hashed - * with the next sibling etc in the path. The last hash is the root. - * - * @tparam NCT Operate on NativeTypes or CircuitTypes - * @tparam N The number of elements in the sibling path - * @param leaf The leaf element of the Merkle tree - * @param leaf_index The index of the leaf element in the Merkle tree - * @param sibling_path The nodes representing the merkle siblings of the leaf, its parent, - * the next parent, etc up to the sibling below the root - * @return The computed Merkle tree root. - * - * TODO need to use conditional assigns instead of `ifs` for circuit version. - * see membership.hpp:check_subtree_membership (left/right/conditional_assign, etc) - */ -template -typename NCT::fr root_from_sibling_path(typename NCT::fr const& leaf, - typename NCT::uint32 const& leaf_index, - std::array const& sibling_path) -{ - auto node = leaf; - for (size_t i = 0; i < N; i++) { - if (leaf_index & (1 << i)) { - node = NCT::merkle_hash(sibling_path[i], node); - } else { - node = NCT::merkle_hash(node, sibling_path[i]); - } - } - return node; // root -} - -/** - * @brief Calculate the Merkle tree root from the sibling path and leaf. - * - * @details The leaf is hashed with its sibling, and then the result is hashed - * with the next sibling etc in the path. The last hash is the root. - * - * @tparam NCT Operate on NativeTypes or CircuitTypes - * @tparam N The number of elements in the sibling path - * @param leaf The leaf element of the Merkle tree - * @param leaf_index The index of the leaf element in the Merkle tree - * @param sibling_path The nodes representing the merkle siblings of the leaf, its parent, - * the next parent, etc up to the sibling below the root - * @return The computed Merkle tree root. - * - * TODO need to use conditional assigns instead of `ifs` for circuit version. - * see membership.hpp:check_subtree_membership (left/right/conditional_assign, etc) - */ -template -typename NCT::fr root_from_sibling_path(typename NCT::fr const& leaf, - typename NCT::fr const& leaf_index, - std::array const& sibling_path) -{ - auto node = leaf; - uint256_t index = leaf_index; - for (size_t i = 0; i < N; i++) { - if (index & 1) { - node = NCT::merkle_hash(sibling_path[i], node); - } else { - node = NCT::merkle_hash(node, sibling_path[i]); - } - index >>= uint256_t(1); - } - return node; // root -} - -/** - * @brief Get the sibling path of an item in a given merkle tree - * - * WARNING: this function is for testing purposes only! leaf_index is an fr - * in `MembershipWitness` but is a `size_t` here. This could lead to overflows - * on `1 << i` if the tree is large enough. - * - * @tparam N height of tree (not including root) - * @param tree merkle tree to operate on - * @param leaf_index index of the leaf to get path for - * @param subtree_depth_to_skip skip some number of bottom layers - * @return std::array sibling path - */ -template -std::array get_sibling_path(MerkleTree& tree, size_t leaf_index, size_t const& subtree_depth_to_skip) -{ - std::array sibling_path; - auto path = tree.get_hash_path(leaf_index); - // slice out the skip - leaf_index = leaf_index >> (subtree_depth_to_skip); - for (size_t i = 0; i < N; i++) { - if (leaf_index & (1 << i)) { - sibling_path[i] = path[subtree_depth_to_skip + i].first; - } else { - sibling_path[i] = path[subtree_depth_to_skip + i].second; - } - } - return sibling_path; -} - -template -void check_membership(Builder& builder, - typename NCT::fr const& value, - typename NCT::fr const& index, - std::array const& sibling_path, - typename NCT::fr const& root, - std::string const& msg) -{ - const auto calculated_root = root_from_sibling_path(value, index, sibling_path); - builder.do_assert(calculated_root == root, - std::string("Membership check failed: ") + msg, - aztec3::utils::CircuitErrorCode::MEMBERSHIP_CHECK_FAILED); -} - -/** - * @brief Calculate the function tree root from the sibling path and leaf preimage. - * - * @tparam NCT (native or circuit) - * @param selector in leaf preimage - * @param is_internal in leaf preimage - * @param is_private in leaf preimage - * @param vk_hash in leaf preimage - * @param acir_hash in leaf preimage - * @param function_leaf_index leaf index in the function tree - * @param function_leaf_sibling_path - * @return NCT::fr - */ -template typename NCT::fr function_tree_root_from_siblings( - FunctionSelector const& selector, - typename NCT::boolean const& is_internal, - typename NCT::boolean const& is_private, - typename NCT::fr const& vk_hash, - typename NCT::fr const& acir_hash, - typename NCT::fr const& function_leaf_index, - std::array const& function_leaf_sibling_path) -{ - const auto function_leaf_preimage = FunctionLeafPreimage{ - .selector = selector, - .is_internal = is_internal, - .is_private = is_private, - .vk_hash = vk_hash, - .acir_hash = acir_hash, - }; - - const auto function_leaf = function_leaf_preimage.hash(); - - auto function_tree_root = - root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path); - return function_tree_root; -} - -/** - * @brief Calculate the contract tree root from the sibling path and leaf preimage. - * - * @tparam NCT (native or circuit) - * @param function_tree_root in leaf preimage - * @param storage_contract_address in leaf preimage - * @param portal_contract_address in leaf preimage - * @param contract_leaf_index leaf index in the function tree - * @param contract_leaf_sibling_path - * @return NCT::fr - */ -template typename NCT::fr contract_tree_root_from_siblings( - typename NCT::fr const& function_tree_root, - typename NCT::address const& storage_contract_address, - typename NCT::address const& portal_contract_address, - typename NCT::fr const& contract_leaf_index, - std::array const& contract_leaf_sibling_path) -{ - const ContractLeafPreimage contract_leaf_preimage{ storage_contract_address, - portal_contract_address, - function_tree_root }; - - const auto contract_leaf = contract_leaf_preimage.hash(); - - const auto computed_contract_tree_root = - root_from_sibling_path(contract_leaf, contract_leaf_index, contract_leaf_sibling_path); - return computed_contract_tree_root; -} - -/** - * @brief Compute sibling path for an empty tree. - * - * @tparam NCT (native or circuit) - * @tparam TREE_HEIGHT - * @param zero_leaf the leaf value that corresponds to a zero preimage - * @return std::array - */ -template -std::array compute_empty_sibling_path(typename NCT::fr const& zero_leaf) -{ - std::array sibling_path = { zero_leaf }; - for (size_t i = 1; i < TREE_HEIGHT; i++) { - // hash previous sibling with itself to get node above - sibling_path[i] = NCT::merkle_hash(sibling_path[i - 1], sibling_path[i - 1]); - } - return sibling_path; -} - -/** - * @brief Compute the value to be inserted into the public data tree - * @param value The value to be inserted into the public data tree - * @return The hash value required for insertion into the public data tree - */ -template typename NCT::fr compute_public_data_tree_value(typename NCT::fr const& value) -{ - // as it's a public value, it doesn't require hashing. - // leaving this function here in case we decide to change this. - return value; -} - -/** - * @brief Compute the index for inserting a value into the public data tree - * @param contract_address The address of the contract to which the inserted element belongs - * @param storage_slot The storage slot to which the inserted element belongs - * @return The index for insertion into the public data tree - */ -template typename NCT::fr compute_public_data_tree_index(typename NCT::address const& contract_address, - typename NCT::fr const& storage_slot) -{ - return NCT::hash({ contract_address.to_field(), storage_slot }, GeneratorIndex::PUBLIC_LEAF_INDEX); -} - -template typename NCT::fr compute_l2_to_l1_hash(typename NCT::address const& contract_address, - typename NCT::fr const& rollup_version_id, - typename NCT::fr const& portal_contract_address, - typename NCT::fr const& chain_id, - typename NCT::fr const& content) -{ - using fr = typename NCT::fr; - - std::vector const inputs = { - contract_address.to_field(), rollup_version_id, portal_contract_address, chain_id, content, - }; - - constexpr auto const num_bytes = 5 * 32; - std::array calldata_hash_inputs_bytes; - // Convert all into a buffer, then copy into the array, then hash - for (size_t i = 0; i < inputs.size(); i++) { - auto as_bytes = inputs[i].to_buffer(); - - auto offset = i * 32; - std::copy(as_bytes.begin(), as_bytes.end(), calldata_hash_inputs_bytes.begin() + offset); - } - - std::vector const calldata_hash_inputs_bytes_vec(calldata_hash_inputs_bytes.begin(), - calldata_hash_inputs_bytes.end()); - - // @todo @LHerskind NOTE sha to field! - return sha256::sha256_to_field(calldata_hash_inputs_bytes_vec); -} - -/** - * @brief Computes sha256 hash of 2 input hashes stored in 4 fields. - * @param hashes 4 fields containing 2 hashes [high, low, high, low]. - * @return Resulting sha256 hash stored in 2 fields. - */ -template std::array accumulate_sha256( - std::array const& hashes) -{ - using fr = typename NCT::fr; - - // Generate a 512 bit input from right and left 256 bit hashes - constexpr auto num_bytes = 2 * 32; - std::array hash_input_bytes; - for (size_t i = 0; i < 4; i++) { - auto half = hashes[i].to_buffer(); - for (size_t j = 0; j < 16; j++) { - hash_input_bytes[i * 16 + j] = half[16 + j]; - } - } - - // Compute the sha256 - std::vector const hash_input_bytes_vec(hash_input_bytes.begin(), hash_input_bytes.end()); - auto h = sha256::sha256(hash_input_bytes_vec); - - // Split the hash into two fields, a high and a low - std::array buf_1; - std::array buf_2; - for (uint8_t i = 0; i < 16; i++) { - buf_1[i] = 0; - buf_1[16 + i] = h[i]; - buf_2[i] = 0; - buf_2[16 + i] = h[i + 16]; - } - auto high = fr::serialize_from_buffer(buf_1.data()); - auto low = fr::serialize_from_buffer(buf_2.data()); - - return { high, low }; -} - -} // namespace aztec3::circuits diff --git a/circuits/cpp/src/aztec3/circuits/kernel/CMakeLists.txt b/circuits/cpp/src/aztec3/circuits/kernel/CMakeLists.txt deleted file mode 100644 index 88e86fd9163..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -circuits_cmake_module( - aztec3_circuits_kernel - - # Question: why can't I link to these barretenberg modules? - # aztec3_circuits_abis - aztec3_circuits_apps - - barretenberg -) \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/.test.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/.test.cpp deleted file mode 100644 index c682ed1cbd0..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/.test.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#include "index.hpp" -#include "init.hpp" -#include "testing_harness.hpp" - -#include "aztec3/circuits/apps/test_apps/basic_contract_deployment/basic_contract_deployment.hpp" -#include "aztec3/circuits/apps/test_apps/escrow/deposit.hpp" - -#include - -#include - -namespace { - -using aztec3::circuits::apps::test_apps::basic_contract_deployment::constructor; -using aztec3::circuits::apps::test_apps::escrow::deposit; - -using aztec3::circuits::kernel::private_kernel::testing_harness::do_private_call_get_kernel_inputs_init; -using aztec3::circuits::kernel::private_kernel::testing_harness::do_private_call_get_kernel_inputs_inner; - -} // namespace - -namespace aztec3::circuits::kernel::private_kernel { - -class private_kernel_tests : public ::testing::Test { - protected: - static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../barretenberg/cpp/srs_db/ignition"); } -}; - -/** - * @brief Check private kernel circuit for arbitrary valid app proof and previous kernel proof - * @details The purpose of this test is to check the private kernel circuit given a valid app proof and a valid previous - * private kernel proof. To avoid doing actual proof construction, we simply read in an arbitrary but valid proof and a - * corresponding valid verification key from file. The same proof and vkey data is used for both the app and the - * previous kernel. - * @note The choice of app circuit (currently 'deposit') is entirely arbitrary and can be replaced with any other valid - * app circuit. - */ -TEST_F(private_kernel_tests, circuit_basic) -{ - NT::fr const& amount = 5; - NT::fr const& asset_id = 1; - NT::fr const& memo = 999; - std::array const& empty_logs_hash = { NT::fr(16), NT::fr(69) }; - NT::fr const& empty_log_preimages_length = NT::fr(100); - - // Generate private inputs including proofs and vkeys for app circuit and previous kernel - auto const& private_inputs = do_private_call_get_kernel_inputs_inner(false, - deposit, - { amount, asset_id, memo }, - empty_logs_hash, - empty_logs_hash, - empty_log_preimages_length, - empty_log_preimages_length, - empty_logs_hash, - empty_logs_hash, - empty_log_preimages_length, - empty_log_preimages_length, - true); - - // Execute and prove the first kernel iteration - Builder private_kernel_builder; - private_kernel_circuit(private_kernel_builder, private_inputs, true); - - // Check the private kernel circuit - EXPECT_TRUE(private_kernel_builder.check_circuit()); -} - -// TODO(1998): Lack of support for msgpack deserialization for Circuitresult type for this test -// to be able to call private_kernel__sim_init. -/** - * @brief Some private circuit simulation checked against its results via cbinds - */ -/* -TEST_F(private_kernel_tests, circuit_cbinds) -{ - NT::fr const& arg0 = 5; - NT::fr const& arg1 = 1; - NT::fr const& arg2 = 999; - std::array const& encrypted_logs_hash = { NT::fr(16), NT::fr(69) }; - NT::fr const& encrypted_log_preimages_length = NT::fr(100); - std::array const& unencrypted_logs_hash = { NT::fr(26), NT::fr(47) }; - NT::fr const& unencrypted_log_preimages_length = NT::fr(50); - - // first run actual simulation to get public inputs - auto const& private_inputs = do_private_call_get_kernel_inputs_init(true, - constructor, - { arg0, arg1, arg2 }, - encrypted_logs_hash, - unencrypted_logs_hash, - encrypted_log_preimages_length, - unencrypted_log_preimages_length, - true); - DummyBuilder builder = DummyBuilder("private_kernel_tests__circuit_create_proof_cbinds"); - auto const& public_inputs = native_private_kernel_circuit_initial(builder, private_inputs); - - auto exp_result = builder.result_or_error(public_inputs); - // Does not compile. See https://github.com/AztecProtocol/aztec-packages/issues/1998 - auto res = call_msgpack_cbind(private_kernel__sim_init, private_inputs); - - ASSERT_TRUE(exp_result.result == res.result); -} -*/ - -} // namespace aztec3::circuits::kernel::private_kernel diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/c_bind.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/c_bind.cpp deleted file mode 100644 index 0044f2e179e..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/c_bind.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "c_bind.h" - -#include "index.hpp" -#include "utils.hpp" - -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_init.hpp" -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_inner.hpp" -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_ordering.hpp" -#include "aztec3/constants.hpp" - -#include - -#include - -namespace { -using Builder = UltraCircuitBuilder; -using NT = aztec3::utils::types::NativeTypes; -using DummyCircuitBuilder = aztec3::utils::DummyCircuitBuilder; -using aztec3::circuits::abis::private_kernel::PrivateKernelInputsInit; -using aztec3::circuits::abis::private_kernel::PrivateKernelInputsInner; -using aztec3::circuits::abis::private_kernel::PrivateKernelInputsOrdering; -using aztec3::circuits::kernel::private_kernel::native_private_kernel_circuit_initial; -using aztec3::circuits::kernel::private_kernel::native_private_kernel_circuit_inner; -using aztec3::circuits::kernel::private_kernel::native_private_kernel_circuit_ordering; -using aztec3::circuits::kernel::private_kernel::utils::dummy_previous_kernel; - -} // namespace - -// WASM Cbinds - -CBIND(private_kernel__dummy_previous_kernel, []() { return dummy_previous_kernel(); }); - -CBIND(private_kernel__sim_init, [](PrivateKernelInputsInit private_inputs) { - DummyCircuitBuilder builder = DummyCircuitBuilder("private_kernel__sim_init"); - auto const& public_inputs = native_private_kernel_circuit_initial(builder, private_inputs); - return builder.result_or_error(public_inputs); -}); - -CBIND(private_kernel__sim_inner, [](PrivateKernelInputsInner private_inputs) { - DummyCircuitBuilder builder = DummyCircuitBuilder("private_kernel__sim_inner"); - auto const& public_inputs = native_private_kernel_circuit_inner(builder, private_inputs); - return builder.result_or_error(public_inputs); -}); - -CBIND(private_kernel__sim_ordering, [](PrivateKernelInputsOrdering private_inputs) { - DummyCircuitBuilder builder = DummyCircuitBuilder("private_kernel__sim_ordering"); - auto const& public_inputs = native_private_kernel_circuit_ordering(builder, private_inputs); - return builder.result_or_error(public_inputs); -}); diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/c_bind.h b/circuits/cpp/src/aztec3/circuits/kernel/private/c_bind.h deleted file mode 100644 index b88b051c326..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/c_bind.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include - -#include -#include - -CBIND_DECL(private_kernel__dummy_previous_kernel); -CBIND_DECL(private_kernel__sim_init); -CBIND_DECL(private_kernel__sim_inner); -CBIND_DECL(private_kernel__sim_ordering); diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/common.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/common.cpp deleted file mode 100644 index 101ead9ec52..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/common.cpp +++ /dev/null @@ -1,438 +0,0 @@ -#include "common.hpp" - -#include "init.hpp" - -#include "aztec3/circuits/abis/complete_address.hpp" -#include "aztec3/circuits/abis/contract_deployment_data.hpp" -#include "aztec3/circuits/abis/function_data.hpp" -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/new_contract_data.hpp" -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/private_kernel/private_call_data.hpp" -#include "aztec3/circuits/abis/read_request_membership_witness.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/array.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" - -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; - -using aztec3::circuits::abis::CompleteAddress; -using aztec3::circuits::abis::ContractDeploymentData; -using aztec3::circuits::abis::ContractLeafPreimage; -using aztec3::circuits::abis::FunctionData; -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using aztec3::circuits::abis::NewContractData; -using aztec3::circuits::abis::ReadRequestMembershipWitness; - -using aztec3::utils::array_push; -using aztec3::utils::is_array_empty; -using aztec3::utils::push_array_to_array; -using aztec3::utils::validate_array; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; -using CircuitErrorCode = aztec3::utils::CircuitErrorCode; -using aztec3::circuits::abis::private_kernel::PrivateCallData; - -namespace aztec3::circuits::kernel::private_kernel { - -void common_validate_call_stack(DummyBuilder& builder, PrivateCallData const& private_call) -{ - const auto& stack = private_call.call_stack_item.public_inputs.private_call_stack; - const auto& preimages = private_call.private_call_stack_preimages; - for (size_t i = 0; i < stack.size(); ++i) { - const auto& hash = stack[i]; - const auto& preimage = preimages[i]; - - // Note: this assumes it's computationally infeasible to have `0` as a valid call_stack_item_hash. - // Assumes `hash == 0` means "this stack item is empty". - const auto calculated_hash = hash == 0 ? 0 : preimage.hash(); - builder.do_assert(hash == calculated_hash, - format("private_call_stack[", i, "] = ", hash, "; does not reconcile"), - CircuitErrorCode::PRIVATE_KERNEL__PRIVATE_CALL_STACK_ITEM_HASH_MISMATCH); - } -} - -/** - * @brief Validate all read requests against the historical note hash tree root. - * Use their membership witnesses to do so. If the historical root is not yet - * initialized, initialize it using the first read request here (if present). - * - * @details More info here: - * - https://discourse.aztec.network/t/to-read-or-not-to-read/178 - * - https://discourse.aztec.network/t/spending-notes-which-havent-yet-been-inserted/180 - * - * @param builder - * @param historical_note_hash_tree_root This is a reference to the historical root which all - * read requests are checked against here. - * @param read_requests the commitments being read by this private call - 'transient note reads' here are - * `inner_note_hashes` (not yet siloed, not unique), but 'pre-existing note reads' are `unique_siloed_note_hashes` - * @param read_request_membership_witnesses used to compute the note hash tree root - * for a given request which is essentially a membership check - */ -void common_validate_read_requests(DummyBuilder& builder, - NT::fr const& historical_note_hash_tree_root, - std::array const& read_requests, - std::array, - MAX_READ_REQUESTS_PER_CALL> const& read_request_membership_witnesses) -{ - // membership witnesses must resolve to the same note hash tree root - // for every request in all kernel iterations - for (size_t rr_idx = 0; rr_idx < aztec3::MAX_READ_REQUESTS_PER_CALL; rr_idx++) { - const auto& read_request = read_requests[rr_idx]; - const auto& witness = read_request_membership_witnesses[rr_idx]; - - // A pending commitment is the one that is not yet added to note hash tree - // A "transient read" is when we try to "read" a pending commitment within a transaction - // between function calls, as opposed to reading the outputs of a previous transaction - // which is a "pending read". - // We determine if it is a transient read depending on the leaf index from the membership witness - // Note that the Merkle membership proof would be null and void in case of an transient read - // but we use the leaf index as a placeholder to detect a 'pending note read'. - if (read_request != 0 && !witness.is_transient) { - const auto& root_for_read_request = - root_from_sibling_path(read_request, witness.leaf_index, witness.sibling_path); - builder.do_assert( - root_for_read_request == historical_note_hash_tree_root, - format("note hash tree root mismatch at read_request[", - rr_idx, - "]", - "\n\texpected root: ", - historical_note_hash_tree_root, - "\n\tbut got root*: ", - root_for_read_request, - "\n\tread_request**: ", - read_request, - "\n\tleaf_index: ", - witness.leaf_index, - "\n\tis_transient: ", - witness.is_transient, - "\n\thint_to_commitment: ", - witness.hint_to_commitment, - "\n\t* got root by treating the read_request as a leaf in the note hash tree " - "and merkle-hashing to a root using the membership witness" - "\n\t** for 'pre-existing note reads', the read_request is the unique_siloed_note_hash " - "(it has been hashed with contract address and then a nonce)"), - CircuitErrorCode::PRIVATE_KERNEL__READ_REQUEST_NOTE_HASH_TREE_ROOT_MISMATCH); - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1354): do we need to enforce - // that a non-transient read_request was derived from the proper/current contract address? - } - } -} - -/** - * @brief We validate that relevant arrays assumed to be zero-padded on the right comply to this format. - * - * @param builder - * @param app_public_inputs Reference to the private_circuit_public_inputs of the current kernel iteration. - */ -void common_validate_arrays(DummyBuilder& builder, PrivateCircuitPublicInputs const& app_public_inputs) -{ - // Each of the following arrays is expected to be zero-padded. - // In addition, some of the following arrays (new_commitments, etc...) are passed - // to push_array_to_array() routines which rely on the passed arrays to be well-formed. - validate_array(builder, app_public_inputs.return_values, "App public inputs - Return values"); - validate_array(builder, app_public_inputs.read_requests, "App public inputs - Read requests"); - validate_array(builder, app_public_inputs.new_commitments, "App public inputs - New commitments"); - validate_array(builder, app_public_inputs.new_nullifiers, "App public inputs - New nullifiers"); - validate_array(builder, app_public_inputs.nullified_commitments, "App public inputs - Nullified commitments"); - validate_array(builder, app_public_inputs.private_call_stack, "App public inputs - Private call stack"); - validate_array(builder, app_public_inputs.public_call_stack, "App public inputs - Public call stack"); - validate_array(builder, app_public_inputs.new_l2_to_l1_msgs, "App public inputs - New L2 to L1 messages"); - // encrypted_logs_hash and unencrypted_logs_hash have their own integrity checks. -} - -/** - * @brief We validate that relevant arrays assumed to be zero-padded on the right comply to this format. - * - * @param builder - * @param end Reference to previous_kernel.public_inputs.end. - */ -void common_validate_previous_kernel_arrays(DummyBuilder& builder, CombinedAccumulatedData const& end) -{ - // Each of the following arrays is expected to be zero-padded. - validate_array(builder, end.read_requests, "Accumulated data - Read Requests"); - validate_array(builder, end.new_commitments, "Accumulated data - New commitments"); - validate_array(builder, end.new_nullifiers, "Accumulated data - New nullifiers"); - validate_array(builder, end.nullified_commitments, "Accumulated data - Nullified commitments"); - validate_array(builder, end.private_call_stack, "Accumulated data - Private call stack"); - validate_array(builder, end.public_call_stack, "Accumulated data - Public call stack"); - validate_array(builder, end.new_l2_to_l1_msgs, "Accumulated data - New L2 to L1 messages"); -} - -void common_validate_previous_kernel_0th_nullifier(DummyBuilder& builder, CombinedAccumulatedData const& end) -{ - builder.do_assert(end.new_nullifiers[0] != 0, - "The 0th nullifier in the accumulated nullifier array is zero", - CircuitErrorCode::PRIVATE_KERNEL__0TH_NULLIFIER_IS_ZERO); -} - -void common_validate_previous_kernel_values(DummyBuilder& builder, CombinedAccumulatedData const& end) -{ - common_validate_previous_kernel_arrays(builder, end); - common_validate_previous_kernel_0th_nullifier(builder, end); -} - -void common_update_end_values(DummyBuilder& builder, - PrivateCallData const& private_call, - KernelCircuitPublicInputs& public_inputs) -{ - const auto private_call_public_inputs = private_call.call_stack_item.public_inputs; - - const auto& read_requests = private_call_public_inputs.read_requests; - const auto& read_request_membership_witnesses = private_call.read_request_membership_witnesses; - - - const auto& new_commitments = private_call_public_inputs.new_commitments; - const auto& new_nullifiers = private_call_public_inputs.new_nullifiers; - const auto& nullified_commitments = private_call_public_inputs.nullified_commitments; - - const auto& is_static_call = private_call_public_inputs.call_context.is_static_call; - - if (is_static_call) { - // No state changes are allowed for static calls: - builder.do_assert(is_array_empty(new_commitments) == true, - "new_commitments must be empty for static calls", - CircuitErrorCode::PRIVATE_KERNEL__NEW_COMMITMENTS_PROHIBITED_IN_STATIC_CALL); - builder.do_assert(is_array_empty(new_nullifiers) == true, - "new_nullifiers must be empty for static calls", - CircuitErrorCode::PRIVATE_KERNEL__NEW_NULLIFIERS_PROHIBITED_IN_STATIC_CALL); - } - - const auto& storage_contract_address = private_call_public_inputs.call_context.storage_contract_address; - - // Transient read requests and witnesses are accumulated in public_inputs.end - // We silo the read requests (domain separation per contract address) - { - for (size_t i = 0; i < read_requests.size(); ++i) { - const auto& read_request = read_requests[i]; - const auto& witness = read_request_membership_witnesses[i]; - if (witness.is_transient) { // only forward transient to public inputs - // TODO (David): This is pushing zeroed read requests for public inputs if they are transient. Is that - // correct? - const auto siloed_read_request = - read_request == 0 ? 0 : silo_commitment(storage_contract_address, read_request); - array_push(builder, - public_inputs.end.read_requests, - siloed_read_request, - format(PRIVATE_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, - "too many transient read requests in one tx")); - } - } - } - - // Enhance commitments and nullifiers with domain separation whereby domain is the contract. - { - // nullifiers - std::array siloed_new_nullifiers{}; - for (size_t i = 0; i < MAX_NEW_NULLIFIERS_PER_CALL; ++i) { - siloed_new_nullifiers[i] = - new_nullifiers[i] == 0 ? 0 : silo_nullifier(storage_contract_address, new_nullifiers[i]); - } - push_array_to_array( - builder, - siloed_new_nullifiers, - public_inputs.end.new_nullifiers, - format(PRIVATE_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, "too many new nullifiers in one tx")); - - // commitments - std::array siloed_new_commitments{}; - for (size_t i = 0; i < new_commitments.size(); ++i) { - siloed_new_commitments[i] = - new_commitments[i] == 0 ? 0 : silo_commitment(storage_contract_address, new_commitments[i]); - } - push_array_to_array( - builder, - siloed_new_commitments, - public_inputs.end.new_commitments, - format(PRIVATE_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, "too many new commitments in one tx")); - - // nullified commitments (for matching transient nullifiers to transient commitments) - // Since every new_nullifiers entry is paired with a nullified_commitment, EMPTY - // is used here for nullified_commitments of persistable nullifiers. EMPTY will still - // take up a slot in the nullified_commitments array so that the array lines up properly - // with new_nullifiers. This is necessary since the constant-size circuit-array functions - // we use assume that the first 0-valued array entry designates the end of the array. - std::array siloed_nullified_commitments{}; - for (size_t i = 0; i < MAX_NEW_NULLIFIERS_PER_CALL; ++i) { - siloed_nullified_commitments[i] = - nullified_commitments[i] == fr(0) ? fr(0) // don't silo when empty - : nullified_commitments[i] == fr(EMPTY_NULLIFIED_COMMITMENT) - ? fr(EMPTY_NULLIFIED_COMMITMENT) // don't silo when empty - : silo_commitment(storage_contract_address, nullified_commitments[i]); - } - - push_array_to_array( - builder, - siloed_nullified_commitments, - public_inputs.end.nullified_commitments, - format(PRIVATE_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, "too many new nullified commitments in one tx")); - } - - { // call stacks - const auto& this_private_call_stack = private_call_public_inputs.private_call_stack; - push_array_to_array( - builder, - this_private_call_stack, - public_inputs.end.private_call_stack, - format(PRIVATE_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, "too many private call stacks in one tx")); - - const auto& this_public_call_stack = private_call_public_inputs.public_call_stack; - push_array_to_array( - builder, - this_public_call_stack, - public_inputs.end.public_call_stack, - format(PRIVATE_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, "too many public call stacks in one tx")); - } - - { // new l2 to l1 messages - const auto& portal_contract_address = private_call.portal_contract_address; - const auto& new_l2_to_l1_msgs = private_call_public_inputs.new_l2_to_l1_msgs; - std::array new_l2_to_l1_msgs_to_insert{}; - for (size_t i = 0; i < new_l2_to_l1_msgs.size(); ++i) { - if (!new_l2_to_l1_msgs[i].is_zero()) { - new_l2_to_l1_msgs_to_insert[i] = compute_l2_to_l1_hash(storage_contract_address, - private_call_public_inputs.version, - portal_contract_address, - private_call_public_inputs.chain_id, - new_l2_to_l1_msgs[i]); - } - } - push_array_to_array( - builder, - new_l2_to_l1_msgs_to_insert, - public_inputs.end.new_l2_to_l1_msgs, - format(PRIVATE_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, "too many new l2 to l1 messages in one tx")); - } - - { // logs hashes - // See the following thread if not clear: - // https://discourse.aztec.network/t/proposal-forcing-the-sequencer-to-actually-submit-data-to-l1/426 - const auto& previous_encrypted_logs_hash = public_inputs.end.encrypted_logs_hash; - const auto& current_encrypted_logs_hash = private_call_public_inputs.encrypted_logs_hash; - public_inputs.end.encrypted_logs_hash = accumulate_sha256({ previous_encrypted_logs_hash[0], - previous_encrypted_logs_hash[1], - current_encrypted_logs_hash[0], - current_encrypted_logs_hash[1] }); - - const auto& previous_unencrypted_logs_hash = public_inputs.end.unencrypted_logs_hash; - const auto& current_unencrypted_logs_hash = private_call_public_inputs.unencrypted_logs_hash; - public_inputs.end.unencrypted_logs_hash = accumulate_sha256({ previous_unencrypted_logs_hash[0], - previous_unencrypted_logs_hash[1], - current_unencrypted_logs_hash[0], - current_unencrypted_logs_hash[1] }); - - // Add log preimages lengths from current iteration to accumulated lengths - public_inputs.end.encrypted_log_preimages_length = public_inputs.end.encrypted_log_preimages_length + - private_call_public_inputs.encrypted_log_preimages_length; - public_inputs.end.unencrypted_log_preimages_length = - public_inputs.end.unencrypted_log_preimages_length + - private_call_public_inputs.unencrypted_log_preimages_length; - } -} - -void common_contract_logic(DummyBuilder& builder, - PrivateCallData const& private_call, - KernelCircuitPublicInputs& public_inputs, - ContractDeploymentData const& contract_dep_data, - FunctionData const& function_data) -{ - const auto private_call_public_inputs = private_call.call_stack_item.public_inputs; - const auto& storage_contract_address = private_call_public_inputs.call_context.storage_contract_address; - const auto& portal_contract_address = private_call.portal_contract_address; - - // TODO(#3062) VKs are mocked out for now - // const auto private_call_vk_hash = stdlib::recursion::verification_key::hash_native(private_call.vk); - const auto private_call_vk_hash = 0; - - const auto is_contract_deployment = public_inputs.constants.tx_context.is_contract_deployment_tx; - - if (is_contract_deployment) { - auto constructor_hash = - compute_constructor_hash(function_data, private_call_public_inputs.args_hash, private_call_vk_hash); - - auto const new_contract_address = CompleteAddress::compute(contract_dep_data.deployer_public_key, - contract_dep_data.contract_address_salt, - contract_dep_data.function_tree_root, - constructor_hash) - .address; - - // Add new contract data if its a contract deployment function - NewContractData const native_new_contract_data{ new_contract_address, - portal_contract_address, - contract_dep_data.function_tree_root }; - - array_push(builder, - public_inputs.end.new_contracts, - native_new_contract_data, - format(PRIVATE_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, "too many contracts created in one tx")); - - // TODO(#3062) VKs are mocked out for now - // builder.do_assert(contract_dep_data.constructor_vk_hash == private_call_vk_hash, - // "constructor_vk_hash doesn't match private_call_vk_hash", - // CircuitErrorCode::PRIVATE_KERNEL__INVALID_CONSTRUCTOR_VK_HASH); - - // must imply == derived address - builder.do_assert(storage_contract_address == new_contract_address, - "contract address supplied doesn't match derived address", - CircuitErrorCode::PRIVATE_KERNEL__INVALID_CONTRACT_ADDRESS); - - // compute contract address nullifier - auto const blake_input = new_contract_address.to_field().to_buffer(); - auto const new_contract_address_nullifier = NT::fr::serialize_from_buffer(NT::blake2s(blake_input).data()); - - // push the contract address nullifier to nullifier vector - array_push(builder, - public_inputs.end.new_nullifiers, - new_contract_address_nullifier, - format(PRIVATE_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, - "too many nullifiers in one tx to add the new contract address")); - } else { - // non-contract deployments must specify contract address being interacted with - builder.do_assert(storage_contract_address != 0, - "contract address can't be 0 for non-contract deployment related transactions", - CircuitErrorCode::PRIVATE_KERNEL__INVALID_CONTRACT_ADDRESS); - - /* We need to compute the root of the contract tree, starting from the function's VK: - * - Compute the vk_hash (done above) - * - Compute the function_leaf: hash(function_selector, is_internal, is_private, vk_hash, acir_hash) - * - Hash the function_leaf with the function_leaf's sibling_path to get the function_tree_root - * - Compute the contract_leaf: hash(contract_address, portal_contract_address, function_tree_root) - * - Hash the contract_leaf with the contract_leaf's sibling_path to get the contract_tree_root - */ - - // Ensures that if the function is internal, only the contract itself can call it - if (private_call.call_stack_item.function_data.is_internal) { - builder.do_assert( - storage_contract_address == private_call.call_stack_item.public_inputs.call_context.msg_sender, - "call is internal, but msg_sender is not self", - CircuitErrorCode::PRIVATE_KERNEL__IS_INTERNAL_BUT_NOT_SELF_CALL); - } - - // The logic below ensures that the contract exists in the contracts tree - auto const& computed_function_tree_root = - function_tree_root_from_siblings(private_call.call_stack_item.function_data.selector, - private_call.call_stack_item.function_data.is_internal, - true, // is_private - private_call_vk_hash, - private_call.acir_hash, - private_call.function_leaf_membership_witness.leaf_index, - private_call.function_leaf_membership_witness.sibling_path); - - auto const& computed_contract_tree_root = - contract_tree_root_from_siblings(computed_function_tree_root, - storage_contract_address, - portal_contract_address, - private_call.contract_leaf_membership_witness.leaf_index, - private_call.contract_leaf_membership_witness.sibling_path); - - auto const& purported_contract_tree_root = - private_call.call_stack_item.public_inputs.block_header.contract_tree_root; - - builder.do_assert( - computed_contract_tree_root == purported_contract_tree_root, - "computed_contract_tree_root doesn't match purported_contract_tree_root", - CircuitErrorCode::PRIVATE_KERNEL__COMPUTED_CONTRACT_TREE_ROOT_AND_PURPORTED_CONTRACT_TREE_ROOT_MISMATCH); - } -} - -} // namespace aztec3::circuits::kernel::private_kernel diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/common.hpp b/circuits/cpp/src/aztec3/circuits/kernel/private/common.hpp deleted file mode 100644 index 2e1191a252f..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/common.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -#include "init.hpp" - -#include "aztec3/circuits/abis/combined_accumulated_data.hpp" -#include "aztec3/circuits/abis/contract_deployment_data.hpp" -#include "aztec3/circuits/abis/function_data.hpp" -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/previous_kernel_data.hpp" -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/private_kernel/private_call_data.hpp" -#include "aztec3/circuits/abis/read_request_membership_witness.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" - - -namespace aztec3::circuits::kernel::private_kernel { - -using aztec3::circuits::abis::CombinedAccumulatedData; -using aztec3::circuits::abis::ContractDeploymentData; -using aztec3::circuits::abis::FunctionData; -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using aztec3::circuits::abis::PreviousKernelData; -using aztec3::circuits::abis::PrivateCircuitPublicInputs; -using aztec3::circuits::abis::ReadRequestMembershipWitness; -using aztec3::circuits::abis::private_kernel::PrivateCallData; - -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; - - -// TODO(suyash): Add comments to these as well as other functions in PKC-init. -void common_validate_call_stack(DummyBuilder& builder, PrivateCallData const& private_call); - -void common_validate_read_requests(DummyBuilder& builder, - NT::fr const& historical_note_hash_tree_root, - std::array const& read_requests, - std::array, - MAX_READ_REQUESTS_PER_CALL> const& read_request_membership_witnesses); - -void common_validate_arrays(DummyBuilder& builder, PrivateCircuitPublicInputs const& app_public_inputs); -void common_validate_previous_kernel_arrays(DummyBuilder& builder, CombinedAccumulatedData const& end); -void common_validate_previous_kernel_values(DummyBuilder& builder, CombinedAccumulatedData const& end); -void common_validate_previous_kernel_0th_nullifier(DummyBuilder& builder, CombinedAccumulatedData const& end); - -void common_update_end_values(DummyBuilder& builder, - PrivateCallData const& private_call, - KernelCircuitPublicInputs& public_inputs); - -void common_contract_logic(DummyBuilder& builder, - PrivateCallData const& private_call, - KernelCircuitPublicInputs& public_inputs, - ContractDeploymentData const& contract_dep_data, - FunctionData const& function_data); - -template -void common_initialize_end_values(PreviousKernelData const& previous_kernel, KernelPublicInputs& public_inputs) -{ - public_inputs.constants = previous_kernel.public_inputs.constants; - - // Ensure the arrays are the same as previously, before we start pushing more data onto them in other - // functions within this circuit: - auto& end = public_inputs.end; - const auto& start = previous_kernel.public_inputs.end; - - end.new_commitments = start.new_commitments; - end.new_nullifiers = start.new_nullifiers; - end.nullified_commitments = start.nullified_commitments; - - end.private_call_stack = start.private_call_stack; - end.public_call_stack = start.public_call_stack; - end.new_l2_to_l1_msgs = start.new_l2_to_l1_msgs; - - end.encrypted_logs_hash = start.encrypted_logs_hash; - end.unencrypted_logs_hash = start.unencrypted_logs_hash; - - end.encrypted_log_preimages_length = start.encrypted_log_preimages_length; - end.unencrypted_log_preimages_length = start.unencrypted_log_preimages_length; - - end.optionally_revealed_data = start.optionally_revealed_data; -} - -} // namespace aztec3::circuits::kernel::private_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/fixtures/ultra_plonk_proof.dat b/circuits/cpp/src/aztec3/circuits/kernel/private/fixtures/ultra_plonk_proof.dat deleted file mode 100644 index e602b755deb..00000000000 Binary files a/circuits/cpp/src/aztec3/circuits/kernel/private/fixtures/ultra_plonk_proof.dat and /dev/null differ diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/fixtures/ultra_plonk_verification_key.dat b/circuits/cpp/src/aztec3/circuits/kernel/private/fixtures/ultra_plonk_verification_key.dat deleted file mode 100644 index 8303a40a67b..00000000000 Binary files a/circuits/cpp/src/aztec3/circuits/kernel/private/fixtures/ultra_plonk_verification_key.dat and /dev/null differ diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/index.hpp b/circuits/cpp/src/aztec3/circuits/kernel/private/index.hpp deleted file mode 100644 index 2e351895bba..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/index.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "init.hpp" -#include "native_private_kernel_circuit_init.hpp" -#include "native_private_kernel_circuit_inner.hpp" -#include "native_private_kernel_circuit_ordering.hpp" -#include "private_kernel_circuit.hpp" \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/init.hpp b/circuits/cpp/src/aztec3/circuits/kernel/private/init.hpp deleted file mode 100644 index 62131e524f8..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/init.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include "aztec3/circuits/apps/function_execution_context.hpp" -#include "aztec3/circuits/apps/oracle_wrapper.hpp" -#include "aztec3/circuits/recursion/aggregator.hpp" -#include "aztec3/oracle/oracle.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -namespace aztec3::circuits::kernel::private_kernel { - -using Builder = UltraCircuitBuilder; - -using Aggregator = aztec3::circuits::recursion::Aggregator; - -// Generic: -using CT = aztec3::utils::types::CircuitTypes; -using NT = aztec3::utils::types::NativeTypes; -using aztec3::utils::types::to_ct; - -using DB = oracle::FakeDB; -using oracle::NativeOracle; -using OracleWrapper = aztec3::circuits::apps::OracleWrapperInterface; - -using FunctionExecutionContext = aztec3::circuits::apps::FunctionExecutionContext; - -// Used when calling library functions like `push_array` which have their own generic error code. -// So we pad this in front of the error message to identify where the error originally came from. -const std::string PRIVATE_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING = "private_kernel_circuit: "; - -} // namespace aztec3::circuits::kernel::private_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit.test.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit.test.cpp deleted file mode 100644 index c2e31a04af1..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit.test.cpp +++ /dev/null @@ -1,221 +0,0 @@ -#include "testing_harness.hpp" - -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_init.hpp" -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_ordering.hpp" -#include "aztec3/circuits/abis/read_request_membership_witness.hpp" -#include "aztec3/circuits/apps/test_apps/escrow/deposit.hpp" -#include "aztec3/circuits/kernel/private/common.hpp" -#include "aztec3/circuits/kernel/private/init.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/circuit_errors.hpp" - -#include "barretenberg/ecc/curves/bn254/fr.hpp" -#include - -#include - -#include -#include - -namespace aztec3::circuits::kernel::private_kernel { - -using aztec3::circuits::apps::test_apps::escrow::deposit; - -using abis::private_kernel::PrivateKernelInputsOrdering; -using aztec3::circuits::kernel::private_kernel::testing_harness::do_private_call_get_kernel_inputs_init; -using aztec3::circuits::kernel::private_kernel::testing_harness::do_private_call_get_kernel_inputs_inner; -using aztec3::utils::array_length; -using aztec3::utils::CircuitErrorCode; - - -// TODO(https://github.com/AztecProtocol/aztec-packages/issues/892): test expected kernel failures if transient -// reads (or their hints) don't match -// TODO(https://github.com/AztecProtocol/aztec-packages/issues/836): test expected kernel failures if nullifiers (or -// their hints) don't match - -/************************************************************** - * MULTI ITERATION UNIT TESTS FOR NATIVE PRIVATE KERNEL CIRCUIT - **************************************************************/ - - -// NOTE: *DO NOT* call fr constructors in static initializers and assign them to constants. This will fail. Instead, -// use lazy initialization or functions. Lambdas were introduced here. amount = 5, asset_id = 1, memo = 999 -const auto standard_test_args = [] { return std::vector{ NT::fr(5), NT::fr(1), NT::fr(999) }; }; -class native_private_kernel_tests : public ::testing::Test { - protected: - static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../barretenberg/cpp/srs_db/ignition"); } -}; - - -// 1. We send transient read request on value 23 and pending commitment 12 -// 2. We send transient read request on value 12 and pending commitment 23 -// We expect both read requests and commitments to be successfully matched in ordering circuit. -TEST_F(native_private_kernel_tests, native_accumulate_transient_read_requests) -{ - auto private_inputs_init = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - private_inputs_init.private_call.call_stack_item.public_inputs.new_commitments[0] = fr(12); - private_inputs_init.private_call.call_stack_item.public_inputs.read_requests[0] = fr(23); - private_inputs_init.private_call.read_request_membership_witnesses[0].is_transient = true; - - std::array read_commitment_hints{}; - read_commitment_hints[0] = fr(1); - - DummyBuilder builder = DummyBuilder("native_private_kernel_tests__native_accumulate_transient_read_requests"); - auto public_inputs = native_private_kernel_circuit_initial(builder, private_inputs_init); - - ASSERT_FALSE(builder.failed()) << "failure: " << builder.get_first_failure() - << " with code: " << builder.get_first_failure().code; - ASSERT_TRUE(array_length(public_inputs.end.new_commitments) == 1); - ASSERT_TRUE(array_length(public_inputs.end.read_requests) == 1); - - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - private_inputs_inner.private_call.call_stack_item.public_inputs.new_commitments[0] = fr(23); - private_inputs_inner.private_call.call_stack_item.public_inputs.read_requests[0] = fr(12); - private_inputs_inner.private_call.read_request_membership_witnesses[0].is_transient = true; - - read_commitment_hints[1] = fr(0); - - // We need to update the previous_kernel's private_call_stack because the current_call_stack_item has changed - // i.e. we changed the new_commitments and read_requests of the current_call_stack_item's public_inputs - private_inputs_inner.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs_inner.private_call.call_stack_item.hash(); - - // The original call is not multi-iterative (call stack depth == 1) and we re-feed the same private call stack - public_inputs.end.private_call_stack = private_inputs_inner.previous_kernel.public_inputs.end.private_call_stack; - private_inputs_inner.previous_kernel.public_inputs = public_inputs; - - public_inputs = native_private_kernel_circuit_inner(builder, private_inputs_inner); - - ASSERT_FALSE(builder.failed()) << "failure: " << builder.get_first_failure() - << " with code: " << builder.get_first_failure().code; - ASSERT_TRUE(array_length(public_inputs.end.new_commitments) == 2); - ASSERT_TRUE(array_length(public_inputs.end.read_requests) == 2); - - auto& previous_kernel = private_inputs_inner.previous_kernel; - previous_kernel.public_inputs = public_inputs; - - PrivateKernelInputsOrdering private_inputs{ previous_kernel, read_commitment_hints }; - auto final_public_inputs = native_private_kernel_circuit_ordering(builder, private_inputs); - - ASSERT_FALSE(builder.failed()) << "failure: " << builder.get_first_failure() - << " with code: " << builder.get_first_failure().code; - ASSERT_TRUE(array_length(final_public_inputs.end.new_commitments) == 2); // no commitments squashed -} - -// 1. We send transient read request on value 23 and pending commitment 10 -// 2. We send transient read request on value 12 and pending commitment 23 -// We expect the read request on value 12 to fail as there is no corresponding pending commitment. -TEST_F(native_private_kernel_tests, native_transient_read_requests_no_match) -{ - auto private_inputs_init = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - private_inputs_init.private_call.call_stack_item.public_inputs.new_commitments[0] = fr(10); - private_inputs_init.private_call.call_stack_item.public_inputs.read_requests[0] = fr(23); - private_inputs_init.private_call.read_request_membership_witnesses[0].is_transient = true; - - std::array read_commitment_hints{}; - read_commitment_hints[0] = fr(1); - - DummyBuilder builder = DummyBuilder("native_private_kernel_tests__native_transient_read_requests_no_match"); - auto public_inputs = native_private_kernel_circuit_initial(builder, private_inputs_init); - - ASSERT_FALSE(builder.failed()) << "failure: " << builder.get_first_failure() - << " with code: " << builder.get_first_failure().code; - ASSERT_TRUE(array_length(public_inputs.end.new_commitments) == 1); - ASSERT_TRUE(array_length(public_inputs.end.read_requests) == 1); - - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - private_inputs_inner.private_call.call_stack_item.public_inputs.new_commitments[0] = fr(23); - private_inputs_inner.private_call.call_stack_item.public_inputs.read_requests[0] = fr(12); - private_inputs_inner.private_call.read_request_membership_witnesses[0].is_transient = true; - - read_commitment_hints[1] = fr(0); // There is not correct possible value. - - // We need to update the previous_kernel's private_call_stack because the current_call_stack_item has changed - // i.e. we changed the new_commitments and read_requests of the current_call_stack_item's public_inputs - private_inputs_inner.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs_inner.private_call.call_stack_item.hash(); - - // The original call is not multi-iterative (call stack depth == 1) and we re-feed the same private call stack - public_inputs.end.private_call_stack = private_inputs_inner.previous_kernel.public_inputs.end.private_call_stack; - private_inputs_inner.previous_kernel.public_inputs = public_inputs; - - public_inputs = native_private_kernel_circuit_inner(builder, private_inputs_inner); - - ASSERT_FALSE(builder.failed()) << "failure: " << builder.get_first_failure() - << " with code: " << builder.get_first_failure().code; - ASSERT_TRUE(array_length(public_inputs.end.new_commitments) == 2); - ASSERT_TRUE(array_length(public_inputs.end.read_requests) == 2); - - auto& previous_kernel = private_inputs_inner.previous_kernel; - previous_kernel.public_inputs = public_inputs; - - PrivateKernelInputsOrdering private_inputs{ previous_kernel, read_commitment_hints }; - auto final_public_inputs = native_private_kernel_circuit_ordering(builder, private_inputs); - - ASSERT_TRUE(builder.failed()); - ASSERT_TRUE(builder.get_first_failure().code == CircuitErrorCode::PRIVATE_KERNEL__TRANSIENT_READ_REQUEST_NO_MATCH); - - ASSERT_TRUE(array_length(final_public_inputs.end.new_commitments) == 2); // no commitments squashed -} - -// Testing that the special value EMPTY_NULLIFIED_COMMITMENT keeps new_nullifiers aligned with nullified_commitments. -TEST_F(native_private_kernel_tests, native_empty_nullified_commitment_respected) -{ - // The 0th nullifier (and corresponding nullified_commitment EMPTY_NULLIFIED_COMMITMENT) which is - // added by the init iteration is set into private_inputs_inner. - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - private_inputs_inner.private_call.call_stack_item.public_inputs.new_commitments[0] = fr(23); - private_inputs_inner.private_call.call_stack_item.public_inputs.new_commitments[1] = fr(33); - - private_inputs_inner.private_call.call_stack_item.public_inputs.new_nullifiers[0] = fr(11); - private_inputs_inner.private_call.call_stack_item.public_inputs.new_nullifiers[1] = fr(18); - - private_inputs_inner.private_call.call_stack_item.public_inputs.nullified_commitments[0] = - fr(EMPTY_NULLIFIED_COMMITMENT); - private_inputs_inner.private_call.call_stack_item.public_inputs.nullified_commitments[1] = fr(33); - - // update the private call stack contents to reflect the above changes which affect the item hash - private_inputs_inner.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs_inner.private_call.call_stack_item.hash(); - - DummyBuilder builder = DummyBuilder("native_private_kernel_tests__native_empty_nullified_commitment_respected"); - - auto public_inputs = native_private_kernel_circuit_inner(builder, private_inputs_inner); - - ASSERT_FALSE(builder.failed()) << "failure: " << builder.get_first_failure() - << " with code: " << builder.get_first_failure().code; - - // EMPTY nullified commitment should keep new_nullifiers aligned with nullified_commitments - // We have to shift the offset by 1 due to the 0th nullifier/nullified_commitment pair. - ASSERT_TRUE(public_inputs.end.nullified_commitments[1] == fr(EMPTY_NULLIFIED_COMMITMENT)); - ASSERT_TRUE(public_inputs.end.nullified_commitments[2] != fr(0) && - public_inputs.end.nullified_commitments[2] != fr(EMPTY_NULLIFIED_COMMITMENT)); - - // Nothing squashed yet (until ordering circuit) - ASSERT_TRUE(array_length(public_inputs.end.new_nullifiers) == 3); // 0th nullifier to be taking into account - ASSERT_TRUE(array_length(public_inputs.end.new_commitments) == 2); - // explicitly EMPTY commitment respected in array - ASSERT_TRUE(array_length(public_inputs.end.nullified_commitments) == 3); - - auto& previous_kernel = private_inputs_inner.previous_kernel; - previous_kernel.public_inputs = public_inputs; - - PrivateKernelInputsOrdering private_inputs{ .previous_kernel = previous_kernel, - .nullifier_commitment_hints = - std::array{ 0, 0, 1 } }; - - auto final_public_inputs = native_private_kernel_circuit_ordering(builder, private_inputs); - - ASSERT_FALSE(builder.failed()) << "failure: " << builder.get_first_failure() - << " with code: " << builder.get_first_failure().code; - - ASSERT_TRUE(array_length(final_public_inputs.end.new_commitments) == 1); // 1/2 commitment squashed - ASSERT_TRUE(array_length(final_public_inputs.end.new_nullifiers) == 2); // 1/2 nullifier squashed (+ 0th nullifier) -} - -} // namespace aztec3::circuits::kernel::private_kernel diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_init.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_init.cpp deleted file mode 100644 index 9c9c0fa1037..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_init.cpp +++ /dev/null @@ -1,192 +0,0 @@ -#include "common.hpp" -#include "init.hpp" - -#include "aztec3/circuits/abis/block_header.hpp" -#include "aztec3/circuits/abis/combined_constant_data.hpp" -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_init.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/array.hpp" - - -namespace { -using NT = aztec3::utils::types::NativeTypes; - -using aztec3::circuits::abis::CombinedConstantData; -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using aztec3::circuits::abis::private_kernel::PrivateKernelInputsInit; -using aztec3::utils::array_push; -using aztec3::utils::CircuitErrorCode; -using aztec3::utils::DummyCircuitBuilder; -using aztec3::utils::is_array_empty; - - -void initialize_end_values(PrivateKernelInputsInit const& private_inputs, - KernelCircuitPublicInputs& public_inputs) -{ - // Define the constants data. - auto const& private_call_public_inputs = private_inputs.private_call.call_stack_item.public_inputs; - auto const constants = CombinedConstantData{ - .block_header = private_call_public_inputs.block_header, - .tx_context = private_inputs.tx_request.tx_context, - }; - - // Set the constants in public_inputs. - public_inputs.constants = constants; -} -} // namespace - -namespace aztec3::circuits::kernel::private_kernel { - -void validate_this_private_call_against_tx_request(DummyCircuitBuilder& builder, - PrivateKernelInputsInit const& private_inputs) -{ - // TODO(mike): this logic might need to change to accommodate the weird edge 3 initial txs (the 'main' tx, the 'fee' - // tx, and the 'gas rebate' tx). - - // Confirm that the TxRequest (user's intent) matches the private call being executed - const auto& tx_request = private_inputs.tx_request; - const auto& call_stack_item = private_inputs.private_call.call_stack_item; - - builder.do_assert(tx_request.origin == call_stack_item.contract_address, - "user's intent does not match initial private call (origin address of tx_request must match " - "call_stack_item's contract_address)", - CircuitErrorCode::PRIVATE_KERNEL__USER_INTENT_MISMATCH_BETWEEN_TX_REQUEST_AND_CALL_STACK_ITEM); - - builder.do_assert(tx_request.function_data.hash() == call_stack_item.function_data.hash(), - "user's intent does not match initial private call (tx_request.function_data must match " - "call_stack_item.function_data)", - CircuitErrorCode::PRIVATE_KERNEL__USER_INTENT_MISMATCH_BETWEEN_TX_REQUEST_AND_CALL_STACK_ITEM); - - builder.do_assert( - tx_request.args_hash == call_stack_item.public_inputs.args_hash, - "user's intent does not match initial private call (noir function args passed to tx_request must match " - "args in the call_stack_item)", - CircuitErrorCode::PRIVATE_KERNEL__USER_INTENT_MISMATCH_BETWEEN_TX_REQUEST_AND_CALL_STACK_ITEM); -}; - -void validate_inputs(DummyCircuitBuilder& builder, PrivateKernelInputsInit const& private_inputs) -{ - const auto& this_call_stack_item = private_inputs.private_call.call_stack_item; - - builder.do_assert(this_call_stack_item.function_data.is_private == true, - "Cannot execute a non-private function with the private kernel circuit", - CircuitErrorCode::PRIVATE_KERNEL__NON_PRIVATE_FUNCTION_EXECUTED_WITH_PRIVATE_KERNEL); - - // TODO(mike): change to allow 3 initial calls on the private call stack, so a fee can be paid and a gas - // rebate can be paid. - - /* If we are going to have 3 initial calls on the private call stack, - * then do we still need the `private_call_stack` - * despite no longer needing a full `previous_kernel` - */ - - builder.do_assert(this_call_stack_item.public_inputs.call_context.is_delegate_call == false, - "Users cannot make a delegatecall", - CircuitErrorCode::PRIVATE_KERNEL__UNSUPPORTED_OP); - builder.do_assert(this_call_stack_item.public_inputs.call_context.is_static_call == false, - "Users cannot make a static call", - CircuitErrorCode::PRIVATE_KERNEL__UNSUPPORTED_OP); - - // The below also prevents delegatecall/staticcall in the base case - builder.do_assert(this_call_stack_item.public_inputs.call_context.storage_contract_address == - this_call_stack_item.contract_address, - "Storage contract address must be that of the called contract", - CircuitErrorCode::PRIVATE_KERNEL__CONTRACT_ADDRESS_MISMATCH); -} - -void update_end_values(DummyCircuitBuilder& builder, - PrivateKernelInputsInit const& private_inputs, - KernelCircuitPublicInputs& public_inputs) -{ - // We only initialized constants member of public_inputs so far. Therefore, there must not be any - // new nullifiers or logs as part of public_inputs. - builder.do_assert(is_array_empty(public_inputs.end.new_commitments), - "public_inputs.end.new_commitments must start as empty in initial kernel iteration", - CircuitErrorCode::PRIVATE_KERNEL__UNSUPPORTED_OP); - builder.do_assert(is_array_empty(public_inputs.end.new_nullifiers), - "public_inputs.end.new_nullifiers must start as empty in initial kernel iteration", - CircuitErrorCode::PRIVATE_KERNEL__UNSUPPORTED_OP); - builder.do_assert(is_array_empty(public_inputs.end.nullified_commitments), - "public_inputs.end.nullified_commitments must start as empty in initial kernel iteration", - CircuitErrorCode::PRIVATE_KERNEL__UNSUPPORTED_OP); - builder.do_assert(is_array_empty(public_inputs.end.encrypted_logs_hash), - "public_inputs.end.encrypted_logs_hash must start as empty in initial kernel iteration", - CircuitErrorCode::PRIVATE_KERNEL__UNSUPPORTED_OP); - builder.do_assert(is_array_empty(public_inputs.end.unencrypted_logs_hash), - "public_inputs.end.unencrypted_logs_hash must start as empty in initial kernel iteration", - CircuitErrorCode::PRIVATE_KERNEL__UNSUPPORTED_OP); - builder.do_assert(is_array_empty(public_inputs.end.read_requests), - "public_inputs.end.read_requests must start as empty in initial kernel iteration", - CircuitErrorCode::PRIVATE_KERNEL__UNSUPPORTED_OP); - builder.do_assert(public_inputs.end.encrypted_log_preimages_length == NT::fr(0), - "public_inputs.end.encrypted_log_preimages_length must start as 0 in initial kernel iteration", - CircuitErrorCode::PRIVATE_KERNEL__UNSUPPORTED_OP); - builder.do_assert(public_inputs.end.unencrypted_log_preimages_length == NT::fr(0), - "public_inputs.end.unencrypted_log_preimages_length must start as 0 in initial kernel iteration", - CircuitErrorCode::PRIVATE_KERNEL__UNSUPPORTED_OP); - - // Since it's the first iteration, we need to push the the tx hash nullifier into the `new_nullifiers` array - array_push(builder, - public_inputs.end.new_nullifiers, - private_inputs.tx_request.hash(), - format(PRIVATE_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, - "could not push tx hash nullifier into new_nullifiers array. Too many new nullifiers in one tx")); - // Push an empty nullified commitment too since each nullifier must - // be paired with a nonzero (real or "empty") nullified commitment - array_push(builder, - public_inputs.end.nullified_commitments, - NT::fr(EMPTY_NULLIFIED_COMMITMENT), - format(PRIVATE_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, - "could not push tx hash nullifier into new_nullifiers array. Too many new nullifiers in one tx")); - - // Note that we do not need to nullify the transaction request nonce anymore. - // Should an account want to additionally use nonces for replay protection or handling cancellations, - // they will be able to do so in the account contract logic: - // https://github.com/AztecProtocol/aztec-packages/issues/660 -} - -KernelCircuitPublicInputs native_private_kernel_circuit_initial(DummyCircuitBuilder& builder, - PrivateKernelInputsInit const& private_inputs) -{ - // We'll be pushing data to this during execution of this circuit. - KernelCircuitPublicInputs public_inputs{}; - - // Do this before any functions can modify the inputs. - initialize_end_values(private_inputs, public_inputs); - - validate_inputs(builder, private_inputs); - - common_validate_arrays(builder, private_inputs.private_call.call_stack_item.public_inputs); - - validate_this_private_call_against_tx_request(builder, private_inputs); - - common_validate_call_stack(builder, private_inputs.private_call); - - common_validate_read_requests( - builder, - public_inputs.constants.block_header.note_hash_tree_root, - private_inputs.private_call.call_stack_item.public_inputs.read_requests, // read requests from private call - private_inputs.private_call.read_request_membership_witnesses); - - // TODO(dbanks12): feels like update_end_values should happen after contract logic - update_end_values(builder, private_inputs, public_inputs); - common_update_end_values(builder, private_inputs.private_call, public_inputs); - - common_contract_logic(builder, - private_inputs.private_call, - public_inputs, - private_inputs.tx_request.tx_context.contract_deployment_data, - private_inputs.tx_request.function_data); - - // This is where a real circuit would perform recursive verification of the previous kernel proof and private call - // proof. - - // In the native version, as there is no verify_proofs call, we can initialize aggregation object with the default - // constructor. - NT::AggregationObject const empty_aggregation_object{}; - public_inputs.end.aggregation_object = empty_aggregation_object; - - return public_inputs; -}; - -} // namespace aztec3::circuits::kernel::private_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_init.hpp b/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_init.hpp deleted file mode 100644 index 8baabb77f1f..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_init.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "init.hpp" - -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_init.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" - -namespace aztec3::circuits::kernel::private_kernel { - -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using aztec3::circuits::abis::private_kernel::PrivateKernelInputsInit; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; - -KernelCircuitPublicInputs native_private_kernel_circuit_initial(DummyBuilder& builder, - PrivateKernelInputsInit const& private_inputs); - -} // namespace aztec3::circuits::kernel::private_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_init.test.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_init.test.cpp deleted file mode 100644 index f502436d603..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_init.test.cpp +++ /dev/null @@ -1,827 +0,0 @@ -#include "testing_harness.hpp" - -#include "aztec3/circuits/abis/read_request_membership_witness.hpp" -#include "aztec3/circuits/apps/test_apps/basic_contract_deployment/basic_contract_deployment.hpp" -#include "aztec3/circuits/apps/test_apps/escrow/deposit.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/circuits/kernel/private/init.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/circuit_errors.hpp" - -#include - -#include - -#include -#include - -namespace aztec3::circuits::kernel::private_kernel { - -using aztec3::circuits::silo_nullifier; -using aztec3::circuits::apps::test_apps::basic_contract_deployment::constructor; -using aztec3::circuits::apps::test_apps::escrow::deposit; -using aztec3::circuits::kernel::private_kernel::testing_harness::do_private_call_get_kernel_inputs_init; -using aztec3::circuits::kernel::private_kernel::testing_harness::get_random_reads; -using aztec3::circuits::kernel::private_kernel::testing_harness::validate_deployed_contract_address; -using aztec3::circuits::kernel::private_kernel::testing_harness::validate_no_new_deployed_contract; - -using aztec3::utils::array_length; -using aztec3::utils::CircuitErrorCode; - - -// NOTE: *DO NOT* call fr constructors in static initializers and assign them to constants. This will fail. Instead, use -// lazy initialization or functions. Lambdas were introduced here. -// amount = 5, asset_id = 1, memo = 999 -const auto standard_test_args = [] { return std::vector{ NT::fr(5), NT::fr(1), NT::fr(999) }; }; - -class native_private_kernel_init_tests : public ::testing::Test { - protected: - static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../barretenberg/cpp/srs_db/ignition"); } -}; - - -/** - ************************************************************** - * Native initial private kernel circuit tests. - ************************************************************** - */ - -/** - * @brief Some private circuit simulation (`deposit`, in this case) - */ -TEST_F(native_private_kernel_init_tests, deposit) -{ - std::array const& encrypted_logs_hash = { NT::fr(16), NT::fr(69) }; - NT::fr const& encrypted_log_preimages_length = NT::fr(100); - std::array const& unencrypted_logs_hash = { NT::fr(26), NT::fr(47) }; - NT::fr const& unencrypted_log_preimages_length = NT::fr(50); - - auto const& private_inputs = do_private_call_get_kernel_inputs_init(false, - deposit, - standard_test_args(), - encrypted_logs_hash, - unencrypted_logs_hash, - encrypted_log_preimages_length, - unencrypted_log_preimages_length); - DummyBuilder builder = DummyBuilder("private_kernel_tests__native_deposit"); - auto const& public_inputs = native_private_kernel_circuit_initial(builder, private_inputs); - - EXPECT_TRUE(validate_no_new_deployed_contract(public_inputs)); - - // Check the first nullifier is hash of the signed tx request - ASSERT_EQ(public_inputs.end.new_nullifiers[0], private_inputs.tx_request.hash()); - - // Log preimages length should increase by `(un)encrypted_log_preimages_length` from private input - ASSERT_EQ(public_inputs.end.encrypted_log_preimages_length, encrypted_log_preimages_length); - ASSERT_EQ(public_inputs.end.unencrypted_log_preimages_length, unencrypted_log_preimages_length); - - // Logs hashes should be a sha256 hash of a 0 value and the `(un)encrypted_logs_hash` from private input - auto const& expected_encrypted_logs_hash = - accumulate_sha256({ fr(0), fr(0), encrypted_logs_hash[0], encrypted_logs_hash[1] }); - ASSERT_EQ(public_inputs.end.encrypted_logs_hash, expected_encrypted_logs_hash); - - auto const& expected_unencrypted_logs_hash = - accumulate_sha256({ fr(0), fr(0), unencrypted_logs_hash[0], unencrypted_logs_hash[1] }); - ASSERT_EQ(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); - - // Assert that builder doesn't give any errors - ASSERT_FALSE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().message, ""); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::NO_ERROR); -} - -/** - * @brief Some private circuit simulation (`constructor`, in this case) - */ -TEST_F(native_private_kernel_init_tests, basic_contract_deployment) -{ - auto const& private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args()); - DummyBuilder builder = DummyBuilder("private_kernel_tests__native_basic_contract_deployment"); - auto const& public_inputs = native_private_kernel_circuit_initial(builder, private_inputs); - - EXPECT_TRUE(validate_deployed_contract_address(private_inputs, public_inputs)); - - // Since there are no logs, log preimages length should be 0 and both logs hashes should be a sha256 hash of 2 zero - // values - ASSERT_EQ(public_inputs.end.encrypted_log_preimages_length, fr(0)); - ASSERT_EQ(public_inputs.end.unencrypted_log_preimages_length, fr(0)); - - auto const& expected_logs_hash = accumulate_sha256({ fr(0), fr(0), fr(0), fr(0) }); - - ASSERT_EQ(public_inputs.end.encrypted_logs_hash, expected_logs_hash); - ASSERT_EQ(public_inputs.end.unencrypted_logs_hash, expected_logs_hash); - - // Assert that builder doesn't give any errors - ASSERT_FALSE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().message, ""); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::NO_ERROR); -} - -TEST_F(native_private_kernel_init_tests, input_validation_malformed_arrays_return_values) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args()); - - std::array malformed_return_values{ fr(0), fr(0), fr(553) }; - private_inputs.private_call.call_stack_item.public_inputs.return_values = malformed_return_values; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_return_values"); - native_private_kernel_circuit_initial(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_init_tests, input_validation_malformed_arrays_read_requests) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args()); - - std::array malformed_read_requests{ fr(0), fr(9123), fr(0), fr(12) }; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = malformed_read_requests; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_read_requests"); - native_private_kernel_circuit_initial(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_init_tests, input_validation_malformed_arrays_commitments) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args()); - - std::array malformed_commitments{ fr(0), fr(9123) }; - private_inputs.private_call.call_stack_item.public_inputs.new_commitments = malformed_commitments; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_commitments"); - native_private_kernel_circuit_initial(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_init_tests, input_validation_malformed_arrays_nullifiers) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args()); - - std::array malformed_nullifiers{}; - malformed_nullifiers[MAX_NEW_NULLIFIERS_PER_CALL - 1] = fr(12); - private_inputs.private_call.call_stack_item.public_inputs.new_nullifiers = malformed_nullifiers; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_nullifiers"); - native_private_kernel_circuit_initial(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_init_tests, input_validation_malformed_arrays_nullified_commitments) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args()); - - std::array malformed_nullified_commitments{ fr(0), - fr(0), - EMPTY_NULLIFIED_COMMITMENT }; - private_inputs.private_call.call_stack_item.public_inputs.nullified_commitments = malformed_nullified_commitments; - - DummyBuilder builder = - DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_nullified_commitments"); - native_private_kernel_circuit_initial(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_init_tests, input_validation_malformed_arrays_private_call_stack) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args()); - - std::array malformed_private_call_stack{ fr(0), fr(888) }; - private_inputs.private_call.call_stack_item.public_inputs.private_call_stack = malformed_private_call_stack; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_private_call_stack"); - native_private_kernel_circuit_initial(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_init_tests, input_validation_malformed_arrays_public_call_stack) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args()); - - std::array malformed_public_call_stack{ fr(0), fr(888) }; - private_inputs.private_call.call_stack_item.public_inputs.public_call_stack = malformed_public_call_stack; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_public_call_stack"); - native_private_kernel_circuit_initial(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_init_tests, input_validation_malformed_arrays_new_l2_to_l1_msgs) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args()); - - std::array malformed_new_l2_to_l1_msgs{}; - malformed_new_l2_to_l1_msgs[MAX_NEW_L2_TO_L1_MSGS_PER_CALL - 1] = fr(1); - private_inputs.private_call.call_stack_item.public_inputs.new_l2_to_l1_msgs = malformed_new_l2_to_l1_msgs; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_new_l2_to_l1_msgs"); - native_private_kernel_circuit_initial(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_init_tests, contract_deployment_call_stack_item_hash_mismatch_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args()); - - // Randomize the first item in the private call stack (i.e. hash of the private call item). - private_inputs.private_call.call_stack_item.public_inputs.private_call_stack[0] = NT::fr::random_element(); - - DummyBuilder builder = - DummyBuilder("private_kernel_tests__contract_deployment_call_stack_item_hash_mismatch_fails"); - native_private_kernel_circuit_initial(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__PRIVATE_CALL_STACK_ITEM_HASH_MISMATCH); -} - -// TODO(#3062) VKs are mocked out for now -// TEST_F(native_private_kernel_init_tests, contract_deployment_incorrect_constructor_vk_hash_fails) -// { -// auto private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args()); - -// // Pollute the constructor vk hash in the tx_request. -// private_inputs.tx_request.tx_context.contract_deployment_data.constructor_vk_hash = NT::fr::random_element(); - -// DummyBuilder builder = -// DummyBuilder("private_kernel_tests__contract_deployment_incorrect_constructor_vk_hash_fails"); -// native_private_kernel_circuit_initial(builder, private_inputs); - -// EXPECT_EQ(builder.failed(), true); -// EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::PRIVATE_KERNEL__INVALID_CONSTRUCTOR_VK_HASH); -// EXPECT_EQ(builder.get_first_failure().message, "constructor_vk_hash doesn't match private_call_vk_hash"); -// } - -TEST_F(native_private_kernel_init_tests, contract_deployment_incorrect_contract_address_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args()); - - // Modify the contract address in appropriate places. - const fr random_address = NT::fr::random_element(); - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address = random_address; - private_inputs.tx_request.origin = random_address; - private_inputs.private_call.call_stack_item.contract_address = random_address; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__contract_deployment_incorrect_contract_address_fails"); - native_private_kernel_circuit_initial(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::PRIVATE_KERNEL__INVALID_CONTRACT_ADDRESS); - EXPECT_EQ(builder.get_first_failure().message, "contract address supplied doesn't match derived address"); -} - -TEST_F(native_private_kernel_init_tests, contract_deployment_contract_address_mismatch_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args()); - - // Modify the storage_contract_address. - const auto random_contract_address = NT::fr::random_element(); - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address = - random_contract_address; - private_inputs.private_call.call_stack_item.contract_address = random_contract_address; - - // Invoke the native private kernel circuit - DummyBuilder builder = DummyBuilder("private_kernel_tests__contract_deployment_contract_address_mismatch_fails"); - native_private_kernel_circuit_initial(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__USER_INTENT_MISMATCH_BETWEEN_TX_REQUEST_AND_CALL_STACK_ITEM); -} - -TEST_F(native_private_kernel_init_tests, contract_deployment_function_data_mismatch_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args()); - - // Modify the function selector in function data. - private_inputs.tx_request.function_data.selector = { - .value = numeric::random::get_engine().get_random_uint32(), - }; - - // Invoke the native private kernel circuit - DummyBuilder builder = DummyBuilder("private_kernel_tests__contract_deployment_function_data_mismatch_fails"); - native_private_kernel_circuit_initial(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__USER_INTENT_MISMATCH_BETWEEN_TX_REQUEST_AND_CALL_STACK_ITEM); - EXPECT_EQ(builder.get_first_failure().message, - "user's intent does not match initial private call (tx_request.function_data must match " - "call_stack_item.function_data)"); -} - -TEST_F(native_private_kernel_init_tests, contract_deployment_args_hash_mismatch_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args()); - - // Modify the args hash in tx request. - private_inputs.tx_request.args_hash = NT::fr::random_element(); - - // Invoke the native private kernel circuit - DummyBuilder builder = DummyBuilder("private_kernel_tests__contract_deployment_args_hash_mismatch_fails"); - native_private_kernel_circuit_initial(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__USER_INTENT_MISMATCH_BETWEEN_TX_REQUEST_AND_CALL_STACK_ITEM); - EXPECT_EQ(builder.get_first_failure().message, - "user's intent does not match initial private call (noir function args passed to tx_request must match " - "args in the call_stack_item)"); -} - -TEST_F(native_private_kernel_init_tests, private_function_is_private_false_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - // Set is_private in function data to false. - private_inputs.private_call.call_stack_item.function_data.is_private = false; - - // Invoke the native private kernel circuit - DummyBuilder builder = DummyBuilder("private_kernel_tests__private_function_is_private_false_fails"); - native_private_kernel_circuit_initial(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__NON_PRIVATE_FUNCTION_EXECUTED_WITH_PRIVATE_KERNEL); - EXPECT_EQ(builder.get_first_failure().message, - "Cannot execute a non-private function with the private kernel circuit"); -} - - -TEST_F(native_private_kernel_init_tests, private_function_static_call_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - // Set is_static_call to true. - private_inputs.private_call.call_stack_item.public_inputs.call_context.is_static_call = true; - - // Invoke the native private kernel circuit - DummyBuilder builder = DummyBuilder("private_kernel_tests__private_function_static_call_fails"); - native_private_kernel_circuit_initial(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::PRIVATE_KERNEL__UNSUPPORTED_OP); - EXPECT_EQ(builder.get_first_failure().message, "Users cannot make a static call"); -} - -TEST_F(native_private_kernel_init_tests, private_function_delegate_call_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - // Set is_delegate_call to true. - private_inputs.private_call.call_stack_item.public_inputs.call_context.is_delegate_call = true; - - // Invoke the native private kernel circuit - DummyBuilder builder = DummyBuilder("private_kernel_tests__private_function_delegate_call_fails"); - native_private_kernel_circuit_initial(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::PRIVATE_KERNEL__UNSUPPORTED_OP); - EXPECT_EQ(builder.get_first_failure().message, "Users cannot make a delegatecall"); -} - -TEST_F(native_private_kernel_init_tests, private_function_incorrect_storage_contract_address_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - // Set the storage_contract_address to a random scalar. - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address = - NT::fr::random_element(); - - // Invoke the native private kernel circuit - DummyBuilder builder = - DummyBuilder("private_kernel_tests__private_function_incorrect_storage_contract_address_fails"); - native_private_kernel_circuit_initial(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::PRIVATE_KERNEL__CONTRACT_ADDRESS_MISMATCH); - EXPECT_EQ(builder.get_first_failure().message, "Storage contract address must be that of the called contract"); -} - -TEST_F(native_private_kernel_init_tests, native_read_request_bad_request) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = silo_nullifier(contract_address, private_inputs.tx_request.hash()); - auto [read_requests, - read_request_membership_witnesses, - _transient_read_requests, - _transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, 2); - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - - // tweak read_request so it gives wrong root when paired with its sibling path - read_requests[1] += 1; - - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - DummyBuilder builder = DummyBuilder("native_private_kernel_init_tests__native_read_request_bad_request"); - auto const& public_inputs = native_private_kernel_circuit_initial(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - ASSERT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__READ_REQUEST_NOTE_HASH_TREE_ROOT_MISMATCH); - - // Check the first nullifier is hash of the signed tx request - ASSERT_EQ(public_inputs.end.new_nullifiers[0], private_inputs.tx_request.hash()); -} - -TEST_F(native_private_kernel_init_tests, native_read_request_bad_leaf_index) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = silo_nullifier(contract_address, private_inputs.tx_request.hash()); - auto [read_requests, - read_request_membership_witnesses, - _transient_read_requests, - _transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, 2); - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - - // tweak leaf index so it gives wrong root when paired with its request and sibling path - read_request_membership_witnesses[1].leaf_index += 1; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - DummyBuilder builder = DummyBuilder("native_private_kernel_init_tests__native_read_request_bad_leaf_index"); - auto const& public_inputs = native_private_kernel_circuit_initial(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - ASSERT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__READ_REQUEST_NOTE_HASH_TREE_ROOT_MISMATCH); - - // Check the first nullifier is hash of the signed tx request - ASSERT_EQ(public_inputs.end.new_nullifiers[0], private_inputs.tx_request.hash()); -} - -TEST_F(native_private_kernel_init_tests, native_read_request_bad_sibling_path) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = silo_nullifier(contract_address, private_inputs.tx_request.hash()); - auto [read_requests, - read_request_membership_witnesses, - _transient_read_requests, - _transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, 2); - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - - // tweak sibling path so it gives wrong root when paired with its request - read_request_membership_witnesses[1].sibling_path[1] += 1; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - DummyBuilder builder = DummyBuilder("native_private_kernel_init_tests__native_read_request_bad_sibling_path"); - auto const& public_inputs = native_private_kernel_circuit_initial(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - ASSERT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__READ_REQUEST_NOTE_HASH_TREE_ROOT_MISMATCH); - - // Check the first nullifier is hash of the signed tx request - ASSERT_EQ(public_inputs.end.new_nullifiers[0], private_inputs.tx_request.hash()); -} - -TEST_F(native_private_kernel_init_tests, native_read_request_root_mismatch) -{ - auto private_inputs = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - // generate two random sets of read requests and mix them so their roots don't match - auto const first_nullifier = silo_nullifier(contract_address, private_inputs.tx_request.hash()); - auto [read_requests0, - read_request_membership_witnesses0, - _transient_read_requests0, - _transient_read_request_membership_witnesses0, - root] = get_random_reads(first_nullifier, contract_address, 2); - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - auto [read_requests1, - read_request_membership_witnesses1, - _transient_read_requests1, - _transient_read_request_membership_witnesses1, - _root] = get_random_reads(first_nullifier, contract_address, 2); - std::array bad_requests{}; - std::array, MAX_READ_REQUESTS_PER_CALL> bad_witnesses; - // note we are using read_requests0 for some and read_requests1 for others - bad_requests[0] = read_requests0[0]; - bad_requests[1] = read_requests0[1]; - bad_requests[2] = read_requests1[0]; - bad_requests[3] = read_requests1[1]; - bad_witnesses[0] = read_request_membership_witnesses0[0]; - bad_witnesses[1] = read_request_membership_witnesses0[1]; - bad_witnesses[2] = read_request_membership_witnesses1[0]; - bad_witnesses[3] = read_request_membership_witnesses1[1]; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = bad_requests; - private_inputs.private_call.read_request_membership_witnesses = bad_witnesses; - - DummyBuilder builder = DummyBuilder("native_private_kernel_init_tests__native_read_request_root_mismatch"); - auto const& public_inputs = native_private_kernel_circuit_initial(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - ASSERT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__READ_REQUEST_NOTE_HASH_TREE_ROOT_MISMATCH); - - // Check the first nullifier is hash of the signed tx request - ASSERT_EQ(public_inputs.end.new_nullifiers[0], private_inputs.tx_request.hash()); -} - -TEST_F(native_private_kernel_init_tests, native_no_read_requests_works) -{ - // no read requests should work - - auto private_inputs = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - // empty requests - std::array const read_requests{}; - std::array, MAX_READ_REQUESTS_PER_CALL> const - read_request_membership_witnesses{}; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - DummyBuilder builder = DummyBuilder("native_private_kernel_init_tests__native_no_read_requests_works"); - auto const& public_inputs = native_private_kernel_circuit_initial(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - auto failure = builder.get_first_failure(); - if (failure.code != CircuitErrorCode::NO_ERROR) { - info("failure: ", failure); - } - ASSERT_FALSE(builder.failed()); - - // Check the first nullifier is hash of the signed tx request - ASSERT_EQ(public_inputs.end.new_nullifiers[0], private_inputs.tx_request.hash()); - - // non-transient read requests are NOT forwarded - ASSERT_EQ(array_length(public_inputs.end.read_requests), 0); -} - -TEST_F(native_private_kernel_init_tests, native_one_read_requests_works) -{ - // one read request should work - - auto private_inputs = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = silo_nullifier(contract_address, private_inputs.tx_request.hash()); - auto [read_requests, - read_request_membership_witnesses, - _transient_read_requests, - _transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, 1); - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - DummyBuilder builder = DummyBuilder("native_private_kernel_init_tests__native_one_read_requests_works"); - auto const& public_inputs = native_private_kernel_circuit_initial(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - auto failure = builder.get_first_failure(); - if (failure.code != CircuitErrorCode::NO_ERROR) { - info("failure: ", failure); - } - ASSERT_FALSE(builder.failed()); - - // Check the first nullifier is hash of the signed tx request - ASSERT_EQ(public_inputs.end.new_nullifiers[0], private_inputs.tx_request.hash()); - - // non-transient read requests are NOT forwarded - ASSERT_EQ(array_length(public_inputs.end.read_requests), 0); -} - -TEST_F(native_private_kernel_init_tests, native_two_read_requests_works) -{ - // two read requests should work - - auto private_inputs = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = silo_nullifier(contract_address, private_inputs.tx_request.hash()); - auto [read_requests, - read_request_membership_witnesses, - _transient_read_requests, - _transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, 2); - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - DummyBuilder builder = DummyBuilder("native_private_kernel_init_tests__native_two_read_requests_works"); - auto const& public_inputs = native_private_kernel_circuit_initial(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - auto failure = builder.get_first_failure(); - if (failure.code != CircuitErrorCode::NO_ERROR) { - info("failure: ", failure); - } - ASSERT_FALSE(builder.failed()); - - // Check the first nullifier is hash of the signed tx request - ASSERT_EQ(public_inputs.end.new_nullifiers[0], private_inputs.tx_request.hash()); - - // non-transient read requests are NOT forwarded - ASSERT_EQ(array_length(public_inputs.end.read_requests), 0); -} - -TEST_F(native_private_kernel_init_tests, native_max_read_requests_works) -{ - // max read requests should work - - auto private_inputs = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = silo_nullifier(contract_address, private_inputs.tx_request.hash()); - auto [read_requests, - read_request_membership_witnesses, - _transient_read_requests, - _transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, MAX_READ_REQUESTS_PER_CALL); - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - DummyBuilder builder = DummyBuilder("native_private_kernel_init_tests__native_max_read_requests_works"); - auto const& public_inputs = native_private_kernel_circuit_initial(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - auto failure = builder.get_first_failure(); - if (failure.code != CircuitErrorCode::NO_ERROR) { - info("failure: ", failure); - } - ASSERT_FALSE(builder.failed()); - - // Check the first nullifier is hash of the signed tx request - ASSERT_EQ(public_inputs.end.new_nullifiers[0], private_inputs.tx_request.hash()); - - // non-transient read requests are NOT forwarded - ASSERT_EQ(array_length(public_inputs.end.read_requests), 0); -} - -// TODO(dbanks12): more tests of read_requests for multiple iterations. -// Check enforcement that inner iterations' read_requests match root in constants -// https://github.com/AztecProtocol/aztec-packages/issues/786 - -TEST_F(native_private_kernel_init_tests, native_one_transient_read_requests_works) -{ - // one transient read request should work - - auto private_inputs = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = silo_nullifier(contract_address, private_inputs.tx_request.hash()); - auto [read_requests, - read_request_membership_witnesses, - transient_read_requests, - transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, 1); - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - - // Make the read request transient - read_requests[0] = transient_read_requests[0]; - read_request_membership_witnesses[0] = transient_read_request_membership_witnesses[0]; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - DummyBuilder builder = DummyBuilder("native_private_kernel_init_tests__native_one_transient_read_requests_works"); - auto const& public_inputs = native_private_kernel_circuit_initial(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - auto failure = builder.get_first_failure(); - if (failure.code != CircuitErrorCode::NO_ERROR) { - info("failure: ", failure); - } - ASSERT_FALSE(builder.failed()); - - ASSERT_EQ(array_length(public_inputs.end.read_requests), 1); // transient read request gets forwarded -} - -// TODO(https://github.com/AztecProtocol/aztec-packages/issues/906): re-enable once kernel supports forwarding/matching -// of transient reads. -TEST_F(native_private_kernel_init_tests, native_max_read_requests_one_transient_works) -{ - // max read requests with one transient should work - auto private_inputs = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = silo_nullifier(contract_address, private_inputs.tx_request.hash()); - auto [read_requests, - read_request_membership_witnesses, - transient_read_requests, - transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, MAX_READ_REQUESTS_PER_CALL); - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - - // Make the read request at position 1 transient - read_requests[1] = transient_read_requests[1]; - read_request_membership_witnesses[1] = transient_read_request_membership_witnesses[1]; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - DummyBuilder builder = - DummyBuilder("native_private_kernel_init_tests__native_max_read_requests_one_transient_works"); - auto const& public_inputs = native_private_kernel_circuit_initial(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - auto failure = builder.get_first_failure(); - if (failure.code != CircuitErrorCode::NO_ERROR) { - info("failure: ", failure); - } - ASSERT_FALSE(builder.failed()); - - // transient read request gets forwarded - ASSERT_EQ(array_length(public_inputs.end.read_requests), 1); -} - -TEST_F(native_private_kernel_init_tests, native_max_read_requests_all_transient_works) -{ - // max read requests with all transient should work - auto private_inputs = do_private_call_get_kernel_inputs_init(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = silo_nullifier(contract_address, private_inputs.tx_request.hash()); - auto [read_requests, - read_request_membership_witnesses, - transient_read_requests, - transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, MAX_READ_REQUESTS_PER_CALL); - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = transient_read_requests; - private_inputs.private_call.read_request_membership_witnesses = transient_read_request_membership_witnesses; - - DummyBuilder builder = - DummyBuilder("native_private_kernel_init_tests__native_max_read_requests_all_transient_works"); - auto const& public_inputs = native_private_kernel_circuit_initial(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - auto failure = builder.get_first_failure(); - if (failure.code != CircuitErrorCode::NO_ERROR) { - info("failure: ", failure); - } - ASSERT_FALSE(builder.failed()); - - // transient read request all get forwarded - ASSERT_EQ(array_length(public_inputs.end.read_requests), MAX_READ_REQUESTS_PER_CALL); -} - -} // namespace aztec3::circuits::kernel::private_kernel diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_inner.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_inner.cpp deleted file mode 100644 index d98423e8322..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_inner.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "common.hpp" -#include "init.hpp" - -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/new_contract_data.hpp" -#include "aztec3/circuits/abis/previous_kernel_data.hpp" -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_inner.hpp" -#include "aztec3/utils/array.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" - -namespace { -using NT = aztec3::utils::types::NativeTypes; - -using aztec3::circuits::abis::ContractLeafPreimage; -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using aztec3::circuits::abis::PreviousKernelData; -using aztec3::circuits::abis::private_kernel::PrivateKernelInputsInner; -using aztec3::circuits::kernel::private_kernel::common_initialize_end_values; -using aztec3::utils::array_length; -using aztec3::utils::array_pop; -using aztec3::utils::CircuitErrorCode; -using aztec3::utils::DummyCircuitBuilder; - -void initialize_end_values(PreviousKernelData const& previous_kernel, KernelCircuitPublicInputs& public_inputs) -{ - common_initialize_end_values(previous_kernel, public_inputs); - - // Ensure the arrays are the same as previously, before we start pushing more data onto them in other - // functions within this circuit: - auto& end = public_inputs.end; - const auto& start = previous_kernel.public_inputs.end; - end.read_requests = start.read_requests; -} -} // namespace - -namespace aztec3::circuits::kernel::private_kernel { - -void pop_and_validate_this_private_call_hash( - DummyCircuitBuilder& builder, - PrivateCallData const& private_call, - std::array& private_call_stack) -{ - // TODO(mike): this logic might need to change to accommodate the weird edge 3 initial txs (the 'main' tx, the - // 'fee' tx, and the 'gas rebate' tx). - const auto popped_private_call_hash = array_pop(private_call_stack); - const auto calculated_this_private_call_hash = private_call.call_stack_item.hash(); - - builder.do_assert( - popped_private_call_hash == calculated_this_private_call_hash, - format("calculated private_call_hash (", - calculated_this_private_call_hash, - ") does not match provided private_call_hash (", - popped_private_call_hash, - ") at the top of the call stack"), - CircuitErrorCode::PRIVATE_KERNEL__CALCULATED_PRIVATE_CALL_HASH_AND_PROVIDED_PRIVATE_CALL_HASH_MISMATCH); -}; - -void validate_contract_tree_root(DummyCircuitBuilder& builder, PrivateKernelInputsInner const& private_inputs) -{ - auto const& purported_contract_tree_root = - private_inputs.private_call.call_stack_item.public_inputs.block_header.contract_tree_root; - auto const& previous_kernel_contract_tree_root = - private_inputs.previous_kernel.public_inputs.constants.block_header.contract_tree_root; - builder.do_assert( - purported_contract_tree_root == previous_kernel_contract_tree_root, - "purported_contract_tree_root doesn't match previous_kernel_contract_tree_root", - CircuitErrorCode::PRIVATE_KERNEL__PURPORTED_CONTRACT_TREE_ROOT_AND_PREVIOUS_KERNEL_CONTRACT_TREE_ROOT_MISMATCH); -} - -void validate_inputs(DummyCircuitBuilder& builder, PrivateKernelInputsInner const& private_inputs) -{ - const auto& this_call_stack_item = private_inputs.private_call.call_stack_item; - - builder.do_assert(this_call_stack_item.function_data.is_private == true, - "Cannot execute a non-private function with the private kernel circuit", - CircuitErrorCode::PRIVATE_KERNEL__NON_PRIVATE_FUNCTION_EXECUTED_WITH_PRIVATE_KERNEL); - - const auto& start = private_inputs.previous_kernel.public_inputs.end; - - // TODO(mike): we might want to range-constrain the call_count to prevent some kind of overflow errors. Having - // said that, iterating 2^254 times isn't feasible. - - NT::fr const start_private_call_stack_length = array_length(start.private_call_stack); - - builder.do_assert(private_inputs.previous_kernel.public_inputs.is_private == true, - "Cannot verify a non-private kernel snark in the private kernel circuit", - CircuitErrorCode::PRIVATE_KERNEL__NON_PRIVATE_KERNEL_VERIFIED_WITH_PRIVATE_KERNEL); - builder.do_assert(this_call_stack_item.function_data.is_constructor == false, - "A constructor must be executed as the first tx in the recursion", - CircuitErrorCode::PRIVATE_KERNEL__CONSTRUCTOR_EXECUTED_IN_RECURSION); - builder.do_assert(start_private_call_stack_length != 0, - "Cannot execute private kernel circuit with an empty private call stack", - CircuitErrorCode::PRIVATE_KERNEL__PRIVATE_CALL_STACK_EMPTY); -} - -KernelCircuitPublicInputs native_private_kernel_circuit_inner(DummyCircuitBuilder& builder, - PrivateKernelInputsInner const& private_inputs) -{ - // We'll be pushing data to this during execution of this circuit. - KernelCircuitPublicInputs public_inputs{}; - - common_validate_previous_kernel_values(builder, private_inputs.previous_kernel.public_inputs.end); - - // Do this before any functions can modify the inputs. - initialize_end_values(private_inputs.previous_kernel, public_inputs); - - validate_inputs(builder, private_inputs); - - common_validate_arrays(builder, private_inputs.private_call.call_stack_item.public_inputs); - - pop_and_validate_this_private_call_hash(builder, private_inputs.private_call, public_inputs.end.private_call_stack); - - common_validate_call_stack(builder, private_inputs.private_call); - - common_validate_read_requests( - builder, - public_inputs.constants.block_header.note_hash_tree_root, - private_inputs.private_call.call_stack_item.public_inputs.read_requests, // read requests from private call - private_inputs.private_call.read_request_membership_witnesses); - - - // TODO(dbanks12): feels like update_end_values should happen later - common_update_end_values(builder, private_inputs.private_call, public_inputs); - - // ensure that historical/purported contract tree root matches the one in previous kernel - validate_contract_tree_root(builder, private_inputs); - - const auto private_call_stack_item = private_inputs.private_call.call_stack_item; - common_contract_logic(builder, - private_inputs.private_call, - public_inputs, - private_call_stack_item.public_inputs.contract_deployment_data, - private_call_stack_item.function_data); - - // This is where a real circuit would perform recursive verification of the previous kernel proof and private call - // proof. - - // Note: given that we skipped the verify_proof function, the aggregation object we get at the end will just be - // the same as we had at the start. public_inputs.end.aggregation_object = aggregation_object; - public_inputs.end.aggregation_object = private_inputs.previous_kernel.public_inputs.end.aggregation_object; - - return public_inputs; -}; - -} // namespace aztec3::circuits::kernel::private_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_inner.hpp b/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_inner.hpp deleted file mode 100644 index 52ff291a27d..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_inner.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "init.hpp" - -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_inner.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" - -namespace aztec3::circuits::kernel::private_kernel { - -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using aztec3::circuits::abis::private_kernel::PrivateKernelInputsInner; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; - -KernelCircuitPublicInputs native_private_kernel_circuit_inner(DummyBuilder& builder, - PrivateKernelInputsInner const& private_inputs); - -} // namespace aztec3::circuits::kernel::private_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_inner.test.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_inner.test.cpp deleted file mode 100644 index d29c08eb590..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_inner.test.cpp +++ /dev/null @@ -1,986 +0,0 @@ -#include "c_bind.h" -#include "testing_harness.hpp" - -#include "aztec3/circuits/abis/membership_witness.hpp" -#include "aztec3/circuits/apps/test_apps/escrow/deposit.hpp" -#include "aztec3/circuits/kernel/private/common.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/array.hpp" -#include "aztec3/utils/circuit_errors.hpp" - -#include - -#include - -#include -#include - -namespace aztec3::circuits::kernel::private_kernel { - -using aztec3::circuits::apps::test_apps::escrow::deposit; - -using aztec3::circuits::kernel::private_kernel::testing_harness::do_private_call_get_kernel_inputs_inner; -using aztec3::circuits::kernel::private_kernel::testing_harness::get_random_reads; -using aztec3::circuits::kernel::private_kernel::testing_harness::validate_no_new_deployed_contract; - -using aztec3::utils::array_length; -using aztec3::utils::CircuitErrorCode; - -// NOTE: *DO NOT* call fr constructors in static initializers and assign them to constants. This will fail. Instead, use -// lazy initialization or functions. Lambdas were introduced here. -// amount = 5, asset_id = 1, memo = 999 -const auto standard_test_args = [] { return std::vector{ NT::fr(5), NT::fr(1), NT::fr(999) }; }; - -class native_private_kernel_inner_tests : public ::testing::Test { - protected: - static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../barretenberg/cpp/srs_db/ignition"); } -}; - -/** - ************************************************************** - * Native inner private kernel circuit tests. - ************************************************************** - */ -TEST_F(native_private_kernel_inner_tests, private_function_zero_storage_contract_address_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - // Set storage_contract_address to 0 - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address = 0; - private_inputs.private_call.call_stack_item.contract_address = 0; - - // Modify the call stack item's hash with the newly added contract address. - private_inputs.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs.private_call.call_stack_item.hash(); - - // Invoke the native private kernel circuit - DummyBuilder builder = DummyBuilder("private_kernel_tests__private_function_zero_storage_contract_address_fails"); - native_private_kernel_circuit_inner(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::PRIVATE_KERNEL__INVALID_CONTRACT_ADDRESS); - EXPECT_EQ(builder.get_first_failure().message, - "contract address can't be 0 for non-contract deployment related transactions"); -} - - -TEST_F(native_private_kernel_inner_tests, private_function_incorrect_is_internal) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - // Make the call internal but msg_sender != storage_contract_address. - private_inputs.private_call.call_stack_item.function_data.is_internal = true; - private_inputs.private_call.call_stack_item.public_inputs.call_context.msg_sender = 1; - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address = 2; - - // We need to update the previous_kernel's private_call_stack because the current_call_stack_item has changed - // i.e. we changed the function_data and public_inputs->call_context of the current_call_stack_item - private_inputs.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs.private_call.call_stack_item.hash(); - - // Invoke the native private kernel circuit - DummyBuilder builder = DummyBuilder("private_kernel_tests__private_function_incorrect_contract_tree_root_fails"); - native_private_kernel_circuit_inner(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::PRIVATE_KERNEL__IS_INTERNAL_BUT_NOT_SELF_CALL); - EXPECT_EQ(builder.get_first_failure().message, "call is internal, but msg_sender is not self"); -} - -TEST_F(native_private_kernel_inner_tests, private_function_incorrect_contract_tree_root_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - // Set historical_tree_root to a random scalar. - private_inputs.previous_kernel.public_inputs.constants.block_header.contract_tree_root = NT::fr::random_element(); - - // Invoke the native private kernel circuit - DummyBuilder builder = DummyBuilder("private_kernel_tests__private_function_incorrect_contract_tree_root_fails"); - native_private_kernel_circuit_inner(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ( - builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__PURPORTED_CONTRACT_TREE_ROOT_AND_PREVIOUS_KERNEL_CONTRACT_TREE_ROOT_MISMATCH); - EXPECT_EQ(builder.get_first_failure().message, - "purported_contract_tree_root doesn't match previous_kernel_contract_tree_root"); -} - -TEST_F(native_private_kernel_inner_tests, private_function_incorrect_contract_leaf_index_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - // Set the leaf index of the contract leaf to 20 (the correct value is 1). - NT::fr const wrong_idx = 20; - private_inputs.private_call.contract_leaf_membership_witness.leaf_index = wrong_idx; - - // Invoke the native private kernel circuit - DummyBuilder builder = DummyBuilder("private_kernel_tests__private_function_incorrect_contract_leaf_index_fails"); - native_private_kernel_circuit_inner(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__COMPUTED_CONTRACT_TREE_ROOT_AND_PURPORTED_CONTRACT_TREE_ROOT_MISMATCH); - EXPECT_EQ(builder.get_first_failure().message, - "computed_contract_tree_root doesn't match purported_contract_tree_root"); -} - -TEST_F(native_private_kernel_inner_tests, private_function_incorrect_contract_leaf_sibling_path_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - // Change the contract leaf's membership proof. - private_inputs.private_call.contract_leaf_membership_witness.sibling_path[0] = fr::random_element(); - - // Invoke the native private kernel circuit - DummyBuilder builder = - DummyBuilder("private_kernel_tests__private_function_incorrect_contract_leaf_sibling_path_fails"); - native_private_kernel_circuit_inner(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__COMPUTED_CONTRACT_TREE_ROOT_AND_PURPORTED_CONTRACT_TREE_ROOT_MISMATCH); - EXPECT_EQ(builder.get_first_failure().message, - "computed_contract_tree_root doesn't match purported_contract_tree_root"); -} - -TEST_F(native_private_kernel_inner_tests, private_function_incorrect_function_leaf_index_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - // Set the leaf index of the function leaf to 10 (the correct value is 1). - NT::fr const wrong_idx = 10; - private_inputs.private_call.function_leaf_membership_witness.leaf_index = wrong_idx; - - // Invoke the native private kernel circuit - DummyBuilder builder = DummyBuilder("private_kernel_tests__private_function_incorrect_contract_leaf_index_fails"); - native_private_kernel_circuit_inner(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__COMPUTED_CONTRACT_TREE_ROOT_AND_PURPORTED_CONTRACT_TREE_ROOT_MISMATCH); - EXPECT_EQ(builder.get_first_failure().message, - "computed_contract_tree_root doesn't match purported_contract_tree_root"); -} - -TEST_F(native_private_kernel_inner_tests, private_function_incorrect_function_leaf_sibling_path_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - // Change the function leaf's membership proof. - private_inputs.private_call.function_leaf_membership_witness.sibling_path[0] = fr::random_element(); - - // Invoke the native private kernel circuit - DummyBuilder builder = - DummyBuilder("private_kernel_tests__private_function_incorrect_contract_leaf_sibling_path_fails"); - native_private_kernel_circuit_inner(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__COMPUTED_CONTRACT_TREE_ROOT_AND_PURPORTED_CONTRACT_TREE_ROOT_MISMATCH); - EXPECT_EQ(builder.get_first_failure().message, - "computed_contract_tree_root doesn't match purported_contract_tree_root"); -} - -TEST_F(native_private_kernel_inner_tests, private_function_incorrect_call_stack_item_hash_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - // Set the first call stack member corresponding to the `deposit` function to random scalar. - private_inputs.private_call.call_stack_item.public_inputs.private_call_stack[0] = NT::fr::random_element(); - - // Invoke the native private kernel circuit - DummyBuilder builder = DummyBuilder("private_kernel_tests__private_function_incorrect_call_stack_item_hash_fails"); - native_private_kernel_circuit_inner(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__CALCULATED_PRIVATE_CALL_HASH_AND_PROVIDED_PRIVATE_CALL_HASH_MISMATCH); -} - -TEST_F(native_private_kernel_inner_tests, input_validation_malformed_arrays_return_values) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_return_values{ fr(0), fr(0), fr(553) }; - private_inputs.private_call.call_stack_item.public_inputs.return_values = malformed_return_values; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_return_values"); - native_private_kernel_circuit_inner(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_inner_tests, input_validation_malformed_arrays_read_requests) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_read_requests{ fr(0), fr(9123), fr(0), fr(12) }; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = malformed_read_requests; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_read_requests"); - native_private_kernel_circuit_inner(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_inner_tests, input_validation_malformed_arrays_commitments) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_commitments{ fr(0), fr(9123) }; - private_inputs.private_call.call_stack_item.public_inputs.new_commitments = malformed_commitments; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_commitments"); - native_private_kernel_circuit_inner(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_inner_tests, input_validation_malformed_arrays_nullifiers) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_nullifiers{}; - malformed_nullifiers[MAX_NEW_NULLIFIERS_PER_CALL - 1] = fr(12); - private_inputs.private_call.call_stack_item.public_inputs.new_nullifiers = malformed_nullifiers; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_nullifiers"); - native_private_kernel_circuit_inner(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_inner_tests, input_validation_malformed_arrays_nullified_commitments) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_nullified_commitments{ fr(0), - fr(0), - EMPTY_NULLIFIED_COMMITMENT }; - private_inputs.private_call.call_stack_item.public_inputs.nullified_commitments = malformed_nullified_commitments; - - DummyBuilder builder = - DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_nullified_commitments"); - native_private_kernel_circuit_inner(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_inner_tests, input_validation_malformed_arrays_private_call_stack) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_private_call_stack{ fr(0), fr(888) }; - private_inputs.private_call.call_stack_item.public_inputs.private_call_stack = malformed_private_call_stack; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_private_call_stack"); - native_private_kernel_circuit_inner(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_inner_tests, input_validation_malformed_arrays_public_call_stack) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_public_call_stack{ fr(0), fr(888) }; - private_inputs.private_call.call_stack_item.public_inputs.public_call_stack = malformed_public_call_stack; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_public_call_stack"); - native_private_kernel_circuit_inner(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_inner_tests, input_validation_malformed_arrays_new_l2_to_l1_msgs) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_new_l2_to_l1_msgs{}; - malformed_new_l2_to_l1_msgs[MAX_NEW_L2_TO_L1_MSGS_PER_CALL - 1] = fr(1); - private_inputs.private_call.call_stack_item.public_inputs.new_l2_to_l1_msgs = malformed_new_l2_to_l1_msgs; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_new_l2_to_l1_msgs"); - native_private_kernel_circuit_inner(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_inner_tests, input_validation_malformed_end_arrays_read_requests) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_read_requests{ fr(0), fr(9123), fr(0), fr(12) }; - private_inputs.previous_kernel.public_inputs.end.read_requests = malformed_read_requests; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_end_arrays_read_requests"); - native_private_kernel_circuit_inner(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_inner_tests, input_validation_malformed_end_arrays_commitments) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_commitments{ fr(0), fr(9123) }; - private_inputs.previous_kernel.public_inputs.end.new_commitments = malformed_commitments; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_end_arrays_commitments"); - native_private_kernel_circuit_inner(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_inner_tests, input_validation_malformed_end_arrays_nullifiers) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_nullifiers{}; - malformed_nullifiers[MAX_NEW_NULLIFIERS_PER_TX - 1] = fr(12); - private_inputs.previous_kernel.public_inputs.end.new_nullifiers = malformed_nullifiers; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_end_arrays_nullifiers"); - native_private_kernel_circuit_inner(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_inner_tests, input_validation_malformed_end_arrays_nullified_commitments) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_nullified_commitments{ fr(0), - fr(0), - EMPTY_NULLIFIED_COMMITMENT }; - private_inputs.previous_kernel.public_inputs.end.nullified_commitments = malformed_nullified_commitments; - - DummyBuilder builder = - DummyBuilder("private_kernel_tests__input_validation_malformed_arrays_end_nullified_commitments"); - native_private_kernel_circuit_inner(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_inner_tests, input_validation_malformed_end_arrays_private_call_stack) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_private_call_stack{ fr(0), fr(888) }; - private_inputs.previous_kernel.public_inputs.end.private_call_stack = malformed_private_call_stack; - - DummyBuilder builder = - DummyBuilder("private_kernel_tests__input_validation_malformed_end_arrays_private_call_stack"); - native_private_kernel_circuit_inner(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_inner_tests, input_validation_malformed_end_arrays_public_call_stack) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_public_call_stack{ fr(0), fr(888) }; - private_inputs.previous_kernel.public_inputs.end.public_call_stack = malformed_public_call_stack; - - DummyBuilder builder = - DummyBuilder("private_kernel_tests__input_validation_malformed_end_arrays_public_call_stack"); - native_private_kernel_circuit_inner(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_inner_tests, input_validation_malformed_end_arrays_l2_to_l1_msgs) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_l2_to_l1_msgs{}; - malformed_l2_to_l1_msgs[MAX_NEW_L2_TO_L1_MSGS_PER_TX - 1] = fr(1); - private_inputs.previous_kernel.public_inputs.end.new_l2_to_l1_msgs = malformed_l2_to_l1_msgs; - - DummyBuilder builder = DummyBuilder("private_kernel_tests__input_validation_malformed_end_arrays_l2_to_l1_msgs"); - native_private_kernel_circuit_inner(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_inner_tests, private_kernel_should_fail_if_aggregating_too_many_commitments) -{ - // Negative test to check if push_array_to_array fails if two many commitments are merged together - DummyBuilder builder = DummyBuilder("should_fail_if_aggregating_too_many_commitments"); - - PrivateKernelInputsInner private_inputs = - do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - // Mock the previous new commitments to be full, therefore no need commitments can be added - std::array full_new_commitments{}; - for (size_t i = 0; i < MAX_NEW_COMMITMENTS_PER_TX; ++i) { - full_new_commitments[i] = i + 1; - } - private_inputs.previous_kernel.public_inputs.end.new_commitments = full_new_commitments; - native_private_kernel_circuit_inner(builder, private_inputs); - - ASSERT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_OVERFLOW); -} - -/** - * @brief Test this dummy cbind - */ -TEST_F(native_private_kernel_inner_tests, cbind_private_kernel__dummy_previous_kernel) -{ - auto func = [] { return aztec3::circuits::kernel::private_kernel::utils::dummy_previous_kernel(); }; - auto [actual, expected] = call_func_and_wrapper(func, private_kernel__dummy_previous_kernel); - // TODO(AD): investigate why direct operator== didn't work - std::stringstream actual_ss; - std::stringstream expected_ss; - actual_ss << actual; - expected_ss << expected; - EXPECT_EQ(actual_ss.str(), expected_ss.str()); -} - -TEST_F(native_private_kernel_inner_tests, native_read_request_bad_request) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = - silo_nullifier(contract_address, private_inputs.previous_kernel.public_inputs.end.new_nullifiers[0]); - auto [read_requests, - read_request_membership_witnesses, - _transient_read_requests, - _transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, 2); - private_inputs.previous_kernel.public_inputs.constants.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - - // tweak read_request so it gives wrong root when paired with its sibling path - read_requests[1] += 1; - - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - // We need to update the previous_kernel's private_call_stack because the current_call_stack_item has changed - // i.e. we changed the public_inputs->read_requests and public_inputs->historical_note_hash_tree_root of the - // current_call_stack_item - private_inputs.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs.private_call.call_stack_item.hash(); - - DummyBuilder builder = DummyBuilder("native_private_kernel_inner_tests__native_read_request_bad_request"); - auto const& public_inputs = native_private_kernel_circuit_inner(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - ASSERT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__READ_REQUEST_NOTE_HASH_TREE_ROOT_MISMATCH); -} - -TEST_F(native_private_kernel_inner_tests, native_read_request_bad_leaf_index) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = - silo_nullifier(contract_address, private_inputs.previous_kernel.public_inputs.end.new_nullifiers[0]); - auto [read_requests, - read_request_membership_witnesses, - _transient_read_requests, - _transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, 2); - private_inputs.previous_kernel.public_inputs.constants.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - - // tweak leaf index so it gives wrong root when paired with its request and sibling path - read_request_membership_witnesses[1].leaf_index += 1; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - // We need to update the previous_kernel's private_call_stack because the current_call_stack_item has changed - // i.e. we changed the public_inputs->read_requests and public_inputs->historical_note_hash_tree_root of the - // current_call_stack_item - private_inputs.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs.private_call.call_stack_item.hash(); - - DummyBuilder builder = DummyBuilder("native_private_kernel_inner_tests__native_read_request_bad_leaf_index"); - auto const& public_inputs = native_private_kernel_circuit_inner(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - ASSERT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__READ_REQUEST_NOTE_HASH_TREE_ROOT_MISMATCH); -} - -TEST_F(native_private_kernel_inner_tests, native_read_request_bad_sibling_path) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = - silo_nullifier(contract_address, private_inputs.previous_kernel.public_inputs.end.new_nullifiers[0]); - auto [read_requests, - read_request_membership_witnesses, - _transient_read_requests, - _transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, 2); - private_inputs.previous_kernel.public_inputs.constants.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - - // tweak sibling path so it gives wrong root when paired with its request - read_request_membership_witnesses[1].sibling_path[1] += 1; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - // We need to update the previous_kernel's private_call_stack because the current_call_stack_item has changed - // i.e. we changed the public_inputs->read_requests and public_inputs->historical_note_hash_tree_root of the - // current_call_stack_item - private_inputs.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs.private_call.call_stack_item.hash(); - - DummyBuilder builder = DummyBuilder("native_private_kernel_inner_tests__native_read_request_bad_sibling_path"); - auto const& public_inputs = native_private_kernel_circuit_inner(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - ASSERT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__READ_REQUEST_NOTE_HASH_TREE_ROOT_MISMATCH); -} - -TEST_F(native_private_kernel_inner_tests, native_read_request_root_mismatch) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - // generate two random sets of read requests and mix them so their roots don't match - auto const first_nullifier = - silo_nullifier(contract_address, private_inputs.previous_kernel.public_inputs.end.new_nullifiers[0]); - auto [read_requests0, - read_request_membership_witnesses0, - _transient_read_requests0, - _transient_read_request_membership_witnesses0, - root] = get_random_reads(first_nullifier, contract_address, 2); - private_inputs.previous_kernel.public_inputs.constants.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - auto [read_requests1, - read_request_membership_witnesses1, - _transient_read_requests1, - _transient_read_request_membership_witnesses1, - _root] = get_random_reads(first_nullifier, contract_address, 2); - std::array bad_requests{}; - std::array, MAX_READ_REQUESTS_PER_CALL> bad_witnesses; - // note we are using read_requests0 for some and read_requests1 for others - bad_requests[0] = read_requests0[0]; - bad_requests[1] = read_requests0[1]; - bad_requests[2] = read_requests1[0]; - bad_requests[3] = read_requests1[1]; - bad_witnesses[0] = read_request_membership_witnesses0[0]; - bad_witnesses[1] = read_request_membership_witnesses0[1]; - bad_witnesses[2] = read_request_membership_witnesses1[0]; - bad_witnesses[3] = read_request_membership_witnesses1[1]; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = bad_requests; - private_inputs.private_call.read_request_membership_witnesses = bad_witnesses; - - // We need to update the previous_kernel's private_call_stack because the current_call_stack_item has changed - // i.e. we changed the public_inputs->read_requests and public_inputs->historical_note_hash_tree_root of the - // current_call_stack_item - private_inputs.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs.private_call.call_stack_item.hash(); - - DummyBuilder builder = DummyBuilder("native_private_kernel_inner_tests__native_read_request_root_mismatch"); - auto const& public_inputs = native_private_kernel_circuit_inner(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - ASSERT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().code, - CircuitErrorCode::PRIVATE_KERNEL__READ_REQUEST_NOTE_HASH_TREE_ROOT_MISMATCH); -} - -TEST_F(native_private_kernel_inner_tests, native_no_read_requests_works) -{ - // no read requests should work - - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - // empty requests - std::array const read_requests{}; - std::array, MAX_READ_REQUESTS_PER_CALL> const - read_request_membership_witnesses{}; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - // We need to update the previous_kernel's private_call_stack because the current_call_stack_item has changed - // i.e. we changed the public_inputs->read_requests of the current_call_stack_item - private_inputs.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs.private_call.call_stack_item.hash(); - - DummyBuilder builder = DummyBuilder("native_private_kernel_inner_tests__native_no_read_requests_works"); - auto const& public_inputs = native_private_kernel_circuit_inner(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - auto failure = builder.get_first_failure(); - if (failure.code != CircuitErrorCode::NO_ERROR) { - info("failure: ", failure); - } - ASSERT_FALSE(builder.failed()); - - // non-transient read requests are NOT forwarded - ASSERT_EQ(array_length(public_inputs.end.read_requests), 0); -} - -TEST_F(native_private_kernel_inner_tests, native_one_read_requests_works) -{ - // one read request should work - - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = - silo_nullifier(contract_address, private_inputs.previous_kernel.public_inputs.end.new_nullifiers[0]); - auto [read_requests, - read_request_membership_witnesses, - _transient_read_requests, - _transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, 1); - private_inputs.previous_kernel.public_inputs.constants.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - // We need to update the previous_kernel's private_call_stack because the current_call_stack_item has changed - // i.e. we changed the public_inputs->read_requests of the current_call_stack_item - private_inputs.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs.private_call.call_stack_item.hash(); - - DummyBuilder builder = DummyBuilder("native_private_kernel_inner_tests__native_one_read_requests_works"); - auto const& public_inputs = native_private_kernel_circuit_inner(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - auto failure = builder.get_first_failure(); - if (failure.code != CircuitErrorCode::NO_ERROR) { - info("failure: ", failure); - } - ASSERT_FALSE(builder.failed()); - - // non-transient read requests are NOT forwarded - ASSERT_EQ(array_length(public_inputs.end.read_requests), 0); -} - -TEST_F(native_private_kernel_inner_tests, native_two_read_requests_works) -{ - // two read requests should work - - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = - silo_nullifier(contract_address, private_inputs.previous_kernel.public_inputs.end.new_nullifiers[0]); - auto [read_requests, - read_request_membership_witnesses, - _transient_read_requests, - _transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, 2); - private_inputs.previous_kernel.public_inputs.constants.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - // We need to update the previous_kernel's private_call_stack because the current_call_stack_item has changed - // i.e. we changed the public_inputs->read_requests of the current_call_stack_item - private_inputs.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs.private_call.call_stack_item.hash(); - - DummyBuilder builder = DummyBuilder("native_private_kernel_inner_tests__native_two_read_requests_works"); - auto const& public_inputs = native_private_kernel_circuit_inner(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - auto failure = builder.get_first_failure(); - if (failure.code != CircuitErrorCode::NO_ERROR) { - info("failure: ", failure); - } - ASSERT_FALSE(builder.failed()); - - // non-transient read requests are NOT forwarded - ASSERT_EQ(array_length(public_inputs.end.read_requests), 0); -} - -TEST_F(native_private_kernel_inner_tests, native_max_read_requests_works) -{ - // max read requests should work - - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = - silo_nullifier(contract_address, private_inputs.previous_kernel.public_inputs.end.new_nullifiers[0]); - auto [read_requests, - read_request_membership_witnesses, - _transient_read_requests, - _transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, MAX_READ_REQUESTS_PER_CALL); - private_inputs.previous_kernel.public_inputs.constants.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - // We need to update the previous_kernel's private_call_stack because the current_call_stack_item has changed - // i.e. we changed the public_inputs->read_requests and public_inputs->historical_note_hash_tree_root of the - // current_call_stack_item - private_inputs.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs.private_call.call_stack_item.hash(); - - DummyBuilder builder = DummyBuilder("native_private_kernel_inner_tests__native_max_read_requests_works"); - auto const& public_inputs = native_private_kernel_circuit_inner(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - auto failure = builder.get_first_failure(); - if (failure.code != CircuitErrorCode::NO_ERROR) { - info("failure: ", failure); - } - ASSERT_FALSE(builder.failed()); - - // non-transient read requests are NOT forwarded - ASSERT_EQ(array_length(public_inputs.end.read_requests), 0); -} - -TEST_F(native_private_kernel_inner_tests, native_one_transient_read_requests_works) -{ - // one transient read request should work - - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = - silo_nullifier(contract_address, private_inputs.previous_kernel.public_inputs.end.new_nullifiers[0]); - auto [read_requests, - read_request_membership_witnesses, - transient_read_requests, - transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, 1); - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - - // Make the read request transient - read_requests[0] = transient_read_requests[0]; - read_request_membership_witnesses[0] = transient_read_request_membership_witnesses[0]; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - // We need to update the previous_kernel's private_call_stack because the current_call_stack_item has changed - // i.e. we changed the public_inputs->read_requests and public_inputs->historical_note_hash_tree_root of the - // current_call_stack_item - private_inputs.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs.private_call.call_stack_item.hash(); - - DummyBuilder builder = DummyBuilder("native_private_kernel_inner_tests__native_one_transient_read_requests_works"); - auto const& public_inputs = native_private_kernel_circuit_inner(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - auto failure = builder.get_first_failure(); - if (failure.code != CircuitErrorCode::NO_ERROR) { - info("failure: ", failure); - } - ASSERT_FALSE(builder.failed()); - - ASSERT_EQ(array_length(public_inputs.end.read_requests), 1); // transient read request gets forwarded -} - -TEST_F(native_private_kernel_inner_tests, native_max_read_requests_one_transient_works) -{ - // max read requests with one transient should work - - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = - silo_nullifier(contract_address, private_inputs.previous_kernel.public_inputs.end.new_nullifiers[0]); - auto [read_requests, - read_request_membership_witnesses, - transient_read_requests, - transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, MAX_READ_REQUESTS_PER_CALL); - private_inputs.previous_kernel.public_inputs.constants.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - - // Make the read request at position 1 transient - read_requests[1] = transient_read_requests[1]; - read_request_membership_witnesses[1] = transient_read_request_membership_witnesses[1]; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = read_requests; - private_inputs.private_call.read_request_membership_witnesses = read_request_membership_witnesses; - - // We need to update the previous_kernel's private_call_stack because the current_call_stack_item has changed - // i.e. we changed the public_inputs->read_requests and public_inputs->historical_note_hash_tree_root of the - // current_call_stack_item - private_inputs.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs.private_call.call_stack_item.hash(); - - DummyBuilder builder = - DummyBuilder("native_private_kernel_inner_tests__native_max_read_requests_one_transient_works"); - auto const& public_inputs = native_private_kernel_circuit_inner(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - auto failure = builder.get_first_failure(); - if (failure.code != CircuitErrorCode::NO_ERROR) { - info("failure: ", failure); - } - ASSERT_FALSE(builder.failed()); - - // transient read request gets forwarded - ASSERT_EQ(array_length(public_inputs.end.read_requests), 1); -} - -TEST_F(native_private_kernel_inner_tests, native_max_read_requests_all_transient_works) -{ - // max read requests with all transient should work - - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - auto const& contract_address = - private_inputs.private_call.call_stack_item.public_inputs.call_context.storage_contract_address; - - auto const first_nullifier = - silo_nullifier(contract_address, private_inputs.previous_kernel.public_inputs.end.new_nullifiers[0]); - auto [read_requests, - read_request_membership_witnesses, - transient_read_requests, - transient_read_request_membership_witnesses, - root] = get_random_reads(first_nullifier, contract_address, MAX_READ_REQUESTS_PER_CALL); - private_inputs.previous_kernel.public_inputs.constants.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.block_header.note_hash_tree_root = root; - private_inputs.private_call.call_stack_item.public_inputs.read_requests = transient_read_requests; - private_inputs.private_call.read_request_membership_witnesses = transient_read_request_membership_witnesses; - - // We need to update the previous_kernel's private_call_stack because the current_call_stack_item has changed - // i.e. we changed the public_inputs->read_requests and public_inputs->historical_note_hash_tree_root of the - // current_call_stack_item - private_inputs.previous_kernel.public_inputs.end.private_call_stack[0] = - private_inputs.private_call.call_stack_item.hash(); - - DummyBuilder builder = - DummyBuilder("native_private_kernel_inner_tests__native_max_read_requests_one_transient_works"); - auto const& public_inputs = native_private_kernel_circuit_inner(builder, private_inputs); - - validate_no_new_deployed_contract(public_inputs); - - auto failure = builder.get_first_failure(); - if (failure.code != CircuitErrorCode::NO_ERROR) { - info("failure: ", failure); - } - ASSERT_FALSE(builder.failed()); - - // transient read request all get forwarded - ASSERT_EQ(array_length(public_inputs.end.read_requests), MAX_READ_REQUESTS_PER_CALL); -} - -TEST_F(native_private_kernel_inner_tests, native_logs_are_hashed_as_expected) -{ - std::array const& encrypted_logs_hash = { NT::fr(16), NT::fr(69) }; - NT::fr const& encrypted_log_preimages_length = NT::fr(100); - std::array const& unencrypted_logs_hash = { NT::fr(26), NT::fr(47) }; - NT::fr const& unencrypted_log_preimages_length = NT::fr(50); - std::array const& public_inputs_encrypted_logs_hash = { NT::fr(80), NT::fr(429) }; - NT::fr const& public_inputs_encrypted_log_preimages_length = NT::fr(13); - std::array const& public_inputs_unencrypted_logs_hash = { NT::fr(956), NT::fr(112) }; - NT::fr const& public_inputs_unencrypted_log_preimages_length = NT::fr(24); - - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, - deposit, - standard_test_args(), - encrypted_logs_hash, - unencrypted_logs_hash, - encrypted_log_preimages_length, - unencrypted_log_preimages_length, - public_inputs_encrypted_logs_hash, - public_inputs_unencrypted_logs_hash, - public_inputs_encrypted_log_preimages_length, - public_inputs_unencrypted_log_preimages_length); - - DummyBuilder builder = DummyBuilder("native_private_kernel_inner_tests__native_logs_are_hashed_as_expected"); - auto const& public_inputs = native_private_kernel_circuit_inner(builder, private_inputs); - - ASSERT_EQ(public_inputs.end.encrypted_log_preimages_length, - encrypted_log_preimages_length + public_inputs_encrypted_log_preimages_length); - ASSERT_EQ(public_inputs.end.unencrypted_log_preimages_length, - unencrypted_log_preimages_length + public_inputs_unencrypted_log_preimages_length); - - auto const& expected_encrypted_logs_hash = accumulate_sha256({ public_inputs_encrypted_logs_hash[0], - public_inputs_encrypted_logs_hash[1], - encrypted_logs_hash[0], - encrypted_logs_hash[1] }); - - ASSERT_EQ(public_inputs.end.encrypted_logs_hash, expected_encrypted_logs_hash); - - auto const& expected_unencrypted_logs_hash = accumulate_sha256({ public_inputs_unencrypted_logs_hash[0], - public_inputs_unencrypted_logs_hash[1], - unencrypted_logs_hash[0], - unencrypted_logs_hash[1] }); - - ASSERT_EQ(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); -} - -TEST_F(native_private_kernel_inner_tests, 0th_nullifier_zero_fails) -{ - auto private_inputs = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - // Change the 0th nullifier to be zero. - private_inputs.previous_kernel.public_inputs.end.new_nullifiers[0] = 0; - - // Invoke the native private kernel circuit - DummyBuilder builder = DummyBuilder("private_kernel_tests__0th_nullifier_zero_fails"); - native_private_kernel_circuit_inner(builder, private_inputs); - - // Assertion checks - EXPECT_TRUE(builder.failed()); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::PRIVATE_KERNEL__0TH_NULLIFIER_IS_ZERO); -} - -} // namespace aztec3::circuits::kernel::private_kernel diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_ordering.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_ordering.cpp deleted file mode 100644 index 19c21eecfb5..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_ordering.cpp +++ /dev/null @@ -1,192 +0,0 @@ -#include "common.hpp" -#include "init.hpp" - -#include "aztec3/circuits/abis/kernel_circuit_public_inputs_final.hpp" -#include "aztec3/circuits/abis/previous_kernel_data.hpp" -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_ordering.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/array.hpp" -#include "aztec3/utils/circuit_errors.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" - -#include - -namespace { -using NT = aztec3::utils::types::NativeTypes; - -using aztec3::circuits::abis::KernelCircuitPublicInputsFinal; -using aztec3::circuits::abis::PreviousKernelData; -using aztec3::circuits::abis::private_kernel::PrivateKernelInputsOrdering; -using aztec3::circuits::kernel::private_kernel::common_initialize_end_values; -using aztec3::utils::array_rearrange; -using aztec3::utils::CircuitErrorCode; -using aztec3::utils::DummyCircuitBuilder; - -void initialize_end_values(PreviousKernelData const& previous_kernel, - KernelCircuitPublicInputsFinal& public_inputs) -{ - common_initialize_end_values(previous_kernel, public_inputs); - public_inputs.end.new_contracts = previous_kernel.public_inputs.end.new_contracts; -} -} // namespace - - -namespace aztec3::circuits::kernel::private_kernel { - -void match_reads_to_commitments(DummyCircuitBuilder& builder, - std::array const& read_requests, - std::array const& read_commitment_hints, - std::array const& new_commitments) -{ - // match reads to commitments from the previous call(s) - for (size_t rr_idx = 0; rr_idx < MAX_READ_REQUESTS_PER_TX; rr_idx++) { - const auto& read_request = read_requests[rr_idx]; - const auto& read_commitment_hint = read_commitment_hints[rr_idx]; - const auto hint_pos = static_cast(uint64_t(read_commitment_hint)); - - if (read_request != 0) { - size_t match_pos = MAX_NEW_COMMITMENTS_PER_TX; - if (hint_pos < MAX_NEW_COMMITMENTS_PER_TX) { - match_pos = read_request == new_commitments[hint_pos] ? hint_pos : match_pos; - } - - builder.do_assert( - match_pos != MAX_NEW_COMMITMENTS_PER_TX, - format("read_request at position [", - rr_idx, - "]* is transient but does not match any new commitment.", - "\n\tread_request: ", - read_request, - "\n\thint_to_commitment: ", - read_commitment_hint, - "\n\t* the read_request position/index is not expected to match position in app-circuit " - "outputs because kernel iterations gradually remove non-transient read_requests as " - "membership checks are resolved."), - CircuitErrorCode::PRIVATE_KERNEL__TRANSIENT_READ_REQUEST_NO_MATCH); - } - } -} - -/** - * @brief This function matches transient nullifiers to commitments and squashes (deletes) them both. - * - * @details A non-zero entry in nullified_commitments at position i implies that - * 1) new_commitments array contains at least an occurrence of nullified_commitments[i] - * 2) this commitment is nullified by new_nullifiers[i] (according to app circuit, the kernel cannot check this on its - * own.) - * Remark: We do not check that new_nullifiers[i] is non-empty. (app circuit responsibility) - * - * @param builder - * @param new_nullifiers public_input's nullifiers that should be squashed when matching a transient commitment - * @param nullified_commitments commitments that each new_nullifier nullifies. 0 here implies non-transient nullifier, - * and a non-zero `nullified_commitment` implies a transient nullifier that MUST be matched to a new_commitment. - * @param new_commitments public_input's commitments to be matched against and squashed when matched to a transient - * nullifier. - */ -void match_nullifiers_to_commitments_and_squash( - DummyCircuitBuilder& builder, - std::array& new_nullifiers, - std::array const& nullified_commitments, - std::array const& nullifier_commitment_hints, - std::array& new_commitments) -{ - // match nullifiers/nullified_commitments to commitments from the previous call(s) - for (size_t n_idx = 0; n_idx < MAX_NEW_NULLIFIERS_PER_TX; n_idx++) { - const auto& nullified_commitment = nullified_commitments[n_idx]; - const auto& nullifier_commitment_hint = nullifier_commitment_hints[n_idx]; - const auto hint_pos = static_cast(uint64_t(nullifier_commitment_hint)); - // Nullified_commitment of value `EMPTY_NULLIFIED_COMMITMENT` implies non-transient (persistable) - // nullifier in which case no attempt will be made to match it to a commitment. - // Non-empty nullified_commitment implies transient nullifier which MUST be matched to a commitment below! - // 0-valued nullified_commitment is empty and will be ignored - if (nullified_commitments[n_idx] != NT::fr(0) && - nullified_commitments[n_idx] != NT::fr(EMPTY_NULLIFIED_COMMITMENT)) { - size_t match_pos = MAX_NEW_COMMITMENTS_PER_TX; - - if (hint_pos < MAX_NEW_COMMITMENTS_PER_TX) { - match_pos = nullified_commitment == new_commitments[hint_pos] ? hint_pos : match_pos; - } - - if (match_pos != MAX_NEW_COMMITMENTS_PER_TX) { - // match found! - // squash both the nullifier and the commitment - // (set to 0 here and then rearrange array after loop) - important("chopped commitment for siloed inner hash note \n", new_commitments[match_pos]); - new_commitments[match_pos] = NT::fr(0); - new_nullifiers[n_idx] = NT::fr(0); - } else { - // Transient nullifiers MUST match a pending commitment - builder.do_assert(false, - format("new_nullifier at position [", - n_idx, - "]* is transient but does not match any new commitment.", - "\n\tnullifier: ", - new_nullifiers[n_idx], - "\n\tnullified_commitment: ", - nullified_commitments[n_idx]), - CircuitErrorCode::PRIVATE_KERNEL__TRANSIENT_NEW_NULLIFIER_NO_MATCH); - } - } - // non-transient (persistable) nullifiers are just kept in new_nullifiers array and forwarded - // to public inputs (used later by base rollup circuit) - } - // Move all zero-ed (removed) entries of these arrays to the end and preserve ordering of other entries - array_rearrange(new_commitments); - array_rearrange(new_nullifiers); -} - -void apply_commitment_nonces(NT::fr const& first_nullifier, - std::array& new_commitments) -{ - for (size_t c_idx = 0; c_idx < MAX_NEW_COMMITMENTS_PER_TX; c_idx++) { - // Apply nonce to all non-zero/non-empty commitments - // Nonce is the hash of the first (0th) nullifier and the commitment's index into new_commitments array - const auto nonce = compute_commitment_nonce(first_nullifier, c_idx); - new_commitments[c_idx] = - new_commitments[c_idx] == 0 ? 0 : compute_unique_commitment(nonce, new_commitments[c_idx]); - } -} - -KernelCircuitPublicInputsFinal native_private_kernel_circuit_ordering( - DummyCircuitBuilder& builder, PrivateKernelInputsOrdering const& private_inputs) -{ - // We'll be pushing data to this during execution of this circuit. - KernelCircuitPublicInputsFinal public_inputs{}; - - common_validate_previous_kernel_values(builder, private_inputs.previous_kernel.public_inputs.end); - - // Do this before any functions can modify the inputs. - initialize_end_values(private_inputs.previous_kernel, public_inputs); - - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1486): validate that `len(new_nullifiers) == - // len(nullified_commitments)` - - // Matching read requests to pending commitments requires the full list of new commitments accumulated over - // all iterations of the private kernel. Therefore, we match reads against new_commitments in - // previous_kernel.public_inputs.end, where "previous kernel" is the last "inner" kernel iteration. - // Remark: The commitments in public_inputs.end have already been siloed by contract address! - match_reads_to_commitments(builder, - private_inputs.previous_kernel.public_inputs.end.read_requests, - private_inputs.read_commitment_hints, - private_inputs.previous_kernel.public_inputs.end.new_commitments); - - // Matching nullifiers to pending commitments requires the full list of new commitments accumulated over - // all iterations of the private kernel. Therefore, we match nullifiers (their nullified_commitments) - // against new_commitments in public_inputs.end which has been initialized to - // previous_kernel.public_inputs.end in common_initialize_*() above. - // Remark: The commitments in public_inputs.end have already been siloed by contract address! - match_nullifiers_to_commitments_and_squash(builder, - public_inputs.end.new_nullifiers, - public_inputs.end.nullified_commitments, - private_inputs.nullifier_commitment_hints, - public_inputs.end.new_commitments); - - // tx hash - const auto& first_nullifier = private_inputs.previous_kernel.public_inputs.end.new_nullifiers[0]; - apply_commitment_nonces(first_nullifier, public_inputs.end.new_commitments); - - return public_inputs; -}; - -} // namespace aztec3::circuits::kernel::private_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_ordering.hpp b/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_ordering.hpp deleted file mode 100644 index 872396c6178..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_ordering.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "init.hpp" - -#include "aztec3/circuits/abis/kernel_circuit_public_inputs_final.hpp" -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_ordering.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" - -#include - -namespace aztec3::circuits::kernel::private_kernel { - -using aztec3::circuits::abis::KernelCircuitPublicInputsFinal; -using aztec3::circuits::abis::private_kernel::PrivateKernelInputsOrdering; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; - -KernelCircuitPublicInputsFinal native_private_kernel_circuit_ordering( - DummyBuilder& builder, PrivateKernelInputsOrdering const& private_inputs); - -} // namespace aztec3::circuits::kernel::private_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_ordering.test.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_ordering.test.cpp deleted file mode 100644 index 76e87056ea8..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit_ordering.test.cpp +++ /dev/null @@ -1,510 +0,0 @@ -#include "testing_harness.hpp" - -#include "aztec3/circuits/apps/test_apps/escrow/deposit.hpp" -#include "aztec3/circuits/kernel/private/common.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/array.hpp" -#include "aztec3/utils/circuit_errors.hpp" - -#include "barretenberg/ecc/curves/bn254/fr.hpp" -#include - -#include - -#include -#include - -namespace aztec3::circuits::kernel::private_kernel { - -using aztec3::circuits::apps::test_apps::escrow::deposit; - -using aztec3::circuits::kernel::private_kernel::testing_harness::do_private_call_get_kernel_inputs_inner; -using aztec3::utils::array_length; -using aztec3::utils::CircuitErrorCode; - -// NOTE: *DO NOT* call fr constructors in static initializers and assign them to constants. This will fail. Instead, use -// lazy initialization or functions. Lambdas were introduced here. -// amount = 5, asset_id = 1, memo = 999 -const auto standard_test_args = [] { return std::vector{ NT::fr(5), NT::fr(1), NT::fr(999) }; }; -class native_private_kernel_ordering_tests : public ::testing::Test { - protected: - static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../barretenberg/cpp/srs_db/ignition"); } -}; - -// TODO(1998): testing cbind calls private_kernel__sim_ordering, private_kernel__sim_init, private_kernel__sim_inner -// in their respective test suites once msgpack capabilities allow it. One current limitation is due to -// the lack of support to deserialize std::variant in particular CircuitResult type. -// See https://github.com/AztecProtocol/aztec-packages/issues/1998 -/** - * @brief Test cbind - */ -// TEST_F(native_private_kernel_ordering_tests, cbind_private_kernel__sim_ordering) -// { -// auto func = [](PrivateKernelInputsOrdering private_inputs) { -// DummyCircuitBuilder builder = DummyCircuitBuilder("private_kernel__sim_ordering"); -// auto const& public_inputs = native_private_kernel_circuit_ordering(builder, private_inputs); -// return builder.result_or_error(public_inputs); -// }; - -// NT::fr const& amount = 5; -// NT::fr const& asset_id = 1; -// NT::fr const& memo = 999; -// std::array const& empty_logs_hash = { NT::fr(16), NT::fr(69) }; -// NT::fr const& empty_log_preimages_length = NT::fr(100); - -// // Generate private inputs including proofs and vkeys for app circuit and previous kernel -// auto const& private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, -// deposit, -// { amount, asset_id, memo }, -// empty_logs_hash, -// empty_logs_hash, -// empty_log_preimages_length, -// empty_log_preimages_length, -// empty_logs_hash, -// empty_logs_hash, -// empty_log_preimages_length, -// empty_log_preimages_length, -// true); -// PrivateKernelInputsOrdering private_inputs{ private_inputs_inner.previous_kernel, -// std::array{ fr(123), fr(89) } }; - -// auto [actual, expected] = call_func_and_wrapper(func, private_kernel__sim_ordering, private_inputs); - -// std::stringstream actual_ss; -// std::stringstream expected_ss; -// actual_ss << actual; -// expected_ss << expected; -// EXPECT_EQ(actual_ss.str(), expected_ss.str()); -// } - -TEST_F(native_private_kernel_ordering_tests, native_matching_one_read_request_to_commitment_works) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array new_nullifiers{}; - std::array siloed_commitments{}; - std::array unique_siloed_commitments{}; - std::array read_requests{}; - std::array hints{}; - - std::array, MAX_READ_REQUESTS_PER_TX> - read_request_membership_witnesses{}; - - new_nullifiers[0] = NT::fr::random_element(); - siloed_commitments[0] = NT::fr::random_element(); // create random commitment - // ordering circuit applies nonces to commitments - const auto nonce = compute_commitment_nonce(new_nullifiers[0], 0); - unique_siloed_commitments[0] = - siloed_commitments[0] == 0 ? 0 : compute_unique_commitment(nonce, siloed_commitments[0]); - - read_requests[0] = siloed_commitments[0]; - // hints[0] == fr(0) due to the default initialization of hints - read_request_membership_witnesses[0].is_transient = true; - - auto& previous_kernel = private_inputs_inner.previous_kernel; - - previous_kernel.public_inputs.end.new_nullifiers = new_nullifiers; - previous_kernel.public_inputs.end.new_commitments = siloed_commitments; - previous_kernel.public_inputs.end.read_requests = read_requests; - - PrivateKernelInputsOrdering private_inputs{ previous_kernel, hints }; - - DummyBuilder builder = - DummyBuilder("native_private_kernel_ordering_tests__native_matching_one_read_request_to_commitment_works"); - auto const& public_inputs = native_private_kernel_circuit_ordering(builder, private_inputs); - - ASSERT_FALSE(builder.failed()) << "failure: " << builder.get_first_failure(); - ASSERT_TRUE(array_length(public_inputs.end.new_commitments) == 1); - ASSERT_TRUE(public_inputs.end.new_commitments[0] == unique_siloed_commitments[0]); -} - -TEST_F(native_private_kernel_ordering_tests, native_matching_some_read_requests_to_commitments_works) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array new_nullifiers{}; - std::array siloed_commitments{}; - std::array unique_siloed_commitments{}; - std::array read_requests{}; - std::array hints{}; - - std::array, MAX_READ_REQUESTS_PER_TX> - read_request_membership_witnesses{}; - - new_nullifiers[0] = NT::fr::random_element(); - const auto& first_nullifier = new_nullifiers[0]; - // create random commitments to input to ordering circuit, and compute their "unique" versions - // to be expected at the output - for (size_t c_idx = 0; c_idx < MAX_NEW_COMMITMENTS_PER_TX; c_idx++) { - siloed_commitments[c_idx] = NT::fr::random_element(); // create random commitment - // ordering circuit applies nonces to commitments - const auto nonce = compute_commitment_nonce(first_nullifier, c_idx); - unique_siloed_commitments[c_idx] = - siloed_commitments[c_idx] == 0 ? 0 : compute_unique_commitment(nonce, siloed_commitments[c_idx]); - } - - read_requests[0] = siloed_commitments[1]; - read_requests[1] = siloed_commitments[3]; - read_request_membership_witnesses[0].is_transient = true; - read_request_membership_witnesses[1].is_transient = true; - hints[0] = fr(1); - hints[1] = fr(3); - - auto& previous_kernel = private_inputs_inner.previous_kernel; - - previous_kernel.public_inputs.end.new_nullifiers = new_nullifiers; - previous_kernel.public_inputs.end.new_commitments = siloed_commitments; - previous_kernel.public_inputs.end.read_requests = read_requests; - - PrivateKernelInputsOrdering private_inputs{ previous_kernel, hints }; - - DummyBuilder builder = - DummyBuilder("native_private_kernel_ordering_tests__native_matching_some_read_requests_to_commitments_works"); - auto const& public_inputs = native_private_kernel_circuit_ordering(builder, private_inputs); - - ASSERT_FALSE(builder.failed()) << "failure: " << builder.get_first_failure(); - ASSERT_TRUE(array_length(public_inputs.end.new_commitments) == MAX_NEW_COMMITMENTS_PER_TX); - // ensure that commitments had nonce applied properly and all appear at output - for (size_t c_idx = 0; c_idx < MAX_NEW_COMMITMENTS_PER_TX; c_idx++) { - ASSERT_TRUE(public_inputs.end.new_commitments[c_idx] == unique_siloed_commitments[c_idx]); - } -} - -TEST_F(native_private_kernel_ordering_tests, native_read_request_unknown_fails) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array siloed_commitments{}; - std::array read_requests{}; - std::array hints{}; - std::array, MAX_READ_REQUESTS_PER_TX> - read_request_membership_witnesses{}; - - for (size_t c_idx = 0; c_idx < MAX_NEW_COMMITMENTS_PER_TX; c_idx++) { - siloed_commitments[c_idx] = NT::fr::random_element(); // create random commitment - read_requests[c_idx] = siloed_commitments[c_idx]; // create random read requests - hints[c_idx] = fr(c_idx); // ^ will match each other! - read_request_membership_witnesses[c_idx].is_transient = true; // ordering circuit only allows transient reads - } - read_requests[3] = NT::fr::random_element(); // force one read request not to match - - auto& previous_kernel = private_inputs_inner.previous_kernel; - - previous_kernel.public_inputs.end.new_commitments = siloed_commitments; - previous_kernel.public_inputs.end.read_requests = read_requests; - - PrivateKernelInputsOrdering private_inputs{ previous_kernel, hints }; - - DummyBuilder builder = DummyBuilder("native_private_kernel_ordering_tests__native_read_request_unknown_fails"); - native_private_kernel_circuit_ordering(builder, private_inputs); - - auto failure = builder.get_first_failure(); - ASSERT_EQ(failure.code, CircuitErrorCode::PRIVATE_KERNEL__TRANSIENT_READ_REQUEST_NO_MATCH); -} - -TEST_F(native_private_kernel_ordering_tests, native_squash_one_of_one_transient_matches_works) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array new_commitments{}; - std::array new_nullifiers{}; - std::array nullifier_commitments{}; - - const auto commitment0 = fr(213); - new_commitments[0] = commitment0; - - new_nullifiers[0] = fr(32); - nullifier_commitments[0] = commitment0; - - auto& previous_kernel = private_inputs_inner.previous_kernel; - - previous_kernel.public_inputs.end.new_commitments = new_commitments; - previous_kernel.public_inputs.end.new_nullifiers = new_nullifiers; - previous_kernel.public_inputs.end.nullified_commitments = nullifier_commitments; - - // Correct nullifier_commitment hint for new_nullifiers[0] == 0 is correct due to the default - // initialization of the array. - PrivateKernelInputsOrdering private_inputs{ .previous_kernel = previous_kernel }; - - DummyBuilder builder = - DummyBuilder("native_private_kernel_ordering_tests__native_squash_one_of_one_transient_matches_works"); - auto public_inputs = native_private_kernel_circuit_ordering(builder, private_inputs); - - ASSERT_FALSE(builder.failed()) << "failure: " << builder.get_first_failure(); - ASSERT_TRUE(array_length(public_inputs.end.new_commitments) == 0); // 1/1 squashed - ASSERT_TRUE(array_length(public_inputs.end.new_nullifiers) == 0); // 1/1 squashed -} - -TEST_F(native_private_kernel_ordering_tests, native_squash_one_of_two_transient_matches_works) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array new_commitments{}; - std::array new_nullifiers{}; - std::array nullifier_commitments{}; - - const auto commitment1 = fr(213); - new_commitments[0] = fr(763); - new_commitments[1] = commitment1; - - new_nullifiers[0] = fr(32); - nullifier_commitments[0] = commitment1; - - auto& previous_kernel = private_inputs_inner.previous_kernel; - - previous_kernel.public_inputs.end.new_commitments = new_commitments; - previous_kernel.public_inputs.end.new_nullifiers = new_nullifiers; - previous_kernel.public_inputs.end.nullified_commitments = nullifier_commitments; - - PrivateKernelInputsOrdering private_inputs{ .previous_kernel = previous_kernel, - .nullifier_commitment_hints = - std::array{ 1 } }; - - DummyBuilder builder = - DummyBuilder("native_private_kernel_ordering_tests__native_squash_one_of_two_transient_matches_works"); - auto public_inputs = native_private_kernel_circuit_ordering(builder, private_inputs); - - ASSERT_FALSE(builder.failed()) << "failure: " << builder.get_first_failure(); - ASSERT_TRUE(array_length(public_inputs.end.new_commitments) == 1); // 1/2 squashed - ASSERT_TRUE(array_length(public_inputs.end.new_nullifiers) == 0); // 1/1 squashed -} - -TEST_F(native_private_kernel_ordering_tests, native_squash_two_of_two_transient_matches_works) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array new_commitments{}; - std::array new_nullifiers{}; - std::array nullifier_commitments{}; - - const auto commitment0 = fr(763); - const auto commitment1 = fr(213); - new_commitments[0] = commitment0; - new_commitments[1] = commitment1; - - new_nullifiers[0] = fr(32); - new_nullifiers[1] = fr(43); - nullifier_commitments[0] = commitment1; - nullifier_commitments[1] = commitment0; - - auto& previous_kernel = private_inputs_inner.previous_kernel; - - previous_kernel.public_inputs.end.new_commitments = new_commitments; - previous_kernel.public_inputs.end.new_nullifiers = new_nullifiers; - previous_kernel.public_inputs.end.nullified_commitments = nullifier_commitments; - - PrivateKernelInputsOrdering private_inputs{ .previous_kernel = previous_kernel, - .nullifier_commitment_hints = - std::array{ 1 } }; - - DummyBuilder builder = - DummyBuilder("native_private_kernel_ordering_tests__native_squash_two_of_two_transient_matches_works"); - auto public_inputs = native_private_kernel_circuit_ordering(builder, private_inputs); - - ASSERT_FALSE(builder.failed()) << "failure: " << builder.get_first_failure(); - ASSERT_TRUE(array_length(public_inputs.end.new_commitments) == 0); // 2/2 squashed - ASSERT_TRUE(array_length(public_inputs.end.new_nullifiers) == 0); // 2/2 squashed -} - -TEST_F(native_private_kernel_ordering_tests, native_empty_nullified_commitment_means_persistent_nullifier_0) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array new_commitments{}; - std::array new_nullifiers{}; - std::array nullifier_commitments{}; - - new_commitments[0] = fr(213); - - new_nullifiers[0] = fr(32); - nullifier_commitments[0] = fr(EMPTY_NULLIFIED_COMMITMENT); - - auto& previous_kernel = private_inputs_inner.previous_kernel; - - previous_kernel.public_inputs.end.new_commitments = new_commitments; - previous_kernel.public_inputs.end.new_nullifiers = new_nullifiers; - previous_kernel.public_inputs.end.nullified_commitments = nullifier_commitments; - - PrivateKernelInputsOrdering private_inputs{ .previous_kernel = previous_kernel }; - - DummyBuilder builder = DummyBuilder( - "native_private_kernel_ordering_tests__native_empty_nullified_commitment_means_persistent_nullifier_0"); - auto public_inputs = native_private_kernel_circuit_ordering(builder, private_inputs); - - ASSERT_FALSE(builder.failed()) << "failure: " << builder.get_first_failure(); - // nullifier and commitment present at output (will become persistent) - ASSERT_TRUE(array_length(public_inputs.end.new_commitments) == 1); - ASSERT_TRUE(array_length(public_inputs.end.new_nullifiers) == 1); -} - -// same as previous test, but this time there are 0 commitments! -TEST_F(native_private_kernel_ordering_tests, native_empty_nullified_commitment_means_persistent_nullifier_1) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array new_commitments{}; - std::array new_nullifiers{}; - std::array nullifier_commitments{}; - - new_nullifiers[0] = fr(32); - nullifier_commitments[0] = fr(EMPTY_NULLIFIED_COMMITMENT); - - auto& previous_kernel = private_inputs_inner.previous_kernel; - - previous_kernel.public_inputs.end.new_commitments = new_commitments; - previous_kernel.public_inputs.end.new_nullifiers = new_nullifiers; - previous_kernel.public_inputs.end.nullified_commitments = nullifier_commitments; - - PrivateKernelInputsOrdering private_inputs{ .previous_kernel = previous_kernel }; - - DummyBuilder builder = DummyBuilder( - "native_private_kernel_ordering_tests__native_empty_nullified_commitment_means_persistent_nullifier_1"); - auto public_inputs = native_private_kernel_circuit_ordering(builder, private_inputs); - - ASSERT_FALSE(builder.failed()) << "failure: " << builder.get_first_failure(); - ASSERT_TRUE(array_length(public_inputs.end.new_commitments) == 0); - // nullifier present at output (will become persistent) - ASSERT_TRUE(array_length(public_inputs.end.new_nullifiers) == 1); -} - -TEST_F(native_private_kernel_ordering_tests, 0th_nullifier_zero_fails) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array new_nullifiers{}; - auto& previous_kernel = private_inputs_inner.previous_kernel; - previous_kernel.public_inputs.end.new_nullifiers = new_nullifiers; - PrivateKernelInputsOrdering private_inputs{ .previous_kernel = previous_kernel }; - - DummyBuilder builder = DummyBuilder("native_private_kernel_ordering_tests__0th_nullifier_zero_fails"); - auto public_inputs = native_private_kernel_circuit_ordering(builder, private_inputs); - - ASSERT_TRUE(builder.failed()); - auto failure = builder.get_first_failure(); - ASSERT_EQ(failure.code, CircuitErrorCode::PRIVATE_KERNEL__0TH_NULLIFIER_IS_ZERO); -} - -TEST_F(native_private_kernel_ordering_tests, input_validation_malformed_end_arrays_read_requests) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_read_requests{ fr(0), fr(9123), fr(0), fr(12) }; - auto& previous_kernel = private_inputs_inner.previous_kernel; - previous_kernel.public_inputs.end.read_requests = malformed_read_requests; - PrivateKernelInputsOrdering private_inputs{ .previous_kernel = previous_kernel }; - - DummyBuilder builder = - DummyBuilder("native_private_kernel_ordering_tests__input_validation_malformed_end_arrays_read_requests"); - native_private_kernel_circuit_ordering(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_ordering_tests, input_validation_malformed_end_arrays_commitments) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_commitments{ fr(0), fr(9123) }; - auto& previous_kernel = private_inputs_inner.previous_kernel; - previous_kernel.public_inputs.end.new_commitments = malformed_commitments; - PrivateKernelInputsOrdering private_inputs{ .previous_kernel = previous_kernel }; - - DummyBuilder builder = - DummyBuilder("native_private_kernel_ordering_tests__input_validation_malformed_end_arrays_commitments"); - native_private_kernel_circuit_ordering(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_ordering_tests, input_validation_malformed_end_arrays_nullifiers) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_nullifiers{}; - malformed_nullifiers[MAX_NEW_NULLIFIERS_PER_TX - 1] = fr(12); - auto& previous_kernel = private_inputs_inner.previous_kernel; - previous_kernel.public_inputs.end.new_nullifiers = malformed_nullifiers; - PrivateKernelInputsOrdering private_inputs{ .previous_kernel = previous_kernel }; - - DummyBuilder builder = - DummyBuilder("native_private_kernel_ordering_tests__input_validation_malformed_end_arrays_nullifiers"); - native_private_kernel_circuit_ordering(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_ordering_tests, input_validation_malformed_end_arrays_nullified_commitments) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_nullified_commitments{ fr(0), - fr(0), - EMPTY_NULLIFIED_COMMITMENT }; - auto& previous_kernel = private_inputs_inner.previous_kernel; - previous_kernel.public_inputs.end.nullified_commitments = malformed_nullified_commitments; - PrivateKernelInputsOrdering private_inputs{ .previous_kernel = previous_kernel }; - - DummyBuilder builder = DummyBuilder( - "native_private_kernel_ordering_tests__input_validation_malformed_end_arrays_nullified_commitments"); - native_private_kernel_circuit_ordering(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_ordering_tests, input_validation_malformed_end_arrays_private_call_stack) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_private_call_stack{ fr(0), fr(888) }; - auto& previous_kernel = private_inputs_inner.previous_kernel; - previous_kernel.public_inputs.end.private_call_stack = malformed_private_call_stack; - PrivateKernelInputsOrdering private_inputs{ .previous_kernel = previous_kernel }; - - DummyBuilder builder = - DummyBuilder("native_private_kernel_ordering_tests__input_validation_malformed_end_arrays_private_call_stack"); - native_private_kernel_circuit_ordering(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_ordering_tests, input_validation_malformed_end_arrays_public_call_stack) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_public_call_stack{ fr(0), fr(888) }; - auto& previous_kernel = private_inputs_inner.previous_kernel; - previous_kernel.public_inputs.end.public_call_stack = malformed_public_call_stack; - PrivateKernelInputsOrdering private_inputs{ .previous_kernel = previous_kernel }; - - DummyBuilder builder = - DummyBuilder("native_private_kernel_ordering_tests__input_validation_malformed_end_arrays_public_call_stack"); - native_private_kernel_circuit_ordering(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -TEST_F(native_private_kernel_ordering_tests, input_validation_malformed_end_arrays_l2_to_l1_msgs) -{ - auto private_inputs_inner = do_private_call_get_kernel_inputs_inner(false, deposit, standard_test_args()); - - std::array malformed_l2_to_l1_msgs{}; - malformed_l2_to_l1_msgs[MAX_NEW_L2_TO_L1_MSGS_PER_TX - 1] = fr(1); - auto& previous_kernel = private_inputs_inner.previous_kernel; - previous_kernel.public_inputs.end.new_l2_to_l1_msgs = malformed_l2_to_l1_msgs; - PrivateKernelInputsOrdering private_inputs{ .previous_kernel = previous_kernel }; - - DummyBuilder builder = - DummyBuilder("native_private_kernel_ordering_tests__input_validation_malformed_end_arrays_l2_to_l1_msgs"); - native_private_kernel_circuit_ordering(builder, private_inputs); - - EXPECT_EQ(builder.failed(), true); - EXPECT_EQ(builder.get_first_failure().code, CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -} - -} // namespace aztec3::circuits::kernel::private_kernel diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/private_kernel_circuit.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/private_kernel_circuit.cpp deleted file mode 100644 index c5586701a2b..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/private_kernel_circuit.cpp +++ /dev/null @@ -1,343 +0,0 @@ -#include "init.hpp" - -#include "aztec3/circuits/abis/complete_address.hpp" -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/new_contract_data.hpp" -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_inner.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/constants.hpp" - -#include - -namespace aztec3::circuits::kernel::private_kernel { - -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using aztec3::circuits::abis::NewContractData; -using aztec3::circuits::abis::private_kernel::PrivateKernelInputsInner; - -using plonk::stdlib::array_length; -using plonk::stdlib::array_pop; -using plonk::stdlib::array_push; -using plonk::stdlib::is_array_empty; -using plonk::stdlib::push_array_to_array; - -using aztec3::circuits::compute_constructor_hash; -using aztec3::circuits::silo_commitment; -using aztec3::circuits::silo_nullifier; - -// TODO: NEED TO RECONCILE THE `proof`'s public inputs (which are uint8's) with the -// private_call.call_stack_item.public_inputs! -CT::AggregationObject verify_proofs(Builder& builder, PrivateKernelInputsInner const& private_inputs) -{ - // compute P0, P1 for private function proof - CT::AggregationObject aggregation_object = - Aggregator::aggregate(&builder, private_inputs.private_call.vk, private_inputs.private_call.proof); - - // computes P0, P1 for previous kernel proof - // AND accumulates all of it in P0_agg, P1_agg - Aggregator::aggregate( - &builder, private_inputs.previous_kernel.vk, private_inputs.previous_kernel.proof, aggregation_object); - - return aggregation_object; -} - -/** - * @brief fill in the initial `end` (AccumulatedData) values by copying - * contents from the previous iteration of this kernel. - * - * @param private_inputs contains the information from the previous kernel iteration - * as well as signed TX request and the private call information - * @param public_inputs should be empty here since it is being initialized in this call - */ -void initialize_end_values(PrivateKernelInputsInner const& private_inputs, - KernelCircuitPublicInputs& public_inputs) -{ - // TODO: Ensure public inputs is empty here - public_inputs.constants = private_inputs.previous_kernel.public_inputs.constants; - - // Ensure the arrays are the same as previously, before we start pushing more data onto them in other functions - // within this circuit: - auto& end = public_inputs.end; - const auto& start = private_inputs.previous_kernel.public_inputs.end; - - // TODO - // end.aggregation_object = start.aggregation_object; - - end.new_commitments = start.new_commitments; - end.new_nullifiers = start.new_nullifiers; - - end.private_call_stack = start.private_call_stack; - end.public_call_stack = start.public_call_stack; - end.new_l2_to_l1_msgs = start.new_l2_to_l1_msgs; - - // TODO - end.new_contracts = start.new_contracts; - - end.optionally_revealed_data = start.optionally_revealed_data; -} - -/** - * @brief Update the AccumulatedData with new commitments, nullifiers, contracts, etc - * and update its running callstack with all items in the current private-circuit/function's - * callstack. - */ -void update_end_values(PrivateKernelInputsInner const& private_inputs, KernelCircuitPublicInputs& public_inputs) -{ - const auto private_call_public_inputs = private_inputs.private_call.call_stack_item.public_inputs; - - // TODO: private call count - const auto& new_commitments = private_call_public_inputs.new_commitments; - const auto& new_nullifiers = private_call_public_inputs.new_nullifiers; - - const auto& is_static_call = private_call_public_inputs.call_context.is_static_call; - - // No state changes are allowed for static calls: - is_static_call.must_imply(is_array_empty(new_commitments) == true); - is_static_call.must_imply(is_array_empty(new_nullifiers) == true); - - // TODO: name change (just contract_address) - const auto& storage_contract_address = private_call_public_inputs.call_context.storage_contract_address; - const auto& portal_contract_address = private_inputs.private_call.portal_contract_address; - const auto& contract_deployment_data = private_call_public_inputs.contract_deployment_data; - - { // contract deployment - // input storage contract address must be 0 if its a constructor call and non-zero otherwise - auto is_contract_deployment = public_inputs.constants.tx_context.is_contract_deployment_tx; - - auto private_call_vk_hash = private_inputs.private_call.vk->hash(); - auto constructor_hash = compute_constructor_hash(private_inputs.private_call.call_stack_item.function_data, - private_call_public_inputs.args_hash, - private_call_vk_hash); - - is_contract_deployment.must_imply(contract_deployment_data.constructor_vk_hash == private_call_vk_hash, - "constructor_vk_hash does not match private call vk hash"); - - // compute the contract address (only valid if this is a contract deployment) - auto const contract_address = abis::CompleteAddress::compute(contract_deployment_data.deployer_public_key, - contract_deployment_data.contract_address_salt, - contract_deployment_data.function_tree_root, - constructor_hash) - .address; - - // must imply == derived address - is_contract_deployment.must_imply( - storage_contract_address == contract_address, - "storage_contract_address must match derived address for contract deployment"); - - // non-contract deployments must specify contract address being interacted with - (!is_contract_deployment) - .must_imply(storage_contract_address != CT::fr(0), - "storage_contract_address must be nonzero for a private function"); - - // compute contract address nullifier - auto blake_input = CT::byte_array(contract_address.to_field()); - auto contract_address_nullifier = CT::fr(CT::blake2s(blake_input)); - - // push the contract address nullifier to nullifier vector - CT::fr const conditional_contract_address_nullifier = - CT::fr::conditional_assign(is_contract_deployment, contract_address_nullifier, CT::fr(0)); - array_push(public_inputs.end.new_nullifiers, conditional_contract_address_nullifier); - - // Add new contract data if its a contract deployment function - auto const new_contract_data = NewContractData{ - .contract_address = contract_address, - .portal_contract_address = portal_contract_address, - .function_tree_root = contract_deployment_data.function_tree_root, - }; - - array_push, MAX_NEW_CONTRACTS_PER_TX>(public_inputs.end.new_contracts, - new_contract_data); - } - - { // commitments, nullifiers, and contracts - std::array siloed_new_commitments; - for (size_t i = 0; i < new_commitments.size(); ++i) { - siloed_new_commitments[i] = CT::fr::conditional_assign( - new_commitments[i] == 0, 0, silo_commitment(storage_contract_address, new_commitments[i])); - } - std::array siloed_new_nullifiers; - for (size_t i = 0; i < new_nullifiers.size(); ++i) { - siloed_new_nullifiers[i] = CT::fr::conditional_assign( - new_nullifiers[i] == 0, 0, silo_nullifier(storage_contract_address, new_nullifiers[i])); - } - - // Add new commitments/etc to AggregatedData - push_array_to_array(siloed_new_commitments, public_inputs.end.new_commitments); - push_array_to_array(siloed_new_nullifiers, public_inputs.end.new_nullifiers); - } - - { // call stacks - // copy the private function circuit's callstack into the AggregatedData - const auto& this_private_call_stack = private_call_public_inputs.private_call_stack; - push_array_to_array(this_private_call_stack, public_inputs.end.private_call_stack); - } - - // { - // const auto& new_l2_to_l1_msgs = private_call_public_inputs.new_l2_to_l1_msgs; - // std::array l1_call_stack; - - // for (size_t i = 0; i < new_l2_to_l1_msgs.size(); ++i) { - // l1_call_stack[i] = CT::fr::conditional_assign( - // new_l2_to_l1_msgs[i] == 0, - // 0, - // CT::hash({ portal_contract_address, new_l2_to_l1_msgs[i] }, GeneratorIndex::L2_TO_L1_MSG)); - // } - // } -} - -/** - * @brief Ensure that the function/call-stack-item currently being processed by the kernel - * matches the one that the previous kernel iteration said should come next. - */ -void validate_this_private_call_hash(PrivateKernelInputsInner const& private_inputs) -{ - const auto& start = private_inputs.previous_kernel.public_inputs.end; - // TODO: this logic might need to change to accommodate the weird edge 3 initial txs (the 'main' tx, the 'fee' tx, - // and the 'gas rebate' tx). - const auto this_private_call_hash = array_pop(start.private_call_stack); - const auto calculated_this_private_call_hash = private_inputs.private_call.call_stack_item.hash(); - - this_private_call_hash.assert_equal(calculated_this_private_call_hash, "this private_call_hash does not reconcile"); -}; - -/** - * @brief Ensure that the callstack inputs are consistent. - * - * @details The private function circuit will output a callstack containing just hashes - * of CallStackItems, but the kernel circuit also needs the actual item preimages. - * So here we just ensure that the callstack preimages in the kernel's private inputs - * matches the function's CallStackItem hashes. - */ -void validate_this_private_call_stack(PrivateKernelInputsInner const& private_inputs) -{ - const auto& stack = private_inputs.private_call.call_stack_item.public_inputs.private_call_stack; - const auto& preimages = private_inputs.private_call.private_call_stack_preimages; - for (size_t i = 0; i < stack.size(); ++i) { - const auto& hash = stack[i]; - const auto& preimage = preimages[i]; - - // Note: this assumes it's computationally infeasible to have `0` as a valid call_stack_item_hash. - // Assumes `hash == 0` means "this stack item is empty". - const auto calculated_hash = CT::fr::conditional_assign(hash == 0, 0, preimage.hash()); - - hash.assert_equal(calculated_hash, format("private_call_stack[", i, "] = ", hash, "; does not reconcile")); - } -}; - -void validate_inputs(PrivateKernelInputsInner const& private_inputs, bool first_iteration) -{ - // this callstack represents the function currently being processed - const auto& this_call_stack_item = private_inputs.private_call.call_stack_item; - - this_call_stack_item.function_data.is_private.assert_equal( - true, "Cannot execute a non-private function with the private kernel circuit"); - - const auto& start = private_inputs.previous_kernel.public_inputs.end; - - // base case: have not processed any functions yet - const CT::boolean is_base_case(first_iteration); - - // TODO: we might want to range-constrain the call_count to prevent some kind of overflow errors - const CT::boolean is_recursive_case = !is_base_case; - - // Grab stack lengths as output from the previous kernel iteration - // These lengths are calculated by counting entries until a non-zero one is encountered - // True array length is constant which is a property we need for circuit inputs, - // but we want to know "length" in terms of how many nonzero entries have been inserted - CT::fr const start_private_call_stack_length = array_length(start.private_call_stack); - CT::fr const start_public_call_stack_length = array_length(start.public_call_stack); - CT::fr const start_new_l2_to_l1_msgs_length = array_length(start.new_l2_to_l1_msgs); - - // Recall: we can't do traditional `if` statements in a circuit; all code paths are always executed. The below is - // some syntactic sugar, which seeks readability similar to an `if` statement. - - // Base Case - std::vector> const base_case_conditions{ - // TODO: change to allow 3 initial calls on the private call stack, so a fee can be paid and a gas - // rebate can be paid. - { start_private_call_stack_length == 1, "Private call stack must be length 1" }, - { start_public_call_stack_length == 0, "Public call stack must be empty" }, - { start_new_l2_to_l1_msgs_length == 0, "L2 to L1 msgs must be empty" }, - - { this_call_stack_item.public_inputs.call_context.is_delegate_call == false, - "Users cannot make a delegatecall" }, - { this_call_stack_item.public_inputs.call_context.is_static_call == false, "Users cannot make a static call" }, - - // The below also prevents delegatecall/staticcall in the base case - { this_call_stack_item.public_inputs.call_context.storage_contract_address == - this_call_stack_item.contract_address, - "Storage contract address must be that of the called contract" }, - - { private_inputs.previous_kernel.vk->contains_recursive_proof == false, - "Mock kernel proof must not contain a recursive proof" } - - // TODO: Assert that the previous kernel data is empty. (Or rather, the verify_proof() function needs a valid - // dummy proof and vk to complete execution, so actually what we want is for that mockvk to be - // hard-coded into the circuit and assert that that is the one which has been used in the base case). - // kernel VK tree contains 16 VKs that would be used to verify kernel proofs depending on the - // number of public inputs each of them spits out. - // TODO (later): merkle membership check that the vk from the previous data is present at leaf 0. - - // TODO: verify signed tx request against current function being called - }; - is_base_case.must_imply(base_case_conditions); - - // Recursive Case - std::vector> const recursive_case_conditions{ - { private_inputs.previous_kernel.public_inputs.is_private == true, - "Cannot verify a non-private kernel snark in the private kernel circuit" }, - { this_call_stack_item.function_data.is_constructor == false, - "A constructor must be executed as the first tx in the recursion" }, - { start_private_call_stack_length != 0, - "Cannot execute private kernel circuit with an empty private call stack" } - // TODO (later): assert that previous kernel VK matches VK for this input size - // TODO (later): membership proof of VK - }; - is_recursive_case.must_imply(recursive_case_conditions); - - // validate constructor hash - // generate contract address - // generate contract address nullifier and add to list - // create new contract data and add to list - // MAYBE: check other contract deployment data: - // function tree, contracts root -} - -// NOTE: THIS IS A VERY UNFINISHED WORK IN PROGRESS. -// TODO: decide what to return. -// TODO: is there a way to identify whether an input has not been used by ths circuit? This would help us more-safely -// ensure we're constraining everything. -KernelCircuitPublicInputs private_kernel_circuit(Builder& builder, - PrivateKernelInputsInner const& _private_inputs, - bool first_iteration) -{ - const PrivateKernelInputsInner private_inputs = _private_inputs.to_circuit_type(builder); - - // We'll be pushing data to this during execution of this circuit. - KernelCircuitPublicInputs public_inputs = KernelCircuitPublicInputs{}.to_circuit_type(builder); - - // Do this before any functions can modify the inputs. - initialize_end_values(private_inputs, public_inputs); - - validate_inputs(private_inputs, first_iteration); - - validate_this_private_call_hash(private_inputs); - - validate_this_private_call_stack(private_inputs); - - // TODO (later): do we need to validate this private_call_stack against end.private_call_stack? - - update_end_values(private_inputs, public_inputs); - - auto aggregation_object = verify_proofs(builder, private_inputs); - - // TODO: kernel vk membership check! - - public_inputs.end.aggregation_object = aggregation_object; - - public_inputs.set_public(); - - return public_inputs.to_native_type(); -}; - -} // namespace aztec3::circuits::kernel::private_kernel diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/private_kernel_circuit.hpp b/circuits/cpp/src/aztec3/circuits/kernel/private/private_kernel_circuit.hpp deleted file mode 100644 index 17d10d4561a..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/private_kernel_circuit.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "init.hpp" - -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_inner.hpp" - -namespace aztec3::circuits::kernel::private_kernel { - -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using aztec3::circuits::abis::private_kernel::PrivateKernelInputsInner; - -KernelCircuitPublicInputs private_kernel_circuit(Builder& builder, - PrivateKernelInputsInner const& private_inputs, - bool first_iteration); - -} // namespace aztec3::circuits::kernel::private_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/testing_harness.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/testing_harness.cpp deleted file mode 100644 index f068662a3e5..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/testing_harness.cpp +++ /dev/null @@ -1,555 +0,0 @@ -#include "testing_harness.hpp" - -#include "index.hpp" -#include "init.hpp" - -#include "aztec3/circuits/abis/block_header.hpp" -#include "aztec3/circuits/abis/call_context.hpp" -#include "aztec3/circuits/abis/call_stack_item.hpp" -#include "aztec3/circuits/abis/combined_accumulated_data.hpp" -#include "aztec3/circuits/abis/combined_constant_data.hpp" -#include "aztec3/circuits/abis/complete_address.hpp" -#include "aztec3/circuits/abis/contract_deployment_data.hpp" -#include "aztec3/circuits/abis/function_data.hpp" -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/private_kernel/private_call_data.hpp" -#include "aztec3/circuits/abis/tx_context.hpp" -#include "aztec3/circuits/abis/tx_request.hpp" -#include "aztec3/circuits/abis/types.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/circuits/kernel/private/utils.hpp" -#include "aztec3/constants.hpp" - -#include - -#include -#include -#include - -namespace aztec3::circuits::kernel::private_kernel::testing_harness { - -using aztec3::circuits::abis::BlockHeader; -using aztec3::circuits::abis::CallContext; -using aztec3::circuits::abis::CallStackItem; -using aztec3::circuits::abis::CombinedAccumulatedData; -using aztec3::circuits::abis::CombinedConstantData; -using aztec3::circuits::abis::ContractDeploymentData; -using aztec3::circuits::abis::FunctionData; -using aztec3::circuits::abis::PrivateCircuitPublicInputs; -using aztec3::circuits::abis::PrivateTypes; -using aztec3::circuits::abis::TxContext; -using aztec3::circuits::abis::TxRequest; -using aztec3::circuits::abis::private_kernel::PrivateCallData; - -using aztec3::utils::array_length; - -/** - * @brief Get the random read requests and their membership requests - * - * @details read requests are siloed by contract address and nonce before being - * inserted into mock note hash tree - * - * @param first_nullifier used when computing nonce for unique_siloed_commitments (note hash tree leaves) - * @param contract_address address to use when siloing read requests - * @param num_read_requests if negative, use random num. Must be < MAX_READ_REQUESTS_PER_CALL - * @return std::tuple - */ -std::tuple, - std::array, MAX_READ_REQUESTS_PER_CALL>, - std::array, - std::array, MAX_READ_REQUESTS_PER_CALL>, - NT::fr> -get_random_reads(NT::fr const& first_nullifier, NT::fr const& contract_address, int const num_read_requests) -{ - std::array transient_read_requests{}; - std::array read_requests{}; - std::array leaves{}; - - // randomize the number of read requests with a configurable minimum - const auto final_num_rr = num_read_requests >= 0 - ? std::min(static_cast(num_read_requests), MAX_READ_REQUESTS_PER_CALL) - : numeric::random::get_engine().get_random_uint8() % (MAX_READ_REQUESTS_PER_CALL + 1); - // randomize private app circuit's read requests - for (size_t rr = 0; rr < final_num_rr; rr++) { - // randomize commitment and its leaf index - // transient read requests are raw (not siloed and not unique at input to kernel circuit) - transient_read_requests[rr] = NT::fr::random_element(); - - const auto siloed_commitment = silo_commitment(contract_address, read_requests[rr]); - const auto nonce = compute_commitment_nonce(first_nullifier, rr); - const auto unique_siloed_commitment = - siloed_commitment == 0 ? 0 : compute_unique_commitment(nonce, siloed_commitment); - - leaves[rr] = unique_siloed_commitment; - read_requests[rr] = unique_siloed_commitment; - } - - // this set and the following loop lets us generate totally random leaf indices - // for read requests while avoiding collisions - std::unordered_set rr_leaf_indices_set; - while (rr_leaf_indices_set.size() < final_num_rr) { - rr_leaf_indices_set.insert(numeric::random::get_engine().get_random_uint32() % NOTE_HASH_TREE_NUM_LEAVES); - } - // set -> vector without collisions - std::vector rr_leaf_indices(rr_leaf_indices_set.begin(), rr_leaf_indices_set.end()); - - MemoryStore note_hash_tree_store; - MerkleTree note_hash_tree = MerkleTree(note_hash_tree_store, NOTE_HASH_TREE_HEIGHT); - - // add the commitments to the note hash tree for each read request - // add them at their corresponding index in the tree - // (in practice the the tree is left-to-right append-only, but here - // we treat it as sparse just to get these commitments in their correct spot) - for (size_t i = 0; i < array_length(leaves); i++) { - note_hash_tree.update_element(rr_leaf_indices[i], leaves[i]); - } - - // compute the merkle sibling paths for each request - std::array, MAX_READ_REQUESTS_PER_CALL> - transient_read_request_membership_witnesses{}; - std::array, MAX_READ_REQUESTS_PER_CALL> - read_request_membership_witnesses{}; - for (size_t i = 0; i < array_length(read_requests); i++) { - read_request_membership_witnesses[i] = { .leaf_index = NT::fr(rr_leaf_indices[i]), - .sibling_path = get_sibling_path( - note_hash_tree, rr_leaf_indices[i], 0), - .is_transient = false, - .hint_to_commitment = 0 }; - transient_read_request_membership_witnesses[i] = { .leaf_index = NT::fr(0), - .sibling_path = - compute_empty_sibling_path(0), - .is_transient = true, - .hint_to_commitment = 0 }; - } - - - return { read_requests, - read_request_membership_witnesses, - transient_read_requests, - transient_read_request_membership_witnesses, - note_hash_tree.root() }; -} // namespace aztec3::circuits::kernel::private_kernel::testing_harness - -std::pair, ContractDeploymentData> create_private_call_deploy_data( - bool const is_constructor, - private_function const& func, - std::vector const& args_vec, - NT::address const& msg_sender, - std::array const& encrypted_logs_hash, - std::array const& unencrypted_logs_hash, - NT::fr const& encrypted_log_preimages_length, - NT::fr const& unencrypted_log_preimages_length, - bool is_circuit) -{ - //*************************************************************************** - // Initialize some inputs to private call and kernel circuits - //*************************************************************************** - // TODO(suyash) randomize inputs - NT::address contract_address = is_constructor ? 0 : 12345; // updated later if in constructor - const NT::uint32 contract_leaf_index = 1; - const NT::uint32 function_leaf_index = 1; - const NT::fr portal_contract_address = 23456; - const NT::fr contract_address_salt = 34567; - const NT::fr acir_hash = 12341234; - - const NT::fr msg_sender_private_key = 123456789; - const Point msg_sender_pub_key = { .x = 123456789, .y = 123456789 }; - - FunctionData const function_data{ - .selector = - { - .value = 1, // TODO: deduce this from the contract, somehow. - }, - .is_private = true, - .is_constructor = is_constructor, - }; - - CallContext call_context{ - .msg_sender = msg_sender, - .storage_contract_address = contract_address, - .portal_contract_address = portal_contract_address, - .function_selector = function_data.selector, - .is_delegate_call = false, - .is_static_call = false, - .is_contract_deployment = is_constructor, - }; - - // sometimes need private call args as array - std::array args{}; - for (size_t i = 0; i < args_vec.size(); ++i) { - args[i] = args_vec[i]; - } - const NT::fr args_hash = compute_var_args_hash(args_vec); - - //*************************************************************************** - // Initialize contract related information like private call VK (and its hash), - // function tree, contract tree, contract address for newly deployed contract, - // etc... - //*************************************************************************** - - // generate private circuit VK and its hash using circuit with dummy inputs - // it is needed below: - // for constructors - to generate the contract address, function leaf, etc - // for private calls - to generate the function leaf, etc - auto const private_circuit_vk = is_circuit ? utils::get_verification_key_from_file() : utils::fake_vk(); - - // TODO(#3062) VKs are mocked out for now - // const NT::fr private_circuit_vk_hash = - // stdlib::recursion::verification_key::hash_native(private_circuit_vk); - const NT::fr private_circuit_vk_hash = 0; - - ContractDeploymentData contract_deployment_data{}; - NT::fr contract_tree_root = 0; // TODO(david) set properly for constructor? - if (is_constructor) { - // TODO(david) compute function tree root from leaves - // create leaf preimage for each function and hash all into tree - // push to array/vector - // use variation of `compute_root_partial_left_tree` to compute the root from leaves - // const auto& function_leaf_preimage = FunctionLeafPreimage{ - // .selector = function_data.selector, - // .is_private = function_data.is_private, - // .vk_hash = private_circuit_vk_hash, - // .acir_hash = acir_hash, - //}; - std::vector const function_leaves(MAX_FUNCTION_LEAVES, EMPTY_FUNCTION_LEAF()); - // const NT::fr& function_tree_root = plonk::stdlib::merkle_tree::compute_tree_root_native(function_leaves); - - // TODO(david) use actual function tree root computed from leaves - // update cdd with actual info - contract_deployment_data = { - .deployer_public_key = msg_sender_pub_key, - .constructor_vk_hash = private_circuit_vk_hash, - .function_tree_root = plonk::stdlib::merkle_tree::compute_tree_root_native(function_leaves), - .contract_address_salt = contract_address_salt, - .portal_contract_address = portal_contract_address, - }; - - // Get constructor hash for use when deriving contract address - auto constructor_hash = compute_constructor_hash(function_data, args_hash, private_circuit_vk_hash); - - // Derive contract address so that it can be used inside the constructor itself - contract_address = abis::CompleteAddress::compute(msg_sender_pub_key, - contract_address_salt, - contract_deployment_data.function_tree_root, - constructor_hash) - .address; - // update the contract address in the call context now that it is known - call_context.storage_contract_address = contract_address; - } else { - const NT::fr& function_tree_root = function_tree_root_from_siblings(function_data.selector, - function_data.is_internal, - function_data.is_private, - private_circuit_vk_hash, - acir_hash, - function_leaf_index, - get_empty_function_siblings()); - - // update contract_tree_root with real value - contract_tree_root = contract_tree_root_from_siblings(function_tree_root, - contract_address, - portal_contract_address, - contract_leaf_index, - get_empty_contract_siblings()); - } - - /** - * If `is_circuit` is true, we are running a real circuit test and therefore we need to generate a real proof using - * a private function builder. For the native tests, we are using a random data as public inputs of the private - * function. As the native private kernel circuit doesn't validate any proofs and we don't currently test - * multi-iterative kernel circuit, this should be fine. - */ - PrivateCircuitPublicInputs private_circuit_public_inputs; - const NT::Proof private_circuit_proof = utils::get_proof_from_file(); - if (is_circuit) { - //*************************************************************************** - // Create a private circuit/call using builder, oracles, execution context - // Generate its proof and public inputs for submission with a TX request - //*************************************************************************** - Builder private_circuit_builder = Builder(); - - DB dummy_db; - NativeOracle oracle = - is_constructor - ? NativeOracle(dummy_db, - contract_address, - function_data, - call_context, - contract_deployment_data, - msg_sender_private_key) - : NativeOracle(dummy_db, contract_address, function_data, call_context, msg_sender_private_key); - - OracleWrapper oracle_wrapper = OracleWrapper(private_circuit_builder, oracle); - - FunctionExecutionContext ctx(private_circuit_builder, oracle_wrapper); - - OptionalPrivateCircuitPublicInputs const opt_private_circuit_public_inputs = func(ctx, args_vec); - private_circuit_public_inputs = opt_private_circuit_public_inputs.remove_optionality(); - // TODO(suyash): this should likely be handled as part of the DB/Oracle/Context infrastructure - private_circuit_public_inputs.block_header.contract_tree_root = contract_tree_root; - - private_circuit_public_inputs.encrypted_logs_hash = encrypted_logs_hash; - private_circuit_public_inputs.unencrypted_logs_hash = unencrypted_logs_hash; - private_circuit_public_inputs.encrypted_log_preimages_length = encrypted_log_preimages_length; - private_circuit_public_inputs.unencrypted_log_preimages_length = unencrypted_log_preimages_length; - } else { - private_circuit_public_inputs = PrivateCircuitPublicInputs{ - .call_context = call_context, - .args_hash = args_hash, - .return_values = {}, - .new_commitments = { NT::fr::random_element() }, // One random commitment - .new_nullifiers = { NT::fr::random_element() }, // One random nullifier - .nullified_commitments = {}, - .private_call_stack = {}, - .new_l2_to_l1_msgs = {}, - .encrypted_logs_hash = encrypted_logs_hash, - .unencrypted_logs_hash = unencrypted_logs_hash, - .encrypted_log_preimages_length = encrypted_log_preimages_length, - .unencrypted_log_preimages_length = unencrypted_log_preimages_length, - .block_header = BlockHeader{ .contract_tree_root = contract_tree_root }, - .contract_deployment_data = contract_deployment_data, - }; - } - - const CallStackItem call_stack_item{ - .contract_address = contract_address, - .function_data = function_data, - .public_inputs = private_circuit_public_inputs, - }; - - //*************************************************************************** - // Now we can construct the full private inputs to the kernel circuit - //*************************************************************************** - - return std::pair, ContractDeploymentData>( - PrivateCallData{ - .call_stack_item = call_stack_item, - // TODO(dbanks12): these tests do not test multiple kernel iterations - // and do not test non-empty callstacks. They should! To have such tests - // we will need to populate these callstackitem preimages - // and ensure they match the hashed callstackitems themselves. - //.private_call_stack_preimages = , - - .proof = private_circuit_proof, - .vk = private_circuit_vk, - - .function_leaf_membership_witness = { - .leaf_index = function_leaf_index, - .sibling_path = get_empty_function_siblings(), - }, - - .contract_leaf_membership_witness = { - .leaf_index = contract_leaf_index, - .sibling_path = get_empty_contract_siblings(), - }, - - .portal_contract_address = portal_contract_address, - - .acir_hash = acir_hash - }, - contract_deployment_data); -} - -/** - * @brief Perform an initial private circuit call and generate the inputs to private kernel - * - * @param is_constructor whether this private circuit call is a constructor - * @param func the private circuit call being validated by this kernel iteration - * @param args_vec the private call's args - * @param encrypted_logs_hash The encrypted logs hash emitted from app circuit. - * @param unencrypted_logs_hash The unencrypted logs hash emitted from app circuit. - * @param encrypted_log_preimages_length The length of encrypted logs emitted from app circuit. - * @param unencrypted_log_preimages_length The length of unencrypted logs emitted from app circuit. - * @param is_circuit boolean to switch to circuit or native (fake vk and no proof) - * @return PrivateInputsInit - the inputs to the private call circuit of an init iteration - */ -PrivateKernelInputsInit do_private_call_get_kernel_inputs_init( - bool const is_constructor, - private_function const& func, - std::vector const& args_vec, - std::array const& encrypted_logs_hash, - std::array const& unencrypted_logs_hash, - NT::fr const& encrypted_log_preimages_length, - NT::fr const& unencrypted_log_preimages_length, - bool is_circuit) -{ - //*************************************************************************** - // Initialize some inputs to private call and kernel circuits - //*************************************************************************** - // TODO(suyash) randomize inputs - - const NT::address msg_sender = - NT::fr(uint256_t(0x01071e9a23e0f7edULL, 0x5d77b35d1830fa3eULL, 0xc6ba3660bb1f0c0bULL, 0x2ef9f7f09867fd6eULL)); - - auto const& [private_call_data, contract_deployment_data] = - create_private_call_deploy_data(is_constructor, - func, - args_vec, - msg_sender, - encrypted_logs_hash, - unencrypted_logs_hash, - encrypted_log_preimages_length, - unencrypted_log_preimages_length, - is_circuit); - - //*************************************************************************** - // We can create a TxRequest from some of the above data. - //*************************************************************************** - auto const tx_request = TxRequest{ .origin = private_call_data.call_stack_item.contract_address, - .function_data = private_call_data.call_stack_item.function_data, - .args_hash = compute_var_args_hash(args_vec), - .tx_context = TxContext{ - .is_fee_payment_tx = false, - .is_rebate_payment_tx = false, - .is_contract_deployment_tx = is_constructor, - .contract_deployment_data = contract_deployment_data, - .chain_id = 1, - } }; - - //*************************************************************************** - // Now we can construct the full private inputs to the kernel circuit - //*************************************************************************** - PrivateKernelInputsInit kernel_private_inputs = PrivateKernelInputsInit{ - .tx_request = tx_request, - .private_call = private_call_data, - }; - - return kernel_private_inputs; -} - - -/** - * @brief Perform an inner private circuit call and generate the inputs to private kernel - * - * @param is_constructor whether this private circuit call is a constructor - * @param func the private circuit call being validated by this kernel iteration - * @param args_vec the private call's args - * @param encrypted_logs_hash The encrypted logs hash emitted from app circuit. - * @param unencrypted_logs_hash The unencrypted logs hash emitted from app circuit. - * @param encrypted_log_preimages_length The length of encrypted logs emitted from app circuit. - * @param unencrypted_log_preimages_length The length of unencrypted logs emitted from app circuit. - * @param public_inputs_encrypted_logs_hash The encrypted logs hash on the output of the previous kernel. - * @param public_inputs_unencrypted_logs_hash The unencrypted logs hash on the output of the previous kernel. - * @param public_inputs_encrypted_log_preimages_length The length of encrypted logs on the output of the previous - * kernel. - * @param public_inputs_unencrypted_log_preimages_length The length of unencrypted logs on the output of the previous - * kernel. - * @param is_circuit boolean to switch to circuit or native (fake vk and no proof) - * @return PrivateInputsInner - the inputs to the private call circuit of an inner iteration - */ -PrivateKernelInputsInner do_private_call_get_kernel_inputs_inner( - bool const is_constructor, - private_function const& func, - std::vector const& args_vec, - std::array const& encrypted_logs_hash, - std::array const& unencrypted_logs_hash, - NT::fr const& encrypted_log_preimages_length, - NT::fr const& unencrypted_log_preimages_length, - std::array const& public_inputs_encrypted_logs_hash, - std::array const& public_inputs_unencrypted_logs_hash, - NT::fr const& public_inputs_encrypted_log_preimages_length, - NT::fr const& public_inputs_unencrypted_log_preimages_length, - bool is_circuit) -{ - //*************************************************************************** - // Initialize some inputs to private call and kernel circuits - //*************************************************************************** - // TODO(suyash) randomize inputs - - const NT::address msg_sender = - NT::fr(uint256_t(0x01071e9a23e0f7edULL, 0x5d77b35d1830fa3eULL, 0xc6ba3660bb1f0c0bULL, 0x2ef9f7f09867fd6eULL)); - - auto const& [private_call_data, contract_deployment_data] = - create_private_call_deploy_data(is_constructor, - func, - args_vec, - msg_sender, - encrypted_logs_hash, - unencrypted_logs_hash, - encrypted_log_preimages_length, - unencrypted_log_preimages_length, - is_circuit); - - const TxContext tx_context = TxContext{ - .is_fee_payment_tx = false, - .is_rebate_payment_tx = false, - .is_contract_deployment_tx = is_constructor, - .contract_deployment_data = contract_deployment_data, - }; - - //*************************************************************************** - // We mock a kernel circuit proof to initialize input required by an inner call - //*************************************************************************** - - std::array initial_kernel_private_call_stack{}; - initial_kernel_private_call_stack[0] = private_call_data.call_stack_item.hash(); - - auto const& private_circuit_public_inputs = private_call_data.call_stack_item.public_inputs; - // Get dummy previous kernel - auto mock_previous_kernel = utils::dummy_previous_kernel(is_circuit); - // Fill in some important fields in public inputs - mock_previous_kernel.public_inputs.end.private_call_stack = initial_kernel_private_call_stack; - mock_previous_kernel.public_inputs.constants = CombinedConstantData{ - .block_header = - BlockHeader{ - .note_hash_tree_root = private_circuit_public_inputs.block_header.note_hash_tree_root, - .contract_tree_root = private_circuit_public_inputs.block_header.contract_tree_root, - }, - .tx_context = tx_context, - }; - mock_previous_kernel.public_inputs.is_private = true; - mock_previous_kernel.public_inputs.end.encrypted_logs_hash = public_inputs_encrypted_logs_hash; - mock_previous_kernel.public_inputs.end.unencrypted_logs_hash = public_inputs_unencrypted_logs_hash; - mock_previous_kernel.public_inputs.end.encrypted_log_preimages_length = - public_inputs_encrypted_log_preimages_length; - mock_previous_kernel.public_inputs.end.unencrypted_log_preimages_length = - public_inputs_unencrypted_log_preimages_length; - mock_previous_kernel.public_inputs.end.new_nullifiers[0] = 321; // 0th nullifier must be non-zero. - mock_previous_kernel.public_inputs.end.nullified_commitments[0] = EMPTY_NULLIFIED_COMMITMENT; - - //*************************************************************************** - // Now we can construct the full private inputs to the kernel circuit - //*************************************************************************** - PrivateKernelInputsInner kernel_private_inputs = PrivateKernelInputsInner{ - .previous_kernel = mock_previous_kernel, - .private_call = private_call_data, - }; - - return kernel_private_inputs; -} - -/** - * @brief Validate that the deployed contract address is correct. - * - * @details Compare the public inputs new contract address - * with one manually computed from private inputs. - * @param private_inputs to be used in manual computation - * @param public_inputs that contain the expected new contract address - */ -bool validate_deployed_contract_address(PrivateKernelInputsInit const& private_inputs, - KernelCircuitPublicInputs const& public_inputs) -{ - auto tx_request = private_inputs.tx_request; - auto cdd = private_inputs.tx_request.tx_context.contract_deployment_data; - - // TODO(#3062) VKs are mocked out for now - // auto private_circuit_vk_hash = - // stdlib::recursion::verification_key::hash_native(private_inputs.private_call.vk); - auto private_circuit_vk_hash = 0; - - auto expected_constructor_hash = compute_constructor_hash( - private_inputs.private_call.call_stack_item.function_data, tx_request.args_hash, private_circuit_vk_hash); - - NT::fr const expected_contract_address = - abis::CompleteAddress::compute( - cdd.deployer_public_key, cdd.contract_address_salt, cdd.function_tree_root, expected_constructor_hash) - .address; - - return (public_inputs.end.new_contracts[0].contract_address.to_field() == expected_contract_address); -} - -bool validate_no_new_deployed_contract(KernelCircuitPublicInputs const& public_inputs) -{ - return (public_inputs.end.new_contracts == CombinedAccumulatedData{}.new_contracts); -} - -} // namespace aztec3::circuits::kernel::private_kernel::testing_harness diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/testing_harness.hpp b/circuits/cpp/src/aztec3/circuits/kernel/private/testing_harness.hpp deleted file mode 100644 index 8ed96456998..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/testing_harness.hpp +++ /dev/null @@ -1,200 +0,0 @@ -#include "index.hpp" -#include "init.hpp" - -#include "aztec3/circuits/abis/contract_deployment_data.hpp" -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/membership_witness.hpp" -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/private_kernel/private_call_data.hpp" -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_init.hpp" -#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_inner.hpp" -#include "aztec3/circuits/abis/read_request_membership_witness.hpp" -#include "aztec3/circuits/abis/tx_request.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/circuits/kernel/private/common.hpp" -#include "aztec3/circuits/kernel/private/utils.hpp" - -#include - -#include -#include - -namespace { - -using aztec3::circuits::compute_empty_sibling_path; -using aztec3::circuits::abis::ContractDeploymentData; -using aztec3::circuits::abis::FunctionLeafPreimage; -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using aztec3::circuits::abis::NewContractData; -using aztec3::circuits::abis::OptionalPrivateCircuitPublicInputs; -using aztec3::circuits::abis::ReadRequestMembershipWitness; -using aztec3::circuits::abis::TxRequest; -using aztec3::circuits::abis::private_kernel::PrivateCallData; -using aztec3::circuits::abis::private_kernel::PrivateKernelInputsInit; -using aztec3::circuits::abis::private_kernel::PrivateKernelInputsInner; - - -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; - -// A type representing any private circuit function -// (for now it works for deposit and constructor) -using private_function = std::function( - FunctionExecutionContext&, std::vector const&)>; - -} // namespace - -namespace aztec3::circuits::kernel::private_kernel::testing_harness { - -using aztec3::circuits::compute_empty_sibling_path; - -// Some helper constants for trees -constexpr size_t MAX_FUNCTION_LEAVES = 1 << aztec3::FUNCTION_TREE_HEIGHT; // 2^(height-1) -// NOTE: *DO NOT* call hashes in static initializers and assign them to constants. This will fail. Instead, use -// lazy initialization or functions. Lambdas were introduced here. -const auto EMPTY_FUNCTION_LEAF = [] { return FunctionLeafPreimage{}.hash(); }; // hash of empty/0 preimage -const auto EMPTY_CONTRACT_LEAF = [] { return NewContractData{}.hash(); }; // hash of empty/0 preimage -constexpr uint64_t NOTE_HASH_TREE_NUM_LEAVES = 1ULL << aztec3::NOTE_HASH_TREE_HEIGHT; // 2^(height-1) - -inline const auto& get_empty_function_siblings() -{ - static auto EMPTY_FUNCTION_SIBLINGS = []() { - const auto result = compute_empty_sibling_path(EMPTY_FUNCTION_LEAF()); - return result; - }(); - return EMPTY_FUNCTION_SIBLINGS; -} - -inline const auto& get_empty_contract_siblings() -{ - static auto EMPTY_CONTRACT_SIBLINGS = []() { - const auto result = compute_empty_sibling_path(EMPTY_CONTRACT_LEAF()); - return result; - }(); - return EMPTY_CONTRACT_SIBLINGS; -} - -/** - * @brief Get the random read requests and their membership requests - * - * @details read requests are siloed by contract address and nonce before being - * inserted into mock note hash tree - * - * @param first_nullifier used when computing nonce for unique_siloed_commitments (note hash tree leaves) - * @param contract_address address to use when siloing read requests - * @param num_read_requests if negative, use random num - * @return tuple including read requests, their membership witnesses, their transient versions, and the - * note hash tree root that contains all of these randomly created commitments at random leaf indices - * std::tuple< - * read_requests, - * read_request_memberships_witnesses, - * transient_read_requests, - * transient_read_request_memberships_witnesses, - * historical_note_hash_tree_root> - */ -std::tuple, - std::array, MAX_READ_REQUESTS_PER_CALL>, - std::array, - std::array, MAX_READ_REQUESTS_PER_CALL>, - NT::fr> -get_random_reads(NT::fr const& first_nullifier, NT::fr const& contract_address, int num_read_requests); - -/** - * @brief Create a private call deploy data object - * - * @param is_constructor Whether this private call is a constructor call - * @param func The private circuit (i.e. constructor in case of contract deployment) call - * @param args_vec Number of args to that private circuit call - * @param msg_sender The sender of the transaction request - * @return std::pair, ContractDeploymentData> - the generated private call data with the - * contract deployment data - */ -std::pair, ContractDeploymentData> create_private_call_deploy_data( - bool is_constructor, - private_function const& func, - std::vector const& args_vec, - NT::address const& msg_sender, - std::array const& encrypted_logs_hash, - NT::fr const& encrypted_log_preimages_length, - bool is_circuit = false); - -/** - * @brief Perform an inner private circuit call and generate the inputs to private kernel - * - * @param is_constructor whether this private circuit call is a constructor - * @param func the private circuit call being validated by this kernel iteration - * @param args_vec the private call's args - * @param encrypted_logs_hash The encrypted logs hash emitted from app circuit. - * @param unencrypted_logs_hash The unencrypted logs hash emitted from app circuit. - * @param encrypted_log_preimages_length The length of encrypted logs emitted from app circuit. - * @param unencrypted_log_preimages_length The length of unencrypted logs emitted from app circuit. - * @param public_inputs_encrypted_logs_hash The encrypted logs hash on the output of the previous kernel. - * @param public_inputs_unencrypted_logs_hash The unencrypted logs hash on the output of the previous kernel. - * @param public_inputs_encrypted_log_preimages_length The length of encrypted logs on the output of the previous - * kernel. - * @param public_inputs_unencrypted_log_preimages_length The length of unencrypted logs on the output of the previous - * kernel. - * @param is_circuit boolean to switch to circuit or native (fake vk and no proof) - * @return PrivateInputsInner - the inputs to the private call circuit of an inner iteration - */ -PrivateKernelInputsInner do_private_call_get_kernel_inputs_inner( - bool is_constructor, - private_function const& func, - std::vector const& args_vec, - std::array const& encrypted_logs_hash = std::array{}, - std::array const& unencrypted_logs_hash = - std::array{}, - NT::fr const& encrypted_log_preimages_length = NT::fr(0), - NT::fr const& unencrypted_log_preimages_length = NT::fr(0), - std::array const& public_inputs_encrypted_logs_hash = - std::array{}, - std::array const& public_inputs_unencrypted_logs_hash = - std::array{}, - NT::fr const& public_inputs_encrypted_log_preimages_length = NT::fr(0), - NT::fr const& public_inputs_unencrypted_log_preimages_length = NT::fr(0), - bool is_circuit = false); - -/** - * @brief Perform an initial private circuit call and generate the inputs to private kernel - * - * @param is_constructor whether this private circuit call is a constructor - * @param func the private circuit call being validated by this kernel iteration - * @param args_vec the private call's args - * @param encrypted_logs_hash The encrypted logs hash emitted from app circuit. - * @param unencrypted_logs_hash The unencrypted logs hash emitted from app circuit. - * @param encrypted_log_preimages_length The length of encrypted logs emitted from app circuit. - * @param unencrypted_log_preimages_length The length of unencrypted logs emitted from app circuit. - * @param is_circuit boolean to switch to circuit or native (fake vk and no proof) - * @return PrivateInputsInit - the inputs to the private call circuit of an init iteration - */ -PrivateKernelInputsInit do_private_call_get_kernel_inputs_init( - bool is_constructor, - private_function const& func, - std::vector const& args_vec, - std::array const& encrypted_logs_hash = std::array{}, - std::array const& unencrypted_logs_hash = - std::array{}, - NT::fr const& encrypted_log_preimages_length = NT::fr(0), - NT::fr const& unencrypted_log_preimages_length = NT::fr(0), - bool is_circuit = false); - -/** - * @brief Validate that the deployed contract address is correct. - * - * @details Compare the public inputs new contract address - * with one manually computed from private inputs. - * @param private_inputs to be used in manual computation - * @param public_inputs that contain the expected new contract address - * @return true or false - */ -bool validate_deployed_contract_address(PrivateKernelInputsInit const& private_inputs, - KernelCircuitPublicInputs const& public_inputs); - -/** - * @brief Checks if there is no newly deployed contract - * - * @param public_inputs that contain the expected new contract deployment data - * @return true or false - */ -bool validate_no_new_deployed_contract(KernelCircuitPublicInputs const& public_inputs); - -} // namespace aztec3::circuits::kernel::private_kernel::testing_harness diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/utils.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/utils.cpp deleted file mode 100644 index de9a52c1f42..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/utils.cpp +++ /dev/null @@ -1,137 +0,0 @@ -#include "index.hpp" -#include "init.hpp" - -#include "aztec3/circuits/mock/mock_kernel_circuit.hpp" - -#include - -#include - -#include - -namespace { -using NT = aztec3::utils::types::NativeTypes; -using AggregationObject = aztec3::utils::types::NativeTypes::AggregationObject; -using aztec3::circuits::abis::PreviousKernelData; -using aztec3::circuits::mock::mock_kernel_circuit; - -} // namespace - -namespace aztec3::circuits::kernel::private_kernel::utils { - -/** - * @brief Utility for reading into a vector from file - * - * @param filename - * @return std::vector - */ -std::vector read_buffer_from_file(const std::string& filename) -{ - std::ifstream file(filename, std::ios::binary); - std::vector buf; - - if (file.is_open()) { - // Get the file size by seeking to the end of the file - file.seekg(0, std::ios::end); - const std::streampos fileSize = file.tellg(); - file.seekg(0, std::ios::beg); - - // Resize the vector to hold the file contents - buf.resize(static_cast(fileSize)); - - // Read the file contents into the vector - file.read(reinterpret_cast(buf.data()), static_cast(fileSize)); - - file.close(); - } else { - std::cout << "Unable to open the file: " << filename << std::endl; - } - - return buf; -} - -/** - * @brief Utility for constructing a proof from proof_data read from a file - * @details Currently hard coded to read an UltraPlonk proof - * - * @return NT::Proof - */ -NT::Proof get_proof_from_file() -{ - NT::Proof proof; - const std::string proof_data_file = "../src/aztec3/circuits/kernel/private/fixtures/ultra_plonk_proof.dat"; - proof.proof_data = read_buffer_from_file(proof_data_file); - return proof; -} - -/** - * @brief Utility for constructing a verification key from verification_key_data stored in file - * @details This verification key corresponds to the UP proof stored in ultra_plonk_proof.dat - * @return std::shared_ptr - */ -std::shared_ptr get_verification_key_from_file() -{ - const std::string vk_data_file = "../src/aztec3/circuits/kernel/private/fixtures/ultra_plonk_verification_key.dat"; - auto vk_buf = utils::read_buffer_from_file(vk_data_file); - NT::VK new_vk; - const uint8_t* vk_iter = vk_buf.data(); - read(vk_iter, new_vk); - - return std::make_shared(new_vk); -} - -/** - * @brief Create a fake verification key - * - * @details will not work with real circuits - * - * @return std::shared_ptr fake verification key - */ -std::shared_ptr fake_vk() -{ - std::map commitments; - commitments["FAKE"] = *new NT::bn254_point(NT::fq(0), NT::fq(0)); - NT::VKData vk_data = { .circuit_type = static_cast(CircuitType::ULTRA), - .circuit_size = 2048, - .num_public_inputs = 116, - .commitments = commitments, - .contains_recursive_proof = false, - .recursive_proof_public_input_indices = {} }; - return std::make_shared(std::move(vk_data), barretenberg::srs::get_crs_factory()->get_verifier_crs()); -} - -/** - * @brief Create a dummy "previous kernel" - * - * @details For use in the first iteration of the kernel circuit - * - * @param real_vk_proof should the vk and proof included be real and usable by real circuits? - * @return PreviousKernelData the previous kernel data for use in the kernel circuit - */ -PreviousKernelData dummy_previous_kernel(bool real_vk_proof = false) -{ - PreviousKernelData const init_previous_kernel{}; - - auto crs_factory = barretenberg::srs::get_crs_factory(); - Builder mock_kernel_builder; - auto mock_kernel_public_inputs = mock_kernel_circuit(mock_kernel_builder, init_previous_kernel.public_inputs); - - NT::Proof const mock_kernel_proof = - real_vk_proof ? get_proof_from_file() : NT::Proof{ .proof_data = std::vector(64, 0) }; - - std::shared_ptr const mock_kernel_vk = real_vk_proof ? get_verification_key_from_file() : fake_vk(); - - PreviousKernelData previous_kernel = { - .public_inputs = mock_kernel_public_inputs, - .proof = mock_kernel_proof, - .vk = mock_kernel_vk, - }; - - // TODO(rahul) assertions don't work in wasm and it isn't worth updating barretenberg to handle our error code - // mechanism. Apparently we are getting rid of this function (dummy_previous_kernel()) soon anyway. - assert(!mock_kernel_builder.failed()); - - return previous_kernel; -} - -} // namespace aztec3::circuits::kernel::private_kernel::utils \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/utils.hpp b/circuits/cpp/src/aztec3/circuits/kernel/private/utils.hpp deleted file mode 100644 index 0e81a13061a..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/utils.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include "index.hpp" -#include "init.hpp" - -namespace { -using NT = aztec3::utils::types::NativeTypes; -using aztec3::circuits::abis::PreviousKernelData; -} // namespace - -namespace aztec3::circuits::kernel::private_kernel::utils { - -std::vector read_buffer_from_file(const std::string&); -NT::Proof get_proof_from_file(); -std::shared_ptr get_verification_key_from_file(); -std::shared_ptr fake_vk(); -PreviousKernelData dummy_previous_kernel(bool real_vk_proof = false); - -} // namespace aztec3::circuits::kernel::private_kernel::utils \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp b/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp deleted file mode 100644 index c87630c2191..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp +++ /dev/null @@ -1,1292 +0,0 @@ -#include "init.hpp" -#include "native_public_kernel_circuit_private_previous_kernel.hpp" -#include "native_public_kernel_circuit_public_previous_kernel.hpp" - -#include "aztec3/circuits/abis/call_context.hpp" -#include "aztec3/circuits/abis/call_stack_item.hpp" -#include "aztec3/circuits/abis/combined_accumulated_data.hpp" -#include "aztec3/circuits/abis/combined_constant_data.hpp" -#include "aztec3/circuits/abis/contract_storage_update_request.hpp" -#include "aztec3/circuits/abis/previous_kernel_data.hpp" -#include "aztec3/circuits/abis/public_kernel/public_call_data.hpp" -#include "aztec3/circuits/abis/public_kernel/public_kernel_inputs.hpp" -#include "aztec3/circuits/abis/tx_context.hpp" -#include "aztec3/circuits/abis/tx_request.hpp" -#include "aztec3/circuits/abis/types.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/array.hpp" -#include "aztec3/utils/circuit_errors.hpp" - -#include - -#include - -namespace aztec3::circuits::kernel::public_kernel { -using DummyCircuitBuilder = aztec3::utils::DummyCircuitBuilder; -using aztec3::circuits::abis::public_kernel::PublicKernelInputs; -using NT = aztec3::utils::types::NativeTypes; -using aztec3::circuits::abis::BlockHeader; -using aztec3::circuits::abis::CallContext; -using aztec3::circuits::abis::CallStackItem; -using aztec3::circuits::abis::CombinedAccumulatedData; -using aztec3::circuits::abis::CombinedConstantData; -using aztec3::circuits::abis::ContractStorageRead; -using aztec3::circuits::abis::ContractStorageUpdateRequest; -using aztec3::circuits::abis::NewContractData; -using aztec3::circuits::abis::OptionallyRevealedData; -using aztec3::circuits::abis::PreviousKernelData; -using aztec3::circuits::abis::PublicCircuitPublicInputs; -using aztec3::circuits::abis::PublicDataRead; -using aztec3::circuits::abis::PublicTypes; -using aztec3::circuits::abis::TxContext; -using aztec3::circuits::abis::TxRequest; -using aztec3::circuits::abis::public_kernel::PublicCallData; -using aztec3::utils::source_arrays_are_in_target; -using PublicCallStackItem = CallStackItem; - -template -std::array array_of_values(NT::uint32& count, NT::uint32 num_values_required = SIZE) -{ - ASSERT(num_values_required <= SIZE); - std::array values{}; - for (size_t i = 0; i < num_values_required; i++) { - values[i] = ++count; - } - return values; -} - -template std::array empty_array_of_values() -{ - std::array values{}; - return values; -} - -std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL> -generate_contract_storage_update_requests(NT::uint32& count, - NT::uint32 num_values_required = MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) -{ - std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL> values; - for (size_t i = 0; i < num_values_required; i++) { - const auto prev = count++; - values[i] = ContractStorageUpdateRequest{ - .storage_slot = prev, - .old_value = prev, - .new_value = count, - }; - }; - return values; -} - -std::array, MAX_PUBLIC_DATA_READS_PER_CALL> generate_contract_storage_reads( - NT::uint32& count, NT::uint32 num_values_required = MAX_PUBLIC_DATA_READS_PER_CALL) -{ - std::array, MAX_PUBLIC_DATA_READS_PER_CALL> values; - for (size_t i = 0; i < num_values_required; i++) { - const auto prev = count++; - values[i] = ContractStorageRead{ - .storage_slot = prev, - .current_value = prev, - }; - }; - return values; -} - -PublicCallStackItem generate_call_stack_item(NT::fr contract_address, - NT::fr msg_sender, - NT::fr storage_contract_address, - NT::fr portal_contract_address, - NT::boolean is_delegate_call, - NT::uint32 seed = 0) -{ - NT::uint32 count = seed + 1; - FunctionData const function_data{ - .selector = - { - .value = count, - }, - .is_private = false, - .is_constructor = false, - }; - CallContext const call_context{ - .msg_sender = msg_sender, - .storage_contract_address = storage_contract_address, - .portal_contract_address = portal_contract_address, - .function_selector = function_data.selector, - .is_delegate_call = is_delegate_call, - .is_static_call = false, - .is_contract_deployment = false, - }; - fr const args_hash = count; - std::array const return_values = array_of_values(count); - std::array const public_call_stack = - array_of_values(count); - std::array const new_commitments = - array_of_values(count); - std::array const new_nullifiers = - array_of_values(count); - std::array const new_l2_to_l1_msgs = - array_of_values(count); - std::array, MAX_PUBLIC_DATA_READS_PER_CALL> const reads = - generate_contract_storage_reads(count); - std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL> const update_requests = - generate_contract_storage_update_requests(count); - - // create the public circuit public inputs - auto const public_circuit_public_inputs = PublicCircuitPublicInputs{ - .call_context = call_context, - .args_hash = args_hash, - .return_values = return_values, - .contract_storage_update_requests = update_requests, - .contract_storage_reads = reads, - .public_call_stack = public_call_stack, - .new_commitments = new_commitments, - .new_nullifiers = new_nullifiers, - .new_l2_to_l1_msgs = new_l2_to_l1_msgs, - - }; - auto call_stack_item = PublicCallStackItem{ - .contract_address = contract_address, - .function_data = function_data, - .public_inputs = public_circuit_public_inputs, - }; - return call_stack_item; -} - -PublicDataRead public_data_read_from_contract_storage_read(ContractStorageRead const& contract_storage_read, - NT::fr const& contract_address) -{ - return PublicDataRead{ - .leaf_index = compute_public_data_tree_index(contract_address, contract_storage_read.storage_slot), - .value = compute_public_data_tree_value(contract_storage_read.current_value), - }; -} - -PublicDataUpdateRequest public_data_update_request_from_contract_storage_update_request( - ContractStorageUpdateRequest const& contract_storage_update_request, NT::fr const& contract_address) -{ - return PublicDataUpdateRequest{ - .leaf_index = - compute_public_data_tree_index(contract_address, contract_storage_update_request.storage_slot), - .old_value = compute_public_data_tree_value(contract_storage_update_request.old_value), - .new_value = compute_public_data_tree_value(contract_storage_update_request.new_value), - }; -} - -std::array, MAX_PUBLIC_DATA_READS_PER_CALL> public_data_reads_from_contract_storage_reads( - std::array, MAX_PUBLIC_DATA_READS_PER_CALL> const& public_data_reads, - NT::fr const& contract_address) -{ - std::array, MAX_PUBLIC_DATA_READS_PER_CALL> values; - for (size_t i = 0; i < MAX_PUBLIC_DATA_READS_PER_CALL; i++) { - const auto& read = public_data_reads[i]; - if (read.is_empty()) { - continue; - } - values[i] = public_data_read_from_contract_storage_read(read, contract_address); - } - return values; -} - -std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL> -public_data_update_requests_from_contract_storage_update_requests( - std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL> const& update_requests, - NT::fr const& contract_address) -{ - std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL> values; - for (size_t i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; i++) { - const auto& update_request = update_requests[i]; - if (update_request.is_empty()) { - continue; - } - values[i] = public_data_update_request_from_contract_storage_update_request(update_request, contract_address); - } - return values; -} - -std::array new_commitments_as_siloed_commitments( - std::array const& new_commitments, NT::fr const& contract_address) -{ - std::array siloed_commitments{}; - for (size_t i = 0; i < MAX_NEW_COMMITMENTS_PER_CALL; ++i) { - if (!new_commitments[i].is_zero()) { - siloed_commitments[i] = silo_commitment(contract_address, new_commitments[i]); - } - } - return siloed_commitments; -} - -std::array new_nullifiers_as_siloed_nullifiers( - std::array const& new_nullifiers, NT::fr const& contract_address) -{ - std::array siloed_nullifiers{}; - for (size_t i = 0; i < MAX_NEW_NULLIFIERS_PER_CALL; ++i) { - if (!new_nullifiers[i].is_zero()) { - siloed_nullifiers[i] = silo_nullifier(contract_address, new_nullifiers[i]); - } - } - return siloed_nullifiers; -} - -std::array new_l2_messages_from_message( - std::array const& new_messages, - NT::fr const& contract_address, - fr const& portal_contract_address, - fr const& chain_id, - fr const& version) -{ - std::array formatted_msgs{}; - for (size_t i = 0; i < MAX_NEW_L2_TO_L1_MSGS_PER_CALL; ++i) { - if (!new_messages[i].is_zero()) { - formatted_msgs[i] = compute_l2_to_l1_hash( - contract_address, version, portal_contract_address, chain_id, new_messages[i]); - } - } - return formatted_msgs; -} - -/** - * @brief Generates the inputs to the public kernel circuit - * - * @param is_constructor whether this public circuit call is a constructor - * @param args_vec the private call's args - * @return PrivateInputs - the inputs to the private call circuit - */ -PublicKernelInputs get_kernel_inputs_with_previous_kernel(NT::boolean private_previous) -{ - NT::uint32 seed = 1000; - - NT::address contract_address = 12345; - const NT::fr portal_contract_address = 23456; - - const NT::address msg_sender = NT::fr(1); - - FunctionData const function_data{ - .selector = - { - .value = 1, - }, - .is_private = false, - .is_constructor = false, - }; - - CallContext const call_context{ - .msg_sender = msg_sender, - .storage_contract_address = contract_address, - .portal_contract_address = portal_contract_address, - .function_selector = function_data.selector, - .is_delegate_call = false, - .is_static_call = false, - .is_contract_deployment = false, - }; - - std::vector const args = { 1, 2, 3 }; - - //*************************************************************************** - // We can create a TxRequest from some of the above data. - //*************************************************************************** - auto const tx_request = TxRequest{ .origin = contract_address, - .function_data = function_data, - .args_hash = compute_var_args_hash(args), - .tx_context = TxContext{ - .is_fee_payment_tx = false, - .is_rebate_payment_tx = false, - .is_contract_deployment_tx = false, - .contract_deployment_data = {}, - .chain_id = 1, - } }; - - std::array child_call_stacks; - NT::fr child_contract_address = 100000; - NT::fr child_portal_contract_address = 200000; - std::array call_stack_hashes{}; - for (size_t i = 0; i < MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL; i++) { - // NOLINTNEXTLINE(readability-suspicious-call-argument) - child_call_stacks[i] = generate_call_stack_item(child_contract_address, - contract_address, - child_contract_address, - child_portal_contract_address, - false, - seed); - call_stack_hashes[i] = child_call_stacks[i].hash(); - child_contract_address++; - child_portal_contract_address++; - } - - std::array const return_values = - array_of_values(seed, RETURN_VALUES_LENGTH / 2); - std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL> const update_requests = - generate_contract_storage_update_requests(seed, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL / 2); - std::array, MAX_PUBLIC_DATA_READS_PER_CALL> const reads = - generate_contract_storage_reads(seed, MAX_PUBLIC_DATA_READS_PER_CALL / 2); - std::array const new_commitments = - array_of_values(seed, MAX_NEW_COMMITMENTS_PER_CALL / 2); - std::array const new_nullifiers = - array_of_values(seed, MAX_NEW_NULLIFIERS_PER_CALL / 2); - std::array const new_l2_to_l1_msgs = - array_of_values(seed, MAX_NEW_L2_TO_L1_MSGS_PER_CALL / 2); - std::array const unencrypted_logs_hash = - array_of_values(seed, NUM_FIELDS_PER_SHA256); - fr const unencrypted_log_preimages_length = ++seed; - BlockHeader block_header = { - .note_hash_tree_root = ++seed, - .nullifier_tree_root = ++seed, - .contract_tree_root = ++seed, - .l1_to_l2_message_tree_root = ++seed, - .archive_root = ++seed, - .private_kernel_vk_tree_root = ++seed, - .public_data_tree_root = ++seed, - .global_variables_hash = ++seed, - }; - - // create the public circuit public inputs - auto const public_circuit_public_inputs = PublicCircuitPublicInputs{ - .call_context = call_context, - .args_hash = compute_var_args_hash(args), - .return_values = return_values, - .contract_storage_update_requests = update_requests, - .contract_storage_reads = reads, - .public_call_stack = call_stack_hashes, - .new_commitments = new_commitments, - .new_nullifiers = new_nullifiers, - .new_l2_to_l1_msgs = new_l2_to_l1_msgs, - .unencrypted_logs_hash = unencrypted_logs_hash, - .unencrypted_log_preimages_length = unencrypted_log_preimages_length, - .block_header = block_header, - }; - - const PublicCallStackItem call_stack_item{ - .contract_address = contract_address, - .function_data = tx_request.function_data, - .public_inputs = public_circuit_public_inputs, - }; - - const PublicCallData public_call_data = { - .call_stack_item = call_stack_item, - .public_call_stack_preimages = child_call_stacks, - .portal_contract_address = portal_contract_address, - .bytecode_hash = 1234567, - }; - - // TODO(914) Should this be unused? - [[maybe_unused]] BlockHeader const historical_tree_roots = { - .note_hash_tree_root = 1000, - .contract_tree_root = 2000, - .l1_to_l2_message_tree_root = 3000, - .private_kernel_vk_tree_root = 4000, - }; - - CombinedConstantData const end_constants = { .block_header = - BlockHeader{ .note_hash_tree_root = ++seed, - .nullifier_tree_root = ++seed, - .contract_tree_root = ++seed, - .private_kernel_vk_tree_root = ++seed }, - .tx_context = TxContext{ - .is_fee_payment_tx = false, - .is_rebate_payment_tx = false, - .is_contract_deployment_tx = false, - .contract_deployment_data = {}, - } }; - - std::array public_call_stack{}; - public_call_stack[0] = public_call_data.call_stack_item.hash(); - - CombinedAccumulatedData const end_accumulated_data = { - .new_commitments = - array_of_values(seed, private_previous ? MAX_NEW_COMMITMENTS_PER_TX / 2 : 0), - .new_nullifiers = - array_of_values(seed, private_previous ? MAX_NEW_NULLIFIERS_PER_TX / 2 : 0), - .private_call_stack = array_of_values(seed, 0), - .public_call_stack = public_call_stack, - .new_l2_to_l1_msgs = array_of_values( - seed, private_previous ? MAX_NEW_L2_TO_L1_MSGS_PER_TX / 2 : 0), - .encrypted_logs_hash = array_of_values( - seed, private_previous ? 2 : 0), // only private kernel is producing encrypted logs - .unencrypted_logs_hash = array_of_values(seed, NUM_FIELDS_PER_SHA256), - .encrypted_log_preimages_length = private_previous ? ++seed : 0, - .unencrypted_log_preimages_length = ++seed, - .new_contracts = std::array, MAX_NEW_CONTRACTS_PER_TX>(), - .optionally_revealed_data = - std::array, MAX_OPTIONALLY_REVEALED_DATA_LENGTH_PER_TX>(), - .public_data_update_requests = - std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX>(), - .public_data_reads = std::array, MAX_PUBLIC_DATA_READS_PER_TX>() - }; - - const KernelCircuitPublicInputs public_inputs = { - .end = end_accumulated_data, - .constants = end_constants, - .is_private = private_previous, - }; - - const PreviousKernelData previous_kernel = { - .public_inputs = public_inputs, - }; - - // NOLINTNEXTLINE(misc-const-correctness) - PublicKernelInputs kernel_inputs = { - .previous_kernel = previous_kernel, - .public_call = public_call_data, - }; - return kernel_inputs; -} // namespace aztec3::circuits::kernel::public_kernel - -template -void validate_public_kernel_outputs_correctly_propagated(const KernelInput& inputs, - const KernelCircuitPublicInputs& public_inputs) -{ - for (size_t i = 0; i < MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL; i++) { - ASSERT_EQ(public_inputs.end.public_call_stack[i], - inputs.public_call.call_stack_item.public_inputs.public_call_stack[i]); - } - - const auto contract_address = inputs.public_call.call_stack_item.contract_address; - size_t st_index = 0; - for (size_t i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; i++) { - const auto& contract_storage_update_request = - inputs.public_call.call_stack_item.public_inputs.contract_storage_update_requests[i]; - if (contract_storage_update_request.is_empty()) { - continue; - } - const auto public_data_update_request = public_data_update_request_from_contract_storage_update_request( - contract_storage_update_request, contract_address); - ASSERT_EQ(public_inputs.end.public_data_update_requests[st_index++], public_data_update_request); - } - - size_t sr_index = 0; - for (size_t i = 0; i < MAX_PUBLIC_DATA_READS_PER_TX; i++) { - const auto& read = inputs.public_call.call_stack_item.public_inputs.contract_storage_reads[i]; - if (read.is_empty()) { - continue; - } - const auto public_read = public_data_read_from_contract_storage_read(read, contract_address); - ASSERT_EQ(public_inputs.end.public_data_reads[sr_index++], public_read); - } -} - -void validate_private_data_propagation(DummyBuilder& builder, - const PublicKernelInputs& inputs, - const KernelCircuitPublicInputs& public_inputs) -{ - ASSERT_TRUE(source_arrays_are_in_target(builder, - inputs.previous_kernel.public_inputs.end.private_call_stack, - std::array{}, - public_inputs.end.private_call_stack)); - - ASSERT_TRUE(source_arrays_are_in_target(builder, - inputs.previous_kernel.public_inputs.end.new_contracts, - std::array, MAX_NEW_CONTRACTS_PER_TX>(), - public_inputs.end.new_contracts)); - - ASSERT_EQ(inputs.previous_kernel.public_inputs.end.encrypted_logs_hash, - inputs.previous_kernel.public_inputs.end.encrypted_logs_hash); - ASSERT_EQ(inputs.previous_kernel.public_inputs.end.encrypted_log_preimages_length, - inputs.previous_kernel.public_inputs.end.encrypted_log_preimages_length); - - ASSERT_EQ(inputs.previous_kernel.public_inputs.end.optionally_revealed_data, - public_inputs.end.optionally_revealed_data); -} - -TEST(public_kernel_tests, only_valid_public_data_reads_should_be_propagated) -{ - DummyBuilder dummyBuilder = DummyBuilder("public_kernel_tests__only_valid_public_data_reads_should_be_propagated"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - // modify the contract storage reads so only 2 are valid and only those should be propagated - const auto first_valid = ContractStorageRead{ - .storage_slot = 123456789, - .current_value = 76543, - }; - const auto second_valid = ContractStorageRead{ - .storage_slot = 123456789, - .current_value = 76543, - }; - std::array, MAX_PUBLIC_DATA_READS_PER_CALL> reads = - std::array, MAX_PUBLIC_DATA_READS_PER_CALL>(); - reads[1] = first_valid; - reads[3] = second_valid; - inputs.public_call.call_stack_item.public_inputs.contract_storage_reads = reads; - - // adjust the call stack item hash for the current call in the previous iteration - inputs.previous_kernel.public_inputs.end.public_call_stack[0] = inputs.public_call.call_stack_item.hash(); - - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_EQ(dummyBuilder.get_first_failure(), utils::CircuitError::no_error()); - ASSERT_FALSE(dummyBuilder.failed()); - - ASSERT_FALSE(public_inputs.is_private); - ASSERT_EQ(public_inputs.constants.tx_context, inputs.previous_kernel.public_inputs.constants.tx_context); - - for (size_t i = 0; i < MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL; i++) { - ASSERT_EQ(public_inputs.end.public_call_stack[i], - inputs.public_call.call_stack_item.public_inputs.public_call_stack[i]); - } - - // only the 2 valid reads should have been propagated - const auto contract_address = inputs.public_call.call_stack_item.contract_address; - const auto public_read_1 = public_data_read_from_contract_storage_read(first_valid, contract_address); - const auto public_read_2 = public_data_read_from_contract_storage_read(second_valid, contract_address); - ASSERT_EQ(public_inputs.end.public_data_reads[0], public_read_1); - ASSERT_EQ(public_inputs.end.public_data_reads[1], public_read_2); -} - -TEST(public_kernel_tests, only_valid_update_requests_should_be_propagated) -{ - DummyBuilder dummyBuilder = DummyBuilder("public_kernel_tests__only_valid_update_requests_should_be_propagated"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - // modify the contract storage update requests so only 2 are valid and only those should be propagated - const auto first_valid = ContractStorageUpdateRequest{ - .storage_slot = 123456789, - .old_value = 76543, - .new_value = 76544, - }; - const auto second_valid = ContractStorageUpdateRequest{ - .storage_slot = 987654321, - .old_value = 86543, - .new_value = 86544, - }; - std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL> update_requests = - std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL>(); - update_requests[1] = first_valid; - update_requests[3] = second_valid; - inputs.public_call.call_stack_item.public_inputs.contract_storage_update_requests = update_requests; - - // adjust the call stack item hash for the current call in the previous iteration - inputs.previous_kernel.public_inputs.end.public_call_stack[0] = inputs.public_call.call_stack_item.hash(); - - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_EQ(dummyBuilder.get_first_failure(), utils::CircuitError::no_error()); - ASSERT_FALSE(dummyBuilder.failed()); - - ASSERT_FALSE(public_inputs.is_private); - ASSERT_EQ(public_inputs.constants.tx_context, inputs.previous_kernel.public_inputs.constants.tx_context); - - for (size_t i = 0; i < MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL; i++) { - ASSERT_EQ(public_inputs.end.public_call_stack[i], - inputs.public_call.call_stack_item.public_inputs.public_call_stack[i]); - } - - // only the 2 valid update requests should have been propagated - const auto contract_address = inputs.public_call.call_stack_item.contract_address; - const auto public_write_1 = - public_data_update_request_from_contract_storage_update_request(first_valid, contract_address); - const auto public_write_2 = - public_data_update_request_from_contract_storage_update_request(second_valid, contract_address); - ASSERT_EQ(public_inputs.end.public_data_update_requests[0], public_write_1); - ASSERT_EQ(public_inputs.end.public_data_update_requests[1], public_write_2); -} - -TEST(public_kernel_tests, constructor_should_fail) -{ - DummyBuilder dummyBuilder = DummyBuilder("public_kernel_tests__constructor_should_fail"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - inputs.public_call.call_stack_item.function_data.is_constructor = true; - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, CircuitErrorCode::PUBLIC_KERNEL__CONSTRUCTOR_NOT_ALLOWED); -} - -TEST(public_kernel_tests, constructor_should_fail_2) -{ - DummyBuilder dummyBuilder = DummyBuilder("public_kernel_tests__constructor_should_fail_2"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - inputs.public_call.call_stack_item.public_inputs.call_context.is_contract_deployment = true; - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, CircuitErrorCode::PUBLIC_KERNEL__CONTRACT_DEPLOYMENT_NOT_ALLOWED); -} - -TEST(public_kernel_tests, no_bytecode_hash_should_fail) -{ - DummyBuilder dummyBuilder = DummyBuilder("public_kernel_tests__no_bytecode_hash_should_fail"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - inputs.public_call.bytecode_hash = 0; - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, CircuitErrorCode::PUBLIC_KERNEL__BYTECODE_HASH_INVALID); -} - - -TEST(public_kernel_tests, invalid_is_internal) -{ - DummyBuilder dummyBuilder = DummyBuilder("public_kernel_tests__no_bytecode_hash_should_fail"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - // Make the call internal but msg_sender != storage_contract_address. - inputs.public_call.call_stack_item.function_data.is_internal = true; - inputs.public_call.call_stack_item.public_inputs.call_context.msg_sender = 1; - inputs.public_call.call_stack_item.public_inputs.call_context.storage_contract_address = 2; - - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, CircuitErrorCode::PUBLIC_KERNEL__IS_INTERNAL_BUT_NOT_SELF_CALL); -} - -TEST(public_kernel_tests, contract_address_must_be_valid) -{ - DummyBuilder dummyBuilder = DummyBuilder("public_kernel_tests__contract_address_must_be_valid"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - inputs.public_call.call_stack_item.contract_address = 0; - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, CircuitErrorCode::PUBLIC_KERNEL__CONTRACT_ADDRESS_INVALID); -} - -TEST(public_kernel_tests, function_selector_must_be_valid) -{ - DummyBuilder dummyBuilder = DummyBuilder("public_kernel_tests__function_selector_must_be_valid"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - inputs.public_call.call_stack_item.function_data.selector = { - .value = 0, - }; - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, CircuitErrorCode::PUBLIC_KERNEL__FUNCTION_SIGNATURE_INVALID); -} - -TEST(public_kernel_tests, private_call_should_fail) -{ - DummyBuilder dummyBuilder = DummyBuilder("public_kernel_tests__private_call_should_fail"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - inputs.public_call.call_stack_item.function_data.is_private = true; - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, CircuitErrorCode::PUBLIC_KERNEL__PRIVATE_FUNCTION_NOT_ALLOWED); -} - -TEST(public_kernel_tests, inconsistent_call_hash_should_fail) -{ - for (size_t i = 0; i < MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL; i++) { - DummyBuilder dummyBuilder = DummyBuilder(format("public_kernel_tests__inconsistent_call_hash_should_fail-", i)); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - // change a value of something in the call stack pre-image - inputs.public_call.public_call_stack_preimages[i].public_inputs.args_hash++; - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, CircuitErrorCode::PUBLIC_KERNEL__PUBLIC_CALL_STACK_MISMATCH); - } -} - -TEST(public_kernel_tests, incorrect_storage_contract_address_fails_for_regular_calls) -{ - for (size_t i = 0; i < MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL; i++) { - DummyBuilder dummyBuilder = - DummyBuilder(format("public_kernel_tests__incorrect_storage_contract_address_fails_for_regular_calls-", i)); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - // change the storage contract address so it does not equal the contract address - const NT::fr new_contract_address = - NT::fr(inputs.public_call.public_call_stack_preimages[i].contract_address) + 1; - inputs.public_call.public_call_stack_preimages[i].public_inputs.call_context.storage_contract_address = - new_contract_address; - // update the call stack item hash after the change in the preimage - inputs.public_call.call_stack_item.public_inputs.public_call_stack[i] = - inputs.public_call.public_call_stack_preimages[i].hash(); - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, - CircuitErrorCode::PUBLIC_KERNEL__PUBLIC_CALL_STACK_INVALID_STORAGE_ADDRESS); - } -} - -TEST(public_kernel_tests, incorrect_msg_sender_fails_for_regular_calls) -{ - for (size_t i = 0; i < MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL; i++) { - DummyBuilder dummyBuilder = - DummyBuilder(format("public_kernel_tests__incorrect_msg_sender_fails_for_regular_calls-", i)); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - // set the msg sender to be the address of the called contract, which is wrong - const auto new_msg_sender = inputs.public_call.public_call_stack_preimages[i].contract_address; - // change the storage contract address so it does not equal the contract address - inputs.public_call.public_call_stack_preimages[i].public_inputs.call_context.msg_sender = new_msg_sender; - // update the call stack item hash after the change in the preimage - inputs.public_call.call_stack_item.public_inputs.public_call_stack[i] = - inputs.public_call.public_call_stack_preimages[i].hash(); - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, - CircuitErrorCode::PUBLIC_KERNEL__PUBLIC_CALL_STACK_INVALID_MSG_SENDER); - } -} - -TEST(public_kernel_tests, public_kernel_circuit_succeeds_for_mixture_of_regular_and_delegate_calls) -{ - DummyBuilder dummyBuilder = - DummyBuilder("public_kernel_tests__public_kernel_circuit_succeeds_for_mixture_of_regular_and_delegate_calls"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - const auto contract_address = NT::fr(inputs.public_call.call_stack_item.contract_address); - const auto origin_msg_sender = NT::fr(inputs.public_call.call_stack_item.public_inputs.call_context.msg_sender); - const auto contract_portal_address = NT::fr(inputs.public_call.portal_contract_address); - - // redefine the child calls/stacks to use some delegate calls - NT::uint32 const seed = 1000; - NT::fr child_contract_address = 100000; - NT::fr child_portal_contract_address = 200000; - NT::boolean is_delegate_call = false; - for (size_t i = 0; i < MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL; i++) { - inputs.public_call.public_call_stack_preimages[i] = - // NOLINTNEXTLINE(readability-suspicious-call-argument) - generate_call_stack_item(child_contract_address, - is_delegate_call ? origin_msg_sender : contract_address, - is_delegate_call ? contract_address : child_contract_address, - is_delegate_call ? contract_portal_address : child_portal_contract_address, - is_delegate_call, - seed); - inputs.public_call.call_stack_item.public_inputs.public_call_stack[i] = - inputs.public_call.public_call_stack_preimages[i].hash(); - - // change the next call type - is_delegate_call = !is_delegate_call; - child_contract_address++; - child_portal_contract_address++; - } - - // we update the hash of the current call stack item in the previous kernel, - // since we modified the hash of the nested calls, which changes the hash of the parent item - inputs.previous_kernel.public_inputs.end.public_call_stack[0] = inputs.public_call.call_stack_item.hash(); - - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_EQ(dummyBuilder.get_first_failure(), utils::CircuitError::no_error()); - ASSERT_FALSE(dummyBuilder.failed()); -} - -TEST(public_kernel_tests, public_kernel_circuit_fails_on_incorrect_msg_sender_in_delegate_call) -{ - DummyBuilder dummyBuilder = - DummyBuilder("public_kernel_tests__public_kernel_circuit_fails_on_incorrect_msg_sender_in_delegate_call"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - const auto contract_address = NT::fr(inputs.public_call.call_stack_item.contract_address); - // const auto origin_msg_sender = NT::fr(inputs.public_call.call_stack_item.public_inputs.call_context.msg_sender); - const auto contract_portal_address = NT::fr(inputs.public_call.portal_contract_address); - - // set the first call stack item to be a delegate call - std::array child_call_stacks; - NT::uint32 const seed = 1000; - NT::fr const child_contract_address = 100000; - std::array call_stack_hashes{}; - child_call_stacks[0] = - // NOLINTNEXTLINE(readability-suspicious-call-argument) - generate_call_stack_item(child_contract_address, - contract_address, // this should be the origin_msg_sender, not the contract address - contract_address, - contract_portal_address, - true, - seed); - call_stack_hashes[0] = child_call_stacks[0].hash(); - - inputs.public_call.call_stack_item.public_inputs.public_call_stack = call_stack_hashes; - inputs.public_call.public_call_stack_preimages = child_call_stacks; - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, - CircuitErrorCode::PUBLIC_KERNEL__PUBLIC_CALL_STACK_INVALID_MSG_SENDER); -} - -TEST(public_kernel_tests, public_kernel_circuit_fails_on_incorrect_storage_contract_in_delegate_call) -{ - DummyBuilder dummyBuilder = - DummyBuilder("public_kernel_tests__public_kernel_circuit_fails_on_incorrect_storage_contract_in_delegate_call"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - // const auto contract_address = NT::fr(inputs.public_call.call_stack_item.contract_address); - const auto origin_msg_sender = NT::fr(inputs.public_call.call_stack_item.public_inputs.call_context.msg_sender); - const auto contract_portal_address = NT::fr(inputs.public_call.portal_contract_address); - - // set the first call stack item to be a delegate call - std::array child_call_stacks; - NT::uint32 const seed = 1000; - NT::fr const child_contract_address = 100000; - std::array call_stack_hashes{}; - child_call_stacks[0] = generate_call_stack_item(child_contract_address, - origin_msg_sender, - child_contract_address, // this should be contract_address - contract_portal_address, - true, - seed); - call_stack_hashes[0] = child_call_stacks[0].hash(); - - inputs.public_call.call_stack_item.public_inputs.public_call_stack = call_stack_hashes; - inputs.public_call.public_call_stack_preimages = child_call_stacks; - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, - CircuitErrorCode::PUBLIC_KERNEL__PUBLIC_CALL_STACK_INVALID_STORAGE_ADDRESS); -} - -TEST(public_kernel_tests, public_kernel_circuit_fails_on_incorrect_portal_contract_in_delegate_call) -{ - DummyBuilder dummyBuilder = - DummyBuilder("public_kernel_tests__public_kernel_circuit_fails_on_incorrect_portal_contract_in_delegate_call"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - const auto contract_address = NT::fr(inputs.public_call.call_stack_item.contract_address); - const auto origin_msg_sender = NT::fr(inputs.public_call.call_stack_item.public_inputs.call_context.msg_sender); - // const auto contract_portal_address = NT::fr(inputs.public_call.portal_contract_address); - - // set the first call stack item to be a delegate call - std::array child_call_stacks; - NT::uint32 const seed = 1000; - NT::fr const child_contract_address = 100000; - NT::fr const child_portal_contract = 200000; - std::array call_stack_hashes{}; - // NOLINTNEXTLINE(readability-suspicious-call-argument) - child_call_stacks[0] = generate_call_stack_item(child_contract_address, - origin_msg_sender, - contract_address, - child_portal_contract, // this should be contract_portal_address - true, - seed); - call_stack_hashes[0] = child_call_stacks[0].hash(); - - inputs.public_call.call_stack_item.public_inputs.public_call_stack = call_stack_hashes; - inputs.public_call.public_call_stack_preimages = child_call_stacks; - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, - CircuitErrorCode::PUBLIC_KERNEL__PUBLIC_CALL_STACK_INVALID_PORTAL_ADDRESS); -} - -TEST(public_kernel_tests, public_kernel_circuit_only_checks_non_empty_call_stacks) -{ - DummyBuilder dummyBuilder = - DummyBuilder("public_kernel_tests__public_kernel_circuit_only_checks_non_empty_call_stacks"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - const auto contract_address = NT::fr(inputs.public_call.call_stack_item.contract_address); - const auto origin_msg_sender = NT::fr(inputs.public_call.call_stack_item.public_inputs.call_context.msg_sender); - // const auto contract_portal_address = NT::fr(inputs.public_call.portal_contract_address); - - // set all but the first call stack item to have a zero call stack hash - // these call stack items will have an contract portal address but will be ignored as the call stack will be ignored - std::array& child_call_stacks = - inputs.public_call.public_call_stack_preimages; - std::array& call_stack_hashes = - inputs.public_call.call_stack_item.public_inputs.public_call_stack; - NT::uint32 const seed = 1000; - NT::fr const child_contract_address = 100000; - NT::fr const child_portal_contract = 200000; - for (size_t i = 1; i < MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL; i++) { - // NOLINTNEXTLINE(readability-suspicious-call-argument) - child_call_stacks[i] = generate_call_stack_item(child_contract_address, - origin_msg_sender, - contract_address, - child_portal_contract, // shuold be contract_portal_address - false, - seed); - // setting this to zero makes the call stack item be ignored so it won't fail - call_stack_hashes[i] = 0; - } - // adjust the call stack item hash for the current call in the previous iteration - inputs.previous_kernel.public_inputs.end.public_call_stack[0] = inputs.public_call.call_stack_item.hash(); - - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_EQ(dummyBuilder.get_first_failure(), utils::CircuitError::no_error()); - ASSERT_FALSE(dummyBuilder.failed()); -} - -TEST(public_kernel_tests, public_kernel_circuit_with_private_previous_kernel_should_succeed) -{ - DummyBuilder dummyBuilder = - DummyBuilder("public_kernel_tests__public_kernel_circuit_with_private_previous_kernel_should_succeed"); - PublicKernelInputs const inputs = get_kernel_inputs_with_previous_kernel(true); - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_FALSE(dummyBuilder.failed()); -} - -TEST(public_kernel_tests, circuit_outputs_should_be_correctly_populated_with_previous_private_kernel) -{ - DummyBuilder dummyBuilder = - DummyBuilder("public_kernel_tests__circuit_outputs_should_be_correctly_populated_with_previous_private_kernel"); - PublicKernelInputs const inputs = get_kernel_inputs_with_previous_kernel(true); - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - - // test that the prior set of private kernel public inputs were copied to the outputs - validate_private_data_propagation(dummyBuilder, inputs, public_inputs); - - validate_public_kernel_outputs_correctly_propagated(inputs, public_inputs); - ASSERT_FALSE(dummyBuilder.failed()); -} - -TEST(public_kernel_tests, private_previous_kernel_non_empty_private_call_stack_should_fail) -{ - DummyBuilder dummyBuilder = - DummyBuilder("public_kernel_tests__private_previous_kernel_non_empty_private_call_stack_should_fail"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - inputs.previous_kernel.public_inputs.end.private_call_stack[0] = 1; - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, CircuitErrorCode::PUBLIC_KERNEL__NON_EMPTY_PRIVATE_CALL_STACK); -} - -TEST(public_kernel_tests, private_previous_kernel_empty_public_call_stack_should_fail) -{ - DummyBuilder dummyBuilder = - DummyBuilder("public_kernel_tests__private_previous_kernel_empty_public_call_stack_should_fail"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - inputs.previous_kernel.public_inputs.end.public_call_stack = - std::array{}; - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, CircuitErrorCode::PUBLIC_KERNEL__EMPTY_PUBLIC_CALL_STACK); -} - -TEST(public_kernel_tests, private_previous_kernel_non_private_previous_kernel_should_fail) -{ - DummyBuilder dummyBuilder = - DummyBuilder("public_kernel_tests__private_previous_kernel_non_private_previous_kernel_should_fail"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - inputs.previous_kernel.public_inputs.is_private = false; - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, CircuitErrorCode::PUBLIC_KERNEL__PREVIOUS_KERNEL_NOT_PRIVATE); -} - -TEST(public_kernel_tests, previous_private_kernel_fails_if_contract_storage_update_requests_on_static_call) -{ - DummyBuilder dummyBuilder = DummyBuilder( - "public_kernel_tests__previous_private_kernel_fails_if_contract_storage_update_requests_on_static_call"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - // the function call has contract storage update requests so setting it to static should fail - inputs.public_call.call_stack_item.public_inputs.call_context.is_static_call = true; - - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ( - dummyBuilder.get_first_failure().code, - CircuitErrorCode::PUBLIC_KERNEL__CALL_CONTEXT_CONTRACT_STORAGE_UPDATE_REQUESTS_PROHIBITED_FOR_STATIC_CALL); -} - -TEST(public_kernel_tests, previous_private_kernel_fails_if_incorrect_storage_contract_on_delegate_call) -{ - DummyBuilder dummyBuilder = DummyBuilder( - "public_kernel_tests__previous_private_kernel_fails_if_incorrect_storage_contract_on_delegate_call"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(true); - - // the function call has the contract address and storage contract address equal and so it should fail for a - // delegate call - inputs.public_call.call_stack_item.public_inputs.call_context.is_delegate_call = true; - - auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, - CircuitErrorCode::PUBLIC_KERNEL__CALL_CONTEXT_INVALID_STORAGE_ADDRESS_FOR_DELEGATE_CALL); -} - -TEST(public_kernel_tests, public_kernel_circuit_with_public_previous_kernel_should_succeed) -{ - DummyBuilder dummyBuilder = - DummyBuilder("public_kernel_tests__public_kernel_circuit_with_public_previous_kernel_should_succeed"); - PublicKernelInputs const inputs = get_kernel_inputs_with_previous_kernel(false); - auto public_inputs = native_public_kernel_circuit_public_previous_kernel(dummyBuilder, inputs); - ASSERT_FALSE(dummyBuilder.failed()); -} - -TEST(public_kernel_tests, public_previous_kernel_empty_public_call_stack_should_fail) -{ - DummyBuilder dummyBuilder = - DummyBuilder("public_kernel_tests__public_previous_kernel_empty_public_call_stack_should_fail"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(false); - inputs.previous_kernel.public_inputs.end.public_call_stack = - std::array{}; - auto public_inputs = native_public_kernel_circuit_public_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, CircuitErrorCode::PUBLIC_KERNEL__EMPTY_PUBLIC_CALL_STACK); -} - -TEST(public_kernel_tests, public_previous_kernel_private_previous_kernel_should_fail) -{ - DummyBuilder dummyBuilder = - DummyBuilder("public_kernel_tests__public_previous_kernel_private_previous_kernel_should_fail"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(false); - inputs.previous_kernel.public_inputs.is_private = true; - auto public_inputs = native_public_kernel_circuit_public_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, CircuitErrorCode::PUBLIC_KERNEL__PREVIOUS_KERNEL_NOT_PUBLIC); -} - -TEST(public_kernel_tests, circuit_outputs_should_be_correctly_populated_with_previous_public_kernel) -{ - DummyBuilder dummyBuilder = - DummyBuilder("public_kernel_tests__circuit_outputs_should_be_correctly_populated_with_previous_public_kernel"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(false); - - // setup 2 previous data writes on the public inputs - const auto first_write = PublicDataUpdateRequest{ - .leaf_index = 123456789, - .old_value = 76543, - .new_value = 76544, - }; - const auto second_write = PublicDataUpdateRequest{ - .leaf_index = 987654321, - .old_value = 86543, - .new_value = 86544, - }; - std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX> initial_writes = - std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX>(); - initial_writes[0] = first_write; - initial_writes[1] = second_write; - inputs.previous_kernel.public_inputs.end.public_data_update_requests = initial_writes; - - // setup 2 previous data reads on the public inputs - const auto first_read = PublicDataRead{ - .leaf_index = 123456789, - .value = 96543, - }; - const auto second_read = PublicDataRead{ - .leaf_index = 987654321, - .value = 96544, - }; - std::array, MAX_PUBLIC_DATA_READS_PER_TX> initial_reads = - std::array, MAX_PUBLIC_DATA_READS_PER_TX>(); - initial_reads[0] = first_read; - initial_reads[1] = second_read; - inputs.previous_kernel.public_inputs.end.public_data_reads = initial_reads; - - // setup 2 previous new commitments - std::array initial_commitments{}; - initial_commitments[0] = fr(1); - initial_commitments[1] = fr(2); - inputs.previous_kernel.public_inputs.end.new_commitments = initial_commitments; - - // setup 2 previous new nullifiers - std::array initial_nullifiers{}; - initial_nullifiers[0] = fr(12345); - initial_nullifiers[1] = fr(67890); - inputs.previous_kernel.public_inputs.end.new_nullifiers = initial_nullifiers; - - // setup 1 new l2 to l1 messages - std::array initial_l2_to_l1_messages{}; - initial_l2_to_l1_messages[0] = fr(1); - inputs.previous_kernel.public_inputs.end.new_l2_to_l1_msgs = initial_l2_to_l1_messages; - - auto public_inputs = native_public_kernel_circuit_public_previous_kernel(dummyBuilder, inputs); - - // test that the prior set of private kernel public inputs were copied to the outputs - validate_private_data_propagation(dummyBuilder, inputs, public_inputs); - - // this call should have been popped from the public call stack and the stack of call pre images pushed on - for (size_t i = 0; i < MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL; i++) { - ASSERT_EQ(public_inputs.end.public_call_stack[i], - inputs.public_call.call_stack_item.public_inputs.public_call_stack[i]); - } - - // we should now see the public data reads and writes, new commitments, new_nullifiers, - // l2_to_l1_messages from this iteration appended to the combined output - ASSERT_EQ(array_length(public_inputs.end.public_data_reads), - array_length(inputs.previous_kernel.public_inputs.end.public_data_reads) + - array_length(inputs.public_call.call_stack_item.public_inputs.contract_storage_reads)); - ASSERT_EQ(array_length(public_inputs.end.public_data_update_requests), - array_length(inputs.previous_kernel.public_inputs.end.public_data_update_requests) + - array_length(inputs.public_call.call_stack_item.public_inputs.contract_storage_update_requests)); - ASSERT_EQ(array_length(public_inputs.end.new_commitments), - array_length(inputs.previous_kernel.public_inputs.end.new_commitments) + - array_length(inputs.public_call.call_stack_item.public_inputs.new_commitments)); - ASSERT_EQ(array_length(public_inputs.end.new_nullifiers), - array_length(inputs.previous_kernel.public_inputs.end.new_nullifiers) + - array_length(inputs.public_call.call_stack_item.public_inputs.new_nullifiers)); - ASSERT_EQ(array_length(public_inputs.end.new_l2_to_l1_msgs), - array_length(inputs.previous_kernel.public_inputs.end.new_l2_to_l1_msgs) + - array_length(inputs.public_call.call_stack_item.public_inputs.new_l2_to_l1_msgs)); - - - const auto contract_address = inputs.public_call.call_stack_item.contract_address; - const auto portal_contract_address = inputs.public_call.portal_contract_address; - std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL> const expected_new_writes = - public_data_update_requests_from_contract_storage_update_requests( - inputs.public_call.call_stack_item.public_inputs.contract_storage_update_requests, contract_address); - - // Unencrypted logs hash and preimage lengths should now be correctly accumulated - auto const& public_inputs_unencrypted_logs_hash = inputs.previous_kernel.public_inputs.end.unencrypted_logs_hash; - auto const& unencrypted_logs_hash = inputs.public_call.call_stack_item.public_inputs.unencrypted_logs_hash; - // TODO(914) Should this be unused? - [[maybe_unused]] auto const& expected_unencrypted_logs_hash = - accumulate_sha256({ public_inputs_unencrypted_logs_hash[0], - public_inputs_unencrypted_logs_hash[1], - unencrypted_logs_hash[0], - unencrypted_logs_hash[1] }); - - auto const& public_inputs_unencrypted_log_preimages_length = - inputs.previous_kernel.public_inputs.end.unencrypted_log_preimages_length; - auto const& unencrypted_log_preimages_length = - inputs.public_call.call_stack_item.public_inputs.unencrypted_log_preimages_length; - ASSERT_EQ(public_inputs.end.unencrypted_log_preimages_length, - unencrypted_log_preimages_length + public_inputs_unencrypted_log_preimages_length); - - ASSERT_TRUE(source_arrays_are_in_target(dummyBuilder, - inputs.previous_kernel.public_inputs.end.public_data_update_requests, - expected_new_writes, - public_inputs.end.public_data_update_requests)); - - std::array, MAX_PUBLIC_DATA_READS_PER_CALL> const expected_new_reads = - public_data_reads_from_contract_storage_reads( - inputs.public_call.call_stack_item.public_inputs.contract_storage_reads, contract_address); - - ASSERT_TRUE(source_arrays_are_in_target(dummyBuilder, - inputs.previous_kernel.public_inputs.end.public_data_reads, - expected_new_reads, - public_inputs.end.public_data_reads)); - - std::array const expected_new_commitments = - new_commitments_as_siloed_commitments(inputs.public_call.call_stack_item.public_inputs.new_commitments, - contract_address); - - ASSERT_TRUE(source_arrays_are_in_target(dummyBuilder, - inputs.previous_kernel.public_inputs.end.new_commitments, - expected_new_commitments, - public_inputs.end.new_commitments)); - - std::array const expected_new_nullifiers = new_nullifiers_as_siloed_nullifiers( - inputs.public_call.call_stack_item.public_inputs.new_nullifiers, contract_address); - - ASSERT_TRUE(source_arrays_are_in_target(dummyBuilder, - inputs.previous_kernel.public_inputs.end.new_nullifiers, - expected_new_nullifiers, - public_inputs.end.new_nullifiers)); - - // Reading the chain id and version from the tx context - fr const chain_id = inputs.previous_kernel.public_inputs.constants.tx_context.chain_id; - fr const version = inputs.previous_kernel.public_inputs.constants.tx_context.version; - - std::array const expected_new_messages = - new_l2_messages_from_message(inputs.public_call.call_stack_item.public_inputs.new_l2_to_l1_msgs, - contract_address, - portal_contract_address, - chain_id, - version); - - ASSERT_TRUE(source_arrays_are_in_target(dummyBuilder, - inputs.previous_kernel.public_inputs.end.new_l2_to_l1_msgs, - expected_new_messages, - public_inputs.end.new_l2_to_l1_msgs)); - - ASSERT_FALSE(dummyBuilder.failed()); -} - -TEST(public_kernel_tests, previous_public_kernel_fails_if_contract_storage_update_requests_on_static_call) -{ - DummyBuilder dummyBuilder = DummyBuilder( - "public_kernel_tests__previous_public_kernel_fails_if_contract_storage_update_requests_on_static_call"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(false); - - // the function call has contract storage update requests so setting it to static should fail - inputs.public_call.call_stack_item.public_inputs.call_context.is_static_call = true; - - auto public_inputs = native_public_kernel_circuit_public_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ( - dummyBuilder.get_first_failure().code, - CircuitErrorCode::PUBLIC_KERNEL__CALL_CONTEXT_CONTRACT_STORAGE_UPDATE_REQUESTS_PROHIBITED_FOR_STATIC_CALL); -} - -TEST(public_kernel_tests, previous_public_kernel_fails_if_incorrect_storage_contract_on_delegate_call) -{ - DummyBuilder dummyBuilder = DummyBuilder( - "public_kernel_tests__previous_public_kernel_fails_if_incorrect_storage_contract_on_delegate_call"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(false); - - // the function call has the contract address and storage contract address equal and so it should fail for a - // delegate call - inputs.public_call.call_stack_item.public_inputs.call_context.is_delegate_call = true; - - auto public_inputs = native_public_kernel_circuit_public_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, - CircuitErrorCode::PUBLIC_KERNEL__CALL_CONTEXT_INVALID_STORAGE_ADDRESS_FOR_DELEGATE_CALL); -} - -TEST(public_kernel_tests, public_kernel_fails_creating_new_commitments_on_static_call) -{ - DummyBuilder dummyBuilder = DummyBuilder("public_kernel_fails_creating_new_commitments_on_static_call"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(false); - - // the function call has the contract address and storage contract address equal and so it should fail for a - // delegate call - inputs.public_call.call_stack_item.public_inputs.call_context.is_static_call = true; - - // set previously set items to 0 - inputs.public_call.call_stack_item.public_inputs.contract_storage_update_requests = - empty_array_of_values, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL>(); - - // regenerate call data hash - inputs.previous_kernel.public_inputs.end.public_call_stack[0] = - get_call_stack_item_hash(inputs.public_call.call_stack_item); - - // Update call stack hash - auto public_inputs = native_public_kernel_circuit_public_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, - CircuitErrorCode::PUBLIC_KERNEL__NEW_COMMITMENTS_PROHIBITED_IN_STATIC_CALL); -} - -TEST(public_kernel_tests, public_kernel_fails_creating_new_nullifiers_on_static_call) -{ - DummyBuilder dummyBuilder = DummyBuilder("public_kernel_fails_creating_new_nullifiers_on_static_call"); - PublicKernelInputs inputs = get_kernel_inputs_with_previous_kernel(false); - - // the function call has the contract address and storage contract address equal and so it should fail for a - // delegate call - inputs.public_call.call_stack_item.public_inputs.call_context.is_static_call = true; - - // set previously set items to 0 - inputs.public_call.call_stack_item.public_inputs.contract_storage_update_requests = - empty_array_of_values, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL>(); - inputs.public_call.call_stack_item.public_inputs.new_commitments = - empty_array_of_values(); - - // regenerate call data hash - inputs.previous_kernel.public_inputs.end.public_call_stack[0] = - get_call_stack_item_hash(inputs.public_call.call_stack_item); - - // Update call stack hash - auto public_inputs = native_public_kernel_circuit_public_previous_kernel(dummyBuilder, inputs); - ASSERT_TRUE(dummyBuilder.failed()); - ASSERT_EQ(dummyBuilder.get_first_failure().code, - CircuitErrorCode::PUBLIC_KERNEL__NEW_NULLIFIERS_PROHIBITED_IN_STATIC_CALL); -} - -TEST(public_kernel_tests, logs_are_handled_as_expected) -{ - DummyBuilder dummyBuilder = DummyBuilder("public_kernel_tests__logs_are_handled_as_expected"); - PublicKernelInputs const& inputs = get_kernel_inputs_with_previous_kernel(true); - std::array const& zero_hash{}; - - // Ensure encrypted logs hash values are non-zero - ASSERT_NE(inputs.previous_kernel.public_inputs.end.encrypted_logs_hash, zero_hash); - - auto const& public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs); - - // Encrypted logs hash values are propagated form input to output without change - ASSERT_EQ(inputs.previous_kernel.public_inputs.end.encrypted_logs_hash, public_inputs.end.encrypted_logs_hash); - - // Unencrypted logs hash and preimage lengths should now be correctly accumulated - auto const& public_inputs_unencrypted_logs_hash = inputs.previous_kernel.public_inputs.end.unencrypted_logs_hash; - auto const& unencrypted_logs_hash = inputs.public_call.call_stack_item.public_inputs.unencrypted_logs_hash; - // TODO(914) Should this be unused? - [[maybe_unused]] auto const& expected_unencrypted_logs_hash = - accumulate_sha256({ public_inputs_unencrypted_logs_hash[0], - public_inputs_unencrypted_logs_hash[1], - unencrypted_logs_hash[0], - unencrypted_logs_hash[1] }); - - auto const& public_inputs_unencrypted_log_preimages_length = - inputs.previous_kernel.public_inputs.end.unencrypted_log_preimages_length; - auto const& unencrypted_log_preimages_length = - inputs.public_call.call_stack_item.public_inputs.unencrypted_log_preimages_length; - ASSERT_EQ(public_inputs.end.unencrypted_log_preimages_length, - unencrypted_log_preimages_length + public_inputs_unencrypted_log_preimages_length); - - ASSERT_FALSE(dummyBuilder.failed()); -} - -} // namespace aztec3::circuits::kernel::public_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/c_bind.cpp b/circuits/cpp/src/aztec3/circuits/kernel/public/c_bind.cpp deleted file mode 100644 index 33fa83c4f3c..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/c_bind.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "c_bind.h" - -#include "index.hpp" -#include "init.hpp" - -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/public_kernel/public_kernel_inputs.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace { -using Builder = UltraCircuitBuilder; -using NT = aztec3::utils::types::NativeTypes; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using aztec3::circuits::abis::public_kernel::PublicKernelInputs; -using aztec3::circuits::kernel::public_kernel::native_public_kernel_circuit_private_previous_kernel; -using aztec3::circuits::kernel::public_kernel::native_public_kernel_circuit_public_previous_kernel; - -// WASM Cbinds -CBIND(public_kernel__sim, [](PublicKernelInputs const& public_kernel_inputs) { - DummyBuilder builder = DummyBuilder("public_kernel__sim"); - KernelCircuitPublicInputs const result = - public_kernel_inputs.previous_kernel.public_inputs.is_private - ? native_public_kernel_circuit_private_previous_kernel(builder, public_kernel_inputs) - : native_public_kernel_circuit_public_previous_kernel(builder, public_kernel_inputs); - return builder.result_or_error(result); -}); - -} // namespace diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/c_bind.h b/circuits/cpp/src/aztec3/circuits/kernel/public/c_bind.h deleted file mode 100644 index 85086a48cff..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/c_bind.h +++ /dev/null @@ -1,6 +0,0 @@ -#include - -#include -#include - -CBIND_DECL(public_kernel__sim); diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/common.cpp b/circuits/cpp/src/aztec3/circuits/kernel/public/common.cpp deleted file mode 100644 index 16023f9fe42..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/common.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "common.hpp" - -#include "init.hpp" - -#include "aztec3/circuits/abis/call_stack_item.hpp" -#include "aztec3/circuits/abis/types.hpp" - -namespace aztec3::circuits::kernel::public_kernel { - -using aztec3::utils::array_pop; - -void common_initialize_end_values(PublicKernelInputs const& public_kernel_inputs, - KernelCircuitPublicInputs& circuit_outputs) -{ - // Initializes the circuit outputs with the end state of the previous iteration - circuit_outputs.constants = public_kernel_inputs.previous_kernel.public_inputs.constants; - - // Ensure the arrays are the same as previously, before we start pushing more data onto them in other functions - // within this circuit: - auto& end = circuit_outputs.end; - const auto& start = public_kernel_inputs.previous_kernel.public_inputs.end; - - end.new_commitments = start.new_commitments; - end.new_nullifiers = start.new_nullifiers; - - end.private_call_stack = start.private_call_stack; - end.public_call_stack = start.public_call_stack; - end.new_l2_to_l1_msgs = start.new_l2_to_l1_msgs; - - end.optionally_revealed_data = start.optionally_revealed_data; - - end.public_data_update_requests = start.public_data_update_requests; - end.public_data_reads = start.public_data_reads; - - // Public kernel does not modify encrypted logs values --> we just copy them to output - end.encrypted_logs_hash = start.encrypted_logs_hash; - end.encrypted_log_preimages_length = start.encrypted_log_preimages_length; - - end.new_contracts = start.new_contracts; -} - -/** - * @brief Validates that the call stack item for this circuit iteration is at the top of the call stack - * @param builder The circuit builder - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - */ -void validate_this_public_call_hash(DummyBuilder& builder, - PublicKernelInputs const& public_kernel_inputs, - KernelCircuitPublicInputs& public_inputs) -{ - // If public call stack is empty, we bail so array_pop doesn't throw_or_abort - if (array_length(public_inputs.end.public_call_stack) == 0) { - builder.do_assert( - false, "Public call stack can't be empty", CircuitErrorCode::PUBLIC_KERNEL__EMPTY_PUBLIC_CALL_STACK); - return; - } - - // Pops the current function execution from the stack and validates it against the call stack item - - // TODO: this logic might need to change to accommodate the weird edge 3 initial txs (the 'main' tx, the 'fee' tx, - // and the 'gas rebate' tx). - const auto popped_public_call_hash = array_pop(public_inputs.end.public_call_stack); - const auto calculated_this_public_call_hash = - get_call_stack_item_hash(public_kernel_inputs.public_call.call_stack_item); - - builder.do_assert( - popped_public_call_hash == calculated_this_public_call_hash, - format("calculated public_call_hash (", - calculated_this_public_call_hash, - ") does not match provided public_call_hash (", - popped_public_call_hash, - ") at the top of the call stack"), - CircuitErrorCode::PUBLIC_KERNEL__CALCULATED_PUBLIC_CALL_HASH_AND_PROVIDED_PUBLIC_CALL_HASH_MISMATCH); -}; -} // namespace aztec3::circuits::kernel::public_kernel diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/common.hpp b/circuits/cpp/src/aztec3/circuits/kernel/public/common.hpp deleted file mode 100644 index 052c3152416..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/common.hpp +++ /dev/null @@ -1,459 +0,0 @@ -#pragma once - -#include "init.hpp" - -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/public_data_update_request.hpp" -#include "aztec3/circuits/abis/public_kernel/public_kernel_inputs.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/utils/array.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" - -namespace aztec3::circuits::kernel::public_kernel { - -using NT = aztec3::utils::types::NativeTypes; -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using aztec3::circuits::abis::PublicDataRead; -using aztec3::circuits::abis::PublicDataUpdateRequest; -using aztec3::circuits::abis::public_kernel::PublicKernelInputs; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; -using aztec3::utils::array_length; -using aztec3::utils::array_push; -using aztec3::utils::push_array_to_array; - -/** - * @brief Validate that all pre-images on the call stack hash to equal the accumulated data - * @tparam The type of kernel input - * @param builder The circuit builder - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - */ -template -void common_validate_call_stack(DummyBuilder& builder, KernelInput const& public_kernel_inputs) -{ - // Ensures that the stack of pre-images corresponds to the call stack - auto& stack = public_kernel_inputs.public_call.call_stack_item.public_inputs.public_call_stack; - auto& preimages = public_kernel_inputs.public_call.public_call_stack_preimages; - - // grab our contract address, our storage contract address and our portal contract address to verify - // child executions in the case of delegate call types - auto our_contract_address = public_kernel_inputs.public_call.call_stack_item.contract_address; - auto our_storage_address = - public_kernel_inputs.public_call.call_stack_item.public_inputs.call_context.storage_contract_address; - auto our_msg_sender = public_kernel_inputs.public_call.call_stack_item.public_inputs.call_context.msg_sender; - auto our_portal_contract_address = - public_kernel_inputs.public_call.call_stack_item.public_inputs.call_context.portal_contract_address; - - for (size_t i = 0; i < stack.size(); ++i) { - const auto& hash = stack[i]; - const auto& preimage = preimages[i]; - - // Note: this assumes it's computationally infeasible to have `0` as a valid call_stack_item_hash. - // Assumes `hash == 0` means "this stack item is empty". - if (hash == 0) { - continue; - } - - const auto is_delegate_call = preimage.public_inputs.call_context.is_delegate_call; - const auto is_static_call = preimage.public_inputs.call_context.is_static_call; - const auto contract_being_called = preimage.contract_address; - - const auto calculated_hash = preimage.hash(); - builder.do_assert( - hash == calculated_hash, - format( - "public_call_stack[", i, "] = ", hash, "; does not reconcile with calculatedHash = ", calculated_hash), - CircuitErrorCode::PUBLIC_KERNEL__PUBLIC_CALL_STACK_MISMATCH); - - // here we validate the msg sender for each call on the stack - // we need to consider regular vs delegate calls - const auto preimage_msg_sender = preimage.public_inputs.call_context.msg_sender; - const auto expected_msg_sender = is_delegate_call ? our_msg_sender : our_contract_address; - builder.do_assert(expected_msg_sender == preimage_msg_sender, - format("call_stack_msg_sender[", - i, - "] = ", - preimage_msg_sender, - " expected ", - expected_msg_sender, - "; does not reconcile"), - CircuitErrorCode::PUBLIC_KERNEL__PUBLIC_CALL_STACK_INVALID_MSG_SENDER); - - // here we validate the storage address for each call on the stack - // we need to consider regular vs delegate calls - const auto preimage_storage_address = preimage.public_inputs.call_context.storage_contract_address; - const auto expected_storage_address = is_delegate_call ? our_storage_address : contract_being_called; - builder.do_assert(expected_storage_address == preimage_storage_address, - format("call_stack_storage_address[", - i, - "] = ", - preimage_storage_address, - " expected ", - expected_storage_address, - "; does not reconcile"), - CircuitErrorCode::PUBLIC_KERNEL__PUBLIC_CALL_STACK_INVALID_STORAGE_ADDRESS); - - // if it is a delegate call then we check that the portal contract in the pre image is our portal contract - const auto preimage_portal_address = preimage.public_inputs.call_context.portal_contract_address; - const auto expected_portal_address = our_portal_contract_address; - builder.do_assert(!is_delegate_call || expected_portal_address == preimage_portal_address, - format("call_stack_portal_address[", - i, - "] = ", - preimage_portal_address, - " expected ", - expected_portal_address, - "; does not reconcile for a delegate call"), - CircuitErrorCode::PUBLIC_KERNEL__PUBLIC_CALL_STACK_INVALID_PORTAL_ADDRESS); - - const auto num_contract_storage_update_requests = - array_length(preimage.public_inputs.contract_storage_update_requests); - builder.do_assert( - !is_static_call || num_contract_storage_update_requests == 0, - format("contract_storage_update_requests[", i, "] should be empty for a static call"), - CircuitErrorCode::PUBLIC_KERNEL__PUBLIC_CALL_STACK_CONTRACT_STORAGE_UPDATES_PROHIBITED_FOR_STATIC_CALL); - } -}; - -/** - * @brief Validates the call context of the current iteration - * @tparam The type of kernel input - * @param builder The circuit builder - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - */ -template -void common_validate_call_context(DummyBuilder& builder, KernelInput const& public_kernel_inputs) -{ - const auto& call_stack_item = public_kernel_inputs.public_call.call_stack_item; - const auto is_delegate_call = call_stack_item.public_inputs.call_context.is_delegate_call; - const auto is_static_call = call_stack_item.public_inputs.call_context.is_static_call; - const auto contract_address = call_stack_item.contract_address; - const auto storage_contract_address = call_stack_item.public_inputs.call_context.storage_contract_address; - const auto contract_storage_update_requests_length = - array_length(call_stack_item.public_inputs.contract_storage_update_requests); - - builder.do_assert(!is_delegate_call || contract_address != storage_contract_address, - std::string("curent contract address must not match storage contract address for delegate calls"), - CircuitErrorCode::PUBLIC_KERNEL__CALL_CONTEXT_INVALID_STORAGE_ADDRESS_FOR_DELEGATE_CALL); - - builder.do_assert( - !is_static_call || contract_storage_update_requests_length == 0, - std::string("No contract storage update requests are allowed for static calls"), - CircuitErrorCode::PUBLIC_KERNEL__CALL_CONTEXT_CONTRACT_STORAGE_UPDATE_REQUESTS_PROHIBITED_FOR_STATIC_CALL); -}; - -/** - * @brief Validates the kernel execution of the current iteration - * @tparam The type of kernel input - * @param builder The circuit builder - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - */ -template -void common_validate_kernel_execution(DummyBuilder& builder, KernelInput const& public_kernel_inputs) -{ - common_validate_call_context(builder, public_kernel_inputs); - common_validate_call_stack(builder, public_kernel_inputs); -}; - -/** - * @brief Validates inputs to the kernel circuit that are common to all invocation scenarios - * @tparam The type of kernel input - * @param builder The circuit builder - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - */ -template -void common_validate_inputs(DummyBuilder& builder, KernelInput const& public_kernel_inputs) -{ - // Validates commons inputs for all type of kernel inputs - const auto& this_call_stack_item = public_kernel_inputs.public_call.call_stack_item; - builder.do_assert(this_call_stack_item.public_inputs.call_context.is_contract_deployment == false, - "Contract deployment can't be a public function", - CircuitErrorCode::PUBLIC_KERNEL__CONTRACT_DEPLOYMENT_NOT_ALLOWED); - builder.do_assert(this_call_stack_item.contract_address != 0, - "Contract address must be non-zero", - CircuitErrorCode::PUBLIC_KERNEL__CONTRACT_ADDRESS_INVALID); - builder.do_assert(this_call_stack_item.function_data.selector.value != 0, - "Function signature must be non-zero", - CircuitErrorCode::PUBLIC_KERNEL__FUNCTION_SIGNATURE_INVALID); - builder.do_assert(this_call_stack_item.function_data.is_constructor == false, - "Constructors can't be public functions", - CircuitErrorCode::PUBLIC_KERNEL__CONSTRUCTOR_NOT_ALLOWED); - builder.do_assert(this_call_stack_item.function_data.is_private == false, - "Cannot execute a private function with the public kernel circuit", - CircuitErrorCode::PUBLIC_KERNEL__PRIVATE_FUNCTION_NOT_ALLOWED); - builder.do_assert(public_kernel_inputs.public_call.bytecode_hash != 0, - "Bytecode hash must be non-zero", - CircuitErrorCode::PUBLIC_KERNEL__BYTECODE_HASH_INVALID); - - if (this_call_stack_item.function_data.is_internal) { - auto const target = this_call_stack_item.contract_address; - auto const sender = this_call_stack_item.public_inputs.call_context.msg_sender; - - builder.do_assert(target == sender, - "call is internal, but msg_sender is not self", - CircuitErrorCode::PUBLIC_KERNEL__IS_INTERNAL_BUT_NOT_SELF_CALL); - } -} - -template -void perform_static_call_checks(Builder& builder, KernelInput const& public_kernel_inputs) -{ - // If the call is a static call, there should be no new commitments or nullifiers. - const auto& public_call_public_inputs = public_kernel_inputs.public_call.call_stack_item.public_inputs; - - const auto& is_static_call = public_call_public_inputs.call_context.is_static_call; - const auto& new_commitments = public_call_public_inputs.new_commitments; - const auto& new_nullifiers = public_call_public_inputs.new_nullifiers; - - if (is_static_call) { - builder.do_assert(utils::is_array_empty(new_commitments) == true, - "no new commitments must be created for static calls", - CircuitErrorCode::PUBLIC_KERNEL__NEW_COMMITMENTS_PROHIBITED_IN_STATIC_CALL); - builder.do_assert(utils::is_array_empty(new_nullifiers) == true, - "no new nullifiers must be created for static calls", - CircuitErrorCode::PUBLIC_KERNEL__NEW_NULLIFIERS_PROHIBITED_IN_STATIC_CALL); - } -} - -/** - * @brief Propagates valid (i.e. non-empty) update requests from this iteration to the circuit output - * @tparam The type of kernel input - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - * @param circuit_outputs The circuit outputs to be populated - */ -template -void propagate_valid_public_data_update_requests(Builder& builder, - KernelInput const& public_kernel_inputs, - KernelCircuitPublicInputs& circuit_outputs) -{ - const auto& contract_address = public_kernel_inputs.public_call.call_stack_item.contract_address; - const auto& update_requests = - public_kernel_inputs.public_call.call_stack_item.public_inputs.contract_storage_update_requests; - for (size_t i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; ++i) { - const auto& update_request = update_requests[i]; - if (update_request.is_empty()) { - continue; - } - const auto new_write = PublicDataUpdateRequest{ - .leaf_index = compute_public_data_tree_index(contract_address, update_request.storage_slot), - .old_value = compute_public_data_tree_value(update_request.old_value), - .new_value = compute_public_data_tree_value(update_request.new_value), - }; - array_push( - builder, - circuit_outputs.end.public_data_update_requests, - new_write, - format(PUBLIC_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, "too many public data update requests in one tx")); - } -} - -/** - * @brief Propagates valid (i.e. non-empty) public data reads from this iteration to the circuit output - * @tparam The type of kernel input - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - * @param circuit_outputs The circuit outputs to be populated - */ -template -void propagate_valid_public_data_reads(Builder& builder, - KernelInput const& public_kernel_inputs, - KernelCircuitPublicInputs& circuit_outputs) -{ - const auto& contract_address = public_kernel_inputs.public_call.call_stack_item.contract_address; - const auto& reads = public_kernel_inputs.public_call.call_stack_item.public_inputs.contract_storage_reads; - for (size_t i = 0; i < MAX_PUBLIC_DATA_READS_PER_TX; ++i) { - const auto& contract_storage_read = reads[i]; - if (contract_storage_read.is_empty()) { - continue; - } - const auto new_read = PublicDataRead{ - .leaf_index = compute_public_data_tree_index(contract_address, contract_storage_read.storage_slot), - .value = compute_public_data_tree_value(contract_storage_read.current_value), - }; - array_push(builder, - circuit_outputs.end.public_data_reads, - new_read, - format(PUBLIC_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, "too many public data reads in one tx")); - } -} - -/** - * @brief Propagates new commitments from this iteration to the circuit output. - * - * @tparam The type of the kernel input - * @tparam The builder type - * @param public_kernel_inputs The inputs to this iteration to the kernel circuit. - * @param circuit_outputs The circuit outputs to be populated - */ -template -void propagate_new_commitments(Builder& builder, - KernelInput const& public_kernel_inputs, - KernelCircuitPublicInputs& circuit_outputs) -{ - // Get the new commitments - const auto& public_call_public_inputs = public_kernel_inputs.public_call.call_stack_item.public_inputs; - - const auto& new_commitments = public_call_public_inputs.new_commitments; - const auto& storage_contract_address = public_call_public_inputs.call_context.storage_contract_address; - - std::array siloed_new_commitments{}; - for (size_t i = 0; i < new_commitments.size(); ++i) { - if (!new_commitments[i].is_zero()) { - siloed_new_commitments[i] = silo_commitment(storage_contract_address, new_commitments[i]); - } - } - - push_array_to_array(builder, - siloed_new_commitments, - circuit_outputs.end.new_commitments, - format(PUBLIC_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, "too many new commitments in one tx")); -} - -/** - * @brief Propagates new nullifiers from this iteration to the circuit output. - * - * @tparam The type of the kernel input - * @tparam The builder type - * @param public_kernel_inputs The inputs to this iteration to the kernel circuit. - * @param circuit_outputs The circuit outputs to be populated - */ -template -void propagate_new_nullifiers(Builder& builder, - KernelInput const& public_kernel_inputs, - KernelCircuitPublicInputs& circuit_outputs) -{ - // Get the new commitments - const auto& public_call_public_inputs = public_kernel_inputs.public_call.call_stack_item.public_inputs; - - const auto& new_nullifiers = public_call_public_inputs.new_nullifiers; - const auto& storage_contract_address = public_call_public_inputs.call_context.storage_contract_address; - - std::array siloed_new_nullifiers{}; - for (size_t i = 0; i < new_nullifiers.size(); ++i) { - if (!new_nullifiers[i].is_zero()) { - siloed_new_nullifiers[i] = silo_nullifier(storage_contract_address, new_nullifiers[i]); - } - } - - push_array_to_array(builder, - siloed_new_nullifiers, - circuit_outputs.end.new_nullifiers, - format(PUBLIC_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, "too many new nullifiers in one tx")); -} - -/** - * @brief Propagates new l2 to l1 messages from this iteration to the circuit output. - * - * @tparam The type of the kernel input - * @param public_kernel_inputs The inputs to this iteration to the kernel circuit. - * @param circuit_outputs The circuit outputs to be populated - */ -template -void propagate_new_l2_to_l1_messages(Builder& builder, - KernelInput const& public_kernel_inputs, - KernelCircuitPublicInputs& circuit_outputs) -{ - // Get the new l2 messages - const auto& public_call_public_inputs = public_kernel_inputs.public_call.call_stack_item.public_inputs; - - const auto& portal_contract_address = public_kernel_inputs.public_call.portal_contract_address; - const auto& storage_contract_address = public_call_public_inputs.call_context.storage_contract_address; - const auto& new_l2_to_l1_msgs = public_call_public_inputs.new_l2_to_l1_msgs; - - std::array new_l2_to_l1_msgs_to_insert{}; - for (size_t i = 0; i < new_l2_to_l1_msgs.size(); ++i) { - if (!new_l2_to_l1_msgs[i].is_zero()) { - const auto chain_id = public_kernel_inputs.previous_kernel.public_inputs.constants.tx_context.chain_id; - const auto version = public_kernel_inputs.previous_kernel.public_inputs.constants.tx_context.version; - - new_l2_to_l1_msgs_to_insert[i] = compute_l2_to_l1_hash( - storage_contract_address, version, portal_contract_address, chain_id, new_l2_to_l1_msgs[i]); - } - } - push_array_to_array( - builder, - new_l2_to_l1_msgs_to_insert, - circuit_outputs.end.new_l2_to_l1_msgs, - format(PUBLIC_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, "too many new l2 to l1 messages in one tx")); -} - -/** - * @brief Accumulates unencrypted logs hashes and lengths. - * @tparam The type of kernel input - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - * @param circuit_outputs The circuit outputs to be populated - * @note See the following thread if not clear: - * https://discourse.aztec.network/t/proposal-forcing-the-sequencer-to-actually-submit-data-to-l1/426 - * @note Used by public kernels which had previous iterations. - */ -template void accumulate_unencrypted_logs(PublicKernelInputs const& public_kernel_inputs, - KernelCircuitPublicInputs& circuit_outputs) -{ - const auto public_call_public_inputs = public_kernel_inputs.public_call.call_stack_item.public_inputs; - - const auto& previous_kernel_end = public_kernel_inputs.previous_kernel.public_inputs.end; - const auto& previous_unencrypted_logs_hash = previous_kernel_end.unencrypted_logs_hash; - - const auto& current_unencrypted_logs_hash = public_call_public_inputs.unencrypted_logs_hash; - circuit_outputs.end.unencrypted_logs_hash = accumulate_sha256({ previous_unencrypted_logs_hash[0], - previous_unencrypted_logs_hash[1], - current_unencrypted_logs_hash[0], - current_unencrypted_logs_hash[1] }); - - // Add log preimages lengths from current iteration to accumulated lengths - const auto& current_unencrypted_log_preimages_length = public_call_public_inputs.unencrypted_log_preimages_length; - circuit_outputs.end.unencrypted_log_preimages_length = - previous_kernel_end.unencrypted_log_preimages_length + current_unencrypted_log_preimages_length; -} - -/** - * @brief Propagates valid (i.e. non-empty) public data reads from this iteration to the circuit output - * @tparam The type of kernel input - * @tparam The current builder - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - * @param circuit_outputs The circuit outputs to be populated - */ -template -void common_update_public_end_values(Builder& builder, - KernelInput const& public_kernel_inputs, - KernelCircuitPublicInputs& circuit_outputs) -{ - // Updates the circuit outputs with new state changes, call stack etc - circuit_outputs.is_private = false; - - // If this call is a static call, certain operations are disallowed, such as creating new state. - perform_static_call_checks(builder, public_kernel_inputs); - - const auto& stack = public_kernel_inputs.public_call.call_stack_item.public_inputs.public_call_stack; - push_array_to_array( - builder, - stack, - circuit_outputs.end.public_call_stack, - format(PUBLIC_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING, "too many public call stack items in one tx")); - - propagate_new_commitments(builder, public_kernel_inputs, circuit_outputs); - propagate_new_nullifiers(builder, public_kernel_inputs, circuit_outputs); - - propagate_new_l2_to_l1_messages(builder, public_kernel_inputs, circuit_outputs); - - propagate_valid_public_data_update_requests(builder, public_kernel_inputs, circuit_outputs); - - propagate_valid_public_data_reads(builder, public_kernel_inputs, circuit_outputs); -} - -/** - * @brief Initializes the circuit output end state from provided inputs - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - * @param circuit_outputs The circuit outputs to be initialized - */ -void common_initialize_end_values(PublicKernelInputs const& public_kernel_inputs, - KernelCircuitPublicInputs& circuit_outputs); - -/** - * @brief Validates that the call stack item for this circuit iteration is at the top of the call stack - * @param builder The circuit builder - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - * @param public_inputs The circuit outputs - */ -void validate_this_public_call_hash(DummyBuilder& builder, - PublicKernelInputs const& public_kernel_inputs, - KernelCircuitPublicInputs& public_inputs); -} // namespace aztec3::circuits::kernel::public_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/index.hpp b/circuits/cpp/src/aztec3/circuits/kernel/public/index.hpp deleted file mode 100644 index db8f855b55c..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/index.hpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "init.hpp" -#include "native_public_kernel_circuit_private_previous_kernel.hpp" -#include "native_public_kernel_circuit_public_previous_kernel.hpp" \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/init.hpp b/circuits/cpp/src/aztec3/circuits/kernel/public/init.hpp deleted file mode 100644 index d146108face..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/init.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once -#include "aztec3/circuits/apps/oracle_wrapper.hpp" -#include "aztec3/circuits/recursion/aggregator.hpp" -#include "aztec3/oracle/oracle.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -namespace aztec3::circuits::kernel::public_kernel { - -using Builder = proof_system::UltraCircuitBuilder; - -using Aggregator = aztec3::circuits::recursion::Aggregator; - -// Generic: -using CT = aztec3::utils::types::CircuitTypes; -using NT = aztec3::utils::types::NativeTypes; -using aztec3::utils::types::to_ct; -using CircuitErrorCode = aztec3::utils::CircuitErrorCode; - -using DB = oracle::FakeDB; -using oracle::NativeOracle; -using OracleWrapper = aztec3::circuits::apps::OracleWrapperInterface; - -// Used when calling library functions like `push_array` which have their own generic error code. -// So we pad this in front of the error message to identify where the error originally came from. -const std::string PUBLIC_KERNEL_CIRCUIT_ERROR_MESSAGE_BEGINNING = "public_kernel_circuit: "; - -} // namespace aztec3::circuits::kernel::public_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_private_previous_kernel.cpp b/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_private_previous_kernel.cpp deleted file mode 100644 index bbb9eda5871..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_private_previous_kernel.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "common.hpp" -#include "init.hpp" -#include "native_public_kernel_circuit_public_previous_kernel.hpp" - -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/public_kernel/public_kernel_inputs.hpp" -#include "aztec3/utils/array.hpp" -#include "aztec3/utils/circuit_errors.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" - -// Purpose of this anonymous namespace is to avoid to clash with the validate_inputs() -// counterpart defined in native_public_kernel_circuit_public_previous_kernel.cpp -namespace { -using CircuitErrorCode = aztec3::utils::CircuitErrorCode; -using aztec3::circuits::kernel::public_kernel::NT; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; -using aztec3::circuits::abis::public_kernel::PublicKernelInputs; -using aztec3::utils::array_length; - -/** - * @brief Validates the kernel circuit inputs specific to having a private previous kernel - * @param builder The circuit builder - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - */ -void validate_inputs(DummyBuilder& builder, PublicKernelInputs const& public_kernel_inputs) -{ - builder.do_assert(array_length(public_kernel_inputs.previous_kernel.public_inputs.end.private_call_stack) == 0, - "Private call stack must be empty when executing in the public kernel (i.e. all private calls " - "must have been completed)", - CircuitErrorCode::PUBLIC_KERNEL__NON_EMPTY_PRIVATE_CALL_STACK); - builder.do_assert(public_kernel_inputs.previous_kernel.public_inputs.is_private == true, - "Previous kernel must be private when in this public kernel version", - CircuitErrorCode::PUBLIC_KERNEL__PREVIOUS_KERNEL_NOT_PRIVATE); -} -} // namespace - -namespace aztec3::circuits::kernel::public_kernel { - -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using aztec3::circuits::kernel::public_kernel::common_initialize_end_values; -using aztec3::circuits::kernel::public_kernel::common_validate_kernel_execution; - - -/** - * @brief Entry point for the native public kernel circuit with a private previous kernel - * @param builder The circuit builder - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - * @return The circuit public inputs - */ -KernelCircuitPublicInputs native_public_kernel_circuit_private_previous_kernel( - DummyBuilder& builder, PublicKernelInputs const& public_kernel_inputs) -{ - // construct the circuit outputs - KernelCircuitPublicInputs public_inputs{}; - - // initialize the end state with our provided previous kernel state - common_initialize_end_values(public_kernel_inputs, public_inputs); - - // validate the inputs common to all invocation circumstances - common_validate_inputs(builder, public_kernel_inputs); - - // validate the inputs unique to having a previous private kernel - validate_inputs(builder, public_kernel_inputs); - - // validate the kernel execution common to all invocation circumstances - common_validate_kernel_execution(builder, public_kernel_inputs); - - // validate our public call hash - validate_this_public_call_hash(builder, public_kernel_inputs, public_inputs); - - // update the public end state of the circuit - common_update_public_end_values(builder, public_kernel_inputs, public_inputs); - - accumulate_unencrypted_logs(public_kernel_inputs, public_inputs); - - return public_inputs; -}; - -} // namespace aztec3::circuits::kernel::public_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_private_previous_kernel.hpp b/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_private_previous_kernel.hpp deleted file mode 100644 index 46eab401e78..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_private_previous_kernel.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "common.hpp" -#include "init.hpp" - -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/public_kernel/public_kernel_inputs.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" - -namespace aztec3::circuits::kernel::public_kernel { - -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using aztec3::circuits::abis::public_kernel::PublicKernelInputs; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; - -KernelCircuitPublicInputs native_public_kernel_circuit_private_previous_kernel( - DummyBuilder& builder, PublicKernelInputs const& public_kernel_inputs); -} // namespace aztec3::circuits::kernel::public_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_public_previous_kernel.cpp b/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_public_previous_kernel.cpp deleted file mode 100644 index 27aa8dc6580..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_public_previous_kernel.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "native_public_kernel_circuit_public_previous_kernel.hpp" - -#include "common.hpp" -#include "init.hpp" - -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/public_kernel/public_kernel_inputs.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" - -// Purpose of this anonymous namespace is to avoid to clash with the validate_inputs() -// counterpart defined in native_public_kernel_circuit_private_previous_kernel.cpp -namespace { -using CircuitErrorCode = aztec3::utils::CircuitErrorCode; -using aztec3::circuits::kernel::public_kernel::NT; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; -using aztec3::circuits::abis::public_kernel::PublicKernelInputs; - -/** - * @brief Validates the kernel circuit inputs specific to having a public previous kernel - * @param builder The circuit builder - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - */ -void validate_inputs(DummyBuilder& builder, PublicKernelInputs const& public_kernel_inputs) -{ - const auto& previous_kernel = public_kernel_inputs.previous_kernel.public_inputs; - builder.do_assert(previous_kernel.is_private == false, - "Previous kernel must be public when in this public kernel version", - CircuitErrorCode::PUBLIC_KERNEL__PREVIOUS_KERNEL_NOT_PUBLIC); -} -} // namespace - -namespace aztec3::circuits::kernel::public_kernel { - -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using aztec3::circuits::kernel::public_kernel::common_validate_kernel_execution; - - -/** - * @brief Entry point for the native public kernel circuit with a public previous kernel - * @param builder The circuit builder - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - * @return The circuit public inputs - */ -KernelCircuitPublicInputs native_public_kernel_circuit_public_previous_kernel( - DummyBuilder& builder, PublicKernelInputs const& public_kernel_inputs) -{ - // construct the circuit outputs - KernelCircuitPublicInputs public_inputs{}; - - // initialize the end state with our provided previous kernel state - common_initialize_end_values(public_kernel_inputs, public_inputs); - - // validate the inputs common to all invocation circumstances - common_validate_inputs(builder, public_kernel_inputs); - - // validate the inputs unique to having a previous public kernel - validate_inputs(builder, public_kernel_inputs); - - // validate the kernel execution common to all invocation circumstances - common_validate_kernel_execution(builder, public_kernel_inputs); - - // validate our public call hash - validate_this_public_call_hash(builder, public_kernel_inputs, public_inputs); - - // update the public end state of the circuit - common_update_public_end_values(builder, public_kernel_inputs, public_inputs); - - accumulate_unencrypted_logs(public_kernel_inputs, public_inputs); - - return public_inputs; -}; - -} // namespace aztec3::circuits::kernel::public_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_public_previous_kernel.hpp b/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_public_previous_kernel.hpp deleted file mode 100644 index 8d21acd913c..00000000000 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_public_previous_kernel.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "common.hpp" -#include "init.hpp" - -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/public_kernel/public_kernel_inputs.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" - -namespace aztec3::circuits::kernel::public_kernel { - -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using aztec3::circuits::abis::public_kernel::PublicKernelInputs; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; - -KernelCircuitPublicInputs native_public_kernel_circuit_public_previous_kernel( - DummyBuilder& builder, PublicKernelInputs const& public_kernel_inputs); -} // namespace aztec3::circuits::kernel::public_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/mock/mock_circuit.hpp b/circuits/cpp/src/aztec3/circuits/mock/mock_circuit.hpp deleted file mode 100644 index 4e5c2744757..00000000000 --- a/circuits/cpp/src/aztec3/circuits/mock/mock_circuit.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include - -namespace aztec3::circuits::mock { - -using namespace plonk::stdlib; - -template void mock_circuit(Builder& builder, std::vector const& public_inputs_) -{ - const auto public_inputs = map(public_inputs_, [&](auto& i) { return field_t(witness_t(&builder, i)); }); - for (auto& p : public_inputs) { - p.set_public(); - } - plonk::stdlib::pedersen::hash({ field_t(witness_t(&builder, 1)), field_t(witness_t(&builder, 1)) }); -} - -} // namespace aztec3::circuits::mock diff --git a/circuits/cpp/src/aztec3/circuits/mock/mock_kernel_circuit.hpp b/circuits/cpp/src/aztec3/circuits/mock/mock_kernel_circuit.hpp deleted file mode 100644 index 53148fd979b..00000000000 --- a/circuits/cpp/src/aztec3/circuits/mock/mock_kernel_circuit.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace { -auto& engine = numeric::random::get_debug_engine(); -} - -namespace aztec3::circuits::mock { - -using aztec3::circuits::abis::KernelCircuitPublicInputs; -using NT = aztec3::utils::types::NativeTypes; -using aztec3::utils::types::CircuitTypes; -using plonk::stdlib::witness_t; - -template -KernelCircuitPublicInputs mock_kernel_circuit(Builder& builder, KernelCircuitPublicInputs const& _public_inputs) -{ - typedef CircuitTypes CT; - typedef typename CT::fr fr; - - auto public_inputs = _public_inputs.to_circuit_type(builder); - - { - std::vector dummy_witness_indices; - // 16 is the number of values added to `proof_witness_indices` at the end of `verify_proof`. - for (size_t i = 0; i < 16; ++i) { - fr const witness = fr(witness_t(&builder, i)); - uint32_t const witness_index = witness.get_witness_index(); - dummy_witness_indices.push_back(witness_index); - } - public_inputs.end.aggregation_object.proof_witness_indices = dummy_witness_indices; - } - - public_inputs.set_public(); - - // NOTE: We don't want a recursive proof in the mock kernel proof. - // We still add dummy witness indices in the recursive proof indices just so that we don't trigger an assertion in - // while setting recursion elements as public inputs. These dummy indices would not be used as we're setting - // contains_recursive_proof to be false. - builder.contains_recursive_proof = false; - - plonk::stdlib::pedersen_hash::hash({ fr(witness_t(&builder, 1)), fr(witness_t(&builder, 1)) }); - return public_inputs.template to_native_type(); -} - -} // namespace aztec3::circuits::mock diff --git a/circuits/cpp/src/aztec3/circuits/recursion/CMakeLists.txt b/circuits/cpp/src/aztec3/circuits/recursion/CMakeLists.txt deleted file mode 100644 index 3386bf2e151..00000000000 --- a/circuits/cpp/src/aztec3/circuits/recursion/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -circuits_cmake_module( - aztec3_circuits_recursion - barretenberg -) \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/recursion/aggregator.hpp b/circuits/cpp/src/aztec3/circuits/recursion/aggregator.hpp deleted file mode 100644 index 343ba12e79e..00000000000 --- a/circuits/cpp/src/aztec3/circuits/recursion/aggregator.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include "init.hpp" - -#include - -namespace aztec3::circuits::recursion { - -class Aggregator { - public: - static CT::AggregationObject aggregate( - Builder* builder, - const std::shared_ptr& vk, - const NT::Proof& proof, - const CT::AggregationObject& previous_aggregation_output = CT::AggregationObject()) - { - CT::AggregationObject result = - verify_proof(builder, vk, proof, previous_aggregation_output); - - return result; - } -}; -} // namespace aztec3::circuits::recursion \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/recursion/init.hpp b/circuits/cpp/src/aztec3/circuits/recursion/init.hpp deleted file mode 100644 index 427d25f502d..00000000000 --- a/circuits/cpp/src/aztec3/circuits/recursion/init.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::recursion { -// Builder -using Builder = UltraCircuitBuilder; - -// Generic types: -using CT = aztec3::utils::types::CircuitTypes; -using NT = aztec3::utils::types::NativeTypes; -using aztec3::utils::types::to_ct; - -// Recursion types and methods -using plonk::stdlib::recursion::verify_proof; -using transcript::Manifest; - -} // namespace aztec3::circuits::recursion \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/CMakeLists.txt b/circuits/cpp/src/aztec3/circuits/rollup/CMakeLists.txt deleted file mode 100644 index d2994796d2c..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -circuits_cmake_module( - aztec3_circuits_rollup - aztec3_circuits_kernel - barretenberg -) \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp b/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp deleted file mode 100644 index fab2b6c9a08..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp +++ /dev/null @@ -1,899 +0,0 @@ -#include "c_bind.h" -#include "index.hpp" -#include "init.hpp" - -#include "aztec3/circuits/abis/append_only_tree_snapshot.hpp" -#include "aztec3/circuits/abis/combined_accumulated_data.hpp" -#include "aztec3/circuits/abis/global_variables.hpp" -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/membership_witness.hpp" -#include "aztec3/circuits/abis/new_contract_data.hpp" -#include "aztec3/circuits/abis/previous_kernel_data.hpp" -#include "aztec3/circuits/abis/public_data_read.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/circuits/kernel/private/utils.hpp" -#include "aztec3/circuits/rollup/components/components.hpp" -#include "aztec3/circuits/rollup/test_utils/utils.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/circuit_errors.hpp" - -#include - -#include - -#include -#include -#include -#include -#include - - -namespace { - - -using aztec3::circuits::abis::PreviousKernelData; - - -// using aztec3::circuits::mock::mock_circuit; -using aztec3::circuits::rollup::test_utils::utils::base_rollup_inputs_from_kernels; -using aztec3::circuits::rollup::test_utils::utils::compare_field_hash_to_expected; -using aztec3::circuits::rollup::test_utils::utils::get_empty_kernel; -using aztec3::circuits::rollup::test_utils::utils::get_initial_nullifier_tree; -// using aztec3::circuits::mock::mock_kernel_inputs; - -using aztec3::circuits::abis::AppendOnlyTreeSnapshot; - -using aztec3::circuits::rollup::native_base_rollup::BaseOrMergeRollupPublicInputs; -using aztec3::circuits::rollup::native_base_rollup::BaseRollupInputs; -using aztec3::circuits::rollup::native_base_rollup::ConstantRollupData; -using aztec3::circuits::rollup::native_base_rollup::NT; - -using aztec3::circuits::abis::NewContractData; - -using aztec3::circuits::rollup::test_utils::utils::make_public_data_update_request; -using aztec3::circuits::rollup::test_utils::utils::make_public_read; - -using DummyCircuitBuilder = aztec3::utils::DummyCircuitBuilder; - -using aztec3::utils::CircuitErrorCode; -} // namespace - -namespace aztec3::circuits::rollup::base::native_base_rollup_circuit { - -class base_rollup_tests : public ::testing::Test { - protected: - static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../barretenberg/cpp/srs_db/ignition"); } - - // TODO(1998): uncomment once https://github.com/AztecProtocol/aztec-packages/issues/1998 is solved and - // use new pattern such as call_func_and_wrapper from test_helper.hpp - - // static void run_cbind(BaseRollupInputs& base_rollup_inputs, - // BaseOrMergeRollupPublicInputs& expected_public_inputs, - // bool compare_pubins = true, - // bool assert_no_circuit_failure = true) - // { - // info("Retesting via cbinds...."); - - // std::vector base_rollup_inputs_vec; - // serialize::write(base_rollup_inputs_vec, base_rollup_inputs); - - // // uint8_t const* proof_data; - // // size_t proof_data_size; - // uint8_t const* public_inputs_buf = nullptr; - // size_t public_inputs_size = 0; - // // info("simulating circuit via cbind"); - // uint8_t* const circuit_failure_ptr = - // base_rollup__sim(base_rollup_inputs_vec.data(), &public_inputs_size, &public_inputs_buf); - - // ASSERT_TRUE(assert_no_circuit_failure ? circuit_failure_ptr == nullptr : circuit_failure_ptr != nullptr); - // // info("Proof size: ", proof_data_size); - // // info("PublicInputs size: ", public_inputs_size); - - // if (compare_pubins) { - // BaseOrMergeRollupPublicInputs public_inputs; - // uint8_t const* public_inputs_buf_tmp = public_inputs_buf; - // serialize::read(public_inputs_buf_tmp, public_inputs); - // ASSERT_EQ(public_inputs.calldata_hash.size(), expected_public_inputs.calldata_hash.size()); - // for (size_t i = 0; i < public_inputs.calldata_hash.size(); i++) { - // ASSERT_EQ(public_inputs.calldata_hash[i], expected_public_inputs.calldata_hash[i]); - // } - - // std::vector expected_public_inputs_vec; - // serialize::write(expected_public_inputs_vec, expected_public_inputs); - - // ASSERT_EQ(public_inputs_size, expected_public_inputs_vec.size()); - // // Just compare the first 10 bytes of the serialized public outputs - // if (public_inputs_size > 10) { - // // for (size_t 0; i < public_inputs_size; i++) { - // for (size_t i = 0; i < 10; i++) { - // ASSERT_EQ(public_inputs_buf[i], expected_public_inputs_vec[i]); - // } - // } - // } - - // // free((void*)proof_data); - // free((void*)public_inputs_buf); - // // info("finished retesting via cbinds..."); - // } -}; - -TEST_F(base_rollup_tests, native_no_new_contract_leafs) -{ - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_no_new_contract_leafs"); - // When there are no contract deployments. The contract tree should be inserting 0 leafs, (not empty leafs); - // Initially, the start_contract_tree_snapshot is empty (leaf is 0. hash it up). - // Get sibling path of index 0 leaf (for circuit to check membership via sibling path) - // No contract leaves -> will insert empty tree -> i.e. end_contract_tree_root = start_contract_tree_root - - BaseRollupInputs emptyInputs = base_rollup_inputs_from_kernels({ get_empty_kernel(), get_empty_kernel() }); - MemoryStore contract_tree_store; - auto empty_contract_tree = MerkleTree(contract_tree_store, CONTRACT_TREE_HEIGHT); - - BaseOrMergeRollupPublicInputs outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, emptyInputs); - - AppendOnlyTreeSnapshot const expectedStartContractTreeSnapshot = { - .root = empty_contract_tree.root(), - .next_available_leaf_index = 0, - }; - AppendOnlyTreeSnapshot const expectedEndContractTreeSnapshot = { - .root = empty_contract_tree.root(), - .next_available_leaf_index = 2, - }; - ASSERT_EQ(outputs.start_contract_tree_snapshot, expectedStartContractTreeSnapshot); - ASSERT_EQ(outputs.end_contract_tree_snapshot, expectedEndContractTreeSnapshot); - ASSERT_EQ(outputs.start_contract_tree_snapshot, emptyInputs.start_contract_tree_snapshot); - ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - // TODO(1998): see above - // run_cbind(emptyInputs, outputs); -} - -TEST_F(base_rollup_tests, native_contract_leaf_inserted) -{ - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_contract_leaf_inserted"); - // When there is a contract deployment, the contract tree should be inserting 1 leaf. - // The remaining leafs should be 0 leafs, (not empty leafs); - - // Create a "mock" contract deployment - NewContractData const new_contract = { - .contract_address = fr(1), - .portal_contract_address = fr(3), - .function_tree_root = fr(2), - }; - - MemoryStore empty_contract_tree_store; - auto empty_contract_tree = MerkleTree(empty_contract_tree_store, CONTRACT_TREE_HEIGHT); - AppendOnlyTreeSnapshot const expected_start_contracts_snapshot = { - .root = empty_contract_tree.root(), - .next_available_leaf_index = 0, - }; - - // create expected end contract tree snapshot - MemoryStore contract_tree_store; - auto expected_end_contracts_snapshot_tree = - stdlib::merkle_tree::MerkleTree(contract_tree_store, CONTRACT_TREE_HEIGHT); - expected_end_contracts_snapshot_tree.update_element(0, new_contract.hash()); - - AppendOnlyTreeSnapshot const expected_end_contracts_snapshot = { - .root = expected_end_contracts_snapshot_tree.root(), - .next_available_leaf_index = 2, - }; - - std::array, 2> kernel_data = { get_empty_kernel(), get_empty_kernel() }; - kernel_data[0].public_inputs.end.new_contracts[0] = new_contract; - BaseRollupInputs inputs = base_rollup_inputs_from_kernels(kernel_data); - - BaseOrMergeRollupPublicInputs outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - - ASSERT_EQ(outputs.start_contract_tree_snapshot, expected_start_contracts_snapshot); - ASSERT_EQ(outputs.start_contract_tree_snapshot, inputs.start_contract_tree_snapshot); - ASSERT_EQ(outputs.end_contract_tree_snapshot, expected_end_contracts_snapshot); - ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - // TODO(1998): see above - // run_cbind(inputs, outputs); -} - -TEST_F(base_rollup_tests, native_contract_leaf_inserted_in_non_empty_snapshot_tree) -{ - DummyCircuitBuilder builder = - DummyCircuitBuilder("base_rollup_tests__native_contract_leaf_inserted_in_non_empty_snapshot_tree"); - // Same as before except our start_contract_snapshot_tree is not empty - std::array, 2> kernel_data = { get_empty_kernel(), get_empty_kernel() }; - - // Create a "mock" contract deployment - NewContractData new_contract = { - .contract_address = fr(1), - .portal_contract_address = fr(3), - .function_tree_root = fr(2), - }; - kernel_data[0].public_inputs.end.new_contracts[0] = new_contract; - BaseRollupInputs inputs = base_rollup_inputs_from_kernels(kernel_data); - - MemoryStore start_contract_tree_snapshot_store; - auto start_contract_tree_snapshot = MerkleTree(start_contract_tree_snapshot_store, CONTRACT_TREE_HEIGHT); - // insert 12 leaves to the tree (next available leaf index is 12) - for (size_t i = 0; i < 12; ++i) { - start_contract_tree_snapshot.update_element(i, fr(i)); - } - // set the start_contract_tree_snapshot - inputs.start_contract_tree_snapshot = { - .root = start_contract_tree_snapshot.root(), - .next_available_leaf_index = 12, - }; - - // Set the new_contracts_subtree_sibling_path - auto sibling_path = get_sibling_path( - start_contract_tree_snapshot, 12, CONTRACT_SUBTREE_HEIGHT); - inputs.new_contracts_subtree_sibling_path = sibling_path; - - // create expected end contract tree snapshot - auto expected_contract_leaf = crypto::pedersen_hash::hash( - { new_contract.contract_address, new_contract.portal_contract_address, new_contract.function_tree_root }, - NativeTypes::get_generator_context(GeneratorIndex::CONTRACT_LEAF)); - - auto expected_end_contract_tree_snapshot_store = start_contract_tree_snapshot_store; - auto expected_end_contracts_snapshot_tree = - MerkleTree(expected_end_contract_tree_snapshot_store, CONTRACT_TREE_HEIGHT); - expected_end_contracts_snapshot_tree.update_element(12, expected_contract_leaf); - - AppendOnlyTreeSnapshot const expected_end_contracts_snapshot = { - .root = expected_end_contracts_snapshot_tree.root(), - .next_available_leaf_index = 14, - }; - BaseOrMergeRollupPublicInputs outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - - ASSERT_EQ(outputs.start_contract_tree_snapshot, inputs.start_contract_tree_snapshot); - ASSERT_EQ(outputs.end_contract_tree_snapshot, expected_end_contracts_snapshot); - ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - // TODO(1998): see above - // run_cbind(inputs, outputs); -} - -TEST_F(base_rollup_tests, native_new_commitments_tree) -{ - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_new_commitments_tree"); - // Create 4 new mock commitments. Add them to kernel data. - // Then get sibling path so we can verify insert them into the tree. - - std::array, 2> kernel_data = { get_empty_kernel(), get_empty_kernel() }; - std::array new_commitments = { 0, 1, 2, 3, 4, 5, 6, 7 }; - for (uint8_t i = 0; i < 2; i++) { - std::array kernel_commitments; - for (uint8_t j = 0; j < MAX_NEW_COMMITMENTS_PER_TX; j++) { - kernel_commitments[j] = new_commitments[i * MAX_NEW_COMMITMENTS_PER_TX + j]; - } - kernel_data[i].public_inputs.end.new_commitments = kernel_commitments; - } - - // get sibling path - MemoryStore note_hash_tree_store; - auto note_hash_tree = MerkleTree(note_hash_tree_store, NOTE_HASH_TREE_HEIGHT); - AppendOnlyTreeSnapshot const expected_start_commitments_snapshot = { - .root = note_hash_tree.root(), - .next_available_leaf_index = 0, - }; - for (size_t i = 0; i < new_commitments.size(); ++i) { - note_hash_tree.update_element(i, new_commitments[i]); - } - AppendOnlyTreeSnapshot const expected_end_commitments_snapshot = { - .root = note_hash_tree.root(), - .next_available_leaf_index = 2 * MAX_NEW_COMMITMENTS_PER_TX, - }; - - auto inputs = base_rollup_inputs_from_kernels(kernel_data); - BaseOrMergeRollupPublicInputs outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - - ASSERT_EQ(outputs.start_note_hash_tree_snapshot, expected_start_commitments_snapshot); - ASSERT_EQ(outputs.start_note_hash_tree_snapshot, inputs.start_note_hash_tree_snapshot); - ASSERT_EQ(outputs.end_note_hash_tree_snapshot, expected_end_commitments_snapshot); - ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - // TODO(1998): see above - // run_cbind(inputs, outputs); -} - -template NT::fr calc_root(NT::fr leaf, NT::uint32 leafIndex, std::array siblingPath) -{ - for (size_t i = 0; i < siblingPath.size(); i++) { - if (leafIndex & (1 << i)) { - leaf = proof_system::plonk::stdlib::merkle_tree::hash_pair_native(siblingPath[i], leaf); - } else { - leaf = proof_system::plonk::stdlib::merkle_tree::hash_pair_native(leaf, siblingPath[i]); - } - } - return leaf; -} - -TEST_F(base_rollup_tests, native_new_nullifier_tree_empty) -{ - /** - * DESCRIPTION - */ - - // This test checks for insertions of all 0 values - // In this special case we will not need to provide sibling paths to check insertion of the nullifier values - // This is because 0 values are not actually inserted into the tree, rather the inserted subtree is left - // empty to begin with. - - std::array const new_nullifiers{}; - std::vector initial_values(2 * MAX_NEW_NULLIFIERS_PER_TX - 1); - - for (size_t i = 0; i < initial_values.size(); i++) { - initial_values[i] = i + 1; - } - - auto nullifier_tree = get_initial_nullifier_tree(initial_values); - auto start_nullifier_tree_snapshot = nullifier_tree.get_snapshot(); - for (auto v : new_nullifiers) { - nullifier_tree.update_element(v); - } - auto end_nullifier_tree_snapshot = nullifier_tree.get_snapshot(); - - /** - * RUN - */ - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_new_nullifier_tree_empty"); - std::array, 2> const kernel_data = { get_empty_kernel(), get_empty_kernel() }; - BaseRollupInputs const empty_inputs = base_rollup_inputs_from_kernels(kernel_data); - - BaseOrMergeRollupPublicInputs const outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, empty_inputs); - - /** - * ASSERT - */ - // Start state - ASSERT_EQ(outputs.start_nullifier_tree_snapshot, start_nullifier_tree_snapshot); - - // End state - ASSERT_EQ(outputs.end_nullifier_tree_snapshot, end_nullifier_tree_snapshot); - ASSERT_EQ(outputs.end_nullifier_tree_snapshot.root, outputs.start_nullifier_tree_snapshot.root); - ASSERT_EQ(outputs.end_nullifier_tree_snapshot.next_available_leaf_index, - outputs.start_nullifier_tree_snapshot.next_available_leaf_index + 2 * MAX_NEW_NULLIFIERS_PER_TX); - ASSERT_FALSE(builder.failed()) << builder.failure_msgs; -} - -void nullifier_insertion_test(std::array new_nullifiers) -{ - // @todo We can probably reuse this more than we are already doing. - // Regression test caught when testing the typescript nullifier tree implementation - - std::vector initial_values(2 * MAX_NEW_NULLIFIERS_PER_TX - 1); - for (size_t i = 0; i < initial_values.size(); i++) { - initial_values[i] = i + 1; - } - - auto nullifier_tree = get_initial_nullifier_tree(initial_values); - auto start_nullifier_tree_snapshot = nullifier_tree.get_snapshot(); - for (auto v : new_nullifiers) { - nullifier_tree.update_element(v); - } - auto end_nullifier_tree_snapshot = nullifier_tree.get_snapshot(); - - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__nullifier_insertion_test"); - std::array, 2> kernel_data = { get_empty_kernel(), get_empty_kernel() }; - for (uint8_t i = 0; i < 2; i++) { - std::array kernel_nullifiers; - for (uint8_t j = 0; j < MAX_NEW_NULLIFIERS_PER_TX; j++) { - kernel_nullifiers[j] = new_nullifiers[i * MAX_NEW_NULLIFIERS_PER_TX + j]; - } - kernel_data[i].public_inputs.end.new_nullifiers = kernel_nullifiers; - } - BaseRollupInputs const inputs = base_rollup_inputs_from_kernels(kernel_data); - - BaseOrMergeRollupPublicInputs const outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - /** - * ASSERT - */ - ASSERT_EQ(outputs.start_nullifier_tree_snapshot, start_nullifier_tree_snapshot); - ASSERT_EQ(outputs.end_nullifier_tree_snapshot, end_nullifier_tree_snapshot); - ASSERT_EQ(outputs.end_nullifier_tree_snapshot.next_available_leaf_index, - outputs.start_nullifier_tree_snapshot.next_available_leaf_index + MAX_NEW_NULLIFIERS_PER_TX * 2); - ASSERT_FALSE(builder.failed()) << builder.failure_msgs; -} - -TEST_F(base_rollup_tests, native_new_nullifier_tree_all_larger) -{ - std::array initial_values; - - for (size_t i = 0; i < initial_values.size(); i++) { - initial_values[i] = 2 * MAX_NEW_NULLIFIERS_PER_TX + i; - } - - nullifier_insertion_test(initial_values); -} - -TEST_F(base_rollup_tests, native_new_nullifier_tree_sparse_insertions) -{ - std::array initial_values; - - for (size_t i = 0; i < initial_values.size(); i++) { - initial_values[i] = 2 * MAX_NEW_NULLIFIERS_PER_TX + 5 * i + 1; - } - nullifier_insertion_test(initial_values); -} - -TEST_F(base_rollup_tests, native_new_nullifier_tree_sparse) -{ - std::array nullifiers; - - for (size_t i = 0; i < nullifiers.size(); i++) { - nullifiers[i] = 2 * MAX_NEW_NULLIFIERS_PER_TX + 5 * i + 1; - } - - std::vector initial_values(2 * MAX_NEW_NULLIFIERS_PER_TX - 1); - - for (size_t i = 0; i < initial_values.size(); i++) { - initial_values[i] = 5 * (i + 1); - } - - auto nullifier_tree = get_initial_nullifier_tree(initial_values); - auto expected_start_nullifier_tree_snapshot = nullifier_tree.get_snapshot(); - for (auto v : nullifiers) { - nullifier_tree.update_element(v); - } - auto expected_end_nullifier_tree_snapshot = nullifier_tree.get_snapshot(); - - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_new_nullifier_tree_sparse"); - BaseRollupInputs const empty_inputs = base_rollup_inputs_from_kernels({ get_empty_kernel(), get_empty_kernel() }); - std::tuple, AppendOnlyTreeSnapshot> inputs_and_snapshots = - test_utils::utils::generate_nullifier_tree_testing_values_explicit(empty_inputs, nullifiers, initial_values); - - BaseRollupInputs const testing_inputs = std::get<0>(inputs_and_snapshots); - - /** - * RUN - */ - - // Run the circuit - BaseOrMergeRollupPublicInputs const outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, testing_inputs); - - /** - * ASSERT - */ - // Start state - ASSERT_EQ(outputs.start_nullifier_tree_snapshot, expected_start_nullifier_tree_snapshot); - - // End state - ASSERT_EQ(outputs.end_nullifier_tree_snapshot, expected_end_nullifier_tree_snapshot); - ASSERT_FALSE(builder.failed()) << builder.failure_msgs; -} - -TEST_F(base_rollup_tests, native_nullifier_tree_regression) -{ - // Regression test caught when testing the typescript nullifier tree implementation - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_nullifier_tree_regression"); - - // This test runs after some data has already been inserted into the tree - // This test will pre-populate the tree with 6 * KERNEL_NEW_NULLIFIERS_LENGTH values (0 item + 6 * - // KERNEL_NEW_NULLIFIERS_LENGTH -1 more) simulating that a rollup inserting two random values has already - // succeeded. Note that this corresponds to 3 (1 already initialized and 2 new ones) base rollups. This rollup - // then adds two further random values that will end up having their low nullifiers point at each other - std::vector initial_values(6 * MAX_NEW_NULLIFIERS_PER_TX - 1, 0); - for (size_t i = 0; i < 2 * MAX_NEW_NULLIFIERS_PER_TX - 1; i++) { - initial_values[i] = i + 1; - } - // Note these are hex representations - initial_values[7] = uint256_t("2bb9aa4a22a6ae7204f2c67abaab59cead6558cde4ee25ce3464704cb2e38136"); - initial_values[8] = uint256_t("16a732095298ccca828c4d747813f8bd46e188079ed17904e2c9de50760833c8"); - - std::array new_nullifiers = { 0 }; - new_nullifiers[0] = uint256_t("16da4f27fb78de7e0db4c5a04b569bc46382c5f471da2f7d670beff1614e0118"), - new_nullifiers[1] = uint256_t("26ab07ce103a55e29f11478eaa36cebd10c4834b143a7debcc7ef53bfdb547dd"); - - auto nullifier_tree = get_initial_nullifier_tree(initial_values); - auto expected_start_nullifier_tree_snapshot = nullifier_tree.get_snapshot(); - for (auto v : new_nullifiers) { - nullifier_tree.update_element(v); - } - auto expected_end_nullifier_tree_snapshot = nullifier_tree.get_snapshot(); - - /** - * RUN - */ - BaseRollupInputs const empty_inputs = base_rollup_inputs_from_kernels({ get_empty_kernel(), get_empty_kernel() }); - std::tuple, AppendOnlyTreeSnapshot> inputs_and_snapshots = - test_utils::utils::generate_nullifier_tree_testing_values_explicit( - empty_inputs, new_nullifiers, initial_values); - BaseRollupInputs const testing_inputs = std::get<0>(inputs_and_snapshots); - // Run the circuit - BaseOrMergeRollupPublicInputs const outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, testing_inputs); - - /** - * ASSERT - */ - // Start state - ASSERT_EQ(outputs.start_nullifier_tree_snapshot, expected_start_nullifier_tree_snapshot); - - // End state - ASSERT_EQ(outputs.end_nullifier_tree_snapshot, expected_end_nullifier_tree_snapshot); - ASSERT_FALSE(builder.failed()) << builder.failure_msgs; -} - -// Another regression test with values from a failing packages test -TEST_F(base_rollup_tests, nullifier_tree_regression_2) -{ - // Regression test caught when testing the typescript nullifier tree implementation - std::array new_nullifiers = { 0 }; - new_nullifiers[0] = uint256_t("2a7d956c1365d259646d2d85babe1abb793bb8789e98df7e2336a29a0c91fd01"); - new_nullifiers[1] = uint256_t("236bf2d113f9ffee89df1a7a04890c9ad3583c6773eb9cdec484184f66abd4c6"); - new_nullifiers[4] = uint256_t("2f5c8a1ee33c7104b244e22a3e481637cd501c9eae868cfab6b16e3b4ef3d635"); - new_nullifiers[5] = uint256_t("0c484a20780e31747cf9f4f6803986525ed98ef587f5155a1c50689c2cad10ae"); - - nullifier_insertion_test(new_nullifiers); -} - -TEST_F(base_rollup_tests, nullifier_tree_regression_3) -{ - std::array new_nullifiers = { 0 }; - new_nullifiers[0] = uint256_t("0740a17aa6437e71836d2adcdcb3f52879bb869cdd9c8fb8dc39a12846cd17f2"); - new_nullifiers[1] = uint256_t("282e0e2f38310a7c7c98b636830b66f3276294560e26ef2499da10892f00af8f"); - new_nullifiers[4] = uint256_t("0f117936e888bd3befb4435f4d65300d25609e95a3d1563f62ef7e58c294f578"); - new_nullifiers[5] = uint256_t("0fcb3908cb15ebf8bab276f5df17524d3b676c8655234e4350953c387fffcdd7"); - - nullifier_insertion_test(new_nullifiers); -} - -TEST_F(base_rollup_tests, native_new_nullifier_tree_double_spend) -{ - /** - * DESCRIPTION - */ - - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_new_nullifier_tree_double_spend"); - BaseRollupInputs const empty_inputs = base_rollup_inputs_from_kernels({ get_empty_kernel(), get_empty_kernel() }); - - fr const nullifier_to_insert = - 2 * MAX_NEW_NULLIFIERS_PER_TX + 4; // arbitrary value greater than 2 * MAX_NEW_NULLIFIERS_PER_TX - std::array new_nullifiers{}; - - new_nullifiers[0] = nullifier_to_insert; - new_nullifiers[2] = nullifier_to_insert; - - std::tuple, AppendOnlyTreeSnapshot> inputs_and_snapshots = - test_utils::utils::generate_nullifier_tree_testing_values(empty_inputs, new_nullifiers, 1); - BaseRollupInputs const testing_inputs = std::get<0>(inputs_and_snapshots); - - BaseOrMergeRollupPublicInputs const outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, testing_inputs); - - ASSERT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().code, CircuitErrorCode::BASE__INVALID_NULLIFIER_RANGE); -} - -TEST_F(base_rollup_tests, native_empty_block_calldata_hash) -{ - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_empty_block_calldata_hash"); - std::vector const zero_bytes_vec = test_utils::utils::get_empty_calldata_leaf(); - auto expected_calldata_hash = sha256::sha256(zero_bytes_vec); - BaseRollupInputs inputs = base_rollup_inputs_from_kernels({ get_empty_kernel(), get_empty_kernel() }); - BaseOrMergeRollupPublicInputs outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - std::array const output_calldata_hash = outputs.calldata_hash; - - ASSERT_TRUE(compare_field_hash_to_expected(output_calldata_hash, expected_calldata_hash) == true); - - ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - // TODO(1998): see above - // run_cbind(inputs, outputs); -} - -TEST_F(base_rollup_tests, native_calldata_hash) -{ - // Execute the base rollup circuit with nullifiers, commitments and a contract deployment. Then check the - // calldata hash against the expected value. - std::array, 2> kernel_data = { get_empty_kernel(), get_empty_kernel() }; - - // Commitments inserted are [1,2,3,4,5,6,7,8 ...]. Nullifiers inserted are [8,9,10,11,12,13,14,15 ...] - for (size_t i = 0; i < 2; ++i) { - for (size_t j = 0; j < MAX_NEW_NULLIFIERS_PER_TX; j++) { - kernel_data[i].public_inputs.end.new_commitments[j] = fr(i * MAX_NEW_NULLIFIERS_PER_TX + j + 1); - kernel_data[i].public_inputs.end.new_nullifiers[j] = fr((2 + i) * MAX_NEW_NULLIFIERS_PER_TX + j); - } - } - - // Add logs hashes - kernel_data[0].public_inputs.end.encrypted_logs_hash = { NT::fr(16), NT::fr(69) }; - kernel_data[1].public_inputs.end.encrypted_logs_hash = { NT::fr(812), NT::fr(234) }; - kernel_data[0].public_inputs.end.unencrypted_logs_hash = { NT::fr(163), NT::fr(212) }; - kernel_data[1].public_inputs.end.unencrypted_logs_hash = { NT::fr(4352), NT::fr(1632) }; - - // Add a contract deployment - NewContractData const new_contract = { - .contract_address = fr(1), - .portal_contract_address = fr(3), - .function_tree_root = fr(2), - }; - kernel_data[0].public_inputs.end.new_contracts[0] = new_contract; - - std::array const expected_calldata_hash = - components::compute_kernels_calldata_hash(kernel_data); - - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_calldata_hash"); - BaseRollupInputs inputs = base_rollup_inputs_from_kernels(kernel_data); - BaseOrMergeRollupPublicInputs outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - - std::array const output_calldata_hash = outputs.calldata_hash; - - ASSERT_EQ(expected_calldata_hash, output_calldata_hash); - - ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - // TODO(1998): see above - // run_cbind(inputs, outputs); -} - -TEST_F(base_rollup_tests, native_compute_membership_archive_negative) -{ - // WRITE a negative test that will fail the inclusion proof - - // Test membership works for empty trees - DummyCircuitBuilder builder = - DummyCircuitBuilder("base_rollup_tests__native_compute_membership_historical_private_data_negative"); - std::array, 2> const kernel_data = { get_empty_kernel(), get_empty_kernel() }; - BaseRollupInputs inputs = base_rollup_inputs_from_kernels(kernel_data); - - MemoryStore blocks_store; - auto archive = MerkleTree(blocks_store, ARCHIVE_HEIGHT); - - // Create an INCORRECT sibling path for the note hash tree root in the historical tree roots. - auto hash_path = archive.get_sibling_path(0); - std::array sibling_path{}; - for (size_t i = 0; i < ARCHIVE_HEIGHT; ++i) { - sibling_path[i] = hash_path[i] + 1; - } - inputs.archive_root_membership_witnesses[0] = { - .leaf_index = 0, - .sibling_path = sibling_path, - }; - - BaseOrMergeRollupPublicInputs const outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - - ASSERT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().message, - "Membership check failed: base_rollup_circuit: historical root is in rollup constants but not in " - "blocks tree at kernel input 0 to this base rollup circuit"); -} - - -TEST_F(base_rollup_tests, native_constants_dont_change) -{ - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_constants_dont_change"); - BaseRollupInputs inputs = base_rollup_inputs_from_kernels({ get_empty_kernel(), get_empty_kernel() }); - BaseOrMergeRollupPublicInputs outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - ASSERT_EQ(inputs.constants, outputs.constants); - EXPECT_FALSE(builder.failed()); - // TODO(1998): see above - // run_cbind(inputs, outputs); -} - -TEST_F(base_rollup_tests, native_constants_dont_match_kernels_chain_id) -{ - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_constants_dont_change"); - BaseRollupInputs inputs = base_rollup_inputs_from_kernels({ get_empty_kernel(), get_empty_kernel() }); - inputs.constants.global_variables.chain_id = 3; - BaseOrMergeRollupPublicInputs const outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - ASSERT_EQ(inputs.constants, outputs.constants); - EXPECT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().message, "kernel chain_id does not match the rollup chain_id"); -} - -TEST_F(base_rollup_tests, native_constants_dont_match_kernels_version) -{ - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_constants_dont_change"); - BaseRollupInputs inputs = base_rollup_inputs_from_kernels({ get_empty_kernel(), get_empty_kernel() }); - inputs.constants.global_variables.version = 3; - BaseOrMergeRollupPublicInputs const outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - ASSERT_EQ(inputs.constants, outputs.constants); - EXPECT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().message, "kernel version does not match the rollup version"); -} - -TEST_F(base_rollup_tests, native_aggregate) -{ - // TODO(rahul): Fix this when aggregation works - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_aggregate"); - BaseRollupInputs inputs = base_rollup_inputs_from_kernels({ get_empty_kernel(), get_empty_kernel() }); - BaseOrMergeRollupPublicInputs const outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - ASSERT_EQ(inputs.kernel_data[0].public_inputs.end.aggregation_object.public_inputs, - outputs.end_aggregation_object.public_inputs); - ASSERT_FALSE(builder.failed()) << builder.failure_msgs; -} - -TEST_F(base_rollup_tests, native_subtree_height_is_0) -{ - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_subtree_height_is_0"); - BaseRollupInputs const inputs = base_rollup_inputs_from_kernels({ get_empty_kernel(), get_empty_kernel() }); - BaseOrMergeRollupPublicInputs const outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - ASSERT_EQ(outputs.rollup_subtree_height, fr(0)); - ASSERT_FALSE(builder.failed()) << builder.failure_msgs; -} - -TEST_F(base_rollup_tests, native_cbind_0) -{ - // @todo Error handling? - BaseRollupInputs inputs = base_rollup_inputs_from_kernels({ get_empty_kernel(), get_empty_kernel() }); - BaseOrMergeRollupPublicInputs ignored_public_inputs; - // TODO(1998): see above - // run_cbind(inputs, ignored_public_inputs, false); -} - -TEST_F(base_rollup_tests, native_single_public_state_read) -{ - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_single_public_state_read"); - MemoryStore note_hash_tree_store; - MerkleTree note_hash_tree(note_hash_tree_store, NOTE_HASH_TREE_HEIGHT); - - MemoryStore contract_tree_store; - MerkleTree contract_tree(contract_tree_store, CONTRACT_TREE_HEIGHT); - - MemoryStore public_data_tree_store; - MerkleTree public_data_tree(public_data_tree_store, PUBLIC_DATA_TREE_HEIGHT); - - MemoryStore l1_to_l2_message_tree_store; - MerkleTree l1_to_l2_message_tree(l1_to_l2_message_tree_store, L1_TO_L2_MSG_TREE_HEIGHT); - - auto data_read = abis::PublicDataRead{ - .leaf_index = fr(1), - .value = fr(42), - }; - - std::array, 2> kernel_data = { get_empty_kernel(), get_empty_kernel() }; - kernel_data[0].public_inputs.end.public_data_reads[0] = data_read; - auto inputs = test_utils::utils::base_rollup_inputs_from_kernels( - kernel_data, note_hash_tree, contract_tree, public_data_tree, l1_to_l2_message_tree); - - BaseOrMergeRollupPublicInputs outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - - ASSERT_EQ(outputs.start_public_data_tree_root, inputs.start_public_data_tree_root); - ASSERT_EQ(outputs.end_public_data_tree_root, public_data_tree.root()); - ASSERT_EQ(outputs.end_public_data_tree_root, outputs.start_public_data_tree_root); - ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - // TODO(1998): see above - // run_cbind(inputs, outputs); -} - -TEST_F(base_rollup_tests, native_single_public_state_write) -{ - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_single_public_state_write"); - MemoryStore note_hash_tree_store; - MerkleTree note_hash_tree(note_hash_tree_store, NOTE_HASH_TREE_HEIGHT); - - MemoryStore contract_tree_store; - MerkleTree contract_tree(contract_tree_store, CONTRACT_TREE_HEIGHT); - - MemoryStore public_data_tree_store; - MerkleTree public_data_tree(public_data_tree_store, PUBLIC_DATA_TREE_HEIGHT); - - MemoryStore l1_to_l2_message_tree_store; - MerkleTree l1_to_l2_message_tree(l1_to_l2_message_tree_store, L1_TO_L2_MSG_TREE_HEIGHT); - - - auto data_write = abis::PublicDataUpdateRequest{ - .leaf_index = fr(1), - .old_value = fr(2), - .new_value = fr(42), - }; - - std::array, 2> kernel_data = { get_empty_kernel(), get_empty_kernel() }; - kernel_data[0].public_inputs.end.public_data_update_requests[0] = data_write; - - auto inputs = test_utils::utils::base_rollup_inputs_from_kernels( - kernel_data, note_hash_tree, contract_tree, public_data_tree, l1_to_l2_message_tree); - - BaseOrMergeRollupPublicInputs outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - - ASSERT_EQ(outputs.start_public_data_tree_root, inputs.start_public_data_tree_root); - ASSERT_EQ(outputs.end_public_data_tree_root, public_data_tree.root()); - ASSERT_NE(outputs.end_public_data_tree_root, outputs.start_public_data_tree_root); - ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - // TODO(1998): see above - // run_cbind(inputs, outputs); -} - -TEST_F(base_rollup_tests, native_multiple_public_state_read_writes) -{ - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_multiple_public_state_read_writes"); - MemoryStore note_hash_tree_store; - MerkleTree note_hash_tree(note_hash_tree_store, NOTE_HASH_TREE_HEIGHT); - - MemoryStore contract_tree_store; - MerkleTree contract_tree(contract_tree_store, CONTRACT_TREE_HEIGHT); - - MemoryStore public_data_tree_store; - MerkleTree public_data_tree(public_data_tree_store, PUBLIC_DATA_TREE_HEIGHT); - - MemoryStore l1_to_l2_message_tree_store; - MerkleTree l1_to_l2_message_tree(l1_to_l2_message_tree_store, L1_TO_L2_MSG_TREE_HEIGHT); - - std::array, 2> kernel_data = { get_empty_kernel(), get_empty_kernel() }; - - // We set up reads and writes such that the right tx will read or write to indices already modified by the left - // tx - kernel_data[0].public_inputs.end.public_data_reads[0] = make_public_read(fr(1), fr(101)); - kernel_data[0].public_inputs.end.public_data_reads[1] = make_public_read(fr(2), fr(102)); - kernel_data[0].public_inputs.end.public_data_update_requests[0] = - make_public_data_update_request(fr(3), fr(103), fr(203)); - kernel_data[0].public_inputs.end.public_data_update_requests[1] = - make_public_data_update_request(fr(4), fr(104), fr(204)); - kernel_data[0].public_inputs.end.public_data_update_requests[2] = - make_public_data_update_request(fr(5), fr(105), fr(205)); - - kernel_data[1].public_inputs.end.public_data_reads[0] = make_public_read(fr(3), fr(203)); - kernel_data[1].public_inputs.end.public_data_reads[1] = make_public_read(fr(11), fr(211)); - kernel_data[1].public_inputs.end.public_data_update_requests[0] = - make_public_data_update_request(fr(12), fr(212), fr(312)); - kernel_data[1].public_inputs.end.public_data_update_requests[1] = - make_public_data_update_request(fr(4), fr(204), fr(304)); - - auto inputs = test_utils::utils::base_rollup_inputs_from_kernels( - kernel_data, note_hash_tree, contract_tree, public_data_tree, l1_to_l2_message_tree); - - BaseOrMergeRollupPublicInputs outputs = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - - ASSERT_EQ(outputs.start_public_data_tree_root, inputs.start_public_data_tree_root); - ASSERT_EQ(outputs.end_public_data_tree_root, public_data_tree.root()); - ASSERT_NE(outputs.end_public_data_tree_root, outputs.start_public_data_tree_root); - ASSERT_FALSE(builder.failed()) << builder.failure_msgs; - // TODO(1998): see above - // run_cbind(inputs, outputs); -} - -// TODO(#2521) - data read validation should happen against the current state of the tx and not the start state. -// https://aztecprotocol.slack.com/archives/C02M7VC7TN0/p1695809629015719?thread_ts=1695653252.007339&cid=C02M7VC7TN0 - -// TEST_F(base_rollup_tests, native_invalid_public_state_read) -// { -// DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup_tests__native_invalid_public_state_read"); -// MemoryStore note_hash_tree_store; -// MerkleTree note_hash_tree(note_hash_tree_store, NOTE_HASH_TREE_HEIGHT); - -// MemoryStore contract_tree_store; -// MerkleTree contract_tree(contract_tree_store, CONTRACT_TREE_HEIGHT); - -// MemoryStore public_data_tree_store; -// MerkleTree public_data_tree(public_data_tree_store, PUBLIC_DATA_TREE_HEIGHT); - -// MemoryStore l1_to_l2_message_tree_store; -// MerkleTree l1_to_l2_message_tree(l1_to_l2_message_tree_store, L1_TO_L2_MSG_TREE_HEIGHT); - -// auto data_read = abis::PublicDataRead{ -// .leaf_index = fr(1), -// .value = fr(42), -// }; - -// std::array, 2> kernel_data = { get_empty_kernel(), get_empty_kernel() }; -// kernel_data[0].public_inputs.end.public_data_reads[0] = data_read; -// auto inputs = test_utils::utils::base_rollup_inputs_from_kernels( -// kernel_data, note_hash_tree, contract_tree, public_data_tree, l1_to_l2_message_tree); - -// // We change the initial tree root so the read value does not match -// public_data_tree.update_element(1, fr(43)); -// inputs.start_public_data_tree_root = public_data_tree.root(); - -// BaseOrMergeRollupPublicInputs outputs = -// aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, inputs); - -// ASSERT_EQ(outputs.start_public_data_tree_root, inputs.start_public_data_tree_root); -// ASSERT_EQ(outputs.end_public_data_tree_root, public_data_tree.root()); -// ASSERT_EQ(outputs.end_public_data_tree_root, outputs.start_public_data_tree_root); -// ASSERT_TRUE(builder.failed()); -// // TODO(1998): see above -// // run_cbind(inputs, outputs, true, false); -// } - -} // namespace aztec3::circuits::rollup::base::native_base_rollup_circuit diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/CMakeLists.txt b/circuits/cpp/src/aztec3/circuits/rollup/base/CMakeLists.txt deleted file mode 100644 index d2994796d2c..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -circuits_cmake_module( - aztec3_circuits_rollup - aztec3_circuits_kernel - barretenberg -) \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.cpp b/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.cpp deleted file mode 100644 index 0be1cd67ae3..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "c_bind.h" - -#include "index.hpp" -#include "init.hpp" - -#include "aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace { -using Builder = UltraCircuitBuilder; -using NT = aztec3::utils::types::NativeTypes; -using DummyCircuitBuilder = aztec3::utils::DummyCircuitBuilder; -using aztec3::circuits::abis::BaseRollupInputs; -using aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit; -} // namespace - -// WASM Cbinds -CBIND(base_rollup__sim, [](BaseRollupInputs const& base_rollup_inputs) { - DummyCircuitBuilder builder = DummyCircuitBuilder("base_rollup__sim"); - auto const& public_inputs = base_rollup_circuit(builder, base_rollup_inputs); - return builder.result_or_error(public_inputs); -}); \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.h b/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.h deleted file mode 100644 index dc833dbda13..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include - -#include -#include - -CBIND_DECL(base_rollup__sim); \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/index.hpp b/circuits/cpp/src/aztec3/circuits/rollup/base/index.hpp deleted file mode 100644 index 82e34f051f1..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/index.hpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "init.hpp" -#include "native_base_rollup_circuit.hpp" \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/init.hpp b/circuits/cpp/src/aztec3/circuits/rollup/base/init.hpp deleted file mode 100644 index ad75c10258b..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/init.hpp +++ /dev/null @@ -1,41 +0,0 @@ - -#pragma once - -#include "aztec3/circuits/abis/append_only_tree_snapshot.hpp" -#include "aztec3/circuits/abis/previous_kernel_data.hpp" -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp" -#include "aztec3/circuits/abis/rollup/base/base_rollup_inputs.hpp" -#include "aztec3/circuits/abis/rollup/constant_rollup_data.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/circuits/recursion/aggregator.hpp" -#include "aztec3/utils/circuit_errors.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::rollup::native_base_rollup { - -using NT = aztec3::utils::types::NativeTypes; - -// Params -using ConstantRollupData = abis::ConstantRollupData; -using BaseRollupInputs = abis::BaseRollupInputs; -using BaseOrMergeRollupPublicInputs = abis::BaseOrMergeRollupPublicInputs; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; -using CircuitErrorCode = aztec3::utils::CircuitErrorCode; - -using Aggregator = aztec3::circuits::recursion::Aggregator; -using AggregationObject = utils::types::NativeTypes::AggregationObject; -using AppendOnlySnapshot = abis::AppendOnlyTreeSnapshot; - -// Tree Aliases -using MemoryStore = stdlib::merkle_tree::MemoryStore; -using MerkleTree = stdlib::merkle_tree::MerkleTree; -using NullifierTree = stdlib::merkle_tree::NullifierMemoryTree; -using NullifierLeafPreimage = abis::NullifierLeafPreimage; - -} // namespace aztec3::circuits::rollup::native_base_rollup \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/native_base_rollup_circuit.cpp b/circuits/cpp/src/aztec3/circuits/rollup/base/native_base_rollup_circuit.cpp deleted file mode 100644 index 47f3da86036..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/native_base_rollup_circuit.cpp +++ /dev/null @@ -1,549 +0,0 @@ -#include "init.hpp" - -#include "aztec3/circuits/abis/membership_witness.hpp" -#include "aztec3/circuits/abis/public_data_read.hpp" -#include "aztec3/circuits/abis/public_data_update_request.hpp" -#include "aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp" -#include "aztec3/circuits/abis/rollup/base/base_rollup_inputs.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/circuits/rollup/components/components.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/circuit_errors.hpp" - -#include - -#include -#include -#include -#include -#include -#include - - -namespace aztec3::circuits::rollup::native_base_rollup { - -// Used when calling library functions like `check_membership` which have their own generic error code. -// So we pad this in front of the error message to identify where the error originally came from. -const std::string BASE_CIRCUIT_ERROR_MESSAGE_BEGINNING = "base_rollup_circuit: "; - -NT::fr calculate_empty_tree_root(const size_t depth) -{ - MemoryStore empty_tree_store; - MerkleTree const empty_tree = MerkleTree(empty_tree_store, depth); - return empty_tree.root(); -} - -// TODO: can we aggregate proofs if we do not have a working circuit impl - -bool verify_kernel_proof(NT::Proof const& kernel_proof) -{ - (void)kernel_proof; - return true; -} - -/** - * @brief Create an aggregation object for the proofs that are provided - * - We add points P0 for each of our proofs - * - We add points P1 for each of our proofs - * - We concat our public inputs - * - * @param baseRollupInputs - * @return AggregationObject - */ -AggregationObject aggregate_proofs(BaseRollupInputs const& baseRollupInputs) -{ - // TODO: NOTE: for now we simply return the aggregation object from the first proof - return baseRollupInputs.kernel_data[0].public_inputs.end.aggregation_object; -} - -/** TODO: implement - * This is not being used - * @brief Get the prover contribution hash object - * - * @return NT::fr - */ -NT::fr get_prover_contribution_hash() -{ - return NT::fr(0); -} - -std::vector calculate_contract_leaves(BaseRollupInputs const& baseRollupInputs) -{ - std::vector contract_leaves; - - for (size_t i = 0; i < 2; i++) { - auto new_contacts = baseRollupInputs.kernel_data[i].public_inputs.end.new_contracts; - - // loop over the new contracts - // TODO: NOTE: we are currently assuming that there is only going to be one - for (auto& leaf_preimage : new_contacts) { - // When there is no contract deployment, we should insert a zero leaf into the tree and ignore the - // member-ship check. This is to ensure that we don't hit "already deployed" errors when we are not - // deploying contracts. e.g., when we are only calling functions on existing contracts. - auto to_push = leaf_preimage.contract_address == NT::address(0) ? NT::fr(0) : leaf_preimage.hash(); - contract_leaves.push_back(to_push); - } - } - - return contract_leaves; -} - -NT::fr calculate_contract_subtree(std::vector contract_leaves) -{ - MemoryStore contracts_tree_store; - MerkleTree contracts_tree(contracts_tree_store, CONTRACT_SUBTREE_HEIGHT); - - - // Compute the merkle root of a contract subtree - // Contracts subtree - for (size_t i = 0; i < contract_leaves.size(); i++) { - contracts_tree.update_element(i, contract_leaves[i]); - } - return contracts_tree.root(); -} - -NT::fr calculate_commitments_subtree(DummyBuilder& builder, BaseRollupInputs const& baseRollupInputs) -{ - MemoryStore commitments_tree_store; - MerkleTree commitments_tree(commitments_tree_store, NOTE_HASH_SUBTREE_HEIGHT); - - - for (size_t i = 0; i < 2; i++) { - auto new_commitments = baseRollupInputs.kernel_data[i].public_inputs.end.new_commitments; - - // Our commitments size MUST be 4 to calculate our subtrees correctly - builder.do_assert(new_commitments.size() == MAX_NEW_COMMITMENTS_PER_TX, - "New commitments in kernel data must be MAX_NEW_COMMITMENTS_PER_TX (see constants.hpp)", - CircuitErrorCode::BASE__INCORRECT_NUM_OF_NEW_COMMITMENTS); - - for (size_t j = 0; j < new_commitments.size(); j++) { - // todo: batch insert - commitments_tree.update_element(i * MAX_NEW_COMMITMENTS_PER_TX + j, new_commitments[j]); - } - } - - // Commitments subtree - return commitments_tree.root(); -} - -/** - * @brief Check all of the provided commitments against the historical tree roots - * - * @param constantBaseRollupData - * @param baseRollupInputs - */ -void perform_archive_membership_checks(DummyBuilder& builder, BaseRollupInputs const& baseRollupInputs) -{ - // For each of the historical_note_hash_tree_membership_checks, we need to do an inclusion proof - // against the historical root provided in the rollup constants - auto historical_root = baseRollupInputs.constants.start_archive_snapshot.root; - - for (size_t i = 0; i < 2; i++) { - // Rebuild the block hash - auto historical_block = baseRollupInputs.kernel_data[i].public_inputs.constants.block_header; - - auto note_hash_tree_root = historical_block.note_hash_tree_root; - auto nullifier_tree_root = historical_block.nullifier_tree_root; - auto contract_tree_root = historical_block.contract_tree_root; - auto l1_to_l2_message_tree_root = historical_block.l1_to_l2_message_tree_root; - auto public_data_tree_root = historical_block.public_data_tree_root; - - auto previous_block_hash = compute_block_hash(historical_block.global_variables_hash, - note_hash_tree_root, - nullifier_tree_root, - contract_tree_root, - l1_to_l2_message_tree_root, - public_data_tree_root); - - abis::MembershipWitness const historical_root_witness = - baseRollupInputs.archive_root_membership_witnesses[i]; - - check_membership(builder, - previous_block_hash, - historical_root_witness.leaf_index, - historical_root_witness.sibling_path, - historical_root, - format(BASE_CIRCUIT_ERROR_MESSAGE_BEGINNING, - "historical root is in rollup constants but not in blocks tree at kernel input ", - i, - " to this base rollup circuit")); - } -} - -NT::fr create_nullifier_subtree( - std::array const& nullifier_leaves) -{ - // Build a merkle tree of the nullifiers - MemoryStore nullifier_subtree_store; - MerkleTree nullifier_subtree(nullifier_subtree_store, NULLIFIER_SUBTREE_HEIGHT); - for (size_t i = 0; i < nullifier_leaves.size(); i++) { - // hash() checks if nullifier is empty (and if so returns 0) - nullifier_subtree.update_element(i, nullifier_leaves[i].hash()); - } - - return nullifier_subtree.root(); -} - -/** - * @brief Check non membership of each of the generated nullifiers in the current tree - * - * @returns The end nullifier tree root - */ -AppendOnlySnapshot check_nullifier_tree_non_membership_and_insert_to_tree(DummyBuilder& builder, - BaseRollupInputs const& baseRollupInputs) -{ - // LADIES AND GENTLEMEN The P L A N ( is simple ) - // 1. Get the previous nullifier set setup - // 2. Check for the first added nullifier that it doesnt exist - // 3. Update the nullifier set - // 4. Calculate a new root with the sibling path - // 5. Use that for the next nullifier check. - // 6. Iterate for all of em - - // BOYS AND GIRLS THE P L A N ( once the first plan is complete ) - // GENERATE OUR NEW NULLIFIER SUBTREE - // 1. We need to point the new nullifiers to point to the index that the previous nullifier replaced - // 2. If we receive the 0 nullifier leaf (where all values are 0, we skip insertion and leave a sparse subtree) - - // New nullifier subtree - std::array nullifier_insertion_subtree; - - // This will update on each iteration - auto current_nullifier_tree_root = baseRollupInputs.start_nullifier_tree_snapshot.root; - - // This will increase with every insertion - auto start_insertion_index = baseRollupInputs.start_nullifier_tree_snapshot.next_available_leaf_index; - auto new_index = start_insertion_index; - - // For each kernel circuit - for (size_t i = 0; i < 2; i++) { - auto new_nullifiers = baseRollupInputs.kernel_data[i].public_inputs.end.new_nullifiers; - // For each of our nullifiers - for (size_t j = 0; j < MAX_NEW_NULLIFIERS_PER_TX; j++) { - // Witness containing index and path - auto nullifier_index = i * MAX_NEW_NULLIFIERS_PER_TX + j; - - auto witness = baseRollupInputs.low_nullifier_membership_witness[nullifier_index]; - // Preimage of the lo-index required for a non-membership proof - auto low_nullifier_preimage = baseRollupInputs.low_nullifier_leaf_preimages[nullifier_index]; - // Newly created nullifier - auto nullifier = new_nullifiers[j]; - - // TODO(maddiaa): reason about this more strongly, can this cause issues? - if (nullifier != 0) { - // Create the nullifier leaf of the new nullifier to be inserted - NullifierLeafPreimage new_nullifier_leaf = { - .leaf_value = nullifier, - .next_value = low_nullifier_preimage.next_value, - .next_index = low_nullifier_preimage.next_index, - }; - - // Assuming populated premier subtree - if (low_nullifier_preimage.is_empty()) { - // check previous nullifier leaves - bool matched = false; - - for (size_t k = 0; k < nullifier_index && !matched; k++) { - if (nullifier_insertion_subtree[k].is_empty()) { - continue; - } - - if ((uint256_t(nullifier_insertion_subtree[k].leaf_value) < uint256_t(nullifier)) && - (uint256_t(nullifier_insertion_subtree[k].next_value) > uint256_t(nullifier) || - nullifier_insertion_subtree[k].next_value == 0)) { - matched = true; - // Update pointers - new_nullifier_leaf.next_index = nullifier_insertion_subtree[k].next_index; - new_nullifier_leaf.next_value = nullifier_insertion_subtree[k].next_value; - - // Update child - nullifier_insertion_subtree[k].next_index = new_index; - nullifier_insertion_subtree[k].next_value = nullifier; - } - } - - // if not matched, our subtree will misformed - we must reject - builder.do_assert( - matched, "Nullifier subtree is malformed", CircuitErrorCode::BASE__INVALID_NULLIFIER_SUBTREE); - - } else { - auto is_less_than_nullifier = uint256_t(low_nullifier_preimage.leaf_value) < uint256_t(nullifier); - auto is_next_greater_than = uint256_t(low_nullifier_preimage.next_value) > uint256_t(nullifier); - - if (!(is_less_than_nullifier && is_next_greater_than)) { - if (low_nullifier_preimage.next_index != 0 && low_nullifier_preimage.next_value != 0) { - builder.do_assert(false, - format("Nullifier (", - nullifier, - ") is not in the correct range. \n ", - "is_less_than_nullifier ", - is_less_than_nullifier, - "\n is_next_greater_than ", - is_next_greater_than, - "\n low_nullifier_preimage.leaf_value ", - low_nullifier_preimage.leaf_value, - "\n low_nullifier_preimage.next_index ", - low_nullifier_preimage.next_index, - "\n low_nullifier_preimage.next_value ", - low_nullifier_preimage.next_value), - CircuitErrorCode::BASE__INVALID_NULLIFIER_RANGE); - } - } - - // Recreate the original low nullifier from the preimage - auto const original_low_nullifier = NullifierLeafPreimage{ - .leaf_value = low_nullifier_preimage.leaf_value, - .next_value = low_nullifier_preimage.next_value, - .next_index = low_nullifier_preimage.next_index, - }; - - // perform membership check for the low nullifier against the original root - check_membership( - builder, - original_low_nullifier.hash(), - witness.leaf_index, - witness.sibling_path, - current_nullifier_tree_root, - format(BASE_CIRCUIT_ERROR_MESSAGE_BEGINNING, "low nullifier not in nullifier tree")); - - // Calculate the new value of the low_nullifier_leaf - auto const updated_low_nullifier = - NullifierLeafPreimage{ .leaf_value = low_nullifier_preimage.leaf_value, - .next_value = nullifier, - .next_index = new_index }; - - // We need another set of witness values for this - current_nullifier_tree_root = root_from_sibling_path( - updated_low_nullifier.hash(), witness.leaf_index, witness.sibling_path); - } - - nullifier_insertion_subtree[nullifier_index] = new_nullifier_leaf; - } else { - // 0 case - NullifierLeafPreimage const new_nullifier_leaf = { .leaf_value = 0, .next_value = 0, .next_index = 0 }; - nullifier_insertion_subtree[nullifier_index] = new_nullifier_leaf; - } - - // increment insertion index - new_index = new_index + 1; - } - } - - // Check that the new subtree is to be inserted at the next location, and is empty currently - const auto empty_nullifier_subtree_root = components::calculate_empty_tree_root(NULLIFIER_SUBTREE_HEIGHT); - auto leafIndexNullifierSubtreeDepth = - baseRollupInputs.start_nullifier_tree_snapshot.next_available_leaf_index >> NULLIFIER_SUBTREE_HEIGHT; - check_membership( - builder, - empty_nullifier_subtree_root, - leafIndexNullifierSubtreeDepth, - baseRollupInputs.new_nullifiers_subtree_sibling_path, - current_nullifier_tree_root, - format(BASE_CIRCUIT_ERROR_MESSAGE_BEGINNING, - "nullifier tree not empty at location where the new nullifier subtree would be inserted")); - - // Create new nullifier subtree to insert into the whole nullifier tree - auto nullifier_sibling_path = baseRollupInputs.new_nullifiers_subtree_sibling_path; - auto nullifier_subtree_root = create_nullifier_subtree(nullifier_insertion_subtree); - - // Calculate the new root - // We are inserting a subtree rather than a full tree here - auto subtree_index = start_insertion_index >> (NULLIFIER_SUBTREE_HEIGHT); - auto new_root = root_from_sibling_path(nullifier_subtree_root, subtree_index, nullifier_sibling_path); - - // Return the new state of the nullifier tree - return { - .root = new_root, - .next_available_leaf_index = new_index, - }; -} - -fr insert_public_data_update_requests( - DummyBuilder& builder, - fr tree_root, - std::array, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX> const& - public_data_update_requests, - size_t witnesses_offset, - std::array, 2 * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX> const& witnesses) -{ - auto root = tree_root; - - for (size_t i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; ++i) { - const auto& state_write = public_data_update_requests[i]; - const auto& witness = witnesses[i + witnesses_offset]; - - if (state_write.is_empty()) { - continue; - } - - check_membership( - builder, - state_write.old_value, - state_write.leaf_index, - witness, - root, - format(BASE_CIRCUIT_ERROR_MESSAGE_BEGINNING, "validate_public_data_update_requests index ", i)); - - root = root_from_sibling_path(state_write.new_value, state_write.leaf_index, witness); - } - - return root; -} - -void validate_public_data_reads( - DummyBuilder& builder, - fr tree_root, - std::array, MAX_PUBLIC_DATA_READS_PER_TX> const& public_data_reads, - size_t witnesses_offset, - std::array, 2 * MAX_PUBLIC_DATA_READS_PER_TX> const& witnesses) -{ - for (size_t i = 0; i < MAX_PUBLIC_DATA_READS_PER_TX; ++i) { - const auto& public_data_read = public_data_reads[i]; - const auto& witness = witnesses[i + witnesses_offset]; - - if (public_data_read.is_empty()) { - continue; - } - - check_membership( - builder, - public_data_read.value, - public_data_read.leaf_index, - witness, - tree_root, - format(BASE_CIRCUIT_ERROR_MESSAGE_BEGINNING, "validate_public_data_reads index ", i + witnesses_offset)); - } -}; - -fr validate_and_process_public_state(DummyBuilder& builder, BaseRollupInputs const& baseRollupInputs) -{ - // TODO(#2521) - data read validation should happen against the current state of the tx and not the start state. - // Blocks all interesting usecases that read and write to the same public state in the same tx. - // https://aztecprotocol.slack.com/archives/C02M7VC7TN0/p1695809629015719?thread_ts=1695653252.007339&cid=C02M7VC7TN0 - - - // Process public data reads and public data update requests for left input - // validate_public_data_reads(builder, - // baseRollupInputs.start_public_data_tree_root, - // baseRollupInputs.kernel_data[0].public_inputs.end.public_data_reads, - // 0, - // baseRollupInputs.new_public_data_reads_sibling_paths); - - auto mid_public_data_tree_root = insert_public_data_update_requests( - builder, - baseRollupInputs.start_public_data_tree_root, - baseRollupInputs.kernel_data[0].public_inputs.end.public_data_update_requests, - 0, - baseRollupInputs.new_public_data_update_requests_sibling_paths); - - - // TODO(#2521) - data read validation should happen against the current state of the tx and not the start state. - // Blocks all interesting usecases that read and write to the same public state in the same tx. - // https://aztecprotocol.slack.com/archives/C02M7VC7TN0/p1695809629015719?thread_ts=1695653252.007339&cid=C02M7VC7TN0 - - - // Process public data reads and public data update requests for right input using the resulting tree root from the - // left one - // validate_public_data_reads(builder, - // mid_public_data_tree_root, - // baseRollupInputs.kernel_data[1].public_inputs.end.public_data_reads, - // MAX_PUBLIC_DATA_READS_PER_TX, - // baseRollupInputs.new_public_data_reads_sibling_paths); - - auto end_public_data_tree_root = insert_public_data_update_requests( - builder, - mid_public_data_tree_root, - baseRollupInputs.kernel_data[1].public_inputs.end.public_data_update_requests, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - baseRollupInputs.new_public_data_update_requests_sibling_paths); - - return end_public_data_tree_root; -} - -BaseOrMergeRollupPublicInputs base_rollup_circuit(DummyBuilder& builder, BaseRollupInputs const& baseRollupInputs) -{ - // Verify the previous kernel proofs - for (size_t i = 0; i < 2; i++) { - NT::Proof const proof = baseRollupInputs.kernel_data[i].proof; - builder.do_assert(verify_kernel_proof(proof), - "kernel proof verification failed", - CircuitErrorCode::BASE__KERNEL_PROOF_VERIFICATION_FAILED); - } - - // Verify the kernel chain_id and versions - for (size_t i = 0; i < 2; i++) { - builder.do_assert(baseRollupInputs.kernel_data[i].public_inputs.constants.tx_context.chain_id == - baseRollupInputs.constants.global_variables.chain_id, - "kernel chain_id does not match the rollup chain_id", - CircuitErrorCode::BASE__INVALID_CHAIN_ID); - builder.do_assert(baseRollupInputs.kernel_data[i].public_inputs.constants.tx_context.version == - baseRollupInputs.constants.global_variables.version, - "kernel version does not match the rollup version", - CircuitErrorCode::BASE__INVALID_VERSION); - } - - // First we compute the contract tree leaves - std::vector const contract_leaves = calculate_contract_leaves(baseRollupInputs); - - // Check contracts and commitments subtrees - NT::fr const contracts_tree_subroot = calculate_contract_subtree(contract_leaves); - NT::fr const commitments_tree_subroot = calculate_commitments_subtree(builder, baseRollupInputs); - - // Insert commitment subtrees: - const auto empty_commitments_subtree_root = components::calculate_empty_tree_root(NOTE_HASH_SUBTREE_HEIGHT); - auto end_note_hash_tree_snapshot = components::insert_subtree_to_snapshot_tree( - builder, - baseRollupInputs.start_note_hash_tree_snapshot, - baseRollupInputs.new_commitments_subtree_sibling_path, - empty_commitments_subtree_root, - commitments_tree_subroot, - NOTE_HASH_SUBTREE_HEIGHT, - format(BASE_CIRCUIT_ERROR_MESSAGE_BEGINNING, - "note hash tree not empty at location where the new commitment subtree would be inserted")); - // Insert contract subtrees: - const auto empty_contracts_subtree_root = components::calculate_empty_tree_root(CONTRACT_SUBTREE_HEIGHT); - auto end_contract_tree_snapshot = components::insert_subtree_to_snapshot_tree( - builder, - baseRollupInputs.start_contract_tree_snapshot, - baseRollupInputs.new_contracts_subtree_sibling_path, - empty_contracts_subtree_root, - contracts_tree_subroot, - CONTRACT_SUBTREE_HEIGHT, - format(BASE_CIRCUIT_ERROR_MESSAGE_BEGINNING, - "contract tree not empty at location where the new contract subtree would be inserted")); - - // Insert nullifiers: - AppendOnlySnapshot const end_nullifier_tree_snapshot = - check_nullifier_tree_non_membership_and_insert_to_tree(builder, baseRollupInputs); - - // Validate public public data reads and public data update requests, and update public data tree - fr const end_public_data_tree_root = validate_and_process_public_state(builder, baseRollupInputs); - - // Calculate the overall calldata hash - std::array const calldata_hash = - components::compute_kernels_calldata_hash(baseRollupInputs.kernel_data); - - // Perform membership checks that the notes provided exist within the historical trees data - perform_archive_membership_checks(builder, baseRollupInputs); - - AggregationObject const aggregation_object = aggregate_proofs(baseRollupInputs); - - BaseOrMergeRollupPublicInputs public_inputs = { - .rollup_type = abis::BASE_ROLLUP_TYPE, - .rollup_subtree_height = fr(0), - .end_aggregation_object = aggregation_object, - .constants = baseRollupInputs.constants, - .start_note_hash_tree_snapshot = baseRollupInputs.start_note_hash_tree_snapshot, - .end_note_hash_tree_snapshot = end_note_hash_tree_snapshot, - .start_nullifier_tree_snapshot = baseRollupInputs.start_nullifier_tree_snapshot, - .end_nullifier_tree_snapshot = end_nullifier_tree_snapshot, - .start_contract_tree_snapshot = baseRollupInputs.start_contract_tree_snapshot, - .end_contract_tree_snapshot = end_contract_tree_snapshot, - .start_public_data_tree_root = baseRollupInputs.start_public_data_tree_root, - .end_public_data_tree_root = end_public_data_tree_root, - .calldata_hash = calldata_hash, - }; - return public_inputs; -} - -} // namespace aztec3::circuits::rollup::native_base_rollup diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/native_base_rollup_circuit.hpp b/circuits/cpp/src/aztec3/circuits/rollup/base/native_base_rollup_circuit.hpp deleted file mode 100644 index 9ea9dbb9a18..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/native_base_rollup_circuit.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "init.hpp" - -// TODO: not needed right at this moment for native impl -#include "aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp" -#include "aztec3/circuits/abis/rollup/base/base_rollup_inputs.hpp" -#include "aztec3/circuits/abis/rollup/constant_rollup_data.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -namespace aztec3::circuits::rollup::native_base_rollup { - -BaseOrMergeRollupPublicInputs base_rollup_circuit(DummyBuilder& builder, BaseRollupInputs const& baseRollupInputs); - -} // namespace aztec3::circuits::rollup::native_base_rollup \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/components/components.cpp b/circuits/cpp/src/aztec3/circuits/rollup/components/components.cpp deleted file mode 100644 index fe3b1463910..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/components/components.cpp +++ /dev/null @@ -1,277 +0,0 @@ -#include "init.hpp" - -#include "aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/circuit_errors.hpp" - -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace aztec3::circuits::rollup::components { - -/** - * @brief Get the root of an empty tree of a given depth - * - * @param depth - * @return NT::fr - */ -NT::fr calculate_empty_tree_root(const size_t depth) -{ - MemoryStore empty_tree_store; - MerkleTree const empty_tree = MerkleTree(empty_tree_store, depth); - return empty_tree.root(); -} - -/** - * @brief Create an aggregation object for the proofs that are provided - * - We add points P0 for each of our proofs - * - We add points P1 for each of our proofs - * - We concat our public inputs - * - * @param mergeRollupInputs - * @return AggregationObject - */ -AggregationObject aggregate_proofs(BaseOrMergeRollupPublicInputs const& left, - BaseOrMergeRollupPublicInputs const& right) -{ - // TODO: NOTE: for now we simply return the aggregation object from the first proof - (void)right; - return left.end_aggregation_object; -} - -/** - * @brief Asserts that the rollup types are the same - * - * @param left - The public inputs of the left rollup (base or merge) - * @param right - The public inputs of the right rollup (base or merge) - */ -void assert_both_input_proofs_of_same_rollup_type(DummyBuilder& builder, - BaseOrMergeRollupPublicInputs const& left, - BaseOrMergeRollupPublicInputs const& right) -{ - builder.do_assert(left.rollup_type == right.rollup_type, - "input proofs are of different rollup types", - utils::CircuitErrorCode::ROLLUP_TYPE_MISMATCH); -} - -/** - * @brief Asserts that the rollup subtree heights are the same and returns the height - * - * @param left - The public inputs of the left rollup (base or merge) - * @param right - The public inputs of the right rollup (base or merge) - * @return NT::fr - The height of the rollup subtrees - */ -NT::fr assert_both_input_proofs_of_same_height_and_return(DummyBuilder& builder, - BaseOrMergeRollupPublicInputs const& left, - BaseOrMergeRollupPublicInputs const& right) -{ - builder.do_assert(left.rollup_subtree_height == right.rollup_subtree_height, - "input proofs are of different rollup heights", - utils::CircuitErrorCode::ROLLUP_HEIGHT_MISMATCH); - return left.rollup_subtree_height; -} - -/** - * @brief Asserts that the constants used in the left and right child are identical - * - * @param left - The public inputs of the left rollup (base or merge) - * @param right - The public inputs of the right rollup (base or merge) - */ -void assert_equal_constants(DummyBuilder& builder, - BaseOrMergeRollupPublicInputs const& left, - BaseOrMergeRollupPublicInputs const& right) -{ - builder.do_assert(left.constants == right.constants, - "input proofs have different constants", - utils::CircuitErrorCode::CONSTANTS_MISMATCH); -} - -/** - * @brief Computes the calldata hash for a base rollup - * - * @param kernel_data - 2 kernels - * @return calldata hash stored in 2 fields - */ -std::array compute_kernels_calldata_hash( - std::array, 2> kernel_data) -{ - // Compute calldata hashes - // Consist of 2 kernels - // 2 * MAX_NEW_COMMITMENTS_PER_TX fields for commitments - // 2 * MAX_NEW_NULLIFIERS_PER_TX fields for nullifiers - // 8 public data update requests (4 per kernel) -> 16 fields - // 4 l2 -> l1 messages (2 per kernel) -> 4 fields - // 2 contract deployments (1 per kernel) -> 6 fields - // 2 encrypted logs hashes (1 per kernel) -> 4 fields --> 2 sha256 hashes --> 64 bytes - // 2 unencrypted logs hashes (1 per kernel) -> 4 fields --> 2 sha256 hashes --> 64 bytes - auto const number_of_inputs = - (MAX_NEW_COMMITMENTS_PER_TX + MAX_NEW_NULLIFIERS_PER_TX + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 + - MAX_NEW_L2_TO_L1_MSGS_PER_TX + MAX_NEW_CONTRACTS_PER_TX * 3 + - NUM_ENCRYPTED_LOGS_HASHES_PER_TX * NUM_FIELDS_PER_SHA256 + - NUM_UNENCRYPTED_LOGS_HASHES_PER_TX * NUM_FIELDS_PER_SHA256) * - 2; - std::array calldata_hash_inputs{}; - - for (size_t i = 0; i < 2; i++) { - auto new_commitments = kernel_data[i].public_inputs.end.new_commitments; - auto new_nullifiers = kernel_data[i].public_inputs.end.new_nullifiers; - auto public_data_update_requests = kernel_data[i].public_inputs.end.public_data_update_requests; - auto newL2ToL1msgs = kernel_data[i].public_inputs.end.new_l2_to_l1_msgs; - auto encryptedLogsHash = kernel_data[i].public_inputs.end.encrypted_logs_hash; - auto unencryptedLogsHash = kernel_data[i].public_inputs.end.unencrypted_logs_hash; - - size_t offset = 0; - - for (size_t j = 0; j < MAX_NEW_COMMITMENTS_PER_TX; j++) { - calldata_hash_inputs[offset + i * MAX_NEW_COMMITMENTS_PER_TX + j] = new_commitments[j]; - } - offset += MAX_NEW_COMMITMENTS_PER_TX * 2; - - for (size_t j = 0; j < MAX_NEW_NULLIFIERS_PER_TX; j++) { - calldata_hash_inputs[offset + i * MAX_NEW_NULLIFIERS_PER_TX + j] = new_nullifiers[j]; - } - offset += MAX_NEW_NULLIFIERS_PER_TX * 2; - - for (size_t j = 0; j < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; j++) { - calldata_hash_inputs[offset + i * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 + j * 2] = - public_data_update_requests[j].leaf_index; - calldata_hash_inputs[offset + i * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 + j * 2 + 1] = - public_data_update_requests[j].new_value; - } - offset += MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 * 2; - - for (size_t j = 0; j < MAX_NEW_L2_TO_L1_MSGS_PER_TX; j++) { - calldata_hash_inputs[offset + i * MAX_NEW_L2_TO_L1_MSGS_PER_TX + j] = newL2ToL1msgs[j]; - } - offset += MAX_NEW_L2_TO_L1_MSGS_PER_TX * 2; - - auto const contract_leaf = kernel_data[i].public_inputs.end.new_contracts[0]; - calldata_hash_inputs[offset + i] = contract_leaf.hash(); - - offset += MAX_NEW_CONTRACTS_PER_TX * 2; - - auto new_contracts = kernel_data[i].public_inputs.end.new_contracts; - calldata_hash_inputs[offset + i * 2] = new_contracts[0].contract_address; - calldata_hash_inputs[offset + i * 2 + 1] = new_contracts[0].portal_contract_address; - - offset += MAX_NEW_CONTRACTS_PER_TX * 2 * 2; - - for (size_t j = 0; j < NUM_FIELDS_PER_SHA256; j++) { - calldata_hash_inputs[offset + i * 2 + j] = encryptedLogsHash[j]; - } - - offset += NUM_ENCRYPTED_LOGS_HASHES_PER_TX * NUM_FIELDS_PER_SHA256 * 2; - - for (size_t j = 0; j < NUM_FIELDS_PER_SHA256; j++) { - calldata_hash_inputs[offset + i * 2 + j] = unencryptedLogsHash[j]; - } - } - - // OPTIMIZE DATA OVERHEAD - // The data structure calldata_hash_inputs contains 2 * 2 * NUM_FIELDS_PER_SHA256 fr entries for logsHashes. (2 - // kernels and 2 types of log per kernel). One sha-256 hash value represented in fr array is actually splitted into - // 2 fields because fr is 254 bits (smaller than 256 bits). By serializing such a (fr-based) hash value back into - // bytes, we only need 32 bytes (256 bits), while the standard fr-array to bytes serialization would return 64 - // bytes. For the unencryptedlogs and encryptedlogs, we therefore need 2 * NUM_FIELDS_PER_SHA256 * 32 bytes instead - // of 2 * 2 * NUM_FIELDS_PER_SHA256 * 32 bytes (half of this is saved). - - // We subtract 2 * NUM_FIELDS_PER_SHA256 * 32 bytes as explained above. - constexpr auto num_bytes = (calldata_hash_inputs.size() - NUM_FIELDS_PER_SHA256 * 2) * 32; - std::array calldata_hash_inputs_bytes{}; - - // Serialize everything from calldata_hash_inputs except the logs at this stage and copy into - // calldata_hash_inputs_bytes; - for (size_t i = 0; i < calldata_hash_inputs.size() - NUM_FIELDS_PER_SHA256 * 2 * 2; i++) { - auto as_bytes = calldata_hash_inputs[i].to_buffer(); - auto offset = i * 32; - std::copy(as_bytes.begin(), as_bytes.end(), calldata_hash_inputs_bytes.begin() + offset); - } - - // Copy the 4 fields of 2 encrypted logs to 64 bytes - // Modified version of: - // https://github.com/AztecProtocol/aztec-packages/blob/01080c7f1d2956512b6a9cff0582b43be25b3cc2/circuits/cpp/src/aztec3/circuits/hash.hpp#L350 - const uint32_t encrypted_logs_start_index = calldata_hash_inputs.size() - NUM_FIELDS_PER_SHA256 * 2 * 2; - const uint32_t first_modified_byte_encrypted = - num_bytes - NUM_FIELDS_PER_SHA256 * 2 * - 32; // offsetting by number of bytes occupied by all the logs hashes (in the optimized form) - for (uint8_t i = 0; i < 4; i++) { - auto half = calldata_hash_inputs[encrypted_logs_start_index + i].to_buffer(); - for (uint8_t j = 0; j < 16; j++) { - calldata_hash_inputs_bytes[first_modified_byte_encrypted + i * 16 + j] = half[16 + j]; - } - } - - // Do the same for the unencrypted logs - const uint32_t unencrypted_logs_start_index = calldata_hash_inputs.size() - NUM_FIELDS_PER_SHA256 * 2; - const uint32_t first_modified_byte_unencrypted = - num_bytes - NUM_FIELDS_PER_SHA256 * 32; // offsetting num bytes occupied by unencrypted logs hashes - for (uint8_t i = 0; i < 4; i++) { - auto half = calldata_hash_inputs[unencrypted_logs_start_index + i].to_buffer(); - for (uint8_t j = 0; j < 16; j++) { - calldata_hash_inputs_bytes[first_modified_byte_unencrypted + i * 16 + j] = half[16 + j]; - } - } - - std::vector const calldata_hash_inputs_bytes_vec(calldata_hash_inputs_bytes.begin(), - calldata_hash_inputs_bytes.end()); - - auto h = sha256::sha256(calldata_hash_inputs_bytes_vec); - - // Split the hash into two fields, a high and a low - std::array buf_1; - std::array buf_2; - for (uint8_t i = 0; i < 16; i++) { - buf_1[i] = 0; - buf_1[16 + i] = h[i]; - buf_2[i] = 0; - buf_2[16 + i] = h[i + 16]; - } - auto high = fr::serialize_from_buffer(buf_1.data()); - auto low = fr::serialize_from_buffer(buf_2.data()); - - return std::array{ high, low }; -} - -/** - * @brief From two previous rollup data, compute a single calldata hash - * - * @param previous_rollup_data - * @return calldata hash stored in 2 fields - */ -std::array compute_calldata_hash( - std::array, 2> previous_rollup_data) -{ - return accumulate_sha256({ previous_rollup_data[0].base_or_merge_rollup_public_inputs.calldata_hash[0], - previous_rollup_data[0].base_or_merge_rollup_public_inputs.calldata_hash[1], - previous_rollup_data[1].base_or_merge_rollup_public_inputs.calldata_hash[0], - previous_rollup_data[1].base_or_merge_rollup_public_inputs.calldata_hash[1] }); -} - -// asserts that the end snapshot of previous_rollup 0 equals the start snapshot of previous_rollup 1 (i.e. ensure they -// follow on from one-another). Ensures that right uses the tres that was updated by left. -void assert_prev_rollups_follow_on_from_each_other(DummyBuilder& builder, - BaseOrMergeRollupPublicInputs const& left, - BaseOrMergeRollupPublicInputs const& right) -{ - builder.do_assert(left.end_note_hash_tree_snapshot == right.start_note_hash_tree_snapshot, - "input proofs have different note hash tree snapshots", - utils::CircuitErrorCode::NOTE_HASH_TREE_SNAPSHOT_MISMATCH); - builder.do_assert(left.end_nullifier_tree_snapshot == right.start_nullifier_tree_snapshot, - "input proofs have different nullifier tree snapshots", - utils::CircuitErrorCode::NULLIFIER_TREE_SNAPSHOT_MISMATCH); - builder.do_assert(left.end_contract_tree_snapshot == right.start_contract_tree_snapshot, - "input proofs have different contract tree snapshots", - utils::CircuitErrorCode::CONTRACT_TREE_SNAPSHOT_MISMATCH); - builder.do_assert(left.end_public_data_tree_root == right.start_public_data_tree_root, - "input proofs have different public data tree snapshots", - utils::CircuitErrorCode::CONTRACT_TREE_SNAPSHOT_MISMATCH); -} - -} // namespace aztec3::circuits::rollup::components \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/components/components.hpp b/circuits/cpp/src/aztec3/circuits/rollup/components/components.hpp deleted file mode 100644 index 2e64593dc65..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/components/components.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -#include "init.hpp" - -#include "aztec3/utils/circuit_errors.hpp" - -using aztec3::circuits::check_membership; -using aztec3::circuits::root_from_sibling_path; - -namespace aztec3::circuits::rollup::components { -NT::fr calculate_empty_tree_root(size_t depth); -std::array compute_kernels_calldata_hash( - std::array, 2> kernel_data); -std::array compute_calldata_hash( - std::array, 2> previous_rollup_data); -void assert_prev_rollups_follow_on_from_each_other(DummyBuilder& builder, - BaseOrMergeRollupPublicInputs const& left, - BaseOrMergeRollupPublicInputs const& right); -void assert_both_input_proofs_of_same_rollup_type(DummyBuilder& builder, - BaseOrMergeRollupPublicInputs const& left, - BaseOrMergeRollupPublicInputs const& right); -NT::fr assert_both_input_proofs_of_same_height_and_return(DummyBuilder& builder, - BaseOrMergeRollupPublicInputs const& left, - BaseOrMergeRollupPublicInputs const& right); -void assert_equal_constants(DummyBuilder& builder, - BaseOrMergeRollupPublicInputs const& left, - BaseOrMergeRollupPublicInputs const& right); - -AggregationObject aggregate_proofs(BaseOrMergeRollupPublicInputs const& left, - BaseOrMergeRollupPublicInputs const& right); - -template AppendOnlySnapshot insert_subtree_to_snapshot_tree(DummyBuilder& builder, - AppendOnlySnapshot snapshot, - std::array siblingPath, - NT::fr emptySubtreeRoot, - NT::fr subtreeRootToInsert, - uint8_t subtreeDepth, - std::string const& emptySubtreeCheckErrorMessage) -{ - // TODO: Sanity check len of siblingPath > height of subtree - // TODO: Ensure height of subtree is correct (eg 3 for commitments, 1 for contracts) - auto leafIndexAtDepth = snapshot.next_available_leaf_index >> subtreeDepth; - - // Check that the current root is correct and that there is an empty subtree at the insertion location - check_membership( - builder, emptySubtreeRoot, leafIndexAtDepth, siblingPath, snapshot.root, emptySubtreeCheckErrorMessage); - - // if index of leaf is x, index of its parent is x/2 or x >> 1. We need to find the parent `subtreeDepth` levels up. - auto new_root = root_from_sibling_path(subtreeRootToInsert, leafIndexAtDepth, siblingPath); - - // 2^subtreeDepth is the number of leaves added. 2^x = 1 << x - auto new_next_available_leaf_index = snapshot.next_available_leaf_index + (static_cast(1) << subtreeDepth); - - AppendOnlySnapshot newTreeSnapshot = { .root = new_root, - .next_available_leaf_index = new_next_available_leaf_index }; - return newTreeSnapshot; -} -} // namespace aztec3::circuits::rollup::components \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/components/init.hpp b/circuits/cpp/src/aztec3/circuits/rollup/components/init.hpp deleted file mode 100644 index 895cdee4c41..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/components/init.hpp +++ /dev/null @@ -1,30 +0,0 @@ - -#pragma once - -#include "aztec3/circuits/abis/append_only_tree_snapshot.hpp" -#include "aztec3/circuits/abis/previous_kernel_data.hpp" -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp" -#include "aztec3/circuits/abis/rollup/constant_rollup_data.hpp" -#include "aztec3/circuits/abis/rollup/merge/merge_rollup_inputs.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/circuits/recursion/aggregator.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::rollup::components { - -using NT = aztec3::utils::types::NativeTypes; - -// Params -using NT = aztec3::utils::types::NativeTypes; -using AggregationObject = aztec3::utils::types::NativeTypes::AggregationObject; -using BaseOrMergeRollupPublicInputs = aztec3::circuits::abis::BaseOrMergeRollupPublicInputs; -using AppendOnlySnapshot = abis::AppendOnlyTreeSnapshot; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; - -} // namespace aztec3::circuits::rollup::components \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/merge/.test.cpp b/circuits/cpp/src/aztec3/circuits/rollup/merge/.test.cpp deleted file mode 100644 index 85d436a8319..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/merge/.test.cpp +++ /dev/null @@ -1,309 +0,0 @@ -#include "c_bind.h" -#include "index.hpp" -#include "init.hpp" - -#include "aztec3/circuits/rollup/merge/init.hpp" -#include "aztec3/circuits/rollup/test_utils/utils.hpp" - -#include - -#include - -namespace { -using aztec3::circuits::rollup::merge::MergeRollupInputs; -using DummyCircuitBuilder = aztec3::utils::DummyCircuitBuilder; - -using aztec3::circuits::rollup::test_utils::utils::compare_field_hash_to_expected; -using aztec3::circuits::rollup::test_utils::utils::get_empty_kernel; -using aztec3::circuits::rollup::test_utils::utils::get_merge_rollup_inputs; - -using NT = aztec3::utils::types::NativeTypes; - -using KernelData = aztec3::circuits::abis::PreviousKernelData; - -} // namespace -namespace aztec3::circuits::rollup::merge::native_merge_rollup_circuit { - -class merge_rollup_tests : public ::testing::Test { - protected: - static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../barretenberg/cpp/srs_db/ignition"); } - - // TODO(1998): uncomment once https://github.com/AztecProtocol/aztec-packages/issues/1998 is solved and - // use new pattern such as call_func_and_wrapper from test_helper.hpp - - // static void run_cbind(MergeRollupInputs& merge_rollup_inputs, - // BaseOrMergeRollupPublicInputs& expected_public_inputs, - // bool compare_pubins = true) - // { - // info("Retesting via cbinds...."); - // std::vector merge_rollup_inputs_vec; - // serialize::write(merge_rollup_inputs_vec, merge_rollup_inputs); - - // uint8_t const* public_inputs_buf = nullptr; - // // info("simulating circuit via cbind"); - // size_t public_inputs_size = 0; - // info("creating proof"); - // auto* circuit_failure_ptr = - // merge_rollup__sim(merge_rollup_inputs_vec.data(), &public_inputs_size, &public_inputs_buf); - // ASSERT_TRUE(circuit_failure_ptr == nullptr); - // // info("PublicInputs size: ", public_inputs_size); - - // if (compare_pubins) { - // BaseOrMergeRollupPublicInputs public_inputs; - // uint8_t const* public_inputs_buf_tmp = public_inputs_buf; - // serialize::read(public_inputs_buf_tmp, public_inputs); - // ASSERT_EQ(public_inputs.calldata_hash.size(), expected_public_inputs.calldata_hash.size()); - // for (size_t i = 0; i < public_inputs.calldata_hash.size(); i++) { - // ASSERT_EQ(public_inputs.calldata_hash[i], expected_public_inputs.calldata_hash[i]); - // } - - // std::vector expected_public_inputs_vec; - // serialize::write(expected_public_inputs_vec, expected_public_inputs); - - // ASSERT_EQ(public_inputs_size, expected_public_inputs_vec.size()); - // // Just compare the first 10 bytes of the serialized public outputs - // if (public_inputs_size > 10) { - // // for (size_t 0; i < public_inputs_size; i++) { - // for (size_t i = 0; i < 10; i++) { - // ASSERT_EQ(public_inputs_buf[i], expected_public_inputs_vec[i]); - // } - // } - // } - // free((void*)public_inputs_buf); - // } -}; - -TEST_F(merge_rollup_tests, native_different_rollup_type_fails) -{ - DummyBuilder builder = DummyBuilder("merge_rollup_tests__native_different_rollup_type_fails"); - std::array const kernels = { - get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() - }; - MergeRollupInputs mergeInput = get_merge_rollup_inputs(builder, kernels); - mergeInput.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_type = 0; - mergeInput.previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_type = 1; - merge_rollup_circuit(builder, mergeInput); - ASSERT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().message, "input proofs are of different rollup types"); -} - -TEST_F(merge_rollup_tests, native_different_rollup_height_fails) -{ - DummyBuilder builder = DummyBuilder("merge_rollup_tests__native_different_rollup_height_fails"); - std::array const kernels = { - get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() - }; - MergeRollupInputs mergeInput = get_merge_rollup_inputs(builder, kernels); - mergeInput.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_subtree_height = 0; - mergeInput.previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_subtree_height = 1; - merge_rollup_circuit(builder, mergeInput); - ASSERT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().message, "input proofs are of different rollup heights"); -} - -TEST_F(merge_rollup_tests, native_constants_different_failure) -{ - DummyBuilder builder = DummyBuilder("merge_rollup_tests__native_constants_different_failure"); - std::array const kernels = { - get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() - }; - MergeRollupInputs inputs = get_merge_rollup_inputs(builder, kernels); - inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.constants.public_kernel_vk_tree_root = fr(1); - inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.constants.public_kernel_vk_tree_root = fr(0); - merge_rollup_circuit(builder, inputs); - ASSERT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().message, "input proofs have different constants"); -} - -TEST_F(merge_rollup_tests, native_constants_different_chain_id_failure) -{ - DummyBuilder builder = DummyBuilder("merge_rollup_tests__native_constants_different_failure"); - std::array const kernels = { - get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() - }; - MergeRollupInputs inputs = get_merge_rollup_inputs(builder, kernels); - inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.constants.global_variables.chain_id = fr(1); - inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.constants.global_variables.chain_id = fr(0); - merge_rollup_circuit(builder, inputs); - ASSERT_TRUE(builder.failed()); - ASSERT_EQ(builder.get_first_failure().message, "input proofs have different constants"); -} - -TEST_F(merge_rollup_tests, native_fail_if_previous_rollups_dont_follow_on) -{ - DummyBuilder builderA = DummyBuilder("merge_rollup_tests__native_fail_if_previous_rollups_dont_follow_on_A"); - std::array const kernels = { - get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() - }; - MergeRollupInputs const inputs = get_merge_rollup_inputs(builderA, kernels); - auto inputA = inputs; - inputA.previous_rollup_data[0].base_or_merge_rollup_public_inputs.end_note_hash_tree_snapshot = { - .root = fr(0), .next_available_leaf_index = 0 - }; - inputA.previous_rollup_data[1].base_or_merge_rollup_public_inputs.start_note_hash_tree_snapshot = { - .root = fr(1), .next_available_leaf_index = 0 - }; - - merge_rollup_circuit(builderA, inputA); - ASSERT_TRUE(builderA.failed()); - ASSERT_EQ(builderA.get_first_failure().message, "input proofs have different note hash tree snapshots"); - - // do the same for nullifier tree - DummyBuilder builderB = DummyBuilder("merge_rollup_tests__native_fail_if_previous_rollups_dont_follow_on_B"); - auto inputB = inputs; - - inputB.previous_rollup_data[0].base_or_merge_rollup_public_inputs.end_nullifier_tree_snapshot = { - .root = fr(0), .next_available_leaf_index = 0 - }; - inputB.previous_rollup_data[1].base_or_merge_rollup_public_inputs.start_nullifier_tree_snapshot = { - .root = fr(1), .next_available_leaf_index = 0 - }; - merge_rollup_circuit(builderB, inputB); - ASSERT_TRUE(builderB.failed()); - ASSERT_EQ(builderB.get_first_failure().message, "input proofs have different nullifier tree snapshots"); - - // do the same for contract tree - DummyBuilder builderC = DummyBuilder("merge_rollup_tests__native_fail_if_previous_rollups_dont_follow_on_C"); - auto inputC = inputs; - inputC.previous_rollup_data[0].base_or_merge_rollup_public_inputs.end_contract_tree_snapshot = { - .root = fr(0), .next_available_leaf_index = 0 - }; - inputC.previous_rollup_data[1].base_or_merge_rollup_public_inputs.start_contract_tree_snapshot = { - .root = fr(1), .next_available_leaf_index = 0 - }; - merge_rollup_circuit(builderC, inputC); - ASSERT_TRUE(builderC.failed()); - ASSERT_EQ(builderC.get_first_failure().message, "input proofs have different contract tree snapshots"); -} - -TEST_F(merge_rollup_tests, native_rollup_fields_are_set_correctly) -{ - DummyBuilder builder = DummyBuilder("merge_rollup_tests__native_rollup_fields_are_set_correctly"); - std::array const kernels = { - get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() - }; - MergeRollupInputs inputs = get_merge_rollup_inputs(builder, kernels); - BaseOrMergeRollupPublicInputs outputs = merge_rollup_circuit(builder, inputs); - // check that rollup type is set to merge - ASSERT_EQ(outputs.rollup_type, 1); - // check that rollup height is incremented - ASSERT_EQ(outputs.rollup_subtree_height, - inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_subtree_height + 1); - - // set inputs to have a merge rollup type and set the rollup height and test again. - inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_type = 1; - inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_subtree_height = 1; - - inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_type = 1; - inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_subtree_height = 1; - - outputs = merge_rollup_circuit(builder, inputs); - ASSERT_EQ(outputs.rollup_type, 1); - ASSERT_EQ(outputs.rollup_subtree_height, 2); - ASSERT_FALSE(builder.failed()); -} - -TEST_F(merge_rollup_tests, native_start_and_end_snapshots) -{ - DummyBuilder builder = DummyBuilder("merge_rollup_tests__native_start_and_end_snapshots"); - std::array const kernels = { - get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() - }; - MergeRollupInputs inputs = get_merge_rollup_inputs(builder, kernels); - BaseOrMergeRollupPublicInputs const outputs = merge_rollup_circuit(builder, inputs); - // check that start and end snapshots are set correctly - ASSERT_EQ(outputs.start_note_hash_tree_snapshot, - inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_note_hash_tree_snapshot); - ASSERT_EQ(outputs.end_note_hash_tree_snapshot, - inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.end_note_hash_tree_snapshot); - - ASSERT_EQ(outputs.start_nullifier_tree_snapshot, - inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_nullifier_tree_snapshot); - ASSERT_EQ(outputs.end_nullifier_tree_snapshot, - inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.end_nullifier_tree_snapshot); - - ASSERT_EQ(outputs.start_contract_tree_snapshot, - inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_contract_tree_snapshot); - ASSERT_EQ(outputs.end_contract_tree_snapshot, - inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.end_contract_tree_snapshot); - - ASSERT_EQ(outputs.start_public_data_tree_root, - inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_public_data_tree_root); - ASSERT_EQ(outputs.end_public_data_tree_root, - inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.end_public_data_tree_root); - - ASSERT_FALSE(builder.failed()); -} - -TEST_F(merge_rollup_tests, native_calldata_hash) -{ - DummyBuilder builder = DummyBuilder("merge_rollup_tests__native_calldata_hash"); - std::vector const zero_bytes_vec = test_utils::utils::get_empty_calldata_leaf(); - auto call_data_hash_inner = sha256::sha256(zero_bytes_vec); - - std::array hash_input; - for (uint8_t i = 0; i < 32; ++i) { - hash_input[i] = call_data_hash_inner[i]; - hash_input[32 + i] = call_data_hash_inner[i]; - } - - std::vector const calldata_hash_input_bytes_vec(hash_input.begin(), hash_input.end()); - - auto expected_calldata_hash = sha256::sha256(calldata_hash_input_bytes_vec); - - std::array const kernels = { - get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() - }; - MergeRollupInputs const inputs = get_merge_rollup_inputs(builder, kernels); - - BaseOrMergeRollupPublicInputs const outputs = merge_rollup_circuit(builder, inputs); - - std::array const output_calldata_hash = outputs.calldata_hash; - - ASSERT_TRUE(compare_field_hash_to_expected(output_calldata_hash, expected_calldata_hash)); - ASSERT_FALSE(builder.failed()); -} - -TEST_F(merge_rollup_tests, native_constants_dont_change) -{ - DummyBuilder builder = DummyBuilder("merge_rollup_tests__native_constants_dont_change"); - std::array const kernels = { - get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() - }; - MergeRollupInputs inputs = get_merge_rollup_inputs(builder, kernels); - - BaseOrMergeRollupPublicInputs const outputs = merge_rollup_circuit(builder, inputs); - ASSERT_EQ(inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.constants, outputs.constants); - ASSERT_EQ(inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.constants, outputs.constants); -} - -TEST_F(merge_rollup_tests, native_aggregate) -{ - // TODO: Fix this when aggregation works - DummyBuilder builder = DummyBuilder("merge_rollup_tests__native_aggregate"); - std::array const kernels = { - get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() - }; - MergeRollupInputs inputs = get_merge_rollup_inputs(builder, kernels); - - BaseOrMergeRollupPublicInputs const outputs = merge_rollup_circuit(builder, inputs); - ASSERT_EQ(inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.end_aggregation_object.public_inputs, - outputs.end_aggregation_object.public_inputs); - ASSERT_FALSE(builder.failed()); -} - -TEST_F(merge_rollup_tests, native_merge_cbind) -{ - DummyBuilder builder = DummyBuilder("merge_rollup_tests__native_merge_cbind"); - std::array const kernels = { - get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() - }; - MergeRollupInputs inputs = get_merge_rollup_inputs(builder, kernels); - - ASSERT_FALSE(builder.failed()); - BaseOrMergeRollupPublicInputs ignored_public_inputs; - - // TODO(1998): see above - // run_cbind(inputs, ignored_public_inputs, false); -} -} // namespace aztec3::circuits::rollup::merge::native_merge_rollup_circuit diff --git a/circuits/cpp/src/aztec3/circuits/rollup/merge/CMakeLists.txt b/circuits/cpp/src/aztec3/circuits/rollup/merge/CMakeLists.txt deleted file mode 100644 index ba98f5c140d..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/merge/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -circuits_cmake_module( - aztec3_circuits_rollup - barretenberg -) \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/merge/c_bind.cpp b/circuits/cpp/src/aztec3/circuits/rollup/merge/c_bind.cpp deleted file mode 100644 index cd52451cc6c..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/merge/c_bind.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "c_bind.h" - -#include "index.hpp" - -#include "aztec3/utils/dummy_circuit_builder.hpp" - -#include - -namespace { -using NT = aztec3::utils::types::NativeTypes; -using DummyCircuitBuilder = aztec3::utils::DummyCircuitBuilder; -using aztec3::circuits::abis::MergeRollupInputs; -using aztec3::circuits::rollup::merge::merge_rollup_circuit; -} // namespace - -// WASM Cbinds - -CBIND(merge_rollup__sim, [](MergeRollupInputs const& merge_rollup_inputs) { - DummyCircuitBuilder builder = DummyCircuitBuilder("merge_rollup__sim"); - auto const& public_inputs = merge_rollup_circuit(builder, merge_rollup_inputs); - return builder.result_or_error(public_inputs); -}); \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/merge/c_bind.h b/circuits/cpp/src/aztec3/circuits/rollup/merge/c_bind.h deleted file mode 100644 index 5063715b631..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/merge/c_bind.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include - -#include -#include - -CBIND_DECL(merge_rollup__sim); \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/merge/index.hpp b/circuits/cpp/src/aztec3/circuits/rollup/merge/index.hpp deleted file mode 100644 index 38c7f98999e..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/merge/index.hpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "init.hpp" -#include "native_merge_rollup_circuit.hpp" \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/merge/init.hpp b/circuits/cpp/src/aztec3/circuits/rollup/merge/init.hpp deleted file mode 100644 index 34ad4c1f94e..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/merge/init.hpp +++ /dev/null @@ -1,32 +0,0 @@ - -#pragma once - -#include "aztec3/circuits/abis/append_only_tree_snapshot.hpp" -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp" -#include "aztec3/circuits/abis/rollup/constant_rollup_data.hpp" -#include "aztec3/circuits/abis/rollup/merge/merge_rollup_inputs.hpp" -#include "aztec3/circuits/recursion/aggregator.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::rollup::merge { - -using NT = aztec3::utils::types::NativeTypes; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; - -// Params -using ConstantRollupData = abis::ConstantRollupData; -using MergeRollupInputs = abis::MergeRollupInputs; -using PreviousRollupData = abis::PreviousRollupData; -using BaseOrMergeRollupPublicInputs = abis::BaseOrMergeRollupPublicInputs; - -using Aggregator = aztec3::circuits::recursion::Aggregator; -using AggregationObject = utils::types::NativeTypes::AggregationObject; -using AppendOnlySnapshot = abis::AppendOnlyTreeSnapshot; - -} // namespace aztec3::circuits::rollup::merge \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/merge/native_merge_rollup_circuit.cpp b/circuits/cpp/src/aztec3/circuits/rollup/merge/native_merge_rollup_circuit.cpp deleted file mode 100644 index 82e6d56f49d..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/merge/native_merge_rollup_circuit.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "init.hpp" - -#include "aztec3/circuits/rollup/components/components.hpp" - -#include - -#include -#include -#include -#include -#include -#include - -namespace aztec3::circuits::rollup::merge { - -BaseOrMergeRollupPublicInputs merge_rollup_circuit(DummyBuilder& builder, MergeRollupInputs const& mergeRollupInputs) -{ - // TODO: Verify the previous rollup proofs - // TODO: Check both previous rollup vks (in previous_rollup_data) against the permitted set of kernel vks. - // we don't have a set of permitted kernel vks yet. - - auto left = mergeRollupInputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs; - auto right = mergeRollupInputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs; - - // check that both input proofs are either both "BASE" or "MERGE" and not a mix! - // this prevents having wonky commitment, nullifier and contract subtrees. - AggregationObject const aggregation_object = components::aggregate_proofs(left, right); - components::assert_both_input_proofs_of_same_rollup_type(builder, left, right); - auto current_height = components::assert_both_input_proofs_of_same_height_and_return(builder, left, right); - components::assert_equal_constants(builder, left, right); - components::assert_prev_rollups_follow_on_from_each_other(builder, left, right); - - // compute calldata hash: - auto new_calldata_hash = components::compute_calldata_hash(mergeRollupInputs.previous_rollup_data); - - BaseOrMergeRollupPublicInputs public_inputs = { - .rollup_type = abis::MERGE_ROLLUP_TYPE, - .rollup_subtree_height = current_height + 1, - .end_aggregation_object = aggregation_object, - .constants = left.constants, - .start_note_hash_tree_snapshot = left.start_note_hash_tree_snapshot, - .end_note_hash_tree_snapshot = right.end_note_hash_tree_snapshot, - .start_nullifier_tree_snapshot = left.start_nullifier_tree_snapshot, - .end_nullifier_tree_snapshot = right.end_nullifier_tree_snapshot, - .start_contract_tree_snapshot = left.start_contract_tree_snapshot, - .end_contract_tree_snapshot = right.end_contract_tree_snapshot, - .start_public_data_tree_root = left.start_public_data_tree_root, - .end_public_data_tree_root = right.end_public_data_tree_root, - .calldata_hash = new_calldata_hash, - }; - - return public_inputs; -} - -} // namespace aztec3::circuits::rollup::merge \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/merge/native_merge_rollup_circuit.hpp b/circuits/cpp/src/aztec3/circuits/rollup/merge/native_merge_rollup_circuit.hpp deleted file mode 100644 index 9d1e4b24772..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/merge/native_merge_rollup_circuit.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "init.hpp" - -namespace aztec3::circuits::rollup::merge { -BaseOrMergeRollupPublicInputs merge_rollup_circuit(DummyBuilder& builder, MergeRollupInputs const& mergeRollupInputs); -} // namespace aztec3::circuits::rollup::merge \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/root/.test.cpp b/circuits/cpp/src/aztec3/circuits/rollup/root/.test.cpp deleted file mode 100644 index 6be0e29b6c5..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/root/.test.cpp +++ /dev/null @@ -1,337 +0,0 @@ -#include "c_bind.h" -#include "index.hpp" -#include "init.hpp" - -#include "aztec3/circuits/abis/append_only_tree_snapshot.hpp" -#include "aztec3/circuits/abis/combined_accumulated_data.hpp" -#include "aztec3/circuits/abis/global_variables.hpp" -#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/new_contract_data.hpp" -#include "aztec3/circuits/abis/previous_kernel_data.hpp" -#include "aztec3/circuits/abis/rollup/merge/previous_rollup_data.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/circuits/kernel/private/utils.hpp" -#include "aztec3/circuits/rollup/base/init.hpp" -#include "aztec3/circuits/rollup/components/components.hpp" -#include "aztec3/circuits/rollup/test_utils/init.hpp" -#include "aztec3/circuits/rollup/test_utils/utils.hpp" -#include "aztec3/constants.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" - -#include - -#include - -#include -#include -#include -#include - -namespace { - - -using aztec3::circuits::abis::PreviousKernelData; - - -// using aztec3::circuits::mock::mock_circuit; -using aztec3::circuits::rollup::test_utils::utils::compare_field_hash_to_expected; -using aztec3::circuits::rollup::test_utils::utils::get_empty_kernel; -using aztec3::circuits::rollup::test_utils::utils::get_empty_l1_to_l2_messages; -using aztec3::circuits::rollup::test_utils::utils::get_initial_nullifier_tree_empty; -using aztec3::circuits::rollup::test_utils::utils::get_root_rollup_inputs; - -using aztec3::circuits::abis::AppendOnlyTreeSnapshot; - -using aztec3::circuits::rollup::native_base_rollup::BaseOrMergeRollupPublicInputs; -using aztec3::circuits::rollup::native_base_rollup::BaseRollupInputs; -using aztec3::circuits::rollup::native_base_rollup::ConstantRollupData; -using aztec3::circuits::rollup::native_base_rollup::NT; - -using aztec3::circuits::rollup::native_root_rollup::RootRollupInputs; -using aztec3::circuits::rollup::native_root_rollup::RootRollupPublicInputs; - -using aztec3::circuits::abis::NewContractData; - -using MemoryStore = stdlib::merkle_tree::MemoryStore; -using MerkleTree = stdlib::merkle_tree::MerkleTree; - -using KernelData = aztec3::circuits::abis::PreviousKernelData; -} // namespace - -namespace aztec3::circuits::rollup::root::native_root_rollup_circuit { - -class root_rollup_tests : public ::testing::Test { - protected: - static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../barretenberg/cpp/srs_db/ignition"); } - - // TODO(1998): uncomment once https://github.com/AztecProtocol/aztec-packages/issues/1998 is solved and - // use new pattern such as call_func_and_wrapper from test_helper.hpp - - // static void run_cbind(RootRollupInputs& root_rollup_inputs, - // RootRollupPublicInputs& expected_public_inputs, - // bool compare_pubins = true) - // { - // info("Retesting via cbinds...."); - // // info("Verification key size: ", vk_size); - - // std::vector root_rollup_inputs_vec; - // serialize::write(root_rollup_inputs_vec, root_rollup_inputs); - - // // uint8_t const* proof_data; - // // size_t proof_data_size; - // uint8_t const* public_inputs_buf = nullptr; - // size_t public_inputs_size = 0; - // // info("simulating circuit via cbind"); - // uint8_t* const circuit_failure_ptr = - // root_rollup__sim(root_rollup_inputs_vec.data(), &public_inputs_size, &public_inputs_buf); - // ASSERT_TRUE(circuit_failure_ptr == nullptr); - // // info("Proof size: ", proof_data_size); - // // info("PublicInputs size: ", public_inputs_size); - - // if (compare_pubins) { - // RootRollupPublicInputs public_inputs; - // uint8_t const* public_inputs_buf_tmp = public_inputs_buf; - // serialize::read(public_inputs_buf_tmp, public_inputs); - // ASSERT_EQ(public_inputs.calldata_hash.size(), expected_public_inputs.calldata_hash.size()); - // for (size_t i = 0; i < public_inputs.calldata_hash.size(); i++) { - // ASSERT_EQ(public_inputs.calldata_hash[i], expected_public_inputs.calldata_hash[i]); - // } - - // std::vector expected_public_inputs_vec; - // serialize::write(expected_public_inputs_vec, expected_public_inputs); - - // ASSERT_EQ(public_inputs_size, expected_public_inputs_vec.size()); - // // Just compare the first 10 bytes of the serialized public outputs - // if (public_inputs_size > 10) { - // // for (size_t 0; i < public_inputs_size; i++) { - // for (size_t i = 0; i < 10; i++) { - // ASSERT_EQ(public_inputs_buf[i], expected_public_inputs_vec[i]); - // } - // } - // } - - // // free((void*)proof_data); - // free((void*)public_inputs_buf); - // } -}; - -TEST_F(root_rollup_tests, native_check_block_hashes_empty_blocks) -{ - std::vector const zero_bytes_vec = test_utils::utils::get_empty_calldata_leaf(); - auto call_data_hash_inner = sha256::sha256(zero_bytes_vec); - - // Compute a new calldata hash based on TWO of the above rollups - std::array hash_input; - for (uint8_t i = 0; i < 32; ++i) { - hash_input[i] = call_data_hash_inner[i]; - hash_input[32 + i] = call_data_hash_inner[i]; - } - std::vector const calldata_hash_input_bytes_vec(hash_input.begin(), hash_input.end()); - auto calldata_hash = sha256::sha256(calldata_hash_input_bytes_vec); - - // get messages - std::array const l1_to_l2_messages = get_empty_l1_to_l2_messages(); - - // hash messages - std::vector const messages_hash_input_bytes_vec(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP * 32, 0); - auto messages_hash = sha256::sha256(messages_hash_input_bytes_vec); - - utils::DummyCircuitBuilder builder = - utils::DummyCircuitBuilder("root_rollup_tests__native_check_block_hashes_empty_blocks"); - std::array const kernels = { - get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() - }; - - RootRollupInputs inputs = get_root_rollup_inputs(builder, kernels, l1_to_l2_messages); - RootRollupPublicInputs outputs = aztec3::circuits::rollup::native_root_rollup::root_rollup_circuit(builder, inputs); - - // check calldata hash - ASSERT_TRUE(compare_field_hash_to_expected(outputs.calldata_hash, calldata_hash)); - // Check messages hash - ASSERT_TRUE(compare_field_hash_to_expected(outputs.l1_to_l2_messages_hash, messages_hash)); - - EXPECT_FALSE(builder.failed()); - - // TODO(1998): see above - // run_cbind(inputs, outputs, true); -} - -TEST_F(root_rollup_tests, native_root_missing_nullifier_logic) -{ - utils::DummyCircuitBuilder builder = - utils::DummyCircuitBuilder("root_rollup_tests__native_root_missing_nullifier_logic"); - - MemoryStore note_hash_tree_store; - MerkleTree note_hash_tree(note_hash_tree_store, NOTE_HASH_TREE_HEIGHT); - - MemoryStore contract_tree_store; - MerkleTree contract_tree(contract_tree_store, CONTRACT_TREE_HEIGHT); - - MemoryStore l1_to_l2_message_tree_store; - MerkleTree l1_to_l2_message_tree(l1_to_l2_message_tree_store, L1_TO_L2_MSG_TREE_HEIGHT); - - MemoryStore public_store; - MerkleTree public_data_tree(public_store, PUBLIC_DATA_TREE_HEIGHT); - - // Create initial nullifier tree with 32 initial nullifiers - auto nullifier_tree = get_initial_nullifier_tree_empty(); - - MemoryStore archive_store; - MerkleTree archive(archive_store, ARCHIVE_HEIGHT); - - std::array kernels = { - get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() - }; - std::array l1_to_l2_messages = get_empty_l1_to_l2_messages(); - - // Calculate the start block hash - abis::GlobalVariables globals = abis::GlobalVariables::empty(); - auto start_block_hash = compute_block_hash_with_globals(globals, - note_hash_tree.root(), - nullifier_tree.root(), - contract_tree.root(), - l1_to_l2_message_tree.root(), - public_data_tree.root()); - archive.update_element(0, start_block_hash); - AppendOnlyTreeSnapshot start_archive_snapshot = { .root = archive.root(), .next_available_leaf_index = 1 }; - - // Create commitments - for (size_t kernel_j = 0; kernel_j < 4; kernel_j++) { - std::array new_commitments; - for (uint8_t commitment_k = 0; commitment_k < MAX_NEW_COMMITMENTS_PER_TX; commitment_k++) { - auto val = fr(kernel_j * MAX_NEW_COMMITMENTS_PER_TX + commitment_k + 1); - new_commitments[commitment_k] = val; - note_hash_tree.update_element(kernel_j * MAX_NEW_COMMITMENTS_PER_TX + commitment_k, val); - } - kernels[kernel_j].public_inputs.end.new_commitments = new_commitments; - - std::array new_l2_to_l1_messages; - for (uint8_t i = 0; i < MAX_NEW_L2_TO_L1_MSGS_PER_TX; i++) { - auto val = fr(kernel_j * MAX_NEW_L2_TO_L1_MSGS_PER_TX + i + 1); - new_l2_to_l1_messages[i] = val; - } - kernels[kernel_j].public_inputs.end.new_l2_to_l1_msgs = new_l2_to_l1_messages; - } - - // @todo @LHerskind: Add nullifiers - // @todo @LHerskind: Add public data writes - - // Contract tree - NewContractData const new_contract = { - .contract_address = fr(1), - .portal_contract_address = fr(3), - .function_tree_root = fr(2), - }; - // Update contract tree - contract_tree.update_element(2, new_contract.hash()); - kernels[2].public_inputs.end.new_contracts[0] = new_contract; - - // l1 to l2 messages snapshot - AppendOnlyTreeSnapshot const start_l1_to_l2_message_tree_snapshot = { .root = l1_to_l2_message_tree.root(), - .next_available_leaf_index = 0 }; - - // Create 16 empty l1 to l2 messages, and update the l1_to_l2 message tree - for (size_t i = 0; i < l1_to_l2_messages.size(); i++) { - l1_to_l2_message_tree.update_element(i, l1_to_l2_messages[i]); - } - - // Get the block hash after. - auto end_block_hash = compute_block_hash_with_globals(globals, - note_hash_tree.root(), - nullifier_tree.root(), - contract_tree.root(), - l1_to_l2_message_tree.root(), - public_data_tree.root()); - archive.update_element(1, end_block_hash); - AppendOnlyTreeSnapshot end_archive_snapshot = { .root = archive.root(), .next_available_leaf_index = 2 }; - - // Compute the end snapshot - AppendOnlyTreeSnapshot const end_l1_to_l2_message_tree_snapshot = { .root = l1_to_l2_message_tree.root(), - .next_available_leaf_index = - NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP }; - - RootRollupInputs rootRollupInputs = get_root_rollup_inputs(builder, kernels, l1_to_l2_messages); - RootRollupPublicInputs outputs = - aztec3::circuits::rollup::native_root_rollup::root_rollup_circuit(builder, rootRollupInputs); - - // Check note hash trees - ASSERT_EQ( - outputs.start_note_hash_tree_snapshot, - rootRollupInputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_note_hash_tree_snapshot); - ASSERT_EQ(outputs.end_note_hash_tree_snapshot, - rootRollupInputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.end_note_hash_tree_snapshot); - AppendOnlyTreeSnapshot const expected_note_hash_tree_snapshot = { .root = note_hash_tree.root(), - .next_available_leaf_index = - 4 * MAX_NEW_COMMITMENTS_PER_TX }; - ASSERT_EQ(outputs.end_note_hash_tree_snapshot, expected_note_hash_tree_snapshot); - - // Check public data trees - ASSERT_EQ(outputs.start_public_data_tree_root, - rootRollupInputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_public_data_tree_root); - ASSERT_EQ(outputs.end_public_data_tree_root, - rootRollupInputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.end_public_data_tree_root); - - // check contract trees - ASSERT_EQ(outputs.start_contract_tree_snapshot, - rootRollupInputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_contract_tree_snapshot); - ASSERT_EQ(outputs.end_contract_tree_snapshot, - rootRollupInputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.end_contract_tree_snapshot); - AppendOnlyTreeSnapshot const expected_contract_tree_snapshot{ .root = contract_tree.root(), - .next_available_leaf_index = 4 }; - ASSERT_EQ(outputs.end_contract_tree_snapshot, expected_contract_tree_snapshot); - - // @todo @LHerskind: Check nullifier trees - - // Check l1 to l2 message trees - ASSERT_EQ(outputs.start_l1_to_l2_message_tree_snapshot, start_l1_to_l2_message_tree_snapshot); - ASSERT_EQ(outputs.start_contract_tree_snapshot, - rootRollupInputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_contract_tree_snapshot); - ASSERT_EQ(outputs.end_contract_tree_snapshot, - rootRollupInputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.end_contract_tree_snapshot); - ASSERT_EQ(outputs.end_l1_to_l2_message_tree_snapshot, end_l1_to_l2_message_tree_snapshot); - - ASSERT_EQ(outputs.start_archive_snapshot, start_archive_snapshot); - ASSERT_EQ(outputs.end_archive_snapshot, end_archive_snapshot); - - // Compute the expected calldata hash for the root rollup (including the l2 -> l1 messages) - auto left = components::compute_kernels_calldata_hash({ kernels[0], kernels[1] }); - auto right = components::compute_kernels_calldata_hash({ kernels[2], kernels[3] }); - auto root = accumulate_sha256({ left[0], left[1], right[0], right[1] }); - ASSERT_EQ(outputs.calldata_hash, root); - - EXPECT_FALSE(builder.failed()); - - // TODO(1998): see above - // run_cbind(rootRollupInputs, outputs, true); -} - -TEST_F(root_rollup_tests, noir_interop_test) -{ - // This is an annoying hack to convert the field into a hex string - // We should add a to_hex and from_hex method to field class - auto to_hex = [](const NT::fr& value) -> std::string { - std::stringstream field_as_hex_stream; - field_as_hex_stream << value; - return field_as_hex_stream.str(); - }; - - MemoryStore merkle_tree_store; - MerkleTree merkle_tree(merkle_tree_store, L1_TO_L2_MSG_SUBTREE_HEIGHT); - - std::array leaves = { 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4 }; - for (size_t i = 0; i < NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP; i++) { - merkle_tree.update_element(i, leaves[i]); - } - auto root = merkle_tree.root(); - auto expected = "0x17e8bb70a11d0c946345950879484d2f4f9fef397ff6adbfdec3baab2d41faab"; - ASSERT_EQ(to_hex(root), expected); - - // Empty subtree is the same as zeroes - MemoryStore empty_tree_store; - MerkleTree const empty_tree = MerkleTree(empty_tree_store, L1_TO_L2_MSG_SUBTREE_HEIGHT); - auto empty_root = empty_tree.root(); - auto expected_empty_root = "0x06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d"; - ASSERT_EQ(to_hex(empty_root), expected_empty_root); -} - -} // namespace aztec3::circuits::rollup::root::native_root_rollup_circuit \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/root/CMakeLists.txt b/circuits/cpp/src/aztec3/circuits/rollup/root/CMakeLists.txt deleted file mode 100644 index d2994796d2c..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/root/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -circuits_cmake_module( - aztec3_circuits_rollup - aztec3_circuits_kernel - barretenberg -) \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/root/c_bind.cpp b/circuits/cpp/src/aztec3/circuits/rollup/root/c_bind.cpp deleted file mode 100644 index 197560a64fb..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/root/c_bind.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "c_bind.h" - -#include "index.hpp" -#include "init.hpp" - -#include "aztec3/constants.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace { -using Builder = UltraCircuitBuilder; -using NT = aztec3::utils::types::NativeTypes; -using DummyCircuitBuilder = aztec3::utils::DummyCircuitBuilder; -using aztec3::circuits::rollup::native_root_rollup::root_rollup_circuit; -using aztec3::circuits::rollup::native_root_rollup::RootRollupInputs; -using aztec3::circuits::rollup::native_root_rollup::RootRollupPublicInputs; - -} // namespace - -// WASM Cbinds -CBIND(root_rollup__sim, [](RootRollupInputs const& root_rollup_inputs) { - DummyCircuitBuilder builder = DummyCircuitBuilder("root_rollup__sim"); - auto const& public_inputs = root_rollup_circuit(builder, root_rollup_inputs); - return builder.result_or_error(public_inputs); -}); \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/root/c_bind.h b/circuits/cpp/src/aztec3/circuits/rollup/root/c_bind.h deleted file mode 100644 index 5105580e922..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/root/c_bind.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include - -#include -#include - -CBIND_DECL(root_rollup__sim); \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/root/index.hpp b/circuits/cpp/src/aztec3/circuits/rollup/root/index.hpp deleted file mode 100644 index 091987013ee..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/root/index.hpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "init.hpp" -#include "native_root_rollup_circuit.hpp" \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/root/init.hpp b/circuits/cpp/src/aztec3/circuits/rollup/root/init.hpp deleted file mode 100644 index f24e7c719f3..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/root/init.hpp +++ /dev/null @@ -1,31 +0,0 @@ - -#pragma once - -#include "aztec3/circuits/abis/append_only_tree_snapshot.hpp" -#include "aztec3/circuits/abis/rollup/constant_rollup_data.hpp" -#include "aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp" -#include "aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp" -#include "aztec3/circuits/recursion/aggregator.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -namespace aztec3::circuits::rollup::native_root_rollup { - -using NT = aztec3::utils::types::NativeTypes; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; - -// Params -using ConstantRollupData = abis::ConstantRollupData; -using RootRollupInputs = abis::RootRollupInputs; -using RootRollupPublicInputs = abis::RootRollupPublicInputs; - -using Aggregator = aztec3::circuits::recursion::Aggregator; - -using MemoryStore = stdlib::merkle_tree::MemoryStore; -using MerkleTree = stdlib::merkle_tree::MerkleTree; - -} // namespace aztec3::circuits::rollup::native_root_rollup diff --git a/circuits/cpp/src/aztec3/circuits/rollup/root/native_root_rollup_circuit.cpp b/circuits/cpp/src/aztec3/circuits/rollup/root/native_root_rollup_circuit.cpp deleted file mode 100644 index da9a256b812..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/root/native_root_rollup_circuit.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include "init.hpp" - -#include "aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp" -#include "aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/circuits/rollup/components/components.hpp" -#include "aztec3/constants.hpp" - -#include -#include -#include -#include -#include -#include - -namespace aztec3::circuits::rollup::native_root_rollup { - -// Used when calling library functions like `check_membership` which have their own generic error code. -// So we pad this in front of the error message to identify where the error originally came from. -const std::string ROOT_CIRCUIT_ERROR_MESSAGE_BEGINNING = "root_rollup_circuit: "; - -// TODO: can we aggregate proofs if we do not have a working circuit impl -// TODO: change the public inputs array - we wont be using this? - -// Access Native types through NT namespace - -/** - * @brief Calculates the messages subtree from the leaves array - * @param leaves - * @return root - */ -NT::fr calculate_subtree(std::array leaves) -{ - MemoryStore merkle_tree_store; - MerkleTree merkle_tree(merkle_tree_store, L1_TO_L2_MSG_SUBTREE_HEIGHT); - - for (size_t i = 0; i < NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP; i++) { - merkle_tree.update_element(i, leaves[i]); - } - return merkle_tree.root(); -} - -/** - * @brief Computes the messages hash from the leaves array - * @param leaves - * @param return - hash split into two field elements - */ -std::array compute_messages_hash( - std::array leaves) -{ - // convert vector of field elements into uint_8 - std::array messages_hash_input_bytes; - for (size_t i = 0; i < NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP; i++) { - auto bytes = leaves[i].to_buffer(); - for (size_t j = 0; j < 32; j++) { - messages_hash_input_bytes[i * 32 + j] = bytes[j]; - } - } - - std::vector const messages_hash_input_bytes_vec(messages_hash_input_bytes.begin(), - messages_hash_input_bytes.end()); - auto h = sha256::sha256(messages_hash_input_bytes_vec); - - std::array buf_1; - std::array buf_2; - for (uint8_t i = 0; i < 16; i++) { - buf_1[i] = 0; - buf_1[16 + i] = h[i]; - buf_2[i] = 0; - buf_2[16 + i] = h[i + 16]; - } - auto high = fr::serialize_from_buffer(buf_1.data()); - auto low = fr::serialize_from_buffer(buf_2.data()); - - return { high, low }; -} - -RootRollupPublicInputs root_rollup_circuit(DummyBuilder& builder, RootRollupInputs const& rootRollupInputs) -{ - // TODO: Verify the previous rollup proofs - // TODO: Check both previous rollup vks (in previous_rollup_data) against the permitted set of kernel vks. - // we don't have a set of permitted kernel vks yet. - - auto left = rootRollupInputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs; - auto right = rootRollupInputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs; - - auto aggregation_object = components::aggregate_proofs(left, right); - components::assert_both_input_proofs_of_same_rollup_type(builder, left, right); - components::assert_both_input_proofs_of_same_height_and_return(builder, left, right); - components::assert_equal_constants(builder, left, right); - components::assert_prev_rollups_follow_on_from_each_other(builder, left, right); - - // Check correct l1 to l2 tree given - // Compute subtree inserting l1 to l2 messages - auto l1_to_l2_subtree_root = calculate_subtree(rootRollupInputs.new_l1_to_l2_messages); - - // Insert subtree into the l1 to l2 data tree - const auto empty_l1_to_l2_subtree_root = components::calculate_empty_tree_root(L1_TO_L2_MSG_SUBTREE_HEIGHT); - auto new_l1_to_l2_message_tree_snapshot = components::insert_subtree_to_snapshot_tree( - builder, - rootRollupInputs.start_l1_to_l2_message_tree_snapshot, - rootRollupInputs.new_l1_to_l2_message_tree_root_sibling_path, - empty_l1_to_l2_subtree_root, - l1_to_l2_subtree_root, - L1_TO_L2_MSG_SUBTREE_HEIGHT, - format(ROOT_CIRCUIT_ERROR_MESSAGE_BEGINNING, - "l1 to l2 message tree not empty at location where subtree would be inserted")); - - // Build the block hash for this iteration from the tree roots and global variables - // Then insert the block into the blocks tree - auto block_hash = compute_block_hash_with_globals(left.constants.global_variables, - right.end_note_hash_tree_snapshot.root, - right.end_nullifier_tree_snapshot.root, - right.end_contract_tree_snapshot.root, - new_l1_to_l2_message_tree_snapshot.root, - right.end_public_data_tree_root); - - // Update the blocks tree - auto end_archive_snapshot = components::insert_subtree_to_snapshot_tree( - builder, - rootRollupInputs.start_archive_snapshot, - rootRollupInputs.new_archive_sibling_path, - fr::zero(), - block_hash, - 0, - format(ROOT_CIRCUIT_ERROR_MESSAGE_BEGINNING, - "blocks tree roots not empty at location where subtree would be inserted")); - - - RootRollupPublicInputs public_inputs = { - .end_aggregation_object = aggregation_object, - .global_variables = left.constants.global_variables, - .start_note_hash_tree_snapshot = left.start_note_hash_tree_snapshot, - .end_note_hash_tree_snapshot = right.end_note_hash_tree_snapshot, - .start_nullifier_tree_snapshot = left.start_nullifier_tree_snapshot, - .end_nullifier_tree_snapshot = right.end_nullifier_tree_snapshot, - .start_contract_tree_snapshot = left.start_contract_tree_snapshot, - .end_contract_tree_snapshot = right.end_contract_tree_snapshot, - .start_public_data_tree_root = left.start_public_data_tree_root, - .end_public_data_tree_root = right.end_public_data_tree_root, - .start_l1_to_l2_message_tree_snapshot = rootRollupInputs.start_l1_to_l2_message_tree_snapshot, - .end_l1_to_l2_message_tree_snapshot = new_l1_to_l2_message_tree_snapshot, - .start_archive_snapshot = rootRollupInputs.start_archive_snapshot, - .end_archive_snapshot = end_archive_snapshot, - .calldata_hash = components::compute_calldata_hash(rootRollupInputs.previous_rollup_data), - .l1_to_l2_messages_hash = compute_messages_hash(rootRollupInputs.new_l1_to_l2_messages) - }; - - return public_inputs; -} - -} // namespace aztec3::circuits::rollup::native_root_rollup diff --git a/circuits/cpp/src/aztec3/circuits/rollup/root/native_root_rollup_circuit.hpp b/circuits/cpp/src/aztec3/circuits/rollup/root/native_root_rollup_circuit.hpp deleted file mode 100644 index d611a114dfd..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/root/native_root_rollup_circuit.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "init.hpp" - -// TODO: not needed right at this moment for native impl -#include "aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp" -#include "aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -namespace aztec3::circuits::rollup::native_root_rollup { - -RootRollupPublicInputs root_rollup_circuit(DummyBuilder& builder, RootRollupInputs const& rootRollupInputs); - -} // namespace aztec3::circuits::rollup::native_root_rollup \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/init.hpp b/circuits/cpp/src/aztec3/circuits/rollup/test_utils/init.hpp deleted file mode 100644 index 4d95d8b7c5d..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/init.hpp +++ /dev/null @@ -1,46 +0,0 @@ - -#pragma once - -#include "aztec3/circuits/abis/append_only_tree_snapshot.hpp" -#include "aztec3/circuits/abis/private_circuit_public_inputs.hpp" -#include "aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp" -#include "aztec3/circuits/abis/rollup/base/base_rollup_inputs.hpp" -#include "aztec3/circuits/abis/rollup/constant_rollup_data.hpp" -#include "aztec3/circuits/abis/rollup/merge/merge_rollup_inputs.hpp" -#include "aztec3/circuits/abis/rollup/merge/previous_rollup_data.hpp" -#include "aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp" -#include "aztec3/circuits/recursion/aggregator.hpp" -#include "aztec3/circuits/rollup/base/native_base_rollup_circuit.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" -#include "aztec3/utils/types/circuit_types.hpp" -#include "aztec3/utils/types/convert.hpp" -#include "aztec3/utils/types/native_types.hpp" - -// TODO(dbanks12) should we force files to explicitly include barretenberg when using it? -#include - -namespace aztec3::circuits::rollup::test_utils { - -using NT = aztec3::utils::types::NativeTypes; - -// Types -using ConstantRollupData = abis::ConstantRollupData; -using BaseRollupInputs = abis::BaseRollupInputs; -using BaseOrMergeRollupPublicInputs = abis::BaseOrMergeRollupPublicInputs; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; - -using Aggregator = aztec3::circuits::recursion::Aggregator; -using AggregationObject = aztec3::utils::types::NativeTypes::AggregationObject; -using AppendOnlySnapshot = abis::AppendOnlyTreeSnapshot; - -using NullifierLeafPreimage = aztec3::circuits::abis::NullifierLeafPreimage; - -// Tree Aliases -using MemoryStore = stdlib::merkle_tree::MemoryStore; -using MerkleTree = stdlib::merkle_tree::MerkleTree; -using NullifierTree = stdlib::merkle_tree::NullifierMemoryTree; -using NullifierLeaf = stdlib::merkle_tree::nullifier_leaf; - -using aztec3::circuits::abis::MembershipWitness; - -} // namespace aztec3::circuits::rollup::test_utils \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/nullifier_tree_testing_harness.cpp b/circuits/cpp/src/aztec3/circuits/rollup/test_utils/nullifier_tree_testing_harness.cpp deleted file mode 100644 index 8ddc564c86c..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/nullifier_tree_testing_harness.cpp +++ /dev/null @@ -1,155 +0,0 @@ -#include "nullifier_tree_testing_harness.hpp" - -#include - -#include -#include - -using NullifierMemoryTree = proof_system::plonk::stdlib::merkle_tree::NullifierMemoryTree; -using nullifier_leaf = proof_system::plonk::stdlib::merkle_tree::nullifier_leaf; - -NullifierMemoryTreeTestingHarness::NullifierMemoryTreeTestingHarness(size_t depth) : NullifierMemoryTree(depth) {} - -// Check for a larger value in an array -bool check_has_less_than(std::vector const& values, fr const& value) -{ - // Must perform comparisons on integers - auto const value_as_uint = uint256_t(value); - for (auto const& v : values) { - // info(v, " ", uint256_t(v) < value_as_uint); - if (uint256_t(v) < value_as_uint) { - return true; - } - } - return false; -} - -// handle synthetic membership assertions -std::tuple, std::vector>, std::vector> -NullifierMemoryTreeTestingHarness::circuit_prep_batch_insert(std::vector const& values) -{ - // Start insertion index - fr const start_insertion_index = this->size(); - - // Low nullifiers - std::vector low_nullifiers; - std::vector pending_insertion_tree; - - // Low nullifier sibling paths - std::vector> sibling_paths; - - // Low nullifier indexes - std::vector low_nullifier_indexes; - - // Keep track of the currently touched nodes while updating - std::map> touched_nodes; - - // Keep track of 0 values - std::vector const empty_sp(depth_, 0); - nullifier_leaf const empty_leaf = { 0, 0, 0 }; - uint32_t const empty_index = 0; - - // Find the leaf with the value closest and less than `value` for each value - for (size_t i = 0; i < values.size(); ++i) { - auto new_value = values[i]; - auto insertion_index = start_insertion_index + i; - - size_t current = 0; - bool is_already_present = false; - std::tie(current, is_already_present) = find_closest_leaf(leaves_, new_value); - - // If the inserted value is 0, then we ignore and provide a dummy low nullifier - if (new_value == 0) { - sibling_paths.push_back(empty_sp); - low_nullifier_indexes.push_back(empty_index); - low_nullifiers.push_back(empty_leaf); - continue; - } - - // If the low_nullifier node has been touched this sub tree insertion, we provide a dummy sibling path - // It will be up to the circuit to check if the included node is valid vs the other nodes that have been - // inserted before it If it has not been touched, we provide a sibling path then update the nodes pointers - auto prev_nodes = touched_nodes.find(current); - - bool has_less_than = false; - if (prev_nodes != touched_nodes.end()) { - has_less_than = check_has_less_than(prev_nodes->second, new_value); - } - // If there is a lower value in the tree, we need to check the current low nullifiers for one that can be used - if (has_less_than) { - for (size_t j = 0; j < pending_insertion_tree.size(); ++j) { - // Skip checking empty values - if (pending_insertion_tree[j].value == 0) { - continue; - } - - if (pending_insertion_tree[j].value < new_value && - (pending_insertion_tree[j].nextValue > new_value || pending_insertion_tree[j].nextValue == 0)) { - // Add a new pending low nullifier for this value - nullifier_leaf const new_leaf = { .value = new_value, - .nextIndex = pending_insertion_tree[j].nextIndex, - .nextValue = pending_insertion_tree[j].nextValue }; - pending_insertion_tree.push_back(new_leaf); - - // Update the pending low nullifier to point at the new value - pending_insertion_tree[j].nextIndex = insertion_index; - pending_insertion_tree[j].nextValue = new_value; - - break; - } - } - - // add empty low nullifier - sibling_paths.push_back(empty_sp); - low_nullifier_indexes.push_back(empty_index); - low_nullifiers.push_back(empty_leaf); - } else { - // Update the touched mapping - if (prev_nodes == touched_nodes.end()) { - std::vector const new_touched_values = { new_value }; - touched_nodes[current] = new_touched_values; - } else { - prev_nodes->second.push_back(new_value); - } - - nullifier_leaf const low_nullifier = leaves_[current].unwrap(); - std::vector const sibling_path = this->get_sibling_path(current); - - sibling_paths.push_back(sibling_path); - low_nullifier_indexes.push_back(static_cast(current)); - low_nullifiers.push_back(low_nullifier); - - // Update the current low nullifier - nullifier_leaf const new_leaf = { .value = low_nullifier.value, - .nextIndex = insertion_index, - .nextValue = new_value }; - - // Update the old leaf in the tree - // update old value in tree - update_element_in_place(current, new_leaf); - } - } - - // Return tuple of low nullifiers and sibling paths - return std::make_tuple(low_nullifiers, sibling_paths, low_nullifier_indexes); -} - -void NullifierMemoryTreeTestingHarness::update_element_in_place(size_t index, const nullifier_leaf& leaf) -{ - // Find the leaf with the value closest and less than `value` - this->leaves_[index].set(leaf); - update_element(index, leaf.hash()); -} - -std::pair NullifierMemoryTreeTestingHarness::find_lower(fr const& value) -{ - size_t current = 0; - bool is_already_present = false; - std::tie(current, is_already_present) = find_closest_leaf(leaves_, value); - - // TODO: handle is already present case - if (!is_already_present) { - return std::make_pair(leaves_[current].unwrap(), current); - } - return std::make_pair(leaves_[current].unwrap(), current); -} \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/nullifier_tree_testing_harness.hpp b/circuits/cpp/src/aztec3/circuits/rollup/test_utils/nullifier_tree_testing_harness.hpp deleted file mode 100644 index fc8384a3622..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/nullifier_tree_testing_harness.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once -#include "aztec3/circuits/abis/append_only_tree_snapshot.hpp" -#include "aztec3/utils/types/native_types.hpp" - -#include - -#include - -namespace { -using aztec3::utils::types::NativeTypes; -} // namespace -/** - * A version of the nullifier memory tree with extra methods specific to testing our rollup circuits. - */ -class NullifierMemoryTreeTestingHarness : public proof_system::plonk::stdlib::merkle_tree::NullifierMemoryTree { - using nullifier_leaf = proof_system::plonk::stdlib::merkle_tree::nullifier_leaf; - - public: - explicit NullifierMemoryTreeTestingHarness(size_t depth); - - using MemoryTree::get_hash_path; - using MemoryTree::root; - using MemoryTree::update_element; - - using NullifierMemoryTree::update_element; - - using NullifierMemoryTree::get_hashes; - using NullifierMemoryTree::get_leaf; - using NullifierMemoryTree::get_leaves; - - // Get the value immediately lower than the given value - std::pair find_lower(fr const& value); - - // Utilities to inspect tree - fr total_size() const { return total_size_; } - fr depth() const { return depth_; } - - // Current size of the tree - fr size() { return leaves_.size(); } - - aztec3::circuits::abis::AppendOnlyTreeSnapshot get_snapshot() - { - return { .root = root(), .next_available_leaf_index = static_cast(leaves_.size()) }; - } - - void update_element_in_place(size_t index, const nullifier_leaf& leaf); - - // Get all of the sibling paths and low nullifier values required to craft an non membership / inclusion proofs - std::tuple, std::vector>, std::vector> - circuit_prep_batch_insert(std::vector const& values); - - protected: - using MemoryTree::depth_; - using MemoryTree::hashes_; - using MemoryTree::root_; - using MemoryTree::total_size_; - using NullifierMemoryTree::leaves_; -}; \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.cpp b/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.cpp deleted file mode 100644 index 7fa9db9203a..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.cpp +++ /dev/null @@ -1,599 +0,0 @@ -#include "utils.hpp" - -#include "nullifier_tree_testing_harness.hpp" - -#include "aztec3/circuits/abis/global_variables.hpp" -#include "aztec3/circuits/abis/membership_witness.hpp" -#include "aztec3/circuits/abis/new_contract_data.hpp" -#include "aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/circuits/kernel/private/utils.hpp" -#include "aztec3/circuits/rollup/base/init.hpp" -#include "aztec3/constants.hpp" - -#include - -#include -#include -#include -#include -namespace { -using NT = aztec3::utils::types::NativeTypes; - -using ConstantRollupData = aztec3::circuits::abis::ConstantRollupData; -using BaseRollupInputs = aztec3::circuits::abis::BaseRollupInputs; -using RootRollupInputs = aztec3::circuits::abis::RootRollupInputs; -using RootRollupPublicInputs = aztec3::circuits::abis::RootRollupPublicInputs; -using DummyCircuitBuilder = aztec3::utils::DummyCircuitBuilder; - -using Aggregator = aztec3::circuits::recursion::Aggregator; -using AppendOnlyTreeSnapshot = aztec3::circuits::abis::AppendOnlyTreeSnapshot; -using KernelData = aztec3::circuits::abis::PreviousKernelData; - -using NullifierLeafPreimage = aztec3::circuits::abis::NullifierLeafPreimage; - -using MemoryStore = stdlib::merkle_tree::MemoryStore; -using MerkleTree = stdlib::merkle_tree::MerkleTree; -using NullifierTree = stdlib::merkle_tree::NullifierMemoryTree; -using NullifierLeaf = stdlib::merkle_tree::nullifier_leaf; - -using aztec3::circuits::abis::MembershipWitness; -using MergeRollupInputs = aztec3::circuits::abis::MergeRollupInputs; -using aztec3::circuits::abis::PreviousRollupData; - -using nullifier_tree_testing_values = std::tuple; - -using aztec3::circuits::kernel::private_kernel::utils::dummy_previous_kernel; -} // namespace - -namespace aztec3::circuits::rollup::test_utils::utils { - -// Want some helper functions for generating kernels with some commitments, nullifiers and contracts - -std::vector get_empty_calldata_leaf() -{ - auto const number_of_inputs = - (MAX_NEW_COMMITMENTS_PER_TX + MAX_NEW_NULLIFIERS_PER_TX + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 + - MAX_NEW_L2_TO_L1_MSGS_PER_TX + MAX_NEW_CONTRACTS_PER_TX * 3 + NUM_ENCRYPTED_LOGS_HASHES_PER_TX * 2 + - NUM_UNENCRYPTED_LOGS_HASHES_PER_TX * 2) * - 2; - - // We subtract 4 from inputs size because 1 logs hash is stored in 2 fields and those 2 fields get converted only - // to 256 bits and there are 4 logs hashes in total. - auto const size = (number_of_inputs - 4) * 32; - std::vector input_data(size, 0); - return input_data; -} - -KernelData get_empty_kernel() -{ - return dummy_previous_kernel(); -} - -std::array get_empty_l1_to_l2_messages() -{ - std::array l1_to_l2_messages = { 0 }; - return l1_to_l2_messages; -} - -BaseRollupInputs base_rollup_inputs_from_kernels(std::array kernel_data, - fr prev_global_variables_hash, - MerkleTree& note_hash_tree, - MerkleTree& nullifier_tree, - MerkleTree& contract_tree, - MerkleTree& public_data_tree, - MerkleTree& l1_to_l2_msg_tree) -{ - // @todo Look at the starting points for all of these. - // By supporting as inputs we can make very generic tests, where it is trivial to try new setups. - MemoryStore archive_store; - MerkleTree archive = MerkleTree(archive_store, ARCHIVE_HEIGHT); - - - BaseRollupInputs baseRollupInputs = { .kernel_data = kernel_data, - .start_note_hash_tree_snapshot = { - .root = note_hash_tree.root(), - .next_available_leaf_index = 0, - }, - .start_contract_tree_snapshot = { - .root = contract_tree.root(), - .next_available_leaf_index = 0, - } - }; - - - std::vector initial_values(2 * MAX_NEW_NULLIFIERS_PER_TX - 1); - - for (size_t i = 0; i < initial_values.size(); i++) { - initial_values[i] = i + 1; - } - - std::array nullifiers; - for (size_t i = 0; i < 2; i++) { - for (size_t j = 0; j < MAX_NEW_NULLIFIERS_PER_TX; j++) { - nullifiers[i * MAX_NEW_NULLIFIERS_PER_TX + j] = kernel_data[i].public_inputs.end.new_nullifiers[j]; - } - } - - // TODO(lasse): It is a bit hacky here that it is always the same location we are inserting it. - - auto temp = generate_nullifier_tree_testing_values_explicit(baseRollupInputs, nullifiers, initial_values); - baseRollupInputs = std::get<0>(temp); - - baseRollupInputs.new_contracts_subtree_sibling_path = - get_sibling_path(contract_tree, 0, CONTRACT_SUBTREE_HEIGHT); - - baseRollupInputs.new_commitments_subtree_sibling_path = - get_sibling_path(note_hash_tree, 0, NOTE_HASH_SUBTREE_HEIGHT); - - - // Update public data tree to generate sibling paths: we first set the initial public data tree to the result of all - // public data reads and old_values from public data update requests. Note that, if the right tx reads or writes an - // index that was already processed by the left one, we don't want to reflect that as part of the initial state, so - // we skip those. - std::set visited_indices; - for (size_t i = 0; i < 2; i++) { - for (auto public_data_read : kernel_data[i].public_inputs.end.public_data_reads) { - auto leaf_index = uint256_t(public_data_read.leaf_index); - if (public_data_read.is_empty() || visited_indices.contains(leaf_index)) { - continue; - } - visited_indices.insert(leaf_index); - public_data_tree.update_element(leaf_index, public_data_read.value); - } - - for (auto public_data_update_request : kernel_data[i].public_inputs.end.public_data_update_requests) { - auto leaf_index = uint256_t(public_data_update_request.leaf_index); - if (public_data_update_request.is_empty() || visited_indices.contains(leaf_index)) { - continue; - } - visited_indices.insert(leaf_index); - public_data_tree.update_element(leaf_index, public_data_update_request.old_value); - } - } - - baseRollupInputs.start_public_data_tree_root = public_data_tree.root(); - - // create the original blocks tree leaf - auto block_hash = compute_block_hash(prev_global_variables_hash, - note_hash_tree.root(), - nullifier_tree.root(), - contract_tree.root(), - l1_to_l2_msg_tree.root(), - public_data_tree.root()); - archive.update_element(0, block_hash); - - ConstantRollupData const constantRollupData = { .start_archive_snapshot = { - .root = archive.root(), - .next_available_leaf_index = 1, - } }; - baseRollupInputs.constants = constantRollupData; - - // Set historical tree roots data in the public inputs. - for (size_t i = 0; i < 2; i++) { - kernel_data[i].public_inputs.constants.block_header.note_hash_tree_root = note_hash_tree.root(); - kernel_data[i].public_inputs.constants.block_header.nullifier_tree_root = nullifier_tree.root(); - kernel_data[i].public_inputs.constants.block_header.nullifier_tree_root = nullifier_tree.root(); - kernel_data[i].public_inputs.constants.block_header.contract_tree_root = contract_tree.root(); - kernel_data[i].public_inputs.constants.block_header.l1_to_l2_message_tree_root = l1_to_l2_msg_tree.root(); - kernel_data[i].public_inputs.constants.block_header.archive_root = archive.root(); - kernel_data[i].public_inputs.constants.block_header.public_data_tree_root = public_data_tree.root(); - kernel_data[i].public_inputs.constants.block_header.global_variables_hash = prev_global_variables_hash; - } - - // Then we collect all sibling paths for the reads in the left tx, and then apply the update requests while - // collecting their paths. And then repeat for the right tx. - for (size_t i = 0; i < 2; i++) { - for (size_t j = 0; j < MAX_PUBLIC_DATA_READS_PER_TX; j++) { - auto public_data_read = kernel_data[i].public_inputs.end.public_data_reads[j]; - if (public_data_read.is_empty()) { - continue; - } - auto leaf_index = uint256_t(public_data_read.leaf_index); - baseRollupInputs.new_public_data_reads_sibling_paths[i * MAX_PUBLIC_DATA_READS_PER_TX + j] = - get_sibling_path(public_data_tree, leaf_index); - } - - for (size_t j = 0; j < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; j++) { - auto public_data_update_request = kernel_data[i].public_inputs.end.public_data_update_requests[j]; - if (public_data_update_request.is_empty()) { - continue; - } - auto leaf_index = uint256_t(public_data_update_request.leaf_index); - public_data_tree.update_element(leaf_index, public_data_update_request.new_value); - baseRollupInputs - .new_public_data_update_requests_sibling_paths[i * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + j] = - get_sibling_path(public_data_tree, leaf_index); - } - } - - // Get historical_root sibling paths - baseRollupInputs.archive_root_membership_witnesses[0] = { - .leaf_index = 0, - .sibling_path = get_sibling_path(archive, 0, 0), - }; - baseRollupInputs.archive_root_membership_witnesses[1] = baseRollupInputs.archive_root_membership_witnesses[0]; - - baseRollupInputs.kernel_data = kernel_data; - - return baseRollupInputs; -} - -BaseRollupInputs base_rollup_inputs_from_kernels(std::array kernel_data) -{ - MemoryStore note_hash_store; - MerkleTree note_hash_tree = MerkleTree(note_hash_store, NOTE_HASH_TREE_HEIGHT); - MemoryStore contract_tree_store; - MerkleTree contract_tree = MerkleTree(contract_tree_store, CONTRACT_TREE_HEIGHT); - MemoryStore l1_to_l2_messages_store; - MerkleTree l1_to_l2_message_tree = MerkleTree(l1_to_l2_messages_store, L1_TO_L2_MSG_TREE_HEIGHT); - - MemoryStore public_data_tree_store; - MerkleTree public_data_tree(public_data_tree_store, PUBLIC_DATA_TREE_HEIGHT); - - - return base_rollup_inputs_from_kernels( - std::move(kernel_data), note_hash_tree, contract_tree, public_data_tree, l1_to_l2_message_tree); -} - -BaseRollupInputs base_rollup_inputs_from_kernels(std::array kernel_data, - abis::GlobalVariables global_variables) -{ - MemoryStore note_hash_store; - MerkleTree note_hash_tree = MerkleTree(note_hash_store, NOTE_HASH_TREE_HEIGHT); - MemoryStore nullifier_data_store; - MerkleTree nullifier_tree = MerkleTree(nullifier_data_store, NOTE_HASH_TREE_HEIGHT); - MemoryStore contract_tree_store; - MerkleTree contract_tree = MerkleTree(contract_tree_store, CONTRACT_TREE_HEIGHT); - MemoryStore l1_to_l2_messages_store; - MerkleTree l1_to_l2_message_tree = MerkleTree(l1_to_l2_messages_store, L1_TO_L2_MSG_TREE_HEIGHT); - - MemoryStore public_data_tree_store; - MerkleTree public_data_tree(public_data_tree_store, PUBLIC_DATA_TREE_HEIGHT); - - - return base_rollup_inputs_from_kernels(std::move(kernel_data), - global_variables.hash(), - note_hash_tree, - nullifier_tree, - contract_tree, - public_data_tree, - l1_to_l2_message_tree); -} - -BaseRollupInputs base_rollup_inputs_from_kernels(std::array kernel_data, - MerkleTree& note_hash_tree, - MerkleTree& contract_tree, - MerkleTree& public_data_tree, - MerkleTree& l1_to_l2_msg_tree) -{ - MemoryStore nullifier_tree_store; - MerkleTree nullifier_tree = MerkleTree(nullifier_tree_store, NULLIFIER_TREE_HEIGHT); - - abis::GlobalVariables prev_globals; - - return base_rollup_inputs_from_kernels(std::move(kernel_data), - prev_globals.hash(), - note_hash_tree, - nullifier_tree, - contract_tree, - public_data_tree, - l1_to_l2_msg_tree); -} - -std::array, 2> get_previous_rollup_data(DummyBuilder& builder, - std::array kernel_data) -{ - // NOTE: Still assuming that this is first and second. Don't handle more rollups atm - auto base_rollup_input_1 = base_rollup_inputs_from_kernels({ kernel_data[0], kernel_data[1] }); - auto base_public_input_1 = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, base_rollup_input_1); - - // Build the trees based on inputs in base_rollup_input_1. - MemoryStore note_hash_store; - MerkleTree note_hash_tree = MerkleTree(note_hash_store, NOTE_HASH_TREE_HEIGHT); - MemoryStore contract_tree_store; - MerkleTree contract_tree = MerkleTree(contract_tree_store, CONTRACT_TREE_HEIGHT); - std::vector initial_values(2 * MAX_NEW_NULLIFIERS_PER_TX - 1); - - for (size_t i = 0; i < initial_values.size(); i++) { - initial_values[i] = i + 1; - } - std::array nullifiers; - - for (size_t i = 0; i < 2; i++) { - for (size_t j = 0; j < MAX_NEW_COMMITMENTS_PER_TX; j++) { - note_hash_tree.update_element(i * MAX_NEW_COMMITMENTS_PER_TX + j, - kernel_data[i].public_inputs.end.new_commitments[j]); - } - auto contract_data = kernel_data[i].public_inputs.end.new_contracts[0]; - if (!contract_data.is_empty()) { - contract_tree.update_element(i, contract_data.hash()); - } - for (size_t j = 0; j < MAX_NEW_NULLIFIERS_PER_TX; j++) { - initial_values.push_back(kernel_data[i].public_inputs.end.new_nullifiers[j]); - nullifiers[i * MAX_NEW_NULLIFIERS_PER_TX + j] = kernel_data[2 + i].public_inputs.end.new_nullifiers[j]; - } - } - - auto base_rollup_input_2 = base_rollup_inputs_from_kernels({ kernel_data[2], kernel_data[3] }); - auto temp = generate_nullifier_tree_testing_values_explicit(base_rollup_input_2, nullifiers, initial_values); - base_rollup_input_2 = std::get<0>(temp); - - base_rollup_input_2.start_note_hash_tree_snapshot = base_public_input_1.end_note_hash_tree_snapshot; - base_rollup_input_2.start_nullifier_tree_snapshot = base_public_input_1.end_nullifier_tree_snapshot; - base_rollup_input_2.start_contract_tree_snapshot = base_public_input_1.end_contract_tree_snapshot; - - base_rollup_input_2.new_contracts_subtree_sibling_path = - get_sibling_path(contract_tree, 2, CONTRACT_SUBTREE_HEIGHT); - base_rollup_input_2.new_commitments_subtree_sibling_path = get_sibling_path( - note_hash_tree, 2 * MAX_NEW_COMMITMENTS_PER_TX, NOTE_HASH_SUBTREE_HEIGHT); - - auto base_public_input_2 = - aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(builder, base_rollup_input_2); - - PreviousRollupData const previous_rollup1 = { - .base_or_merge_rollup_public_inputs = base_public_input_1, - .proof = kernel_data[0].proof, - .vk = kernel_data[0].vk, - .vk_index = 0, - .vk_sibling_path = MembershipWitness(), - }; - PreviousRollupData const previous_rollup2 = { - .base_or_merge_rollup_public_inputs = base_public_input_2, - .proof = kernel_data[2].proof, - .vk = kernel_data[2].vk, - .vk_index = 0, - .vk_sibling_path = MembershipWitness(), - }; - - return { previous_rollup1, previous_rollup2 }; -} - -MergeRollupInputs get_merge_rollup_inputs(utils::DummyBuilder& builder, std::array kernel_data) -{ - MergeRollupInputs inputs = { .previous_rollup_data = get_previous_rollup_data(builder, std::move(kernel_data)) }; - return inputs; -} - - -RootRollupInputs get_root_rollup_inputs(utils::DummyBuilder& builder, - std::array kernel_data, - std::array l1_to_l2_messages) -{ - abis::GlobalVariables globals = { 0, 0, 0, 0 }; - - MemoryStore note_hash_store; - const MerkleTree note_hash_tree(note_hash_store, NOTE_HASH_TREE_HEIGHT); - - auto nullifier_tree = get_initial_nullifier_tree_empty(); - - MemoryStore contract_tree_store; - const MerkleTree contract_tree(contract_tree_store, CONTRACT_TREE_HEIGHT); - - MemoryStore l1_to_l2_msg_tree_store; - MerkleTree l1_to_l2_msg_tree(l1_to_l2_msg_tree_store, L1_TO_L2_MSG_TREE_HEIGHT); - - MemoryStore public_data_tree_store; - MerkleTree public_data_tree(public_data_tree_store, PUBLIC_DATA_TREE_HEIGHT); - - MemoryStore archive_store; - MerkleTree archive(archive_store, ARCHIVE_HEIGHT); - - // Start blocks tree - auto block_hash = compute_block_hash_with_globals(globals, - note_hash_tree.root(), - nullifier_tree.root(), - contract_tree.root(), - l1_to_l2_msg_tree.root(), - public_data_tree.root()); - archive.update_element(0, block_hash); - - // Blocks tree snapshots - AppendOnlyTreeSnapshot const start_archive_snapshot = { - .root = archive.root(), - .next_available_leaf_index = 1, - }; - - // Blocks tree - auto archive_sibling_path = get_sibling_path(archive, 1, 0); - - // l1 to l2 tree - auto l1_to_l2_tree_sibling_path = - get_sibling_path(l1_to_l2_msg_tree, 0, L1_TO_L2_MSG_SUBTREE_HEIGHT); - - // l1_to_l2_message tree snapshots - AppendOnlyTreeSnapshot const start_l1_to_l2_msg_tree_snapshot = { - .root = l1_to_l2_msg_tree.root(), - .next_available_leaf_index = 0, - }; - - RootRollupInputs rootRollupInputs = { - .previous_rollup_data = get_previous_rollup_data(builder, std::move(kernel_data)), - .new_l1_to_l2_messages = l1_to_l2_messages, - .new_l1_to_l2_message_tree_root_sibling_path = l1_to_l2_tree_sibling_path, - .start_l1_to_l2_message_tree_snapshot = start_l1_to_l2_msg_tree_snapshot, - .start_archive_snapshot = start_archive_snapshot, - .new_archive_sibling_path = archive_sibling_path, - }; - return rootRollupInputs; -} - -////////////////////////// -// NULLIFIER TREE BELOW // -////////////////////////// - -/** - * @brief Get initial nullifier tree object - * - * @return NullifierMemoryTreeTestingHarness - */ -NullifierMemoryTreeTestingHarness get_initial_nullifier_tree_empty() -{ - NullifierMemoryTreeTestingHarness nullifier_tree = NullifierMemoryTreeTestingHarness(NULLIFIER_TREE_HEIGHT); - for (size_t i = 0; i < (MAX_NEW_NULLIFIERS_PER_TX * 2 - 1); i++) { - nullifier_tree.update_element(i + 1); - } - return nullifier_tree; -} - -/** - * @brief Get initial nullifier tree object - * - * @param initial_values values to pre-populate the tree - * @return NullifierMemoryTreeTestingHarness - */ -NullifierMemoryTreeTestingHarness get_initial_nullifier_tree(const std::vector& initial_values) -{ - NullifierMemoryTreeTestingHarness nullifier_tree = NullifierMemoryTreeTestingHarness(NULLIFIER_TREE_HEIGHT); - for (const auto& initial_value : initial_values) { - nullifier_tree.update_element(initial_value); - } - return nullifier_tree; -} - -nullifier_tree_testing_values generate_nullifier_tree_testing_values(BaseRollupInputs inputs, - size_t starting_insertion_value = 0, - size_t spacing = 5) -{ - const size_t NUMBER_OF_NULLIFIERS = MAX_NEW_NULLIFIERS_PER_TX * 2; - std::array nullifiers; - for (size_t i = 0; i < NUMBER_OF_NULLIFIERS; ++i) { - auto insertion_val = (starting_insertion_value + i * spacing); - nullifiers[i] = fr(insertion_val); - } - - // Generate initial values lin spaced - std::vector initial_values; - for (size_t i = 1; i < NUMBER_OF_NULLIFIERS; ++i) { - initial_values.emplace_back(i * spacing); - } - - return utils::generate_nullifier_tree_testing_values_explicit(std::move(inputs), nullifiers, initial_values); -} - -nullifier_tree_testing_values generate_nullifier_tree_testing_values( - BaseRollupInputs inputs, std::array new_nullifiers, size_t spacing = 5) -{ - // Generate initial values lin spaced - std::vector initial_values; - for (size_t i = 1; i < 2 * MAX_NEW_NULLIFIERS_PER_TX; ++i) { - initial_values.emplace_back(i * spacing); - } - - return utils::generate_nullifier_tree_testing_values_explicit(std::move(inputs), new_nullifiers, initial_values); -} - -nullifier_tree_testing_values generate_nullifier_tree_testing_values_explicit( - BaseRollupInputs rollupInputs, - std::array new_nullifiers, - const std::vector& initial_values) -{ - size_t const start_tree_size = initial_values.size() + 1; - // Generate nullifier tree testing values - NullifierMemoryTreeTestingHarness nullifier_tree = get_initial_nullifier_tree(initial_values); - NullifierMemoryTreeTestingHarness reference_tree = get_initial_nullifier_tree(initial_values); - - AppendOnlyTreeSnapshot const nullifier_tree_start_snapshot = nullifier_tree.get_snapshot(); - - const size_t NUMBER_OF_NULLIFIERS = MAX_NEW_NULLIFIERS_PER_TX * 2; - std::array new_nullifier_leaves{}; - - // Calculate the predecessor nullifier pre-images - // Get insertion values - std::vector insertion_values; - std::array new_nullifiers_kernel_1{}; - std::array new_nullifiers_kernel_2{}; - - for (size_t i = 0; i < NUMBER_OF_NULLIFIERS; ++i) { - auto insertion_val = new_nullifiers[i]; - if (i < MAX_NEW_NULLIFIERS_PER_TX) { - new_nullifiers_kernel_1[i] = insertion_val; - } else { - new_nullifiers_kernel_2[i - MAX_NEW_NULLIFIERS_PER_TX] = insertion_val; - } - insertion_values.push_back(insertion_val); - reference_tree.update_element(insertion_val); - } - - // Get the hash paths etc from the insertion values - auto witnesses_and_preimages = nullifier_tree.circuit_prep_batch_insert(insertion_values); - - auto new_nullifier_leaves_preimages = std::get<0>(witnesses_and_preimages); - auto new_nullifier_leaves_sibling_paths = std::get<1>(witnesses_and_preimages); - auto new_nullifier_leave_indexes = std::get<2>(witnesses_and_preimages); - - // Create witness values from this - std::array, NUMBER_OF_NULLIFIERS> new_membership_witnesses{}; - for (size_t i = 0; i < NUMBER_OF_NULLIFIERS; i++) { - // create an array of the witness from the depth - std::array witness_array{}; - std::copy(new_nullifier_leaves_sibling_paths[i].begin(), - new_nullifier_leaves_sibling_paths[i].end(), - witness_array.begin()); - - MembershipWitness const witness = { - .leaf_index = static_cast(new_nullifier_leave_indexes[i]), - .sibling_path = witness_array, - }; - new_membership_witnesses[i] = witness; - - // Create circuit compatible preimages - issue created to remove this step - NullifierLeafPreimage const preimage = { - .leaf_value = new_nullifier_leaves_preimages[i].value, - .next_value = new_nullifier_leaves_preimages[i].nextValue, - .next_index = NT::uint32(new_nullifier_leaves_preimages[i].nextIndex), - }; - new_nullifier_leaves[i] = preimage; - } - - // Get expected root with subtrees inserted correctly - // Expected end state - AppendOnlyTreeSnapshot const nullifier_tree_end_snapshot = reference_tree.get_snapshot(); - - std::vector sibling_path = reference_tree.get_sibling_path(start_tree_size); - std::array sibling_path_array; - - // Chop the first NULLIFIER-SUBTREE-DEPTH levels from the sibling_path - sibling_path.erase(sibling_path.begin(), sibling_path.begin() + NULLIFIER_SUBTREE_HEIGHT); - std::copy(sibling_path.begin(), sibling_path.end(), sibling_path_array.begin()); - - // Update our start state - // Nullifier trees - rollupInputs.start_nullifier_tree_snapshot = nullifier_tree_start_snapshot; - rollupInputs.new_nullifiers_subtree_sibling_path = sibling_path_array; - - rollupInputs.kernel_data[0].public_inputs.end.new_nullifiers = new_nullifiers_kernel_1; - rollupInputs.kernel_data[1].public_inputs.end.new_nullifiers = new_nullifiers_kernel_2; - - rollupInputs.low_nullifier_leaf_preimages = new_nullifier_leaves; - rollupInputs.low_nullifier_membership_witness = new_membership_witnesses; - - return std::make_tuple(rollupInputs, nullifier_tree_start_snapshot, nullifier_tree_end_snapshot); -} - -/** - * @brief Compares a hash calculated within a circuit (made up of two field elements) against - * one generated natively, (32 bytes) and checks if they match - * - * @param field_hash - * @param expected_hash - * @return true - * @return false - */ -bool compare_field_hash_to_expected(std::array field_hash, - std::array expected_hash) -{ - auto high_buffer = field_hash[0].to_buffer(); - auto low_buffer = field_hash[1].to_buffer(); - - std::array field_expanded_hash; - for (uint8_t i = 0; i < 16; ++i) { - field_expanded_hash[i] = high_buffer[16 + i]; - field_expanded_hash[16 + i] = low_buffer[16 + i]; - } - - return expected_hash == field_expanded_hash; -} - -} // namespace aztec3::circuits::rollup::test_utils::utils diff --git a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.hpp b/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.hpp deleted file mode 100644 index 0bc7e8a069f..00000000000 --- a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.hpp +++ /dev/null @@ -1,130 +0,0 @@ -#pragma once -#include "init.hpp" -#include "nullifier_tree_testing_harness.hpp" - -#include "aztec3/circuits/abis/public_data_update_request.hpp" -#include "aztec3/circuits/hash.hpp" -#include "aztec3/constants.hpp" - -#include - -namespace aztec3::circuits::rollup::test_utils::utils { - -namespace { - -using NT = aztec3::utils::types::NativeTypes; - -// Helpers -using aztec3::circuits::get_sibling_path; - -// Types -using ConstantRollupData = aztec3::circuits::abis::ConstantRollupData; -using BaseRollupInputs = aztec3::circuits::abis::BaseRollupInputs; -using MergeRollupInputs = aztec3::circuits::abis::MergeRollupInputs; -using BaseOrMergeRollupPublicInputs = aztec3::circuits::abis::BaseOrMergeRollupPublicInputs; -using RootRollupInputs = aztec3::circuits::abis::RootRollupInputs; -using DummyBuilder = aztec3::utils::DummyCircuitBuilder; - -using Aggregator = aztec3::circuits::recursion::Aggregator; -using AppendOnlyTreeSnapshot = aztec3::circuits::abis::AppendOnlyTreeSnapshot; - -using NullifierLeafPreimage = aztec3::circuits::abis::NullifierLeafPreimage; - -// Tree Aliases -using MemoryStore = stdlib::merkle_tree::MemoryStore; -using MerkleTree = stdlib::merkle_tree::MerkleTree; -using NullifierTree = stdlib::merkle_tree::NullifierMemoryTree; -using NullifierLeaf = stdlib::merkle_tree::nullifier_leaf; - -using KernelData = aztec3::circuits::abis::PreviousKernelData; - -using aztec3::circuits::abis::MembershipWitness; -using aztec3::circuits::abis::PreviousRollupData; - -using nullifier_tree_testing_values = std::tuple; -} // namespace - -BaseRollupInputs base_rollup_inputs_from_kernels(std::array kernel_data); - -BaseRollupInputs base_rollup_inputs_from_kernels(std::array kernel_data, - abis::GlobalVariables global_variables); - -BaseRollupInputs base_rollup_inputs_from_kernels(std::array kernel_data, - MerkleTree& note_hash_tree, - MerkleTree& contract_tree, - MerkleTree& public_data_tree, - MerkleTree& l1_to_l2_msg_tree); - -BaseRollupInputs base_rollup_inputs_from_kernels(std::array kernel_data, - fr prev_global_variables_hash, - MerkleTree& note_hash_tree, - MerkleTree& nullifier_tree, - MerkleTree& contract_tree, - MerkleTree& public_data_tree, - MerkleTree& l1_to_l2_msg_tree); - - -template std::array get_sibling_path(MerkleTree& tree, uint256_t leafIndex) -{ - std::array siblingPath; - auto path = tree.get_hash_path(leafIndex); - for (size_t i = 0; i < N; i++) { - if (leafIndex & (uint256_t(1) << i)) { - siblingPath[i] = path[i].first; - } else { - siblingPath[i] = path[i].second; - } - } - return siblingPath; -} - -abis::AppendOnlyTreeSnapshot get_snapshot_of_tree_state(NullifierMemoryTreeTestingHarness nullifier_tree); - -nullifier_tree_testing_values generate_nullifier_tree_testing_values_explicit( - BaseRollupInputs inputs, - std::array new_nullifiers, - const std::vector& initial_values); - -nullifier_tree_testing_values generate_nullifier_tree_testing_values(BaseRollupInputs inputs, - size_t starting_insertion_value, - size_t spacing); - -std::array get_empty_l1_to_l2_messages(); - -nullifier_tree_testing_values generate_nullifier_tree_testing_values( - BaseRollupInputs inputs, std::array new_nullifiers, size_t spacing); - -NullifierMemoryTreeTestingHarness get_initial_nullifier_tree_empty(); -NullifierMemoryTreeTestingHarness get_initial_nullifier_tree(const std::vector& initial_values); - -KernelData get_empty_kernel(); - -RootRollupInputs get_root_rollup_inputs(utils::DummyBuilder& builder, - std::array kernel_data, - std::array l1_to_l2_messages); - -MergeRollupInputs get_merge_rollup_inputs(utils::DummyBuilder& builder, std::array kernel_data); - -inline abis::PublicDataUpdateRequest make_public_data_update_request(fr leaf_index, fr old_value, fr new_value) -{ - return abis::PublicDataUpdateRequest{ - .leaf_index = leaf_index, - .old_value = old_value, - .new_value = new_value, - }; -}; - -inline abis::PublicDataRead make_public_read(fr leaf_index, fr value) -{ - return abis::PublicDataRead{ - .leaf_index = leaf_index, - .value = value, - }; -} - -bool compare_field_hash_to_expected(std::array field_hash, - std::array expected_hash); - -std::vector get_empty_calldata_leaf(); - -} // namespace aztec3::circuits::rollup::test_utils::utils diff --git a/circuits/cpp/src/aztec3/constants.hpp b/circuits/cpp/src/aztec3/constants.hpp deleted file mode 100644 index d2c444ac1b3..00000000000 --- a/circuits/cpp/src/aztec3/constants.hpp +++ /dev/null @@ -1,364 +0,0 @@ -#pragma once -#include -#include - -#include -#include -// NOTE: When modifying names of constants or enums do the changes in `src/aztec3/circuits/abis/packers.hpp` as well - -namespace aztec3 { - -/** - * @brief Computes log2 at compile-time for inputs of the form 2^n. - * - * @param input - * @return ⌈ log₂(input) ⌉ - */ -constexpr size_t log2(size_t input) -{ - return static_cast(numeric::get_msb64(static_cast(input))); -} - -constexpr size_t ARGS_LENGTH = 16; -constexpr size_t RETURN_VALUES_LENGTH = 4; - -/** - * Convention for constant array lengths are mainly divided in 2 classes: - * - FUNCTION CALL - * - TRANSACTION - * - * Agreed convention is to use MAX_XXX_PER_CALL resp. MAX_XXX_PER_TX, where XXX denotes a type of element such as - * commitment, or nullifier, e.g.,: - * - MAX_NEW_NULLIFIERS_PER_CALL - * - MAX_NEW_COMMITMENTS_PER_TX - * - * In the kernel circuits, we accumulate elements such as commitments and the nullifiers from all functions calls in a - * transaction. Therefore, we always must have: - * MAX_XXX_PER_TX ≥ MAX_XXX_PER_CALL - * - * For instance: - * MAX_NEW_COMMITMENTS_PER_TX ≥ MAX_NEW_COMMITMENTS_PER_CALL - * MAX_NEW_NULLIFIERS_PER_TX ≥ MAX_NEW_NULLIFIERS_PER_CALL - * - */ - -// docs:start:constants -// "PER CALL" CONSTANTS -constexpr size_t MAX_NEW_COMMITMENTS_PER_CALL = 16; -constexpr size_t MAX_NEW_NULLIFIERS_PER_CALL = 16; -constexpr size_t MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL = 4; -constexpr size_t MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL = 4; -constexpr size_t MAX_NEW_L2_TO_L1_MSGS_PER_CALL = 2; -constexpr size_t MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL = 16; -constexpr size_t MAX_PUBLIC_DATA_READS_PER_CALL = 16; -constexpr size_t MAX_READ_REQUESTS_PER_CALL = 32; - - -// "PER TRANSACTION" CONSTANTS -constexpr size_t MAX_NEW_COMMITMENTS_PER_TX = MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL * MAX_NEW_COMMITMENTS_PER_CALL; -constexpr size_t MAX_NEW_NULLIFIERS_PER_TX = MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL * MAX_NEW_NULLIFIERS_PER_CALL; -constexpr size_t MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX = 8; -constexpr size_t MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX = 8; -constexpr size_t MAX_NEW_L2_TO_L1_MSGS_PER_TX = 2; -constexpr size_t MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 16; -constexpr size_t MAX_PUBLIC_DATA_READS_PER_TX = 16; -constexpr size_t MAX_NEW_CONTRACTS_PER_TX = 1; -constexpr size_t MAX_OPTIONALLY_REVEALED_DATA_LENGTH_PER_TX = 4; -constexpr size_t MAX_READ_REQUESTS_PER_TX = MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL * MAX_READ_REQUESTS_PER_CALL; -constexpr size_t NUM_ENCRYPTED_LOGS_HASHES_PER_TX = 1; -constexpr size_t NUM_UNENCRYPTED_LOGS_HASHES_PER_TX = 1; -// docs:end:constants - -//////////////////////////////////////////////////////////////////////////////// -// ROLLUP CONTRACT CONSTANTS - constants used only in l1-contracts -//////////////////////////////////////////////////////////////////////////////// -constexpr size_t NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP = 16; -// TODO(961): Use this constant everywhere instead of hard-coded "2". -constexpr size_t KERNELS_PER_BASE_ROLLUP = 2; -constexpr size_t COMMITMENTS_NUM_BYTES_PER_BASE_ROLLUP = KERNELS_PER_BASE_ROLLUP * MAX_NEW_COMMITMENTS_PER_TX * 32; -constexpr size_t MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP = KERNELS_PER_BASE_ROLLUP * MAX_NEW_NULLIFIERS_PER_TX; -constexpr size_t NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = MAX_NEW_NULLIFIERS_PER_BASE_ROLLUP * 32; -constexpr size_t MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP = - KERNELS_PER_BASE_ROLLUP * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; -constexpr size_t PUBLIC_DATA_WRITES_NUM_BYTES_PER_BASE_ROLLUP = - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_BASE_ROLLUP * 64; // old value, new value -constexpr size_t MAX_PUBLIC_DATA_READS_PER_BASE_ROLLUP = KERNELS_PER_BASE_ROLLUP * MAX_PUBLIC_DATA_READS_PER_TX; -constexpr size_t CONTRACTS_NUM_BYTES_PER_BASE_ROLLUP = KERNELS_PER_BASE_ROLLUP * MAX_NEW_CONTRACTS_PER_TX * 32; -constexpr size_t CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP = - KERNELS_PER_BASE_ROLLUP * MAX_NEW_CONTRACTS_PER_TX * 64; // aztec address + eth address (padded to 0x20) -constexpr size_t CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP_UNPADDED = - KERNELS_PER_BASE_ROLLUP * MAX_NEW_CONTRACTS_PER_TX * - 52; // same as prev except doesn't pad eth address. So 0x20 (aztec address) + 0x14 (eth address) -constexpr size_t L2_TO_L1_MSGS_NUM_BYTES_PER_BASE_ROLLUP = KERNELS_PER_BASE_ROLLUP * MAX_NEW_L2_TO_L1_MSGS_PER_TX * 32; -constexpr size_t LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP = - KERNELS_PER_BASE_ROLLUP * 2 * 32; // 1 for encrypted + 1 for unencrypted - -// TREES RELATED CONSTANTS -constexpr size_t VK_TREE_HEIGHT = 3; -constexpr size_t FUNCTION_TREE_HEIGHT = 5; -constexpr size_t CONTRACT_TREE_HEIGHT = 16; -constexpr size_t NOTE_HASH_TREE_HEIGHT = 32; -constexpr size_t PUBLIC_DATA_TREE_HEIGHT = 254; -constexpr size_t NULLIFIER_TREE_HEIGHT = 20; -constexpr size_t L1_TO_L2_MSG_TREE_HEIGHT = 16; -constexpr size_t ARCHIVE_HEIGHT = 16; -constexpr size_t ROLLUP_VK_TREE_HEIGHT = 8; // TODO: update - - -// SUB-TREES RELATED CONSTANTS -constexpr size_t CONTRACT_SUBTREE_HEIGHT = - static_cast(log2(MAX_NEW_CONTRACTS_PER_TX * KERNELS_PER_BASE_ROLLUP)); -constexpr size_t CONTRACT_SUBTREE_SIBLING_PATH_LENGTH = CONTRACT_TREE_HEIGHT - CONTRACT_SUBTREE_HEIGHT; -constexpr size_t NOTE_HASH_SUBTREE_HEIGHT = - static_cast(log2(KERNELS_PER_BASE_ROLLUP * MAX_NEW_COMMITMENTS_PER_TX)); -constexpr size_t NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH = NOTE_HASH_TREE_HEIGHT - NOTE_HASH_SUBTREE_HEIGHT; -constexpr size_t NULLIFIER_SUBTREE_HEIGHT = - static_cast(log2(KERNELS_PER_BASE_ROLLUP * MAX_NEW_NULLIFIERS_PER_TX)); -constexpr size_t NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH = NULLIFIER_TREE_HEIGHT - NULLIFIER_SUBTREE_HEIGHT; -constexpr size_t L1_TO_L2_MSG_SUBTREE_HEIGHT = static_cast(log2(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP)); -constexpr size_t L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH = L1_TO_L2_MSG_TREE_HEIGHT - L1_TO_L2_MSG_SUBTREE_HEIGHT; - - -// MISC CONSTANTS -constexpr size_t FUNCTION_SELECTOR_NUM_BYTES = 4; // must be <= 31 -constexpr size_t MAPPING_SLOT_PEDERSEN_SEPARATOR = 4; -// sha256 hash is stored in two fields to accommodate all 256-bits of the hash -constexpr size_t NUM_FIELDS_PER_SHA256 = 2; - -/** - * Enumerate the hash_indices which are used for pedersen hashing. - * We start from 1 to avoid the default generators. The generator indices are listed - * based on the number of elements each index hashes. The following conditions must be met: - * - * +-----------+-------------------------------+----------------------+ - * | Hash size | Number of elements hashed (n) | Condition to use | - * |-----------+-------------------------------+----------------------| - * | LOW | n ≤ 8 | 0 < hash_index ≤ 32 | - * | MID | 8 < n ≤ 16 | 32 < hash_index ≤ 40 | - * | HIGH | 16 < n ≤ 48 | 40 < hash_index ≤ 48 | - * +-----------+-------------------------------+----------------------+ - * - * Note: When modifying, modify `GeneratorIndexPacker` in packer.hpp accordingly. - */ -enum GeneratorIndex { - /** - * Indices with size ≤ 8 - */ - DEFAULT = 0, - COMMITMENT = 1, // Size = 7 (unused) - COMMITMENT_NONCE, // Size = 2 - UNIQUE_COMMITMENT, // Size = 2 - SILOED_COMMITMENT, // Size = 2 - NULLIFIER, // Size = 4 (unused) - INITIALIZATION_NULLIFIER, // Size = 2 (unused) - OUTER_NULLIFIER, // Size = 2 - PUBLIC_DATA_READ, // Size = 2 - PUBLIC_DATA_UPDATE_REQUEST, // Size = 3 - FUNCTION_DATA, // Size = 4 - FUNCTION_LEAF, // Size = 5 - CONTRACT_DEPLOYMENT_DATA, // Size = 4 - CONSTRUCTOR, // Size = 3 - CONSTRUCTOR_ARGS, // Size = 8 - CONTRACT_ADDRESS, // Size = 4 - CONTRACT_LEAF, // Size = 3 - CALL_CONTEXT, // Size = 6 - CALL_STACK_ITEM, // Size = 3 - CALL_STACK_ITEM_2, // Size = ? (unused), // TODO see function where it's used for explanation - L1_TO_L2_MESSAGE_SECRET, // Size = 1 - L2_TO_L1_MSG, // Size = 2 (unused) - TX_CONTEXT, // Size = 4 - PUBLIC_LEAF_INDEX, // Size = 2 (unused) - PUBLIC_DATA_LEAF, // Size = ? (unused) // TODO what's the expected size? Assuming ≤ 8 - SIGNED_TX_REQUEST, // Size = 7 - GLOBAL_VARIABLES, // Size = 4 - PARTIAL_ADDRESS, // Size = 7 - BLOCK_HASH, // Size = 6 - /** - * Indices with size ≤ 16 - */ - TX_REQUEST = 33, // Size = 14 - SIGNATURE_PAYLOAD, // Size = 13 - /** - * Indices with size ≤ 44 - */ - VK = 41, // Size = 35 - PRIVATE_CIRCUIT_PUBLIC_INPUTS, // Size = 45 - PUBLIC_CIRCUIT_PUBLIC_INPUTS, // Size = 32 (unused) - FUNCTION_ARGS, // Size ≤ 40 - NUMBER_OF_INDICES, -}; - -static constexpr std::string_view AZTEC_DOMAIN = "__AZTEC_"; -static constexpr std::string generatorIndexDomain(GeneratorIndex idx) -{ - switch (idx) { - case DEFAULT: - return "DEFAULT"; - case COMMITMENT: - return "COMMITMENT"; - case COMMITMENT_NONCE: - return "COMMITMENT_NONCE"; - case UNIQUE_COMMITMENT: - return "UNIQUE_COMMITMENT"; - case SILOED_COMMITMENT: - return "SILOED_COMMITMENT"; - case NULLIFIER: - return "NULLIFIER "; - case INITIALIZATION_NULLIFIER: - return "INITIALIZATION_NULLIFIER"; - case OUTER_NULLIFIER: - return "OUTER_NULLIFIER "; - case PUBLIC_DATA_READ: - return "PUBLIC_DATA_READ"; - case PUBLIC_DATA_UPDATE_REQUEST: - return "PUBLIC_DATA_UPDATE_REQUEST"; - case FUNCTION_DATA: - return "FUNCTION_DATA"; - case FUNCTION_LEAF: - return "FUNCTION_LEAF"; - case CONTRACT_DEPLOYMENT_DATA: - return "CONTRACT_DEPLOYMENT_DATA"; - case CONSTRUCTOR: - return "CONSTRUCTOR"; - case CONSTRUCTOR_ARGS: - return "CONSTRUCTOR_ARGS"; - case CONTRACT_ADDRESS: - return "CONTRACT_ADDRESS"; - case CONTRACT_LEAF: - return "CONTRACT_LEAF"; - case CALL_CONTEXT: - return "CALL_CONTEXT"; - case CALL_STACK_ITEM: - return "CALL_STACK_ITEM"; - case CALL_STACK_ITEM_2: - return "CALL_STACK_ITEM_2"; - case L1_TO_L2_MESSAGE_SECRET: - return "L1_TO_L2_MESSAGE_SECRET "; - case L2_TO_L1_MSG: - return "L2_TO_L1_MSG"; - case TX_CONTEXT: - return "TX_CONTEXT"; - case PUBLIC_LEAF_INDEX: - return "PUBLIC_LEAF_INDEX"; - case PUBLIC_DATA_LEAF: - return "PUBLIC_DATA_LEAF"; - case SIGNED_TX_REQUEST: - return "SIGNED_TX_REQUEST"; - case GLOBAL_VARIABLES: - return "GLOBAL_VARIABLES"; - case PARTIAL_ADDRESS: - return "PARTIAL_ADDRESS"; - case BLOCK_HASH: - return "BLOCK_HASH"; - case TX_REQUEST: - return "TX_REQUEST"; - case SIGNATURE_PAYLOAD: - return "SIGNATURE_PAYLOAD"; - case VK: - return "VK"; - case PRIVATE_CIRCUIT_PUBLIC_INPUTS: - return "PRIVATE_CIRCUIT_PUBLIC_INPUTS"; - case PUBLIC_CIRCUIT_PUBLIC_INPUTS: - return "PUBLIC_CIRCUIT_PUBLIC_INPUTS"; - case FUNCTION_ARGS: - return "FUNCTION_ARGS"; - default: { - throw_or_abort("could not convert GeneratorIndex enum to string_view"); - } - } -} - -// Note: When modifying, modify `StorageSlotGeneratorIndexPacker` in packer.hpp accordingly. -enum StorageSlotGeneratorIndex { - BASE_SLOT, - MAPPING_SLOT, - MAPPING_SLOT_PLACEHOLDER, -}; - -// Enumerate the hash_sub_indices which are used for committing to private state note preimages. -// Start from 1. -// Note: When modifying, modify `PrivateStateNoteGeneratorIndexPacker` in packer.hpp accordingly. -enum PrivateStateNoteGeneratorIndex { - VALUE = 1, - OWNER, - CREATOR, - SALT, - NONCE, - MEMO, - IS_DUMMY, -}; - -// Note: When modifying, modify `PrivateStateTypePacker` in packer.hpp accordingly. -enum PrivateStateType { PARTITIONED = 1, WHOLE }; - -//////////////////////////////////////////////////////////////////////////////// -// NOIR CONSTANTS - constants used only in yarn-packages/noir-contracts -// --> Here because Noir doesn't yet support globals referencing other globals yet and doing so in C++ seems to be the -// best thing to do for now. Move these constants to a noir file once the issue bellow is resolved: -// https://github.com/noir-lang/noir/issues/1734 -constexpr size_t L1_TO_L2_MESSAGE_LENGTH = 8; -// message length + sibling path (same size as tree height) + 1 field for root + 1 field for index -constexpr size_t L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH = L1_TO_L2_MESSAGE_LENGTH + L1_TO_L2_MSG_TREE_HEIGHT + 1 + 1; - -// TODO: Remove these when nested array is supported. -constexpr size_t MAX_NOTE_FIELDS_LENGTH = 20; -// MAX_NOTE_FIELDS_LENGTH + 1: the plus 1 is 1 extra field for nonce. -// + 2 for EXTRA_DATA: [number_of_return_notes, contract_address] -constexpr size_t GET_NOTE_ORACLE_RETURN_LENGTH = MAX_NOTE_FIELDS_LENGTH + 1 + 2; -constexpr size_t GET_NOTES_ORACLE_RETURN_LENGTH = MAX_READ_REQUESTS_PER_CALL * (MAX_NOTE_FIELDS_LENGTH + 1) + 2; -constexpr size_t MAX_NOTES_PER_PAGE = 10; -// + 2 for EXTRA_DATA: [number_of_return_notes, contract_address] -constexpr size_t VIEW_NOTE_ORACLE_RETURN_LENGTH = MAX_NOTES_PER_PAGE * (MAX_NOTE_FIELDS_LENGTH + 1) + 2; - -constexpr size_t CALL_CONTEXT_LENGTH = 7; -// Must be updated if any data is added into the block hash calculation. -constexpr size_t BLOCK_HEADER_LENGTH = 7; -constexpr size_t FUNCTION_DATA_LENGTH = 4; -constexpr size_t CONTRACT_DEPLOYMENT_DATA_LENGTH = 6; - -// Change this ONLY if you have changed the PrivateCircuitPublicInputs structure in C++. -// In other words, if the structure/size of the public inputs of a function call changes then we -// should change this constant as well as the offsets in private_call_stack_item.nr -constexpr size_t PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = - CALL_CONTEXT_LENGTH + 1 // +1 for args_hash - + RETURN_VALUES_LENGTH + MAX_READ_REQUESTS_PER_CALL + - MAX_NEW_COMMITMENTS_PER_CALL + 2 * MAX_NEW_NULLIFIERS_PER_CALL + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + MAX_NEW_L2_TO_L1_MSGS_PER_CALL + NUM_FIELDS_PER_SHA256 + - NUM_FIELDS_PER_SHA256 + 2 // + 2 for logs preimage lengths - + BLOCK_HEADER_LENGTH + CONTRACT_DEPLOYMENT_DATA_LENGTH + 2; // + 2 for chain_id and version - -constexpr size_t PRIVATE_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH = - 1 + 1 // call_context_hash + args_hash - + RETURN_VALUES_LENGTH + MAX_READ_REQUESTS_PER_CALL + - MAX_NEW_COMMITMENTS_PER_CALL + 2 * MAX_NEW_NULLIFIERS_PER_CALL + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + MAX_NEW_L2_TO_L1_MSGS_PER_CALL + NUM_FIELDS_PER_SHA256 + - NUM_FIELDS_PER_SHA256 + 2 // + 2 for logs preimage lengths - + BLOCK_HEADER_LENGTH + 3; // + 3 for contract_deployment_data.hash(), chain_id, version - -constexpr size_t CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 3; -constexpr size_t CONTRACT_STORAGE_READ_LENGTH = 2; - -// Change this ONLY if you have changed the PublicCircuitPublicInputs structure in C++. -constexpr size_t PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = - CALL_CONTEXT_LENGTH + 1 + RETURN_VALUES_LENGTH + // + 1 for args_hash - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL * CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH + - MAX_PUBLIC_DATA_READS_PER_CALL * CONTRACT_STORAGE_READ_LENGTH + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + - MAX_NEW_COMMITMENTS_PER_CALL + MAX_NEW_NULLIFIERS_PER_CALL + MAX_NEW_L2_TO_L1_MSGS_PER_CALL + - NUM_FIELDS_PER_SHA256 + 1 + // + 1 for unencrypted logs preimage length - BLOCK_HEADER_LENGTH + 2; // + 2 for chain_id and version - -constexpr size_t PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH = - 2 + RETURN_VALUES_LENGTH + // + 1 for args_hash + 1 call_context.hash - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL + MAX_PUBLIC_DATA_READS_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + - MAX_NEW_COMMITMENTS_PER_CALL + MAX_NEW_NULLIFIERS_PER_CALL + MAX_NEW_L2_TO_L1_MSGS_PER_CALL + - NUM_FIELDS_PER_SHA256 + // unencrypted_logs_hash (being represented by NUM_FIELDS_PER_SHA256) - BLOCK_HEADER_LENGTH + 2; // unencrypted_log_preimages_length + prover_address - - -// Size of the return value of a private function call, -constexpr size_t CALL_PRIVATE_FUNCTION_RETURN_SIZE = - 1 + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH + 1; - -constexpr size_t EMPTY_NULLIFIED_COMMITMENT = 1000000; - -} // namespace aztec3 \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/dbs/CMakeLists.txt b/circuits/cpp/src/aztec3/dbs/CMakeLists.txt deleted file mode 100644 index 49c80213432..00000000000 --- a/circuits/cpp/src/aztec3/dbs/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -if(NOT WASM) - include(FetchContent) - FetchContent_Declare( - leveldb - GIT_REPOSITORY https://github.com/google/leveldb.git - GIT_TAG 1.22 - ) - - FetchContent_GetProperties(leveldb) - if(NOT leveldb_POPULATED) - FetchContent_Populate(leveldb) - set(LEVELDB_BUILD_TESTS OFF CACHE BOOL "LevelDB tests off") - add_subdirectory(${leveldb_SOURCE_DIR} ${leveldb_BINARY_DIR} EXCLUDE_FROM_ALL) - endif() - - target_compile_options( - leveldb - PRIVATE - -Wno-sign-conversion - -Wno-unused-parameter - -Wno-shorten-64-to-32 - -Wno-implicit-int-conversion - -Wno-conversion - -Wno-implicit-fallthrough - ) - - link_libraries(leveldb) -endif() - -circuits_cmake_module( - aztec3_dbs - barretenberg -) \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/dbs/private_state_db.hpp b/circuits/cpp/src/aztec3/dbs/private_state_db.hpp deleted file mode 100644 index 60d4ecaedf8..00000000000 --- a/circuits/cpp/src/aztec3/dbs/private_state_db.hpp +++ /dev/null @@ -1,151 +0,0 @@ -// // TODO: move the leveldb_store to a more neutral module. -// #include "../constants.hpp" - -// #include "aztec3/utils/types/native_types.hpp" - -// #include - -// namespace aztec3::db { - -// using aztec3::GeneratorIndex; -// using crypto::pedersen::hash; - -// char const* PRIVATE_STATE_DB_PATH = "./private_state_var.db"; - -// struct PrivateStateVar { -// bool is_partitioned = false; -// std::vector active_private_state_preimages; -// }; - -// // contract->storageSlots->[current->historical] - -// /** -// * Hmmm... There are multiple active leaves for partitioned states. -// * -// * [contract_Address, storage_slot] -> { -// * is_partitioned, -// * earliest_active_commitment, -// * earliest_commitment, -// * } -// * -// * commitment -> { -// * PrivateStateVar, -// * next_active_commitment, -// * next_commitment, -// * } -// */ - -// template class PrivateStateDb { -// public: -// PrivateStateDb(Store& store, size_t max_state_var_id) -// : store_(store) -// , max_state_var_id_(max_state_var_id) -// {} - -// // we need a linked list through all active commitments, and another linked list through all (active & inactive) -// // commitments. - -// PrivateStateCommitment get_earliest_active_commitment(fr const& contract_address, fr const& state_var_id) -// { -// const fr& storage_slot = state_var_id; -// const fr db_key = -// commit_native(std::vector{ contract_address, storage_slot }, GeneratorIndex::UNIVERSAL_STORAGE_SLOT); -// } - -// PrivateStateCommitment get_earliest_active_commitment(fr const& contract_address, -// fr const& state_var_id, -// fr const& mapping_key) -// { -// const fr storage_slot = -// commit_native(std::vector{ state_var_id, mapping_key }, GeneratorIndex::MAPPING_STORAGE_SLOT); -// const fr db_key = -// commit_native(std::vector{ contract_address, storage_slot }, GeneratorIndex::UNIVERSAL_STORAGE_SLOT); - -// std::vector data; - -// bool success = store_.get(db_key, data); - -// return data; -// } - -// fr get_current_private_state_value(fr const& contract_address, fr const& state_var_id) -// { -// PrivateStateCommitment earliest_active_commitment = -// get_earliest_active_commitment(contract_address, state_var_id); -// } - -// fr get_current_private_state_value(fr const& contract_address, fr const& state_var_id, fr const& mapping_key) {} - -// void write_metadata(std::ostream& os) -// { -// write(os, data_tree_.root()); -// write(os, nullifier_tree_.root()); -// write(os, root_tree_.root()); -// write(os, defi_tree_.root()); -// write(os, data_tree_.size()); -// write(os, nullifier_tree_.size()); -// write(os, root_tree_.size()); -// write(os, defi_tree_.size()); -// } - -// void get(std::istream& is, std::ostream& os) -// { -// GetRequest get_request; -// read(is, get_request); -// // std::cerr << get_request << std::endl; -// auto tree = trees_[get_request.tree_id]; -// auto path = tree->get_hash_path(get_request.index); -// auto leaf = get_request.index & 0x1 ? path[0].second : path[0].first; -// write(os, leaf == fr::neg_one() ? fr(0) : leaf); -// } - -// void get_path(std::istream& is, std::ostream& os) -// { -// GetRequest get_request; -// read(is, get_request); -// // std::cerr << get_request << std::endl; -// auto tree = trees_[get_request.tree_id]; -// auto path = tree->get_hash_path(get_request.index); -// write(os, path); -// } - -// void put(std::istream& is, std::ostream& os) -// { -// PutRequest put_request; -// read(is, put_request); -// // std::cerr << put_request << std::endl; -// PutResponse put_response; -// put_response.root = trees_[put_request.tree_id]->update_element(put_request.index, put_request.value); -// write(os, put_response); -// } - -// void batch_put(std::istream& is, std::ostream& os) -// { -// std::vector put_requests; -// read(is, put_requests); -// for (auto& put_request : put_requests) { -// trees_[put_request.tree_id]->update_element(put_request.index, put_request.value); -// } -// write_metadata(os); -// } - -// void commit(std::ostream& os) -// { -// // std::cerr << "COMMIT" << std::endl; -// store_.commit(); -// write_metadata(os); -// } - -// void rollback(std::ostream& os) -// { -// // std::cerr << "ROLLBACK" << std::endl; -// store_.rollback(); -// write_metadata(os); -// } - -// private: -// Store& store_; -// size_t max_state_var_id_; -// }; - -// } // namespace aztec3::db \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/oracle/CMakeLists.txt b/circuits/cpp/src/aztec3/oracle/CMakeLists.txt deleted file mode 100644 index 1e9734a1d34..00000000000 --- a/circuits/cpp/src/aztec3/oracle/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -circuits_cmake_module( - aztec3_oracle - aztec3_circuits_apps - barretenberg -) \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/oracle/README.md b/circuits/cpp/src/aztec3/oracle/README.md deleted file mode 100644 index 43cc17cfa67..00000000000 --- a/circuits/cpp/src/aztec3/oracle/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# aztec3::circuits::oracle - -When Aztec3 makes a call to a circuit executor (such as Noir or the test apps in aztec3/circuits/apps/test_apps), we don't pass _all_ public inputs when calling the circuit; only the `args` inputs are sent initially. - -Why? - -This has two main benefits: - -- We only need one implementation of the circuit's logic: the circuit itself. We don't need to implement a separate native version of the circuit to 'predict' what commitments/nullifiers and other values will need to ultimately become inputs to the circuit. -- There are occasions where it's difficult to predict the inputs required in advance. E.g. if a circuit_1 makes a call to another circuit, circuit_2, at some other contract_address, but that address is calculated within the body of circuit_1. We'd need to independently deduce the address which would be called so that we could grab the correct contract_address, VK, vkIndex, proving key (etc) from the DB. - -Instead, we provide an oracle to the circuit executor when we call it. As the circuit is executed, it'll occasionally reach points where it needs more input data. The circuit executor can query the oracle (the Aztec3 node) for more data. The oracle can grab data from its DB and return it the circuit executor. The circuit executor can then convert the data into witnesses and continue with some more of the circuit's execution. - diff --git a/circuits/cpp/src/aztec3/oracle/fake_db.hpp b/circuits/cpp/src/aztec3/oracle/fake_db.hpp deleted file mode 100644 index a14ffa6f57e..00000000000 --- a/circuits/cpp/src/aztec3/oracle/fake_db.hpp +++ /dev/null @@ -1,161 +0,0 @@ -#pragma once - -#include "aztec3/circuits/abis/call_context.hpp" -#include "aztec3/circuits/apps/notes/default_private_note/note_preimage.hpp" -#include "aztec3/circuits/apps/notes/default_singleton_private_note/note_preimage.hpp" -#include "aztec3/circuits/apps/utxo_datum.hpp" -#include "aztec3/utils/types/native_types.hpp" - -namespace aztec3::oracle { - -using aztec3::circuits::apps::UTXOSLoadDatum; - -using aztec3::circuits::apps::notes::DefaultPrivateNotePreimage; - -using aztec3::circuits::apps::notes::DefaultSingletonPrivateNotePreimage; - -using NT = aztec3::utils::types::NativeTypes; - -// A temporary stub, whilst building other things first. -class FakeDB { - public: - FakeDB() = default; - - /** - * For getting a singleton UTXO (not a set). - * - * NOTICE: this fake db stub is hard-coded to a DefaultPrivateNotePreimage which _itself_ is hard-coded to the value - * type being a field. - * So if you want to test other note types against this stub DB, you'll need to write your own stub DB entry. - */ - static UTXOSLoadDatum> get_utxo_sload_datum( - NT::address const& contract_address, - NT::grumpkin_point const& storage_slot_point, - DefaultPrivateNotePreimage const& advice) - // NT::address const& owner, - // NT::fr required_utxo_tree_root, - // size_t utxo_tree_depth) - { - (void)storage_slot_point; // Not used in this 'fake' implementation. - - DefaultPrivateNotePreimage const preimage{ - .value = 100, - .owner = advice.owner, - .creator_address = 0, - .memo = 3456, - .salt = 1234, - .nonce = 2345, - .is_dummy = false, - }; - - const size_t utxo_tree_depth = 32; - const NT::fr required_utxo_tree_root = 2468; - - std::vector sibling_path(utxo_tree_depth); - std::fill(sibling_path.begin(), sibling_path.end(), 1); // Fill with 1's to be lazy. TODO: return a valid path. - - return { - .commitment = 1, - .contract_address = contract_address, - .preimage = preimage, - - .sibling_path = sibling_path, - .leaf_index = 2, - .historical_note_hash_tree_root = required_utxo_tree_root, - }; - }; - - /** - * For getting a set of UTXOs. - * - * * NOTICE: this fake db stub is hard-coded to a DefaultPrivateNotePreimage which _itself_ is hard-coded to the - * value type being a field. - * So if you want to test other note types against this stub DB, you'll need to write your own stub DB entry. - */ - static std::vector>> get_utxo_sload_data( - NT::address const& contract_address, - NT::grumpkin_point const& storage_slot_point, - size_t const& num_notes, - DefaultPrivateNotePreimage const& advice) - // NT::address const& owner, - // NT::fr required_utxo_tree_root, - // size_t utxo_tree_depth) - { - (void)storage_slot_point; // Not used in this 'fake' implementation. - - std::vector>> data; - - const size_t utxo_tree_depth = 32; - const NT::fr required_utxo_tree_root = 2468; - - std::vector sibling_path(utxo_tree_depth); - std::fill(sibling_path.begin(), sibling_path.end(), 1); // Fill with 1's to be lazy. TODO: return a valid path. - - for (size_t i = 0; i < num_notes; i++) { - DefaultPrivateNotePreimage const preimage{ - .value = 100 + i, - .owner = advice.owner, - .creator_address = 0, - .memo = 3456, - .salt = 1234, - .nonce = 2345, - .is_dummy = false, - }; - - data.push_back({ - .commitment = 1, - .contract_address = contract_address, - .preimage = preimage, - - .sibling_path = sibling_path, - .leaf_index = 2, - .historical_note_hash_tree_root = required_utxo_tree_root, - }); - } - - return data; - }; - - /** - * For getting a singleton UTXO (not a set). - * - * NOTICE: this fake db stub is hard-coded to a DefaultSingletonPrivateNotePreimage which _itself_ is hard-coded to - * the value type being a field. So if you want to test other note types against this stub DB, you'll need to write - * your own stub DB entry. - */ - static UTXOSLoadDatum> get_utxo_sload_datum( - NT::address const& contract_address, - NT::grumpkin_point const& storage_slot_point, - DefaultSingletonPrivateNotePreimage const& advice) - // NT::address const& owner, - // NT::fr required_utxo_tree_root, - // size_t utxo_tree_depth) - { - (void)storage_slot_point; // Not used in this 'fake' implementation. - - DefaultSingletonPrivateNotePreimage const preimage{ - .value = 100, - .owner = advice.owner, - .salt = 1234, - .nonce = 2345, - }; - - const size_t utxo_tree_depth = 32; - const NT::fr required_utxo_tree_root = 2468; - - std::vector sibling_path(utxo_tree_depth); - std::fill(sibling_path.begin(), sibling_path.end(), 1); // Fill with 1's to be lazy. TODO: return a valid path. - - return { - .commitment = 1, - .contract_address = contract_address, - .preimage = preimage, - - .sibling_path = sibling_path, - .leaf_index = 2, - .historical_note_hash_tree_root = required_utxo_tree_root, - }; - }; -}; - -} // namespace aztec3::oracle \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/oracle/oracle.hpp b/circuits/cpp/src/aztec3/oracle/oracle.hpp deleted file mode 100644 index 8744f30f0ec..00000000000 --- a/circuits/cpp/src/aztec3/oracle/oracle.hpp +++ /dev/null @@ -1,150 +0,0 @@ -#pragma once - -#include "fake_db.hpp" - -#include "aztec3/circuits/abis/call_context.hpp" -#include "aztec3/circuits/abis/contract_deployment_data.hpp" -#include "aztec3/circuits/abis/function_data.hpp" -#include "aztec3/circuits/apps/notes/default_singleton_private_note/note_preimage.hpp" -#include "aztec3/circuits/apps/utxo_datum.hpp" -#include "aztec3/utils/types/native_types.hpp" - -namespace aztec3::oracle { - -using aztec3::circuits::abis::CallContext; -using aztec3::circuits::abis::ContractDeploymentData; -using aztec3::circuits::abis::FunctionData; - -using aztec3::circuits::apps::UTXOSLoadDatum; - -using NT = aztec3::utils::types::NativeTypes; - -/// Note: the server will always serve NATIVE types to the circuit, since eventually we'll be passing data to Noir (so -/// won't be handling circuit types at all from the Aztec3 end). -template class NativeOracleInterface { - public: - DB& db; - - NativeOracleInterface(DB& db, - NT::address const& actual_contract_address, - FunctionData const& function_data, - CallContext const& call_context, - std::optional const& msg_sender_private_key = std::nullopt) - : db(db) - , actual_contract_address(actual_contract_address) - , function_data(function_data) - , call_context(call_context) - // , portal_contract_address(portal_contract_address) - , msg_sender_private_key(msg_sender_private_key){}; - - NativeOracleInterface(DB& db, - NT::address const& actual_contract_address, - FunctionData const& function_data, - CallContext const& call_context, - ContractDeploymentData const& contract_deployment_data, - std::optional const& msg_sender_private_key = std::nullopt) - : db(db) - , actual_contract_address(actual_contract_address) - , function_data(function_data) - , call_context(call_context) - , contract_deployment_data(contract_deployment_data) - // , portal_contract_address(portal_contract_address) - , msg_sender_private_key(msg_sender_private_key){}; - - NT::fr get_msg_sender_private_key() - { - if (!msg_sender_private_key) { - throw_or_abort("no private key stored in memory"); - } - if (msg_sender_private_key_already_got) { - throw_or_abort("msg_sender_private_key: " + already_got_error); - } - msg_sender_private_key_already_got = true; - return *msg_sender_private_key; - }; - - // NT::fr get_portal_contract_address() - // { - // if (portal_contract_address_already_got) { - // throw_or_abort(already_got_error); - // } - // portal_contract_address_already_got = true; - // return portal_contract_address; - // }; - - NT::address get_actual_contract_address() { return actual_contract_address; }; - - FunctionData get_function_data() { return function_data; }; - - CallContext get_call_context() - { - if (call_context_already_got) { - throw_or_abort("call_context: " + already_got_error); - } - call_context_already_got = true; - return call_context; - }; - - ContractDeploymentData get_contract_deployment_data() - { - if (contract_deployment_data_already_got) { - throw_or_abort("contract_deployment_data: " + already_got_error); - } - contract_deployment_data_already_got = true; - return contract_deployment_data; - }; - - template - UTXOSLoadDatum get_utxo_sload_datum(NT::grumpkin_point const storage_slot_point, - NotePreimage const advice) - { - // TODO: consider whether it's actually safe to bypass get_call_context() here... - const auto& contract_address = call_context.storage_contract_address; - return db.get_utxo_sload_datum(contract_address, storage_slot_point, advice); - } - - template - std::vector> get_utxo_sload_data(NT::grumpkin_point const storage_slot_point, - size_t const& num_notes, - NotePreimage const advice) - { - // TODO: consider whether it's actually safe to bypass get_call_context() here... - const auto& contract_address = call_context.storage_contract_address; - return db.get_utxo_sload_data(contract_address, storage_slot_point, num_notes, advice); - } - - NT::fr generate_salt() const { return NT::fr::random_element(); } - - NT::fr generate_random_element() const { return NT::fr::random_element(); } - - private: - // We MUST make these values private, so the circuit isn't able to `get` these values more than once (the getter - // functions can check this). This will help us write secure circuits. If we were to query the same thing twice, an - // untrustworthy oracle could give two different pieces of information. As long as this (trusted) oracle catches - // double-queries, we can ensure the circuit we build doesn't query twice. - - // Note: actual_contract_address and function_data are NOT to be provided to the circuit, so don't include - // getter methods for these in the OracleWrapper. - NT::address actual_contract_address; // not to be confused with call_context.storage_contract_address; - FunctionData function_data; - - CallContext call_context; - ContractDeploymentData contract_deployment_data; - // NT::fr portal_contract_address; - std::optional msg_sender_private_key; - - // Ensure functions called only once: - bool actual_contract_address_already_got = false; - bool function_data_already_got = false; - bool call_context_already_got = false; - bool contract_deployment_data_already_got = false; - // bool portal_contract_address_already_got = false; - bool msg_sender_private_key_already_got = false; - std::string already_got_error = - "Your circuit has already accessed this value. Don't ask the oracle twice, since " - "it shouldn't be trusted, and could lead to circuit bugs"; -}; - -using NativeOracle = NativeOracleInterface; - -} // namespace aztec3::oracle \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/utils/CMakeLists.txt b/circuits/cpp/src/aztec3/utils/CMakeLists.txt deleted file mode 100644 index 5bda22d8e8a..00000000000 --- a/circuits/cpp/src/aztec3/utils/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -add_subdirectory(types) - -circuits_cmake_module( - aztec3_utils - barretenberg -) \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/utils/array.hpp b/circuits/cpp/src/aztec3/utils/array.hpp deleted file mode 100644 index 310e89cdbab..00000000000 --- a/circuits/cpp/src/aztec3/utils/array.hpp +++ /dev/null @@ -1,290 +0,0 @@ -#pragma once -#include "./types/native_types.hpp" - -#include "aztec3/utils/circuit_errors.hpp" - -#include - -#include - -/** - * NOTE: see bberg's stdlib/primitives/field/array.hpp for the corresponding circuit implementations of these functions. - */ -namespace aztec3::utils { - -using NT = types::NativeTypes; - -/** - * @brief Helper method to determine if a value is 'empty' based on what empty means for it's type - * @tparam The type of the input value - * @param The value being queried for 'emptiness' - * @return Whether the value is 'empty' - */ -template bool is_empty(T const& value) -{ - if constexpr (std::is_same::value) { - return value == NT::fr(0); - } else { - return value.is_empty(); - } -} - -/** - * @brief Helper method to generate an 'empty' value of a given type - * @tparam The type of the value to return - * @return The empty value - */ -template T empty_value() -{ - if constexpr (std::is_same::value) { - return NT::fr(0); - } else { - return T(); - } -} - -/** - * @brief Helper method to determine the number of non 'empty' items in an array - * @tparam The type of the value stored in the array - * @tparam The size of the array - * @param The array being evaluated for it's length - * @return The number of non-empty items in the array - */ -template size_t array_length(std::array const& arr) -{ - size_t length = 0; - for (const auto& e : arr) { - if (is_empty(e)) { - break; - } - length++; - } - return length; -}; - -/** - * @brief Routine which validates that all zero values of an array form a contiguous region at the end, i.e., - of the form: [*,*,*...,0,0,0,0] where any * is non-zero. Note that a full array of non-zero values is - valid. - * @tparam The type of the values stored in the array. - * @tparam The builder type. - * @tparam The size of the array. - * @param builder The builder which will assert on an array being malformed. - * @param arr The array to validate. - * @param error_message The prefix to the error message set by the caller - */ -template -void validate_array(Builder& builder, std::array const& arr, std::string const& error_message) -{ - size_t first_zero_pos = SIZE; - size_t last_non_zero_pos = 0; - for (size_t i = 0; i < SIZE; i++) { - if (!is_empty(arr[i])) { - last_non_zero_pos = i; - } else if (is_empty(arr[i]) && first_zero_pos == SIZE) { - first_zero_pos = i; - } - } - - builder.do_assert( - last_non_zero_pos <= first_zero_pos, // Only case when equality holds is for a full zeros array. - format( - error_message, - " - array is not well-formed. A non-zero value occurred after a zero. Last position of a non-zero value: ", - last_non_zero_pos, - "; First position of a zero-value: ", - first_zero_pos), - CircuitErrorCode::ARRAY_NOT_ZERO_RIGHT_PADDED); -}; - -/** - * @brief Helper method to return the last non-empty item in an array - * @tparam The type of the value stored in the array - * @tparam The size of the array - * @param The array from which we are to return a value - * @return The returned item - */ -template T array_pop(std::array& arr) -{ - for (size_t i = arr.max_size() - 1; i != static_cast(-1); i--) { - if (!is_empty(arr[i])) { - const auto temp = arr[i]; - arr[i] = empty_value(); - return temp; - } - } - throw_or_abort("array_pop cannot pop from an empty array"); -}; - -/** - * @brief Helper method to push an item into the first empty slot in an array - * @tparam The type of the value stored in the array - * @tparam The builder type - * @tparam The size of the array - * @param The array into which we want to store the value - * @param The value to store - * @param The error message to display if the array is full - */ -template -void array_push(Builder& builder, std::array& arr, T const& value, std::string const& error_message) -{ - for (size_t i = 0; i < arr.size(); ++i) { - if (is_empty(arr[i])) { - arr[i] = value; - return; - } - } - builder.do_assert(false, - format(error_message, " - array_push: capacity exceeded. Limit: ", arr.size()), - CircuitErrorCode::ARRAY_OVERFLOW); -}; - -/** - * @brief Helper method to move all non-zero elements to the left of the array. E.g., [0,7,4,0,5] --> [7,4,5,0,0] - * Remark: The ordering of the non-zero values is preserved. - * - * @tparam The type of the value stored in the array - * @tparam The size of the array - * @param The array into which we want to store the value - */ -template void array_rearrange(std::array& arr) -{ - size_t target_pos = 0; - for (size_t i = 0; i < SIZE; i++) { - if constexpr (std::is_same::value) { - if (arr[i] != NT::fr(0)) { - arr[target_pos] = arr[i]; - target_pos++; - } - } else { - if (!arr[i].is_empty()) { - arr[target_pos] = arr[i]; - target_pos++; - } - } - } - - // Cleaning needed to avoid duplicate values, e.g., [1,0,3,0] --> [1,3,3,0] otherwise. - for (size_t i = target_pos; i < SIZE; i++) { - if constexpr (std::is_same::value) { - arr[i] = NT::fr(0); - } else { - arr[i] = T{}; - } - } -} - -/** - * @brief Helper method to determine if an array contains all 'empty' items - * @tparam The type of the value stored in the array - * @tparam The size of the array - * @param The array to evaluate for non-empty items - */ -template NT::boolean is_array_empty(std::array const& arr) -{ - for (size_t i = 0; i < arr.size(); ++i) { - if (!is_empty(arr[i])) { - return false; - } - } - return true; -}; - -/** - * @brief Inserts the `source` array at the first 'empty' index of the `target` array. - * Ensures that all values after the first 'empty' index are 'empty' too. - * Fails if the `source` array is too large vs the remaining capacity of the `target` array. - * @tparam The size of the `source` array - * @tparam The size of the `target` array - * @tparam The type of the value stored in the arrays - * @param The `source` array - * @param The `target` array - * @param The error message to display if the `source` array is too large - */ -template -void push_array_to_array(Builder& builder, - std::array const& source, - std::array& target, - std::string const& error_message) -{ - // Check if the `source` array is too large vs the remaining capacity of the `target` array - size_t const source_size = array_length(source); - size_t const target_size = array_length(target); - - builder.do_assert(source_size <= size_2 - target_size, - format(error_message, - " - push_array_to_array exceeded capacity. Limit: ", - size_2 - target_size, - " but required size: ", - source_size), - CircuitErrorCode::ARRAY_OVERFLOW); - - // Ensure that there are no non-zero values in the `target` array after the first zero-valued index - for (size_t i = target_size; i < size_2; i++) { - builder.do_assert( - is_empty(target[i]), - format(error_message, " - push_array_to_array inserting into a non empty space at index, ", i), - CircuitErrorCode::ARRAY_OVERFLOW); - } - // Copy the non-zero elements of the `source` array to the `target` array at the first zero-valued index - auto zero_index = target_size; - for (size_t i = 0; i < size_1; i++) { - if (!is_empty(source[i])) { - target[zero_index] = source[i]; - zero_index++; - } - } -} - -/** - * @brief Verifies that the contents of 2 arrays are included within a third - * Ensures that all values after the concatenated values are zero. - * Fails if the `source` arrays combined are too large vs the size of the `target` array. - * @tparam The size of the `source` 1 array - * @tparam The size of the `source` 2 array - * @tparam The size of the `target` array - * @tparam The type of the value stored in the arrays - * @param The first `source` array - * @param The second `source` array - * @param The `target` array - * @return Whether the source arrays are indeed in the target - */ -template -bool source_arrays_are_in_target(Builder& builder, - std::array const& source1, - std::array const& source2, - std::array const& target) -{ - // Check if the `source` arrays are too large vs the size of the `target` array - size_t const source1_size = array_length(source1); - size_t const source2_size = array_length(source2); - builder.do_assert(source1_size + source2_size <= size_3, - "source_arrays_are_in_target: source arrays are too large vs the size of the target", - CircuitErrorCode::ARRAY_OVERFLOW); - - // first ensure that all non-empty items in the first source are in the target - size_t target_index = 0; - for (size_t i = 0; i < source1_size; ++i) { - if (source1[i] != target[target_index]) { - return false; - } - ++target_index; - } - - // now ensure that all non-empty items in the second source are in the target - for (size_t i = 0; i < source2_size; ++i) { - if (source2[i] != target[target_index]) { - return false; - } - ++target_index; - } - - for (; target_index < size_3; ++target_index) { - if (!is_empty(target[target_index])) { - return false; - } - } - return true; -} - -} // namespace aztec3::utils diff --git a/circuits/cpp/src/aztec3/utils/array.test.cpp b/circuits/cpp/src/aztec3/utils/array.test.cpp deleted file mode 100644 index a371e4ce44f..00000000000 --- a/circuits/cpp/src/aztec3/utils/array.test.cpp +++ /dev/null @@ -1,298 +0,0 @@ -#include "array.hpp" - -#include "aztec3/circuits/hash.hpp" -#include "aztec3/utils/dummy_circuit_builder.hpp" - -#include - -#include -#include -#include -#include -#include - -namespace aztec3::utils { - -using fr = NT::fr; - -template -void rearrange_and_check(std::array& input, std::array const& expected, std::string name) -{ - array_rearrange(input); - - for (size_t i = 0; i < N; i++) { - ASSERT_EQ(input[i], expected[i]) << "Mismatch for test vector " << name << " at position " << i; - } -}; - -TEST(hash_tests, noir_l2_l1_interop_hashing) -{ - // This is an annoying hack to convert the field into a hex string - // We should add a to_hex and from_hex method to field class - auto to_hex = [](const NT::fr& value) -> std::string { - std::stringstream field_as_hex_stream; - field_as_hex_stream << value; - return field_as_hex_stream.str(); - }; - - // All zeroes case - auto address = NT::address(0); - auto res = circuits::compute_l2_to_l1_hash(address, fr(0), fr(0), fr(0), fr(0)); - auto res_as_hex = to_hex(res); - ASSERT_EQ(res_as_hex, "0x2266ac2f9f0c19c015239ef5ea85862fc6fac00db73779b220a4d49c4856c2e1"); - - // Non-zero case - address = NT::address(1); - res = circuits::compute_l2_to_l1_hash(address, fr(2), fr(3), fr(4), fr(5)); - res_as_hex = to_hex(res); - ASSERT_EQ(res_as_hex, "0x0f24729168d4450a5681beafa5e3a899ac28bd17bf5a4877dab37bcd834e1634"); - - // Smoke test that sha256_to_field is also the same in Noir - // For an l2_to_l1 hash the maximum size of the buffer that will be sha256'd is 160 bytes - size_t max_buffer_size = 160; - std::vector buffer(max_buffer_size); // Creating a vector of size 160 - for (size_t i = 0; i < 160; ++i) { - buffer[i] = static_cast(i); - } - - res = sha256::sha256_to_field(buffer); - res_as_hex = to_hex(res); - ASSERT_EQ(res_as_hex, "0x142a6d57007171f6eaa33d55976d9dbe739c889c8e920f115f7808dea184c718"); -} - -TEST(utils_array_tests, rearrange_test_vector1) -{ - std::array test_vec{ fr(2), fr(4), fr(0), fr(12), fr(0) }; - std::array const test_vec_rearranged{ fr(2), fr(4), fr(12), fr(0), fr(0) }; - - rearrange_and_check(test_vec, test_vec_rearranged, "1"); -} - -TEST(utils_array_tests, rearrange_test_vector2) -{ - std::array test_vec{ fr(0), fr(99), fr(0), fr(103), fr(0), fr(17) }; - std::array const test_vec_rearranged{ fr(99), fr(103), fr(17), fr(0), fr(0), fr(0) }; - - rearrange_and_check(test_vec, test_vec_rearranged, "2"); -} - -TEST(utils_array_tests, rearrange_test_vector3) -{ - std::array test_vec{ fr(0), fr(0), fr(12), fr(0) }; - std::array const test_vec_rearranged{ fr(12), fr(0), fr(0), fr(0) }; - - rearrange_and_check(test_vec, test_vec_rearranged, "3"); -} - -TEST(utils_array_tests, rearrange_test_vector_identical) -{ - std::array test_vec{ fr(2), fr(4), fr(7), fr(12), fr(9) }; - std::array const test_vec_rearranged{ fr(2), fr(4), fr(7), fr(12), fr(9) }; - - rearrange_and_check(test_vec, test_vec_rearranged, "identical"); -} - -TEST(utils_array_tests, rearrange_test_vector_empty) -{ - std::array test_vec{}; - std::array const test_vec_rearranged{}; - - rearrange_and_check(test_vec, test_vec_rearranged, "empty"); -} - -TEST(utils_array_tests, rearrange_test_vector_all_zeros) -{ - std::array test_vec{ fr(0), fr(0), fr(0), fr(0), fr(0), fr(0), fr(0) }; - std::array const test_vec_rearranged{ fr(0), fr(0), fr(0), fr(0), fr(0), fr(0), fr(0) }; - - rearrange_and_check(test_vec, test_vec_rearranged, "all zeros"); -} - -TEST(utils_array_tests, rearrange_test_vector_long_alternated) -{ - const size_t SIZE = 10000; - std::array test_vec{}; - std::array test_vec_rearranged{}; - - for (size_t i = 0; i < SIZE; i++) { - test_vec[i] = (i % 2 == 0) ? fr(0) : fr(i); - } - - for (size_t i = 0; i < SIZE / 2; i++) { - test_vec_rearranged[i] = fr(2 * i + 1); - } - - for (size_t i = SIZE / 2; i < SIZE; i++) { - test_vec_rearranged[i] = fr(0); - } - - rearrange_and_check(test_vec, test_vec_rearranged, "long alternated"); -} - -TEST(utils_array_tests, rearrange_test_vector_long_zeros_right) -{ - const size_t SIZE = 10000; - std::array test_vec{}; - std::array test_vec_rearranged{}; - - for (size_t i = 0; i < SIZE / 2; i++) { - test_vec[i] = fr(i + 1); - test_vec_rearranged[i] = fr(i + 1); - } - - for (size_t i = SIZE / 2; i < SIZE; i++) { - test_vec[i] = fr(0); - test_vec_rearranged[i] = fr(0); - } - - rearrange_and_check(test_vec, test_vec_rearranged, "long zeros right"); -} - -TEST(utils_array_tests, rearrange_test_vector_long_zeros_left) -{ - const size_t SIZE = 10000; - std::array test_vec{}; - std::array test_vec_rearranged{}; - - for (size_t i = 0; i < SIZE / 2; i++) { - test_vec[i] = fr(0); - test_vec_rearranged[i] = fr(i + 1); - } - - for (size_t i = SIZE / 2; i < SIZE; i++) { - test_vec[i] = fr(i - SIZE / 2 + 1); - test_vec_rearranged[i] = fr(0); - } - - rearrange_and_check(test_vec, test_vec_rearranged, "long zeros left"); -} - -TEST(utils_array_validation, test_vector_all_zeros) -{ - const size_t SIZE = 64; - std::array test_vec{}; - DummyCircuitBuilder dummyBuilder("Builder for array validation test vectors"); - validate_array(dummyBuilder, test_vec, "Test vector with all zeros"); - - EXPECT_FALSE(dummyBuilder.failed()) << dummyBuilder.get_first_failure(); -} - -TEST(utils_array_validation, test_vector_all_non_zeros) -{ - const size_t SIZE = 64; - std::array test_vec; - unsigned int gen = 4127; - for (size_t i = 0; i < SIZE; i++) { - test_vec[i] = fr(gen); - gen = 761 * gen % 5619; - } - - DummyCircuitBuilder dummyBuilder("Builder for array validation test vectors"); - validate_array(dummyBuilder, test_vec, "Test vector with all non zeros"); - - EXPECT_FALSE(dummyBuilder.failed()) << dummyBuilder.get_first_failure(); -} - -TEST(utils_array_validation, test_vector_valid_one_zero) -{ - const size_t SIZE = 110; - std::array test_vec{}; - unsigned int gen = 4159; - for (size_t i = 0; i < SIZE - 1; i++) { - test_vec[i] = fr(gen); - gen = 71 * gen % 2613; - } - - DummyCircuitBuilder dummyBuilder("Builder for array validation test vectors"); - validate_array(dummyBuilder, test_vec, "Test vector with a single zero at the end"); - - EXPECT_FALSE(dummyBuilder.failed()) << dummyBuilder.get_first_failure(); -} - -TEST(utils_array_validation, test_vector_valid_one_non_zero) -{ - const size_t SIZE = 110; - std::array test_vec{}; - test_vec[0] = fr(124); - DummyCircuitBuilder dummyBuilder("Builder for array validation test vectors"); - validate_array(dummyBuilder, test_vec, "Test vector with a single non-zero at the beginning"); - - EXPECT_FALSE(dummyBuilder.failed()) << dummyBuilder.get_first_failure(); -} - -TEST(utils_array_validation, test_vector_invalid_one_zero_middle) -{ - const size_t SIZE = 128; - std::array test_vec{}; - unsigned int gen = 354; - for (size_t i = 0; i < SIZE; i++) { - test_vec[i] = fr(gen); - gen = 319 * gen % 2213; - } - test_vec[67] = fr(0); - DummyCircuitBuilder dummyBuilder("Builder for array validation test vectors"); - validate_array(dummyBuilder, test_vec, "Test vector with a single zero in the middle"); - - EXPECT_TRUE(dummyBuilder.failed()); -} - -TEST(utils_array_validation, test_vector_invalid_one_zero_beginning) -{ - const size_t SIZE = 128; - std::array test_vec{}; - unsigned int gen = 447; - for (size_t i = 0; i < SIZE; i++) { - test_vec[i] = fr(gen); - gen = 39 * gen % 12313; - } - test_vec[0] = fr(0); - DummyCircuitBuilder dummyBuilder("Builder for array validation test vectors"); - validate_array(dummyBuilder, test_vec, "Test vector with a single zero at the beginning"); - - EXPECT_TRUE(dummyBuilder.failed()); -} - -TEST(utils_array_validation, test_vector_invalid_zero_both_ends) -{ - const size_t SIZE = 128; - std::array test_vec{}; - unsigned int gen = 47; - for (size_t i = 0; i < SIZE; i++) { - test_vec[i] = fr(gen); - gen = 6439 * gen % 82313; - } - test_vec[0] = fr(0); - test_vec[SIZE - 1] = fr(0); - DummyCircuitBuilder dummyBuilder("Builder for array validation test vectors"); - validate_array(dummyBuilder, test_vec, "Test vector with a zero at each end"); - - EXPECT_TRUE(dummyBuilder.failed()); -} - -TEST(utils_array_validation, test_vector_invalid_non_zero_last) -{ - const size_t SIZE = 203; - std::array test_vec{}; - test_vec[SIZE - 1] = fr(785); - DummyCircuitBuilder dummyBuilder("Builder for array validation test vectors"); - validate_array(dummyBuilder, test_vec, "Test vector with a non-zero at the end"); - - EXPECT_TRUE(dummyBuilder.failed()); -} - -TEST(utils_array_validation, test_vector_invalid_alternate) -{ - const size_t SIZE = 203; - std::array test_vec{}; - unsigned int gen = 83; - for (size_t i = 0; i < SIZE; i += 2) { - test_vec[i] = fr(gen); - gen = 2437 * gen % 2314; - } - DummyCircuitBuilder dummyBuilder("Builder for array validation test vectors"); - validate_array(dummyBuilder, test_vec, "Test vector with alternating zero and non-zero values."); - - EXPECT_TRUE(dummyBuilder.failed()); -} - -} // namespace aztec3::utils \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/utils/circuit_errors.hpp b/circuits/cpp/src/aztec3/utils/circuit_errors.hpp deleted file mode 100644 index 5fa0213d178..00000000000 --- a/circuits/cpp/src/aztec3/utils/circuit_errors.hpp +++ /dev/null @@ -1,125 +0,0 @@ -#pragma once - -#include - -#include - -namespace aztec3::utils { - -enum CircuitErrorCode : uint16_t { - NO_ERROR = 0, - UNINITIALIZED_RESULT = 1, // Default for CircuitResult - // Private kernel related errors - PRIVATE_KERNEL_CIRCUIT_FAILED = 2000, - PRIVATE_KERNEL__INVALID_CONSTRUCTOR_VK_HASH = 2001, - PRIVATE_KERNEL__INVALID_CONTRACT_ADDRESS = 2002, - PRIVATE_KERNEL__PURPORTED_CONTRACT_TREE_ROOT_AND_PREVIOUS_KERNEL_CONTRACT_TREE_ROOT_MISMATCH = 2003, - PRIVATE_KERNEL__COMPUTED_CONTRACT_TREE_ROOT_AND_PURPORTED_CONTRACT_TREE_ROOT_MISMATCH = 2004, - PRIVATE_KERNEL__NEW_COMMITMENTS_PROHIBITED_IN_STATIC_CALL = 2005, - PRIVATE_KERNEL__NEW_NULLIFIERS_PROHIBITED_IN_STATIC_CALL = 2006, - PRIVATE_KERNEL__CALCULATED_PRIVATE_CALL_HASH_AND_PROVIDED_PRIVATE_CALL_HASH_MISMATCH = 2007, - PRIVATE_KERNEL__PRIVATE_CALL_STACK_ITEM_HASH_MISMATCH = 2008, - PRIVATE_KERNEL__NON_PRIVATE_FUNCTION_EXECUTED_WITH_PRIVATE_KERNEL = 2009, - PRIVATE_KERNEL__MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL_MISMATCH = 2010, - PRIVATE_KERNEL__UNSUPPORTED_OP = 2011, - PRIVATE_KERNEL__CONTRACT_ADDRESS_MISMATCH = 2012, - PRIVATE_KERNEL__NON_PRIVATE_KERNEL_VERIFIED_WITH_PRIVATE_KERNEL = 2013, - PRIVATE_KERNEL__CONSTRUCTOR_EXECUTED_IN_RECURSION = 2014, - PRIVATE_KERNEL__PRIVATE_CALL_STACK_EMPTY = 2015, - PRIVATE_KERNEL__KERNEL_PROOF_CONTAINS_RECURSIVE_PROOF = 2016, - PRIVATE_KERNEL__USER_INTENT_MISMATCH_BETWEEN_TX_REQUEST_AND_CALL_STACK_ITEM = 2017, - PRIVATE_KERNEL__READ_REQUEST_NOTE_HASH_TREE_ROOT_MISMATCH = 2018, - PRIVATE_KERNEL__TRANSIENT_READ_REQUEST_NO_MATCH = 2019, - PRIVATE_KERNEL__READ_REQUEST_WITNESSES_ARRAY_LENGTH_MISMATCH = 2020, - PRIVATE_KERNEL__UNRESOLVED_NON_TRANSIENT_READ_REQUEST = 2021, - PRIVATE_KERNEL__IS_INTERNAL_BUT_NOT_SELF_CALL = 2022, - PRIVATE_KERNEL__TRANSIENT_NEW_NULLIFIER_NO_MATCH = 2023, - PRIVATE_KERNEL__0TH_NULLIFIER_IS_ZERO = 2024, - - // Public kernel related errors - PUBLIC_KERNEL_CIRCUIT_FAILED = 3000, - PUBLIC_KERNEL__UNSUPPORTED_OP = 3001, - PUBLIC_KERNEL__PRIVATE_FUNCTION_NOT_ALLOWED = 3002, - PUBLIC_KERNEL__CONTRACT_ADDRESS_MISMATCH = 3003, - PUBLIC_KERNEL__EMPTY_PUBLIC_CALL_STACK = 3004, - PUBLIC_KERNEL__NON_EMPTY_PRIVATE_CALL_STACK = 3005, - PUBLIC_KERNEL__PREVIOUS_KERNEL_NOT_PRIVATE = 3009, - PUBLIC_KERNEL__PREVIOUS_KERNEL_NOT_PUBLIC = 3010, - PUBLIC_KERNEL__CALCULATED_PUBLIC_CALL_HASH_AND_PROVIDED_PUBLIC_CALL_HASH_MISMATCH = 3011, - PUBLIC_KERNEL__PUBLIC_CALL_STACK_MISMATCH = 3012, - PUBLIC_KERNEL__CONTRACT_DEPLOYMENT_NOT_ALLOWED = 3013, - PUBLIC_KERNEL__CONSTRUCTOR_NOT_ALLOWED = 3014, - PUBLIC_KERNEL__CONTRACT_ADDRESS_INVALID = 3015, - PUBLIC_KERNEL__FUNCTION_SIGNATURE_INVALID = 3016, - PUBLIC_KERNEL__BYTECODE_HASH_INVALID = 3017, - PUBLIC_KERNEL__CALL_CONTEXT_INVALID = 3018, - PUBLIC_KERNEL__DELEGATE_CALL_PROHIBITED_BY_USER = 3019, - PUBLIC_KERNEL__STATIC_CALL_PROHIBITED_BY_USER = 3019, - PUBLIC_KERNEL__PUBLIC_CALL_STACK_INVALID_MSG_SENDER = 3020, - PUBLIC_KERNEL__PUBLIC_CALL_STACK_INVALID_STORAGE_ADDRESS = 3021, - PUBLIC_KERNEL__PUBLIC_CALL_STACK_INVALID_PORTAL_ADDRESS = 3022, - PUBLIC_KERNEL__PUBLIC_CALL_STACK_CONTRACT_STORAGE_UPDATES_PROHIBITED_FOR_STATIC_CALL = 3022, - PUBLIC_KERNEL__CALL_CONTEXT_INVALID_STORAGE_ADDRESS_FOR_DELEGATE_CALL = 3023, - PUBLIC_KERNEL__CALL_CONTEXT_CONTRACT_STORAGE_UPDATE_REQUESTS_PROHIBITED_FOR_STATIC_CALL = 3024, - PUBLIC_KERNEL__NEW_NULLIFIERS_NOT_EMPTY_IN_FIRST_ITERATION = 3025, - PUBLIC_KERNEL__NEW_COMMITMENTS_PROHIBITED_IN_STATIC_CALL = 3026, - PUBLIC_KERNEL__NEW_NULLIFIERS_PROHIBITED_IN_STATIC_CALL = 3027, - PUBLIC_KERNEL__IS_INTERNAL_BUT_NOT_SELF_CALL = 3028, - - BASE__CIRCUIT_FAILED = 4000, - BASE__KERNEL_PROOF_VERIFICATION_FAILED = 4001, - BASE__INCORRECT_NUM_OF_NEW_COMMITMENTS = 4002, - BASE__INVALID_NULLIFIER_SUBTREE = 4003, - BASE__INVALID_NULLIFIER_RANGE = 4004, - BASE__INVALID_PUBLIC_DATA_READS = 4005, - BASE__INVALID_PUBLIC_DATA_UPDATE_REQUESTS = 4006, - BASE__INVALID_CHAIN_ID = 4007, - BASE__INVALID_VERSION = 4008, - BASE__INVALID_BLOCK_HASH = 4009, - - MERGE_CIRCUIT_FAILED = 6000, - - // Component errors (used by all circuits) - ROLLUP_TYPE_MISMATCH = 7001, - ROLLUP_HEIGHT_MISMATCH = 7002, - CONSTANTS_MISMATCH = 7003, - NOTE_HASH_TREE_SNAPSHOT_MISMATCH = 7004, - NULLIFIER_TREE_SNAPSHOT_MISMATCH = 7005, - CONTRACT_TREE_SNAPSHOT_MISMATCH = 7006, - PUBLIC_DATA_TREE_ROOT_MISMATCH = 7007, - MEMBERSHIP_CHECK_FAILED = 7008, - ARRAY_OVERFLOW = 7009, - ARRAY_NOT_ZERO_RIGHT_PADDED = 7010, - - ROOT_CIRCUIT_FAILED = 8000, - -}; - -struct CircuitError { - // using int for easy serialization - uint16_t code = CircuitErrorCode::NO_ERROR; - std::string message; - - // for serialization, update with new fields - MSGPACK_FIELDS(code, message); - static CircuitError no_error() { return { CircuitErrorCode::NO_ERROR, "" }; } - - bool operator==(CircuitError const& other) const { return code == other.code && message == other.message; } -}; - -// Define CircuitResult as a std::variant T + error union type -// We do not use std::variant directly as we need default-constructible types for msgpack -template struct CircuitResult { - CircuitResult() : result(CircuitError{ UNINITIALIZED_RESULT, "" }) {} - explicit CircuitResult(const T& value) : result(value) {} - explicit CircuitResult(const CircuitError& value) : result(value) {} - std::variant result; - - // for serialization: delegate to msgpack std::variant support - void msgpack_pack(auto& packer) const { packer.pack(result); } - void msgpack_unpack(auto obj) { result = obj; } - // for schema serialization: delegate to msgpack std::variant support - void msgpack_schema(auto& packer) const { packer.pack_schema(result); } -}; - -} // namespace aztec3::utils diff --git a/circuits/cpp/src/aztec3/utils/dummy_circuit_builder.hpp b/circuits/cpp/src/aztec3/utils/dummy_circuit_builder.hpp deleted file mode 100644 index 95d637f1b04..00000000000 --- a/circuits/cpp/src/aztec3/utils/dummy_circuit_builder.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once -#include "aztec3/utils/circuit_errors.hpp" - -#include -#include -#include -#include -#include - -namespace aztec3::utils { - -class DummyCircuitBuilder { - public: - std::vector failure_msgs; - // method that created this builder instance. Useful for logging. - std::string method_name; - - explicit DummyCircuitBuilder(std::string method_name) : method_name(std::move(method_name)) {} - - void do_assert(bool const& assertion, std::string const& msg, CircuitErrorCode error_code) - { - if (!assertion) { -#ifdef __wasm__ - info("Error(", error_code, "): ", msg); -#endif - failure_msgs.push_back(CircuitError{ error_code, msg }); - } - } - - [[nodiscard]] bool failed() const { return !failure_msgs.empty(); } - - CircuitError get_first_failure() - { - if (failed()) { - return failure_msgs[0]; - } - return CircuitError::no_error(); - } - - /** - * Returns 'value' as a CircuitResult, unless there was an error. - * If there was an error, return it instead. - * @tparam T the value type. - * @param value the value. - * @return the value, or last error if it exists. - */ - template CircuitResult result_or_error(const T& value) - { - CircuitError const failure = get_first_failure(); - if (failure.code != CircuitErrorCode::NO_ERROR) { - return CircuitResult{ failure }; - } - return CircuitResult{ value }; - } - - uint8_t* alloc_and_serialize_first_failure() - { - CircuitError const failure = get_first_failure(); - if (failure.code == CircuitErrorCode::NO_ERROR) { - return nullptr; - } - info(this->method_name, ": builder.get_first_failure() = ", failure_msgs[0]); - - - // serialize circuit failure to bytes vec - std::vector circuit_failure_vec; - serialize::write(circuit_failure_vec, failure); - - // copy to output buffer - auto* raw_failure_buf = static_cast(malloc(circuit_failure_vec.size())); - memcpy(raw_failure_buf, (void*)circuit_failure_vec.data(), circuit_failure_vec.size()); - return raw_failure_buf; - } -}; - -} // namespace aztec3::utils diff --git a/circuits/cpp/src/aztec3/utils/msgpack_derived_equals.hpp b/circuits/cpp/src/aztec3/utils/msgpack_derived_equals.hpp deleted file mode 100644 index 9d1fda1f6a2..00000000000 --- a/circuits/cpp/src/aztec3/utils/msgpack_derived_equals.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#include - -namespace aztec3::utils { -// Auxiliary function for comparison of elements from tuples -template -auto _compare_msgpack_tuples(const Tuple1& t1, const Tuple2& t2, std::index_sequence) // NOLINT -{ - // Compare every 2nd value from our key1, value1, key2, value2 list - return ((std::get(t1) == std::get(t2)) && ...); -} - -// Function to check equality of msgpack objects based on their values. -// Normally, you should instead use operator==() = default; -// BoolLike represents a type like the boolean DSL type -template BoolLike msgpack_derived_equals(const T& obj1, const T& obj2) -{ - BoolLike are_equal; - // De-serialize objects to alternating key-value tuples and compare the values - const_cast(obj1).msgpack([&](auto&... args1) { // NOLINT - const_cast(obj2).msgpack([&](auto&... args2) { // NOLINT - auto tuple1 = std::tie(args1...); - auto tuple2 = std::tie(args2...); - are_equal = _compare_msgpack_tuples(tuple1, tuple2, std::make_index_sequence{}); - }); - }); - return are_equal; -} -} // namespace aztec3::utils diff --git a/circuits/cpp/src/aztec3/utils/msgpack_derived_output.hpp b/circuits/cpp/src/aztec3/utils/msgpack_derived_output.hpp deleted file mode 100644 index b134651e923..00000000000 --- a/circuits/cpp/src/aztec3/utils/msgpack_derived_output.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include - -#include -#include - -namespace aztec3::utils { - -template std::ostream& msgpack_derived_output(std::ostream& os, const T& value); - -inline void _msgpack_derived_output_helper(std::ostream& os) -{ - // base case - (void)os; // unused -} -inline void _msgpack_derived_output_helper(std::ostream& os, - const std::string& key, - const auto& value, - const auto&... rest) -{ - os << key << ": "; - msgpack_derived_output(os, value); - os << '\n'; - _msgpack_derived_output_helper(os, rest...); // NOLINT -} -// Specialization if we have msgpack -template void msgpack_derived_output(std::ostream& os, const T& value) -{ - const_cast(value).msgpack([&](auto&... args) { _msgpack_derived_output_helper(os, args...); }); // NOLINT -} - -// Otherwise -template std::ostream& msgpack_derived_output(std::ostream& os, const T& value) -{ - return os << value; -} -} // namespace aztec3::utils diff --git a/circuits/cpp/src/aztec3/utils/types/CMakeLists.txt b/circuits/cpp/src/aztec3/utils/types/CMakeLists.txt deleted file mode 100644 index 0e089a172fe..00000000000 --- a/circuits/cpp/src/aztec3/utils/types/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -circuits_cmake_module( - aztec3_types - barretenberg -) \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/utils/types/circuit_types.hpp b/circuits/cpp/src/aztec3/utils/types/circuit_types.hpp deleted file mode 100644 index e9bc1fc610e..00000000000 --- a/circuits/cpp/src/aztec3/utils/types/circuit_types.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#pragma once - -// TODO(dbanks12) consider removing this include which is used by consumers of circuit_types.hpp - -#include "aztec3/constants.hpp" - -#include - -using namespace proof_system::plonk; - -// Note: Inner proving system type for recursion is inflexibly set to UltraPlonk. -namespace aztec3::utils::types { - -template struct CircuitTypes { - // Basic uint types - using boolean = plonk::stdlib::bool_t; - using uint8 = plonk::stdlib::uint8; - using uint16 = plonk::stdlib::uint16; - using uint32 = plonk::stdlib::uint32; - using uint64 = plonk::stdlib::uint64; - - // Types related to the bn254 curve - using fr = plonk::stdlib::field_t; - using safe_fr = plonk::stdlib::safe_uint_t; - using address = plonk::stdlib::address_t; - using fq = plonk::stdlib::bigfield; - - using witness = plonk::stdlib::witness_t; - - // typedef fq grumpkin_fr; - // typedef fr grumpkin_fq; - using grumpkin_point = plonk::stdlib::cycle_group; // affine - - using bn254 = plonk::stdlib::bn254; - // typedef bn254::g1_ct bn254_point; - using bn254_point = plonk::stdlib::element; // affine - - using bit_array = plonk::stdlib::bit_array; - using byte_array = plonk::stdlib::byte_array; - using packed_byte_array = plonk::stdlib::packed_byte_array; - - using schnorr_signature = plonk::stdlib::schnorr::signature_bits; - using ecdsa_signature = plonk::stdlib::ecdsa::signature; - - using AggregationObject = plonk::stdlib::recursion::aggregation_state; - using VK = plonk::stdlib::recursion::verification_key; - // Notice: no CircuitType for a Proof: we only ever handle native; the verify_proof() function swallows the - // 'circuit-type-ness' of the proof. - - static crypto::GeneratorContext get_generator_context(const size_t hash_index) - { - crypto::GeneratorContext result; - result.offset = hash_index; - return result; - } - - /// TODO: lots of these compress / commit functions aren't actually used: remove them. - - // Define the 'circuit' version of the function `hash`, with the name `hash`: - static fr hash(std::vector const& inputs, const size_t hash_index = 0) - { - return plonk::stdlib::pedersen_hash::hash(inputs, get_generator_context(hash_index)); - } - - - static fr hash(std::vector const& inputs, - std::vector const& hash_sub_indices, - const size_t hash_index = 0) - { - return plonk::stdlib::pedersen_hash::hash(inputs, hash_sub_indices, get_generator_context(hash_index)); - } - - /** - * @brief Compute the hash for a pair of left and right nodes in a merkle tree. - * - * @details Compress the two nodes using the default/0-generator which is reserved - * for internal merkle hashing. - * - * @param left The left child node - * @param right The right child node - * @return The computed Merkle tree hash for the given pair of nodes - */ - static fr merkle_hash(fr left, fr right) - { - // use 0-generator for internal merkle hashing - return plonk::stdlib::pedersen_hash::hash({ left, right }, 0); - }; - - static grumpkin_point commit(const std::vector& inputs, const size_t hash_index = 0) - { - return plonk::stdlib::pedersen_commitment::commit(inputs, get_generator_context(hash_index)); - }; - - static byte_array blake2s(const byte_array& input) { return plonk::stdlib::blake2s(input); } -}; - -} // namespace aztec3::utils::types diff --git a/circuits/cpp/src/aztec3/utils/types/convert.hpp b/circuits/cpp/src/aztec3/utils/types/convert.hpp deleted file mode 100644 index cf127a78125..00000000000 --- a/circuits/cpp/src/aztec3/utils/types/convert.hpp +++ /dev/null @@ -1,278 +0,0 @@ -#pragma once - -#include "circuit_types.hpp" -#include "native_types.hpp" - -#include - -#include - -namespace aztec3::utils::types { - -using plonk::stdlib::witness_t; - -namespace { - -template using CT = aztec3::utils::types::CircuitTypes; -using NT = aztec3::utils::types::NativeTypes; - -} // namespace - -/// TODO: Lots of identical functions here (but for their in/out types). Can we use templates? I couldn't figure out how -/// to keep the NT:: or CT:: prefixes with templates. -template typename CT::boolean to_ct(Builder& builder, typename NT::boolean const& e) -{ - return typename CT::boolean(witness_t(&builder, e)); -}; - -template typename CT::fr to_ct(Builder& builder, typename NT::fr const& e) -{ - return typename CT::fr(witness_t(&builder, e)); -}; - -template typename CT::fq to_ct(Builder& builder, typename NT::fq const& e) -{ - return typename CT::fq(witness_t(&builder, e)); -}; - -template typename CT::address to_ct(Builder& builder, typename NT::address const& e) -{ - return typename CT::address(witness_t(&builder, e)); -}; - -template typename CT::uint32 to_ct(Builder& builder, typename NT::uint32 const& e) -{ - return typename CT::uint32(witness_t(&builder, e)); -}; - -template -typename CT::grumpkin_point to_ct(Builder& builder, typename NT::grumpkin_point const& e) -{ - return plonk::stdlib::cycle_group::from_witness(builder, e); -}; - -template typename CT::bn254_point to_ct(Builder& builder, typename NT::bn254_point const& e) -{ - return CT::bn254_point::from_witness(&builder, e); -}; - -template -typename CT::ecdsa_signature to_ct(Builder& builder, typename NT::ecdsa_signature const& e) -{ - return CT::ecdsa_signature::template from_witness(&builder, e); -}; - -template -std::optional::boolean> to_ct(Builder& builder, std::optional const& e) -{ - return e ? std::make_optional::boolean>(to_ct(builder, *e)) : std::nullopt; -}; - -template -std::optional::fr> to_ct(Builder& builder, std::optional const& e) -{ - return e ? std::make_optional::fr>(to_ct(builder, *e)) : std::nullopt; -}; - -template -std::optional::address> to_ct(Builder& builder, std::optional const& e) -{ - return e ? std::make_optional::address>(to_ct(builder, *e)) : std::nullopt; -}; - -template -std::optional::grumpkin_point> to_ct(Builder& builder, - std::optional const& e) -{ - return e ? std::make_optional::grumpkin_point>(to_ct(builder, *e)) : std::nullopt; -}; - -template -std::optional::ecdsa_signature> to_ct(Builder& builder, - std::optional const& e) -{ - return e ? std::make_optional::ecdsa_signature>(to_ct(&builder, e)) : std::nullopt; -}; - -template -std::vector::fr> to_ct(Builder& builder, std::vector const& vec) -{ - auto ref_to_ct = [&](typename NT::fr const& e) { return to_ct(builder, e); }; - - return map(vec, ref_to_ct); -}; - -template -std::optional::fr>> to_ct(Builder& builder, - std::optional> const& vec) -{ - auto ref_to_ct = [&](typename NT::fr const& e) { return to_ct(builder, e); }; - - return vec ? std::make_optional::fr>>(map(*vec, ref_to_ct)) : std::nullopt; -}; - -template -std::array::fr, SIZE> to_ct(Builder& builder, std::array const& arr) -{ - auto ref_to_ct = [&](typename NT::fr const& e) { return to_ct(builder, e); }; - - return map(arr, ref_to_ct); -}; - - -template std::array::fr>, SIZE> to_ct( - Builder& builder, std::array, SIZE> const& arr) -{ - auto ref_to_ct = [&](std::optional const& e) { return to_ct(builder, e); }; - - return map(arr, ref_to_ct); -}; - -/** - * @brief Convert from an array of any native types (NT_TYPE) to array of circuit types (CT_TYPE) - */ -template -std::array to_ct(Builder& builder, std::array const& arr) -{ - auto ref_to_ct = [&](NT_TYPE const& e) { return e.to_circuit_type(builder); }; - - return map(arr, ref_to_ct); -}; - -/** - * @brief Convert from an array of any native types (NT_TYPE) to array of circuit types (CT_TYPE). - * Allow array entries to be optional. - */ -template -std::array, SIZE> to_ct(Builder& builder, std::array, SIZE> const& arr) -{ - auto ref_to_ct = [&](std::optional const& e) { return e.to_circuit_type(builder); }; - - return map(arr, ref_to_ct); -}; - -// to_nt() below ******************************** - -template typename NT::boolean to_nt(typename CT::boolean const& e) -{ - return e.get_value(); -}; - -template typename NT::fr to_nt(typename CT::fr const& e) -{ - return e.get_value(); -}; - -template typename NT::fq to_nt(typename CT::fq const& e) -{ - return e.get_value(); -}; - -template typename NT::address to_nt(typename CT::address const& e) -{ - return NT::address(e.address_.get_value()); // TODO: add get_value() method to address types. -}; - -template typename NT::uint32 to_nt(typename CT::uint32 const& e) -{ - NT::uint256 const e_256 = e.get_value(); - NT::uint64 const e_64 = e_256.data[0]; // TODO: check that this endianness is correct! - auto const e_32 = static_cast(e_64); - return e_32; -}; - -template typename NT::grumpkin_point to_nt(typename CT::grumpkin_point const& e) -{ - return NT::grumpkin_point{ e.x.get_value(), e.y.get_value() }; -}; - -template typename NT::bn254_point to_nt(typename CT::bn254_point const& e) -{ - return e.get_value(); -}; - -template typename NT::ecdsa_signature to_nt(typename CT::ecdsa_signature const& e) -{ - std::vector r_bytes = e.r.get_value(); - std::vector s_bytes = e.s.get_value(); - const uint8_t v_byte = e.v.get_value(); - - std::array r_array; - std::array s_array; - std::copy(r_bytes.begin(), r_bytes.end(), r_array.begin()); - std::copy(s_bytes.begin(), s_bytes.end(), s_array.begin()); - - return NT::ecdsa_signature{ r_array, s_array, v_byte }; -}; - -template -std::optional to_nt(std::optional::boolean> const& e) -{ - return e ? std::make_optional(to_nt(*e)) : std::nullopt; -}; - -template std::optional to_nt(std::optional::fr> const& e) -{ - return e ? std::make_optional(to_nt(*e)) : std::nullopt; -}; - -template -std::optional to_nt(std::optional::address> const& e) -{ - return e ? std::make_optional(to_nt(*e)) : std::nullopt; -}; - -template -std::optional to_nt(std::optional::grumpkin_point> const& e) -{ - return e ? std::make_optional(to_nt(*e)) : std::nullopt; -}; - -template -std::optional to_nt(std::optional::ecdsa_signature> const& e) -{ - return e ? std::make_optional(to_nt(*e)) : std::nullopt; -}; - -template std::vector to_nt(std::vector::fr> const& vec) -{ - auto ref_to_nt = [&](typename CT::fr const& e) { return to_nt(e); }; - - return map(vec, ref_to_nt); -}; - -template -std::optional> to_nt(std::optional::fr>> const& vec) -{ - auto ref_to_nt = [&](typename CT::fr const& e) { return to_nt(e); }; - - return vec ? std::make_optional>(map(*vec, ref_to_nt)) : std::nullopt; -}; - -template -std::array to_nt(std::array::fr, SIZE> const& arr) -{ - auto ref_to_nt = [&](typename CT::fr const& e) { return to_nt(e); }; - - return map(arr, ref_to_nt); -}; - -// template -// std::optional> to_nt( -// std::optional::fr, SIZE>> const& arr) -// { -// auto ref_to_nt = [&](typename CT::fr const& e) { return to_nt(e); }; - -// return arr ? std::make_optional>(map(arr, ref_to_nt)) : std::nullopt; -// }; - -template std::array, SIZE> to_nt( - std::array::fr>, SIZE> const& arr) -{ - auto ref_to_nt = [&](std::optional::fr> const& e) { return to_nt(e); }; - - return map(arr, ref_to_nt); -}; - - -} // namespace aztec3::utils::types diff --git a/circuits/cpp/src/aztec3/utils/types/native_types.hpp b/circuits/cpp/src/aztec3/utils/types/native_types.hpp deleted file mode 100644 index fb2ba5788bd..00000000000 --- a/circuits/cpp/src/aztec3/utils/types/native_types.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once -#include "aztec3/constants.hpp" - -#include -namespace aztec3::utils::types { - -struct NativeTypes { - using boolean = bool; - - using uint8 = uint8_t; - using uint16 = uint16_t; - using uint32 = uint32_t; - using uint64 = uint64_t; - using uint256 = uint256_t; - - using fr = barretenberg::fr; - using address = proof_system::plonk::stdlib::address; - - using fq = barretenberg::fq; - - // typedef fq grumpkin_fr; - // typedef fr grumpkin_fq; - using grumpkin_point = grumpkin::g1::affine_element; - // typedef grumpkin::g1::element grumpkin_jac_point; - - using bn254_point = barretenberg::g1::affine_element; - // typedef barretenberg::g1::element bn254_jac_point; - // typedef barretenberg::g1 bn254_group; - - using bit_array = std::vector; - using byte_array = std::vector; - using packed_byte_array = std::string; - - using schnorr_signature = crypto::schnorr::signature; - using ecdsa_signature = crypto::ecdsa::signature; - - using AggregationObject = proof_system::plonk::stdlib::recursion::native_aggregation_state; - using VKData = plonk::verification_key_data; - using VK = plonk::verification_key; - using Proof = plonk::proof; - - static crypto::GeneratorContext get_generator_context(const size_t hash_index) - { - crypto::GeneratorContext result; - result.offset = hash_index; - return result; - } - - // Define the 'native' version of the function `hash`, with the name `hash`: - static fr hash(const std::vector& inputs, const size_t hash_index = 0) - { - return crypto::pedersen_hash::hash(inputs, get_generator_context(hash_index)); - } - - /** - * @brief Compute the hash for a pair of left and right nodes in a merkle tree. - * - * @details Compress the two nodes using the default/0-generator which is reserved - * for internal merkle hashing. - * - * @param left The left child node - * @param right The right child node - * @return The computed Merkle tree hash for the given pair of nodes - */ - static fr merkle_hash(fr left, fr right) - { - // use 0-generator for internal merkle hashing - // use lookup namespace since we now use ultraplonk - return crypto::pedersen_hash::hash({ left, right }, 0); - } - - static grumpkin_point commit(const std::vector& inputs, const size_t hash_index = 0) - { - return crypto::pedersen_commitment::commit_native(inputs, get_generator_context(hash_index)); - } - - static byte_array blake2s(const byte_array& input) - { - auto res = blake2::blake2s(input); - return byte_array(res.begin(), res.end()); - } - - static byte_array blake3s(const byte_array& input) { return blake3::blake3s(input); } -}; - -} // namespace aztec3::utils::types \ No newline at end of file diff --git a/circuits/cpp/srs_db b/circuits/cpp/srs_db deleted file mode 120000 index 003731dd615..00000000000 --- a/circuits/cpp/srs_db +++ /dev/null @@ -1 +0,0 @@ -barretenberg/cpp/srs_db \ No newline at end of file diff --git a/docs/.dockerignore b/docs/.dockerignore index e9573dbf7ff..b5f7883caaf 100644 --- a/docs/.dockerignore +++ b/docs/.dockerignore @@ -10,9 +10,6 @@ build/ Debug/ Release/ -circuits/cpp/build/ -circuits/cpp/build-wasm/ -circuits/cpp/build-coverage/ barretenberg/ # Ignore Node.js build artifacts diff --git a/docs/Dockerfile.dockerignore b/docs/Dockerfile.dockerignore index ab13fbd2925..cedb373cab3 100644 --- a/docs/Dockerfile.dockerignore +++ b/docs/Dockerfile.dockerignore @@ -7,7 +7,6 @@ docs/node_modules !l1-contracts/src !l1-contracts/test !barretenberg/cpp/src/barretenberg -!circuits/cpp/src !.release-please-manifest.json !boxes diff --git a/noir/tooling/backend_interface/src/cli/mod.rs b/noir/tooling/backend_interface/src/cli/mod.rs index 3ea65f28103..b4dec859839 100644 --- a/noir/tooling/backend_interface/src/cli/mod.rs +++ b/noir/tooling/backend_interface/src/cli/mod.rs @@ -1,4 +1,4 @@ -// Reference: https://github.com/AztecProtocol/aztec-packages/blob/master/circuits/cpp/barretenberg/cpp/src/barretenberg/bb/main.cpp +// Reference: https://github.com/AztecProtocol/aztec-packages/blob/master/barretenberg/cpp/src/barretenberg/bb/main.cpp mod contract; mod gates;