From c83282582536421ae67bbd936b3059597d908253 Mon Sep 17 00:00:00 2001 From: ledwards2225 <98505400+ledwards2225@users.noreply.github.com> Date: Mon, 25 Sep 2023 13:16:35 -0700 Subject: [PATCH] chore: kill Turbo (#2442) Bye, Turbo. (There is no longer any practical use case for TurboPlonk and is thus clutter. This work removes it entirely). --- .circleci/config.yml | 14 - barretenberg/cpp/docs/Fuzzing.md | 40 +- .../cpp/src/barretenberg/barretenberg.hpp | 1 - .../cpp/src/barretenberg/common/fuzzer.hpp | 4 - .../barretenberg/common/fuzzer_constants.hpp | 5 +- .../cpp/src/barretenberg/dsl/types.hpp | 14 +- .../honk/composer/ultra_composer.test.cpp | 72 +- .../barretenberg/join_split_example/types.hpp | 12 +- .../plonk/composer/composer_lib.cpp | 2 +- .../plonk/composer/turbo_composer.cpp | 174 -- .../plonk/composer/turbo_composer.hpp | 122 -- .../plonk/composer/turbo_composer.test.cpp | 1171 ------------- .../plonk/composer/ultra_composer.test.cpp | 73 +- .../src/barretenberg/plonk/flavor/flavor.hpp | 13 - .../commitment_scheme.test.cpp | 4 +- .../kate_commitment_scheme.cpp | 5 +- .../kate_commitment_scheme.hpp | 1 - .../plonk/proof_system/prover/prover.cpp | 7 +- .../plonk/proof_system/prover/prover.hpp | 2 - .../types/polynomial_manifest.hpp | 30 - .../proof_system/types/program_settings.hpp | 65 +- .../proof_system/types/prover_settings.hpp | 13 - .../proof_system/utils/kate_verification.hpp | 41 - .../proof_system/verification_key/sol_gen.hpp | 4 - .../plonk/proof_system/verifier/verifier.cpp | 1 - .../plonk/proof_system/verifier/verifier.hpp | 2 - .../permutation_widget_impl.hpp | 2 +- .../transition_widgets/fixed_base_widget.hpp | 48 +- ...urbo_logic_widget.hpp => logic_widget.hpp} | 6 +- .../plookup_arithmetic_widget.hpp | 2 +- .../turbo_arithmetic_widget.hpp | 307 ---- .../transition_widgets/turbo_range_widget.hpp | 212 --- .../arithmetization/arithmetization.hpp | 44 - .../circuit_builder/circuit_builder_base.cpp | 1 - .../circuit_builder/turbo_circuit_builder.cpp | 1519 ----------------- .../circuit_builder/turbo_circuit_builder.hpp | 128 -- .../turbo_circuit_builder.test.cpp | 684 -------- .../proof_system/flavor/flavor.hpp | 3 +- .../proof_system/types/circuit_type.hpp | 3 +- .../circuits/recursive_circuit.hpp | 2 +- .../commitment/pedersen/pedersen.bench.cpp | 10 +- .../commitment/pedersen/pedersen.test.cpp | 4 +- .../stdlib/encryption/schnorr/schnorr.cpp | 3 - .../encryption/schnorr/schnorr.test.cpp | 4 +- .../stdlib/hash/blake2s/blake_util.hpp | 4 +- .../stdlib/hash/blake3s/blake3s.test.cpp | 21 +- .../stdlib/hash/pedersen/pedersen.cpp | 11 +- .../stdlib/hash/pedersen/pedersen_gates.hpp | 486 +++--- .../primitives/bigfield/bigfield.test.cpp | 4 +- .../bigfield/bigfield_all.fuzzer.cpp | 2 +- .../primitives/bigfield/bigfield_impl.hpp | 7 +- .../bigfield/bigfield_turbo.fuzzer.cpp | 3 - .../stdlib/primitives/biggroup/biggroup.hpp | 1 - .../primitives/biggroup/biggroup.test.cpp | 2 +- .../primitives/biggroup/biggroup_bn254.hpp | 2 +- .../primitives/biggroup/biggroup_impl.hpp | 2 +- .../primitives/bit_array/bit_array.test.cpp | 3 +- .../bit_array/bit_array_all.fuzzer.cpp | 2 +- .../bit_array/bit_array_turbo.fuzzer.cpp | 3 - .../stdlib/primitives/bool/bool.test.cpp | 3 +- .../primitives/bool/bool_all.fuzzer.cpp | 2 +- .../primitives/bool/bool_turbo.fuzzer.cpp | 3 - .../primitives/byte_array/byte_array.test.cpp | 3 +- .../byte_array/byte_array_all.fuzzer.cpp | 2 +- .../byte_array/byte_array_turbo.fuzzer.cpp | 3 - .../circuit_builders/circuit_builders.hpp | 11 +- .../circuit_builders/circuit_builders_fwd.hpp | 12 +- .../stdlib/primitives/field/array.test.cpp | 4 +- .../stdlib/primitives/field/field.cpp | 12 - .../stdlib/primitives/field/field.hpp | 4 +- .../stdlib/primitives/field/field.test.cpp | 10 +- .../primitives/field/field_all.fuzzer.cpp | 2 +- .../primitives/field/field_turbo.fuzzer.cpp | 3 - .../stdlib/primitives/group/group.test.cpp | 3 +- .../stdlib/primitives/logic/logic.test.cpp | 3 +- .../packed_byte_array.test.cpp | 3 +- .../primitives/safe_uint/safe_uint.test.cpp | 3 +- .../safe_uint/safe_uint_all.fuzzer.cpp | 2 +- .../safe_uint/safe_uint_turbo.fuzzer.cpp | 3 - .../stdlib/primitives/uint/logic.cpp | 12 +- .../stdlib/primitives/uint/uint.cpp | 10 +- .../stdlib/primitives/uint/uint.test.cpp | 5 +- .../primitives/uint/uint_all.fuzzer.cpp | 2 +- .../primitives/uint/uint_turbo.fuzzer.cpp | 3 - .../verification_key.test.cpp | 4 +- .../recursion/verifier/program_settings.hpp | 62 +- .../recursion/verifier/verifier.test.cpp | 5 +- .../verifier/verifier_turbo.test.cpp | 537 ------ .../src/barretenberg/stdlib/types/turbo.hpp | 68 - .../barretenberg/transcript/transcript.cpp | 2 +- barretenberg/sol/README.md | 13 +- .../sol/test/base/DifferentialFuzzer.sol | 3 - .../aztec3/circuits/kernel/private/utils.cpp | 2 +- .../circuits.js/src/structs/shared.ts | 3 +- .../src/structs/verification_key.ts | 67 +- 95 files changed, 443 insertions(+), 5873 deletions(-) delete mode 100644 barretenberg/cpp/src/barretenberg/plonk/composer/turbo_composer.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/plonk/composer/turbo_composer.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/plonk/composer/turbo_composer.test.cpp rename barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/{turbo_logic_widget.hpp => logic_widget.hpp} (96%) delete mode 100644 barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/turbo_arithmetic_widget.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/turbo_range_widget.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.test.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_turbo.fuzzer.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_array/bit_array_turbo.fuzzer.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool_turbo.fuzzer.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array_turbo.fuzzer.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field_turbo.fuzzer.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint_turbo.fuzzer.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/uint_turbo.fuzzer.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/stdlib/recursion/verifier/verifier_turbo.test.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/stdlib/types/turbo.hpp diff --git a/.circleci/config.yml b/.circleci/config.yml index 78753c70010..6466bd7e881 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -191,18 +191,6 @@ jobs: command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 proof_system_tests - *save_logs - barretenberg-stdlib-recursion-turbo-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 stdlib_recursion_tests --gtest_filter=*turbo* - - *save_logs - barretenberg-stdlib-recursion-ultra-tests: docker: - image: aztecprotocol/alpine-build-image @@ -1040,14 +1028,12 @@ workflows: - barretenberg-dsl-tests: *bb_test - barretenberg-tests: *bb_test - barretenberg-stdlib-tests: *bb_test - - barretenberg-stdlib-recursion-turbo-tests: *bb_test - barretenberg-stdlib-recursion-ultra-tests: *bb_test - barretenberg-join-split-tests: *bb_test # - barretenberg-benchmark-aggregator: # requires: # - barretenberg-tests # - barretenberg-stdlib-tests - # - barretenberg-stdlib-recursion-turbo-tests # - barretenberg-stdlib-recursion-ultra-tests # - barretenberg-join-split-tests # filters: diff --git a/barretenberg/cpp/docs/Fuzzing.md b/barretenberg/cpp/docs/Fuzzing.md index 7efc814e84c..7dc3a6bde9f 100644 --- a/barretenberg/cpp/docs/Fuzzing.md +++ b/barretenberg/cpp/docs/Fuzzing.md @@ -1,14 +1,18 @@ # Fuzzing barretenberg + ## Intro + We are gradually introducing fuzzing of various primitives into barretenberg, focusing first and foremost on in-cicruit types. If you are developing / patching a primitive and there is a fuzzer available for it, please take the time to update the fuzzer (if you've added new functionality) and run it for at least a few hours to increase security. ## Build To build with standard clang: + ```bash cmake --preset fuzzing cmake --build --preset fuzzing ``` + Fuzzing build turns off building tests and benchmarks, since they are incompatible with libfuzzer interface. To turn on address sanitizer add `-DADDRESS_SANITIZER=ON`. Note that address sanitizer can be used to explore crashes. @@ -27,35 +31,43 @@ cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER= -DCMA ``` ## Currently supported -Currently we have fuzzers for bigfield, bit_array, bool, byte_array, field, safe_uint and uint. Each of them is available in 3 versions: StandardPlonk, TurboPlonk, ALL (differential fuzzing of 2 versions). + +Currently we have fuzzers for bigfield, bit_array, bool, byte_array, field, safe_uint and uint. Each of them is available in 2 versions: StandardPlonk, ALL (differential fuzzing of 2 versions). To compile all fuzzers just type `make`. + ## Running the fuzzer + TODO: add information about saved testcases You can simply run a fuzzer by executing the built executable, for example, + ```bash -./bin/stdlib_primitives_bigfield_turbo_fuzzer +./bin/stdlib_primitives_bigfield_standard_fuzzer ``` + This is useful if you added a feature/instruction or changed some logic and want to quickly test if there are any really bad bugs. To run the fuzzer seriously, I'd recommend: + ```bash mkdir ../../../_testcases; mkdir crashes; ./bin/ -timeout=1 -len_control=500 -workers=8 -jobs=8 -entropic=1 -shrink=1 -artifact_prefix=crashes/ -use_value_profile=1 ../../../_testcases ``` + You can watch the progress of the fuzzer in one of the generated logs fuzz-.log The purpose of each parameter: -+ -timeout=1 - If a testcase takes more than 1 second to execute, it will be treated as a crash -+ -len_control=500 - Slows down the increase of testcase size. Especially important for heavy classes like bigfield, keeps the number of executions per second at a decent rate -+ -worker=8 - The number of threads that can simultaneously execute testcases. Should be less or equal to the number of jobs -+ -jobs=8 - After how many crashes the fuzzer will stop fuzzing. If a crash is executed and the number of jobs is more than workers then the fuzzer will proceed to give the worker a new job. The 8/8 worker/job configuration ensures that the fuzzer will quit after 8 crashes and until the first crash all the workers are busy. -+ -entropic=1 - Entropic should be enabled by default, but in case it isn't, enable it. A better power schedule than the old one. -+ -shrink=1 - If a new testcase is encountered that has the same coverage as some previous one in the corpus and the testcase is smaller, replace the one in the corpus with the new one. Helps keep exec/s higher. -+ -artifact_prefix=crashes/ - Where to save crashes/timeouts/ooms. -+ -use_value_profile=1 - Leverage libfuzzer internal CMP analysis. Very useful, but blows the corpus up. -+ (../../../_testcases) - The path to the folder, where corpus testcases are going to be saved and loaded from (also loads testcases from there at the start of fuzzing). - -Log structure is described here https://llvm.org/docs/LibFuzzer.html + +- -timeout=1 - If a testcase takes more than 1 second to execute, it will be treated as a crash +- -len_control=500 - Slows down the increase of testcase size. Especially important for heavy classes like bigfield, keeps the number of executions per second at a decent rate +- -worker=8 - The number of threads that can simultaneously execute testcases. Should be less or equal to the number of jobs +- -jobs=8 - After how many crashes the fuzzer will stop fuzzing. If a crash is executed and the number of jobs is more than workers then the fuzzer will proceed to give the worker a new job. The 8/8 worker/job configuration ensures that the fuzzer will quit after 8 crashes and until the first crash all the workers are busy. +- -entropic=1 - Entropic should be enabled by default, but in case it isn't, enable it. A better power schedule than the old one. +- -shrink=1 - If a new testcase is encountered that has the same coverage as some previous one in the corpus and the testcase is smaller, replace the one in the corpus with the new one. Helps keep exec/s higher. +- -artifact_prefix=crashes/ - Where to save crashes/timeouts/ooms. +- -use_value_profile=1 - Leverage libfuzzer internal CMP analysis. Very useful, but blows the corpus up. +- (../../../\_testcases) - The path to the folder, where corpus testcases are going to be saved and loaded from (also loads testcases from there at the start of fuzzing). + +Log structure is described here https://llvm.org/docs/LibFuzzer.html If you've found an issue, stopped the fuzzer, you can minimize the corpus to get rid of repetitions and then start from a minimized corpus @@ -67,10 +79,12 @@ cp ../../../_testcases_minimized/* ../../../_testcases ``` If you've found a crash, you can minimize the crash to make the root cause more obvious: + ```bash mkdir minimized_crashes ./bin/ -minimize_crash=1 -artifact_prefix=minimized_crashes ``` + Also, both bigfield and safeuint fuzzer containt the SHOW_INFORMATION preprocessor cases, which enable the printing of instructions and values to make debugging the crash easier. # Coverage reports diff --git a/barretenberg/cpp/src/barretenberg/barretenberg.hpp b/barretenberg/cpp/src/barretenberg/barretenberg.hpp index 329f31bb1ca..9ee9413e151 100644 --- a/barretenberg/cpp/src/barretenberg/barretenberg.hpp +++ b/barretenberg/cpp/src/barretenberg/barretenberg.hpp @@ -24,7 +24,6 @@ #include "numeric/uint256/uint256.hpp" #include "plonk/proof_system/types/proof.hpp" #include "plonk/proof_system/verification_key/verification_key.hpp" -#include "proof_system/circuit_builder/turbo_circuit_builder.hpp" #include "proof_system/circuit_builder/ultra_circuit_builder.hpp" #include "proof_system/types/circuit_type.hpp" // TODO(https://github.com/AztecProtocol/barretenberg/issues/491): diff --git a/barretenberg/cpp/src/barretenberg/common/fuzzer.hpp b/barretenberg/cpp/src/barretenberg/common/fuzzer.hpp index 891c247d232..2e56c71afa9 100644 --- a/barretenberg/cpp/src/barretenberg/common/fuzzer.hpp +++ b/barretenberg/cpp/src/barretenberg/common/fuzzer.hpp @@ -1,7 +1,6 @@ #pragma once #include "barretenberg/numeric/uint256/uint256.hpp" #include "barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp" -#include "barretenberg/proof_system/circuit_builder/turbo_circuit_builder.hpp" #include // NOLINTBEGIN(cppcoreguidelines-macro-usage, google-runtime-int) @@ -693,9 +692,6 @@ constexpr void RunWithBuilders(const uint8_t* Data, const size_t Size, FastRando if (Composers & 1) { RunWithBuilder(Data, Size, VarianceRNG); } - if (Composers & 2) { - RunWithBuilder(Data, Size, VarianceRNG); - } } // NOLINTEND(cppcoreguidelines-macro-usage, google-runtime-int) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/common/fuzzer_constants.hpp b/barretenberg/cpp/src/barretenberg/common/fuzzer_constants.hpp index 6f7a6400070..0a9603ceefb 100644 --- a/barretenberg/cpp/src/barretenberg/common/fuzzer_constants.hpp +++ b/barretenberg/cpp/src/barretenberg/common/fuzzer_constants.hpp @@ -1,7 +1,4 @@ #pragma once #include -enum CircuitType : uint64_t { - Standard = 1 << 0, - Turbo = 1 << 1, -}; +enum CircuitType : uint64_t { Standard = 1 << 0 }; diff --git a/barretenberg/cpp/src/barretenberg/dsl/types.hpp b/barretenberg/cpp/src/barretenberg/dsl/types.hpp index af7902ea0e0..935def071a2 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/types.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/types.hpp @@ -1,9 +1,7 @@ #pragma once -#include "barretenberg/plonk/composer/turbo_composer.hpp" #include "barretenberg/plonk/composer/ultra_composer.hpp" #include "barretenberg/plonk/proof_system/prover/prover.hpp" -#include "barretenberg/proof_system/circuit_builder/turbo_circuit_builder.hpp" #include "barretenberg/stdlib/commitment/pedersen/pedersen.hpp" #include "barretenberg/stdlib/commitment/pedersen/pedersen_plookup.hpp" #include "barretenberg/stdlib/encryption/schnorr/schnorr.hpp" @@ -30,15 +28,11 @@ namespace acir_format { using Builder = proof_system::UltraCircuitBuilder; using Composer = plonk::UltraComposer; -using Prover = std::conditional_t< - std::same_as, - plonk::UltraWithKeccakProver, - std::conditional_t, plonk::TurboProver, plonk::Prover>>; +using Prover = + std::conditional_t, plonk::UltraWithKeccakProver, plonk::Prover>; -using Verifier = std::conditional_t< - std::same_as, - plonk::UltraWithKeccakVerifier, - std::conditional_t, plonk::TurboVerifier, plonk::Verifier>>; +using Verifier = + std::conditional_t, plonk::UltraWithKeccakVerifier, plonk::Verifier>; using RecursiveProver = plonk::UltraProver; diff --git a/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.test.cpp b/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.test.cpp index 6daa41d2f14..9b1775da7d5 100644 --- a/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.test.cpp @@ -368,54 +368,48 @@ TEST_F(UltraHonkComposerTests, non_trivial_tag_permutation_and_cycles) TEST_F(UltraHonkComposerTests, bad_tag_permutation) { - auto circuit_builder = proof_system::UltraCircuitBuilder(); - fr a = fr::random_element(); - fr b = -a; - - auto a_idx = circuit_builder.add_variable(a); - auto b_idx = circuit_builder.add_variable(b); - auto c_idx = circuit_builder.add_variable(b); - auto d_idx = circuit_builder.add_variable(a + 1); + { + auto circuit_builder = proof_system::UltraCircuitBuilder(); + fr a = fr::random_element(); + fr b = -a; - circuit_builder.create_add_gate({ a_idx, b_idx, circuit_builder.zero_idx, 1, 1, 0, 0 }); - circuit_builder.create_add_gate({ c_idx, d_idx, circuit_builder.zero_idx, 1, 1, 0, -1 }); + auto a_idx = circuit_builder.add_variable(a); + auto b_idx = circuit_builder.add_variable(b); + auto c_idx = circuit_builder.add_variable(b); + auto d_idx = circuit_builder.add_variable(a + 1); - circuit_builder.create_tag(1, 2); - circuit_builder.create_tag(2, 1); + circuit_builder.create_add_gate({ a_idx, b_idx, circuit_builder.zero_idx, 1, 1, 0, 0 }); + circuit_builder.create_add_gate({ c_idx, d_idx, circuit_builder.zero_idx, 1, 1, 0, -1 }); - circuit_builder.assign_tag(a_idx, 1); - circuit_builder.assign_tag(b_idx, 1); - circuit_builder.assign_tag(c_idx, 2); - circuit_builder.assign_tag(d_idx, 2); + circuit_builder.create_tag(1, 2); + circuit_builder.create_tag(2, 1); - auto composer = UltraComposer(); - prove_and_verify(circuit_builder, composer, /*expected_result=*/false); -} + circuit_builder.assign_tag(a_idx, 1); + circuit_builder.assign_tag(b_idx, 1); + circuit_builder.assign_tag(c_idx, 2); + circuit_builder.assign_tag(d_idx, 2); -// same as above but with turbocomposer to check reason of failue is really tag mismatch -TEST_F(UltraHonkComposerTests, bad_tag_turbo_permutation) -{ - auto circuit_builder = proof_system::UltraCircuitBuilder(); - fr a = fr::random_element(); - fr b = -a; + auto composer = UltraComposer(); + prove_and_verify(circuit_builder, composer, /*expected_result=*/false); + } + // Same as above but without tag creation to check reason of failure is really tag mismatch + { + auto circuit_builder = proof_system::UltraCircuitBuilder(); + fr a = fr::random_element(); + fr b = -a; - auto a_idx = circuit_builder.add_variable(a); - auto b_idx = circuit_builder.add_variable(b); - auto c_idx = circuit_builder.add_variable(b); - auto d_idx = circuit_builder.add_variable(a + 1); + auto a_idx = circuit_builder.add_variable(a); + auto b_idx = circuit_builder.add_variable(b); + auto c_idx = circuit_builder.add_variable(b); + auto d_idx = circuit_builder.add_variable(a + 1); - circuit_builder.create_add_gate({ a_idx, b_idx, circuit_builder.zero_idx, 1, 1, 0, 0 }); - circuit_builder.create_add_gate({ c_idx, d_idx, circuit_builder.zero_idx, 1, 1, 0, -1 }); + circuit_builder.create_add_gate({ a_idx, b_idx, circuit_builder.zero_idx, 1, 1, 0, 0 }); + circuit_builder.create_add_gate({ c_idx, d_idx, circuit_builder.zero_idx, 1, 1, 0, -1 }); - auto composer = UltraComposer(); - // circuit_builder.create_add_gate({ a_idx, b_idx, circuit_builder.zero_idx, fr::one(), fr::neg_one(), - // fr::zero(), fr::zero() }); circuit_builder.create_add_gate({ a_idx, b_idx, circuit_builder.zero_idx, - // fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); circuit_builder.create_add_gate({ a_idx, b_idx, - // circuit_builder.zero_idx, fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); - // auto prover = composer.create_prover(circuit_builder); - // auto verifier = composer.create_verifier(circuit_builder); + auto composer = UltraComposer(); - prove_and_verify(circuit_builder, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); + } } TEST_F(UltraHonkComposerTests, sort_widget) diff --git a/barretenberg/cpp/src/barretenberg/join_split_example/types.hpp b/barretenberg/cpp/src/barretenberg/join_split_example/types.hpp index 2fff791d38d..386d2bff4b3 100644 --- a/barretenberg/cpp/src/barretenberg/join_split_example/types.hpp +++ b/barretenberg/cpp/src/barretenberg/join_split_example/types.hpp @@ -2,7 +2,6 @@ #include "barretenberg/honk/composer/ultra_composer.hpp" #include "barretenberg/plonk/composer/standard_composer.hpp" -#include "barretenberg/plonk/composer/turbo_composer.hpp" #include "barretenberg/plonk/composer/ultra_composer.hpp" #include "barretenberg/plonk/proof_system/prover/prover.hpp" @@ -21,15 +20,10 @@ namespace join_split_example { using Builder = proof_system::UltraCircuitBuilder; using Composer = plonk::UltraComposer; -using Prover = std::conditional_t< - std::same_as, - plonk::UltraProver, - std::conditional_t, plonk::TurboProver, plonk::Prover>>; +using Prover = std::conditional_t, plonk::UltraProver, plonk::Prover>; -using Verifier = std::conditional_t< - std::same_as, - plonk::UltraVerifier, - std::conditional_t, plonk::TurboVerifier, plonk::Verifier>>; +using Verifier = + std::conditional_t, plonk::UltraVerifier, plonk::Verifier>; using witness_ct = proof_system::plonk::stdlib::witness_t; using public_witness_ct = proof_system::plonk::stdlib::public_witness_t; diff --git a/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.cpp b/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.cpp index 931ab21e16e..b3a13a11fbb 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.cpp +++ b/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.cpp @@ -30,7 +30,7 @@ void compute_monomial_and_coset_selector_forms(plonk::proving_key* circuit_provi barretenberg::polynomial selector_poly_fft(selector_poly, circuit_proving_key->circuit_size * 4 + 4); selector_poly_fft.coset_fft(circuit_proving_key->large_domain); - // TODO(luke): For Standard/Turbo, the lagrange polynomials can be removed from the store at this point but this + // TODO(luke): For Standard, the lagrange polynomials can be removed from the store at this point but this // is not the case for Ultra. Implement? circuit_proving_key->polynomial_store.put(selector_properties[i].name, std::move(selector_poly)); circuit_proving_key->polynomial_store.put(selector_properties[i].name + "_fft", std::move(selector_poly_fft)); diff --git a/barretenberg/cpp/src/barretenberg/plonk/composer/turbo_composer.cpp b/barretenberg/cpp/src/barretenberg/plonk/composer/turbo_composer.cpp deleted file mode 100644 index 9c6937adb8c..00000000000 --- a/barretenberg/cpp/src/barretenberg/plonk/composer/turbo_composer.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include "turbo_composer.hpp" -#include "barretenberg/numeric/bitop/get_msb.hpp" -#include "barretenberg/plonk/composer/composer_lib.hpp" -#include "barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.hpp" -#include "barretenberg/plonk/proof_system/widgets/random_widgets/permutation_widget.hpp" -#include "barretenberg/plonk/proof_system/widgets/transition_widgets/fixed_base_widget.hpp" -#include "barretenberg/plonk/proof_system/widgets/transition_widgets/transition_widget.hpp" -#include "barretenberg/plonk/proof_system/widgets/transition_widgets/turbo_arithmetic_widget.hpp" -#include "barretenberg/plonk/proof_system/widgets/transition_widgets/turbo_logic_widget.hpp" -#include "barretenberg/plonk/proof_system/widgets/transition_widgets/turbo_range_widget.hpp" -#include "barretenberg/proof_system/circuit_builder/turbo_circuit_builder.hpp" -#include "barretenberg/proof_system/composer/composer_lib.hpp" -#include "barretenberg/proof_system/composer/permutation_lib.hpp" - -using namespace barretenberg; - -namespace proof_system::plonk { - -/** - * Compute proving key - * - * 1. Load crs. - * 2. Initialize this.circuit_proving_key. - * 3. Create constraint selector polynomials from each of this composer's `selectors` vectors and add them to the - * proving key. - * 4. Compute sigma polynomial - * - * @return Pointer to the initialized proving key updated with selector polynomials. - * */ -std::shared_ptr TurboComposer::compute_proving_key(const CircuitBuilder& circuit_constructor) -{ - if (circuit_proving_key) { - return circuit_proving_key; - } - const size_t minimum_circuit_size = 0; - const size_t num_randomized_gates = NUM_RESERVED_GATES; - // Initialize circuit_proving_key - // TODO(#392)(Kesha): replace composer types. - circuit_proving_key = initialize_proving_key( - circuit_constructor, crs_factory_.get(), minimum_circuit_size, num_randomized_gates, CircuitType::TURBO); - - construct_selector_polynomials(circuit_constructor, circuit_proving_key.get()); - - enforce_nonzero_selector_polynomials(circuit_constructor, circuit_proving_key.get()); - - compute_monomial_and_coset_selector_forms(circuit_proving_key.get(), turbo_selector_properties()); - - // Compute sigma polynomials (TODO(kesha): we should update that late) - compute_standard_plonk_sigma_permutations(circuit_constructor, circuit_proving_key.get()); - circuit_proving_key->recursive_proof_public_input_indices = - std::vector(circuit_constructor.recursive_proof_public_input_indices.begin(), - circuit_constructor.recursive_proof_public_input_indices.end()); - circuit_proving_key->contains_recursive_proof = circuit_constructor.contains_recursive_proof; - return circuit_proving_key; -} - -/** - * Compute verification key consisting of selector precommitments. - * - * @return Pointer to created circuit verification key. - * */ -std::shared_ptr TurboComposer::compute_verification_key( - const CircuitBuilder& circuit_constructor) -{ - if (circuit_verification_key) { - return circuit_verification_key; - } - if (!circuit_proving_key) { - compute_proving_key(circuit_constructor); - } - - circuit_verification_key = - plonk::compute_verification_key_common(circuit_proving_key, crs_factory_->get_verifier_crs()); - circuit_verification_key->circuit_type = circuit_proving_key->circuit_type; - circuit_verification_key->recursive_proof_public_input_indices = - std::vector(circuit_constructor.recursive_proof_public_input_indices.begin(), - circuit_constructor.recursive_proof_public_input_indices.end()); - circuit_verification_key->contains_recursive_proof = circuit_constructor.contains_recursive_proof; - - return circuit_verification_key; -} -/** - * Compute witness polynomials (w_1, w_2, w_3, w_4). - * - * @details Fills 3 or 4 witness polynomials w_1, w_2, w_3, w_4 with the values of in-circuit variables. The beginning - * of w_1, w_2 polynomials is filled with public_input values. - * @return Witness with computed witness polynomials. - * - * @tparam Program settings needed to establish if w_4 is being used. - * */ -void TurboComposer::compute_witness(const CircuitBuilder& circuit_constructor, const size_t minimum_circuit_size) -{ - - if (computed_witness) { - return; - } - const size_t num_gates = circuit_constructor.num_gates; - const size_t num_public_inputs = circuit_constructor.public_inputs.size(); - - const size_t num_constraints = std::max(minimum_circuit_size, num_gates + num_public_inputs); - const size_t subgroup_size = circuit_constructor.get_circuit_subgroup_size(num_constraints + NUM_RESERVED_GATES); - - auto wire_polynomial_evaluations = construct_wire_polynomials_base(circuit_constructor, subgroup_size); - - for (size_t j = 0; j < program_width; ++j) { - std::string index = std::to_string(j + 1); - circuit_proving_key->polynomial_store.put("w_" + index + "_lagrange", - std::move(wire_polynomial_evaluations[j])); - } - computed_witness = true; -} -/** - * Create prover. - * 1. Compute the starting polynomials (q_l, etc, sigma, witness polynomials). - * 2. Initialize StandardProver with them. - * 3. Add Permutation and arithmetic widgets to the prover. - * 4. Add KateCommitmentScheme to the prover. - * - * @return Initialized prover. - * */ -plonk::TurboProver TurboComposer::create_prover(const CircuitBuilder& circuit_constructor) -{ - // Compute q_l, etc. and sigma polynomials. - compute_proving_key(circuit_constructor); - - // Compute witness polynomials. - compute_witness(circuit_constructor); - - plonk::TurboProver output_state(circuit_proving_key, create_manifest(circuit_constructor.public_inputs.size())); - - auto permutation_widget = std::make_unique>(circuit_proving_key.get()); - - auto arithmetic_widget = std::make_unique>(circuit_proving_key.get()); - auto fixed_base_widget = std::make_unique>(circuit_proving_key.get()); - auto range_widget = std::make_unique>(circuit_proving_key.get()); - auto logic_widget = std::make_unique>(circuit_proving_key.get()); - - output_state.random_widgets.emplace_back(std::move(permutation_widget)); - - output_state.transition_widgets.emplace_back(std::move(arithmetic_widget)); - output_state.transition_widgets.emplace_back(std::move(fixed_base_widget)); - output_state.transition_widgets.emplace_back(std::move(range_widget)); - output_state.transition_widgets.emplace_back(std::move(logic_widget)); - - std::unique_ptr> kate_commitment_scheme = - std::make_unique>(); - - output_state.commitment_scheme = std::move(kate_commitment_scheme); - - return output_state; -} - -/** - * Create verifier: compute verification key, - * initialize verifier with it and an initial manifest and initialize commitment_scheme. - * - * @return The verifier. - * */ -plonk::TurboVerifier TurboComposer::create_verifier(const CircuitBuilder& circuit_constructor) -{ - auto verification_key = compute_verification_key(circuit_constructor); - - plonk::TurboVerifier output_state(circuit_verification_key, - create_manifest(circuit_constructor.public_inputs.size())); - - std::unique_ptr> kate_commitment_scheme = - std::make_unique>(); - - output_state.commitment_scheme = std::move(kate_commitment_scheme); - - return output_state; -} - -} // namespace proof_system::plonk diff --git a/barretenberg/cpp/src/barretenberg/plonk/composer/turbo_composer.hpp b/barretenberg/cpp/src/barretenberg/plonk/composer/turbo_composer.hpp deleted file mode 100644 index 8f124c3787d..00000000000 --- a/barretenberg/cpp/src/barretenberg/plonk/composer/turbo_composer.hpp +++ /dev/null @@ -1,122 +0,0 @@ -#pragma once - -#include "barretenberg/plonk/composer/composer_lib.hpp" -#include "barretenberg/plonk/flavor/flavor.hpp" -#include "barretenberg/plonk/proof_system/prover/prover.hpp" -#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" -#include "barretenberg/plonk/proof_system/verifier/verifier.hpp" -#include "barretenberg/proof_system/composer/composer_lib.hpp" -#include "barretenberg/srs/factories/file_crs_factory.hpp" - -namespace proof_system::plonk { -class TurboComposer { - public: - using Flavor = plonk::flavor::Turbo; - using CircuitBuilder = TurboCircuitBuilder; - - static constexpr std::string_view NAME_STRING = "TurboPlonk"; - static constexpr size_t NUM_RESERVED_GATES = 4; // equal to the number of evaluations leaked - static constexpr size_t program_width = CircuitBuilder::program_width; - - std::shared_ptr circuit_proving_key; - std::shared_ptr circuit_verification_key; - - // The crs_factory holds the path to the srs and exposes methods to extract the srs elements - std::shared_ptr> crs_factory_; - - bool computed_witness = false; - TurboComposer() - : TurboComposer(std::shared_ptr>( - new barretenberg::srs::factories::FileCrsFactory("../srs_db/ignition"))) - {} - - TurboComposer(std::shared_ptr> crs_factory) - : crs_factory_(std::move(crs_factory)) - {} - TurboComposer(std::unique_ptr>&& crs_factory) - : crs_factory_(std::move(crs_factory)) - {} - TurboComposer(std::shared_ptr p_key, std::shared_ptr v_key) - : circuit_proving_key(std::move(p_key)) - , circuit_verification_key(std::move(v_key)) - {} - TurboComposer(TurboComposer&& other) = default; - TurboComposer& operator=(TurboComposer&& other) noexcept = default; - ~TurboComposer() {} - - std::shared_ptr compute_proving_key(const CircuitBuilder& circuit_constructor); - std::shared_ptr compute_verification_key(const CircuitBuilder& circuit_constructor); - void compute_witness(const CircuitBuilder& circuit_constructor, const size_t minimum_circuit_size = 0); - - TurboProver create_prover(const CircuitBuilder& circuit_constructor); - TurboVerifier create_verifier(const CircuitBuilder& circuit_constructor); - inline std::vector turbo_selector_properties() - { - const std::vector result{ - { "q_m", false }, { "q_c", false }, { "q_1", false }, { "q_2", false }, - { "q_3", false }, { "q_4", false }, { "q_5", false }, { "q_arith", false }, - { "q_fixed_base", false }, { "q_range", false }, { "q_logic", false }, - }; - return result; - } - - static transcript::Manifest create_manifest(const size_t num_public_inputs) - { - // add public inputs.... - constexpr size_t g1_size = 64; - constexpr size_t fr_size = 32; - const size_t public_input_size = fr_size * num_public_inputs; - const transcript::Manifest output = transcript::Manifest( - { transcript::Manifest::RoundManifest( - { { "circuit_size", 4, true }, { "public_input_size", 4, true } }, "init", 1), - - transcript::Manifest::RoundManifest({}, "eta", 0), - - transcript::Manifest::RoundManifest( - { - { "public_inputs", public_input_size, false }, - { "W_1", g1_size, false }, - { "W_2", g1_size, false }, - { "W_3", g1_size, false }, - { "W_4", g1_size, false }, - }, - "beta", - 2), - transcript::Manifest::RoundManifest({ { "Z_PERM", g1_size, false } }, "alpha", 1), - transcript::Manifest::RoundManifest( - { - { "T_1", g1_size, false }, - { "T_2", g1_size, false }, - { "T_3", g1_size, false }, - { "T_4", g1_size, false }, - }, - "z", - 1), - - transcript::Manifest::RoundManifest( - { - { "t", fr_size, true, -1 }, { "w_1", fr_size, false, 0 }, - { "w_2", fr_size, false, 1 }, { "w_3", fr_size, false, 2 }, - { "w_4", fr_size, false, 3 }, { "sigma_1", fr_size, false, 4 }, - { "sigma_2", fr_size, false, 5 }, { "sigma_3", fr_size, false, 6 }, - { "sigma_4", fr_size, false, 7 }, { "q_1", fr_size, false, 8 }, - { "q_2", fr_size, false, 9 }, { "q_3", fr_size, false, 10 }, - { "q_4", fr_size, false, 11 }, { "q_5", fr_size, false, 12 }, - { "q_m", fr_size, false, 13 }, { "q_c", fr_size, false, 14 }, - { "q_arith", fr_size, false, 15 }, { "q_logic", fr_size, false, 16 }, - { "q_range", fr_size, false, 17 }, { "q_fixed_base", fr_size, false, 18 }, - { "z_perm", fr_size, false, 19 }, { "z_perm_omega", fr_size, false, 19 }, - { "w_1_omega", fr_size, false, 0 }, { "w_2_omega", fr_size, false, 1 }, - { "w_3_omega", fr_size, false, 2 }, { "w_4_omega", fr_size, false, 3 }, - }, - "nu", - TURBO_MANIFEST_SIZE, - true), - - transcript::Manifest::RoundManifest( - { { "PI_Z", g1_size, false }, { "PI_Z_OMEGA", g1_size, false } }, "separator", 3) }); - - return output; - } -}; -} // namespace proof_system::plonk diff --git a/barretenberg/cpp/src/barretenberg/plonk/composer/turbo_composer.test.cpp b/barretenberg/cpp/src/barretenberg/plonk/composer/turbo_composer.test.cpp deleted file mode 100644 index f57a7a4a1c8..00000000000 --- a/barretenberg/cpp/src/barretenberg/plonk/composer/turbo_composer.test.cpp +++ /dev/null @@ -1,1171 +0,0 @@ -#include - -#include "barretenberg/crypto/generators/fixed_base_scalar_mul.hpp" -#include "barretenberg/crypto/generators/generator_data.hpp" -#include "barretenberg/plonk/composer/turbo_composer.hpp" -#include "barretenberg/plonk/proof_system/proving_key/serialize.hpp" -#include "barretenberg/proof_system/circuit_builder/turbo_circuit_builder.hpp" - -using namespace barretenberg; -using namespace proof_system; -using namespace proof_system::plonk; -using namespace crypto::generators; - -namespace proof_system::plonk::test_turbo_plonk_composer { -namespace { -auto& engine = numeric::random::get_debug_engine(); -} - -TEST(turbo_plonk_composer, base_case) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - fr a = fr::one(); - builder.add_public_variable(a); - - auto prover = composer.create_prover(builder); - auto verifier = composer.create_verifier(builder); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - EXPECT_EQ(result, true); -} - -TEST(turbo_plonk_composer, composer_from_serialized_keys) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - fr a = fr::one(); - builder.add_public_variable(a); - - auto pk_buf = to_buffer(*composer.compute_proving_key(builder)); - auto vk_buf = to_buffer(*composer.compute_verification_key(builder)); - auto pk_data = from_buffer(pk_buf); - auto vk_data = from_buffer(vk_buf); - - auto crs = std::make_unique>("../srs_db/ignition"); - auto proving_key = - std::make_shared(std::move(pk_data), crs->get_prover_crs(pk_data.circuit_size + 1)); - auto verification_key = std::make_shared(std::move(vk_data), crs->get_verifier_crs()); - - auto builder2 = TurboCircuitBuilder(); - auto composer2 = TurboComposer(proving_key, verification_key); - builder2.add_public_variable(a); - - auto prover = composer2.create_prover(builder); - auto verifier = composer2.create_verifier(builder); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - EXPECT_EQ(result, true); -} - -TEST(turbo_plonk_composer, test_add_gate_proofs) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - fr a = fr::one(); - fr b = fr::one(); - fr c = a + b; - fr d = a + c; - uint32_t a_idx = builder.add_variable(a); - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c); - uint32_t d_idx = builder.add_variable(d); - - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ d_idx, c_idx, a_idx, fr::one(), fr::neg_one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ b_idx, a_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - - // TODO: proof fails if one wire contains all zeros. Should we support this? - uint32_t zero_idx = builder.add_variable(fr::zero()); - - builder.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, a_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - auto prover = composer.create_prover(builder); - - auto verifier = composer.create_verifier(builder); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - EXPECT_EQ(result, true); -} - -TEST(turbo_plonk_composer, test_mul_gate_proofs) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - fr q[7]{ fr::random_element(), fr::random_element(), fr::random_element(), fr::random_element(), - fr::random_element(), fr::random_element(), fr::random_element() }; - fr q_inv[7]{ - q[0].invert(), q[1].invert(), q[2].invert(), q[3].invert(), q[4].invert(), q[5].invert(), q[6].invert(), - }; - - fr a = fr::random_element(); - fr b = fr::random_element(); - fr c = -((((q[0] * a) + (q[1] * b)) + q[3]) * q_inv[2]); - fr d = -((((q[4] * (a * b)) + q[6]) * q_inv[5])); - - uint32_t a_idx = builder.add_public_variable(a); - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c); - uint32_t d_idx = builder.add_variable(d); - - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - - uint32_t zero_idx = builder.add_variable(fr::zero()); - uint32_t one_idx = builder.add_variable(fr::one()); - builder.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, one_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - uint32_t e_idx = builder.add_variable(a - fr::one()); - builder.create_add_gate({ e_idx, b_idx, c_idx, q[0], q[1], q[2], (q[3] + q[0]) }); - auto prover = composer.create_prover(builder); - - auto verifier = composer.create_verifier(builder); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - - EXPECT_EQ(result, true); -} - -TEST(turbo_plonk_composer, small_scalar_multipliers) -{ - constexpr size_t num_bits = 63; - constexpr size_t num_quads_base = (num_bits - 1) >> 1; - constexpr size_t num_quads = ((num_quads_base << 1) + 1 < num_bits) ? num_quads_base + 1 : num_quads_base; - constexpr size_t num_wnaf_bits = (num_quads << 1) + 1; - constexpr size_t initial_exponent = ((num_bits & 1) == 1) ? num_bits - 1 : num_bits; - constexpr uint64_t bit_mask = (1ULL << num_bits) - 1UL; - auto gen_data = crypto::generators::get_generator_data(DEFAULT_GEN_1); - const crypto::generators::fixed_base_ladder* ladder = gen_data.get_ladder(num_bits); - grumpkin::g1::affine_element generator = gen_data.generator; - - grumpkin::g1::element origin_points[2]; - origin_points[0] = grumpkin::g1::element(ladder[0].one); - origin_points[1] = origin_points[0] + generator; - origin_points[1] = origin_points[1].normalize(); - - grumpkin::fr scalar_multiplier_entropy = grumpkin::fr::random_element(); - grumpkin::fr scalar_multiplier_base{ scalar_multiplier_entropy.data[0] & bit_mask, 0, 0, 0 }; - // scalar_multiplier_base.data[0] = scalar_multiplier_base.data[0] | (1ULL); - scalar_multiplier_base.data[0] = scalar_multiplier_base.data[0] & (~1ULL); - grumpkin::fr scalar_multiplier = scalar_multiplier_base; - - uint64_t wnaf_entries[num_quads + 1] = { 0 }; - if ((scalar_multiplier_base.data[0] & 1) == 0) { - scalar_multiplier_base.data[0] -= 2; - } - bool skew = false; - barretenberg::wnaf::fixed_wnaf(&scalar_multiplier_base.data[0], &wnaf_entries[0], skew, 0); - - fr accumulator_offset = (fr::one() + fr::one()).pow(static_cast(initial_exponent)).invert(); - fr origin_accumulators[2]{ fr::one(), accumulator_offset + fr::one() }; - - grumpkin::g1::element* multiplication_transcript = - static_cast(aligned_alloc(64, sizeof(grumpkin::g1::element) * (num_quads + 1))); - fr* accumulator_transcript = static_cast(aligned_alloc(64, sizeof(fr) * (num_quads + 1))); - - if (skew) { - multiplication_transcript[0] = origin_points[1]; - accumulator_transcript[0] = origin_accumulators[1]; - } else { - multiplication_transcript[0] = origin_points[0]; - accumulator_transcript[0] = origin_accumulators[0]; - } - - fr one = fr::one(); - fr three = ((one + one) + one); - for (size_t i = 0; i < num_quads; ++i) { - uint64_t entry = wnaf_entries[i + 1] & crypto::generators::WNAF_MASK; - fr prev_accumulator = accumulator_transcript[i] + accumulator_transcript[i]; - prev_accumulator = prev_accumulator + prev_accumulator; - - grumpkin::g1::affine_element point_to_add = (entry == 1) ? ladder[i + 1].three : ladder[i + 1].one; - fr scalar_to_add = (entry == 1) ? three : one; - uint64_t predicate = (wnaf_entries[i + 1] >> 31U) & 1U; - if (predicate) { - point_to_add = -point_to_add; - scalar_to_add.self_neg(); - } - accumulator_transcript[i + 1] = prev_accumulator + scalar_to_add; - multiplication_transcript[i + 1] = multiplication_transcript[i] + point_to_add; - } - grumpkin::g1::element::batch_normalize(&multiplication_transcript[0], num_quads + 1); - - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - - fr x_alpha = accumulator_offset; - for (size_t i = 0; i < num_quads; ++i) { - fixed_group_add_quad_ round_quad; - round_quad.d = builder.add_variable(accumulator_transcript[i]); - round_quad.a = builder.add_variable(multiplication_transcript[i].x); - round_quad.b = builder.add_variable(multiplication_transcript[i].y); - round_quad.c = builder.add_variable(x_alpha); - if ((wnaf_entries[i + 1] & 0xffffffU) == 0) { - x_alpha = ladder[i + 1].one.x; - } else { - x_alpha = ladder[i + 1].three.x; - } - round_quad.q_x_1 = ladder[i + 1].q_x_1; - round_quad.q_x_2 = ladder[i + 1].q_x_2; - round_quad.q_y_1 = ladder[i + 1].q_y_1; - round_quad.q_y_2 = ladder[i + 1].q_y_2; - - if (i > 0) { - builder.create_fixed_group_add_gate(round_quad); - } else { - builder.create_fixed_group_add_gate_with_init(round_quad, - { origin_points[0].x, - (origin_points[0].x - origin_points[1].x), - origin_points[0].y, - (origin_points[0].y - origin_points[1].y) }); - } - } - - builder.create_big_add_gate({ builder.add_variable(multiplication_transcript[num_quads].x), - builder.add_variable(multiplication_transcript[num_quads].y), - builder.add_variable(x_alpha), - builder.add_variable(accumulator_transcript[num_quads]), - fr::zero(), - fr::zero(), - fr::zero(), - fr::zero(), - fr::zero() }); - - grumpkin::g1::element expected_point = - grumpkin::g1::element(generator * scalar_multiplier.to_montgomery_form()).normalize(); - EXPECT_EQ((multiplication_transcript[num_quads].x == expected_point.x), true); - EXPECT_EQ((multiplication_transcript[num_quads].y == expected_point.y), true); - - uint64_t result_accumulator = accumulator_transcript[num_quads].from_montgomery_form().data[0]; - uint64_t expected_accumulator = scalar_multiplier.data[0]; - EXPECT_EQ(result_accumulator, expected_accumulator); - - auto prover = composer.create_prover(builder); - - auto verifier = composer.create_verifier(builder); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - - EXPECT_EQ(result, true); - - free(multiplication_transcript); - free(accumulator_transcript); -} - -TEST(turbo_plonk_composer, large_scalar_multipliers) -{ - constexpr size_t num_bits = 254; - constexpr size_t num_quads_base = (num_bits - 1) >> 1; - constexpr size_t num_quads = ((num_quads_base << 1) + 1 < num_bits) ? num_quads_base + 1 : num_quads_base; - constexpr size_t num_wnaf_bits = (num_quads << 1) + 1; - - constexpr size_t initial_exponent = num_bits; // ((num_bits & 1) == 1) ? num_bits - 1 : num_bits; - auto gen_data = crypto::generators::get_generator_data(DEFAULT_GEN_1); - const crypto::generators::fixed_base_ladder* ladder = gen_data.get_ladder(num_bits); - grumpkin::g1::affine_element generator = gen_data.generator; - - grumpkin::g1::element origin_points[2]; - origin_points[0] = grumpkin::g1::element(ladder[0].one); - origin_points[1] = origin_points[0] + generator; - origin_points[1] = origin_points[1].normalize(); - - grumpkin::fr scalar_multiplier_base = grumpkin::fr::random_element(); - - grumpkin::fr scalar_multiplier = scalar_multiplier_base.from_montgomery_form(); - - if ((scalar_multiplier.data[0] & 1) == 0) { - grumpkin::fr two = grumpkin::fr::one() + grumpkin::fr::one(); - scalar_multiplier_base = scalar_multiplier_base - two; - } - scalar_multiplier_base = scalar_multiplier_base.from_montgomery_form(); - uint64_t wnaf_entries[num_quads + 1] = { 0 }; - - bool skew = false; - barretenberg::wnaf::fixed_wnaf(&scalar_multiplier_base.data[0], &wnaf_entries[0], skew, 0); - - fr accumulator_offset = (fr::one() + fr::one()).pow(static_cast(initial_exponent)).invert(); - fr origin_accumulators[2]{ fr::one(), accumulator_offset + fr::one() }; - - grumpkin::g1::element* multiplication_transcript = - static_cast(aligned_alloc(64, sizeof(grumpkin::g1::element) * (num_quads + 1))); - fr* accumulator_transcript = static_cast(aligned_alloc(64, sizeof(fr) * (num_quads + 1))); - - if (skew) { - multiplication_transcript[0] = origin_points[1]; - accumulator_transcript[0] = origin_accumulators[1]; - } else { - multiplication_transcript[0] = origin_points[0]; - accumulator_transcript[0] = origin_accumulators[0]; - } - - fr one = fr::one(); - fr three = ((one + one) + one); - for (size_t i = 0; i < num_quads; ++i) { - uint64_t entry = wnaf_entries[i + 1] & crypto::generators::WNAF_MASK; - fr prev_accumulator = accumulator_transcript[i] + accumulator_transcript[i]; - prev_accumulator = prev_accumulator + prev_accumulator; - - grumpkin::g1::affine_element point_to_add = (entry == 1) ? ladder[i + 1].three : ladder[i + 1].one; - fr scalar_to_add = (entry == 1) ? three : one; - uint64_t predicate = (wnaf_entries[i + 1] >> 31U) & 1U; - if (predicate) { - point_to_add = -point_to_add; - scalar_to_add.self_neg(); - } - accumulator_transcript[i + 1] = prev_accumulator + scalar_to_add; - multiplication_transcript[i + 1] = multiplication_transcript[i] + point_to_add; - } - grumpkin::g1::element::batch_normalize(&multiplication_transcript[0], num_quads + 1); - - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - - fr x_alpha = accumulator_offset; - for (size_t i = 0; i < num_quads; ++i) { - fixed_group_add_quad_ round_quad; - round_quad.d = builder.add_variable(accumulator_transcript[i]); - round_quad.a = builder.add_variable(multiplication_transcript[i].x); - round_quad.b = builder.add_variable(multiplication_transcript[i].y); - round_quad.c = builder.add_variable(x_alpha); - if ((wnaf_entries[i + 1] & 0xffffffU) == 0) { - x_alpha = ladder[i + 1].one.x; - } else { - x_alpha = ladder[i + 1].three.x; - } - round_quad.q_x_1 = ladder[i + 1].q_x_1; - round_quad.q_x_2 = ladder[i + 1].q_x_2; - round_quad.q_y_1 = ladder[i + 1].q_y_1; - round_quad.q_y_2 = ladder[i + 1].q_y_2; - - if (i > 0) { - builder.create_fixed_group_add_gate(round_quad); - } else { - builder.create_fixed_group_add_gate_with_init(round_quad, - { origin_points[0].x, - (origin_points[0].x - origin_points[1].x), - origin_points[0].y, - (origin_points[0].y - origin_points[1].y) }); - } - } - - builder.create_big_add_gate({ builder.add_variable(multiplication_transcript[num_quads].x), - builder.add_variable(multiplication_transcript[num_quads].y), - builder.add_variable(x_alpha), - builder.add_variable(accumulator_transcript[num_quads]), - fr::zero(), - fr::zero(), - fr::zero(), - fr::zero(), - fr::zero() }); - - grumpkin::g1::element expected_point = - grumpkin::g1::element(generator * scalar_multiplier.to_montgomery_form()).normalize(); - EXPECT_EQ((multiplication_transcript[num_quads].x == expected_point.x), true); - EXPECT_EQ((multiplication_transcript[num_quads].y == expected_point.y), true); - - fr result_accumulator = (accumulator_transcript[num_quads]); - fr expected_accumulator = - fr{ scalar_multiplier.data[0], scalar_multiplier.data[1], scalar_multiplier.data[2], scalar_multiplier.data[3] } - .to_montgomery_form(); - EXPECT_EQ((result_accumulator == expected_accumulator), true); - - auto prover = composer.create_prover(builder); - - auto verifier = composer.create_verifier(builder); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - - EXPECT_EQ(result, true); - - free(multiplication_transcript); - free(accumulator_transcript); -} - -TEST(turbo_plonk_composer, range_constraint) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - - for (size_t i = 0; i < 10; ++i) { - uint32_t value = engine.get_random_uint32(); - fr witness_value = fr{ value, 0, 0, 0 }.to_montgomery_form(); - uint32_t witness_index = builder.add_variable(witness_value); - - // include non-nice numbers of bits, that will bleed over gate boundaries - size_t extra_bits = 2 * (i % 4); - - std::vector accumulators = builder.decompose_into_base4_accumulators( - witness_index, 32 + extra_bits, "constraint in test range_constraint fails"); - - for (uint32_t j = 0; j < 16; ++j) { - uint32_t result = (value >> (30U - (2 * j))); - fr source = builder.get_variable(accumulators[j + (extra_bits >> 1)]).from_montgomery_form(); - uint32_t expected = static_cast(source.data[0]); - EXPECT_EQ(result, expected); - } - for (uint32_t j = 1; j < 16; ++j) { - uint32_t left = (value >> (30U - (2 * j))); - uint32_t right = (value >> (30U - (2 * (j - 1)))); - EXPECT_EQ(left - 4 * right < 4, true); - } - } - - uint32_t zero_idx = builder.add_variable(fr::zero()); - uint32_t one_idx = builder.add_variable(fr::one()); - builder.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, one_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - auto prover = composer.create_prover(builder); - - auto verifier = composer.create_verifier(builder); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - - EXPECT_EQ(result, true); -} - -TEST(turbo_plonk_composer, range_constraint_fail) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - - uint64_t value = 0xffffff; - uint32_t witness_index = builder.add_variable(fr(value)); - - builder.decompose_into_base4_accumulators(witness_index, 23, "yay, range constraint fails"); - - auto prover = composer.create_prover(builder); - - auto verifier = composer.create_verifier(builder); - - plonk::proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - - EXPECT_EQ(result, false); -} - -/** - * @brief Test that the `AND` constraint fails when constraining too few bits. - * - */ -TEST(turbo_plonk_composer, and_constraint_failure) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - - uint32_t left_value = 4; - fr left_witness_value = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t left_witness_index = builder.add_variable(left_witness_value); - - uint32_t right_value = 5; - fr right_witness_value = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t right_witness_index = builder.add_variable(right_witness_value); - - // 4 && 5 is 4, so 3 bits are needed, but we only constrain 2 - auto accumulators = builder.create_and_constraint(left_witness_index, right_witness_index, 2); - - auto prover = composer.create_prover(builder); - - auto verifier = composer.create_verifier(builder); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - - if (builder.failed()) { - info("Circuit construction failed; ", builder.err()); - } - - EXPECT_EQ(result, false); -} - -TEST(turbo_plonk_composer, and_constraint) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - - for (size_t i = 0; i < /*10*/ 1; ++i) { - uint32_t left_value = engine.get_random_uint32(); - - fr left_witness_value = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t left_witness_index = builder.add_variable(left_witness_value); - - uint32_t right_value = engine.get_random_uint32(); - fr right_witness_value = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t right_witness_index = builder.add_variable(right_witness_value); - - uint32_t out_value = left_value & right_value; - // include non-nice numbers of bits, that will bleed over gate boundaries - size_t extra_bits = 2 * (i % 4); - - auto accumulators = builder.create_and_constraint(left_witness_index, right_witness_index, 32 + extra_bits); - // builder.create_and_constraint(left_witness_index, right_witness_index, 32 + extra_bits); - - for (uint32_t j = 0; j < 16; ++j) { - uint32_t left_expected = (left_value >> (30U - (2 * j))); - uint32_t right_expected = (right_value >> (30U - (2 * j))); - uint32_t out_expected = left_expected & right_expected; - - fr left_source = builder.get_variable(accumulators.left[j + (extra_bits >> 1)]).from_montgomery_form(); - uint32_t left_result = static_cast(left_source.data[0]); - - fr right_source = builder.get_variable(accumulators.right[j + (extra_bits >> 1)]).from_montgomery_form(); - uint32_t right_result = static_cast(right_source.data[0]); - - fr out_source = builder.get_variable(accumulators.out[j + (extra_bits >> 1)]).from_montgomery_form(); - uint32_t out_result = static_cast(out_source.data[0]); - - EXPECT_EQ(left_result, left_expected); - EXPECT_EQ(right_result, right_expected); - EXPECT_EQ(out_result, out_expected); - } - for (uint32_t j = 1; j < 16; ++j) { - uint32_t left = (left_value >> (30U - (2 * j))); - uint32_t right = (left_value >> (30U - (2 * (j - 1)))); - EXPECT_EQ(left - 4 * right < 4, true); - - left = (right_value >> (30U - (2 * j))); - right = (right_value >> (30U - (2 * (j - 1)))); - EXPECT_EQ(left - 4 * right < 4, true); - - left = (out_value >> (30U - (2 * j))); - right = (out_value >> (30U - (2 * (j - 1)))); - EXPECT_EQ(left - 4 * right < 4, true); - } - } - - uint32_t zero_idx = builder.add_variable(fr::zero()); - uint32_t one_idx = builder.add_variable(fr::one()); - builder.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, one_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - auto prover = composer.create_prover(builder); - - auto verifier = composer.create_verifier(builder); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - - EXPECT_EQ(result, true); -} - -/** - * @brief Test that the `XOR` constraint fails when constraining too few bits. - * - */ -TEST(turbo_plonk_composer, xor_constraint_failure) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - - uint32_t left_value = 4; - fr left_witness_value = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t left_witness_index = builder.add_variable(left_witness_value); - - uint32_t right_value = 1; - fr right_witness_value = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t right_witness_index = builder.add_variable(right_witness_value); - - // 4 && 1 is 5, so 3 bits are needed, but we only constrain 2 - auto accumulators = builder.create_and_constraint(left_witness_index, right_witness_index, 2); - - auto prover = composer.create_prover(builder); - - auto verifier = composer.create_verifier(builder); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - - if (builder.failed()) { - info("Circuit construction failed; ", builder.err()); - } - - EXPECT_EQ(result, false); -} - -TEST(turbo_plonk_composer, xor_constraint) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - - for (size_t i = 0; i < /*10*/ 1; ++i) { - uint32_t left_value = engine.get_random_uint32(); - - fr left_witness_value = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t left_witness_index = builder.add_variable(left_witness_value); - - uint32_t right_value = engine.get_random_uint32(); - fr right_witness_value = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t right_witness_index = builder.add_variable(right_witness_value); - - uint32_t out_value = left_value ^ right_value; - // include non-nice numbers of bits, that will bleed over gate boundaries - size_t extra_bits = 2 * (i % 4); - - auto accumulators = builder.create_xor_constraint(left_witness_index, right_witness_index, 32 + extra_bits); - - for (uint32_t j = 0; j < 16; ++j) { - uint32_t left_expected = (left_value >> (30U - (2 * j))); - uint32_t right_expected = (right_value >> (30U - (2 * j))); - uint32_t out_expected = left_expected ^ right_expected; - - fr left_source = builder.get_variable(accumulators.left[j + (extra_bits >> 1)]).from_montgomery_form(); - uint32_t left_result = static_cast(left_source.data[0]); - - fr right_source = builder.get_variable(accumulators.right[j + (extra_bits >> 1)]).from_montgomery_form(); - uint32_t right_result = static_cast(right_source.data[0]); - - fr out_source = builder.get_variable(accumulators.out[j + (extra_bits >> 1)]).from_montgomery_form(); - uint32_t out_result = static_cast(out_source.data[0]); - - EXPECT_EQ(left_result, left_expected); - EXPECT_EQ(right_result, right_expected); - EXPECT_EQ(out_result, out_expected); - } - for (uint32_t j = 1; j < 16; ++j) { - uint32_t left = (left_value >> (30U - (2 * j))); - uint32_t right = (left_value >> (30U - (2 * (j - 1)))); - EXPECT_EQ(left - 4 * right < 4, true); - - left = (right_value >> (30U - (2 * j))); - right = (right_value >> (30U - (2 * (j - 1)))); - EXPECT_EQ(left - 4 * right < 4, true); - - left = (out_value >> (30U - (2 * j))); - right = (out_value >> (30U - (2 * (j - 1)))); - EXPECT_EQ(left - 4 * right < 4, true); - } - } - - uint32_t zero_idx = builder.add_variable(fr::zero()); - uint32_t one_idx = builder.add_variable(fr::one()); - builder.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, one_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - auto prover = composer.create_prover(builder); - - auto verifier = composer.create_verifier(builder); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - - EXPECT_EQ(result, true); -} - -TEST(turbo_plonk_composer, big_add_gate_with_bit_extract) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - - const auto generate_constraints = [&](uint32_t quad_value) { - uint32_t quad_accumulator_left = - (engine.get_random_uint32() & 0x3fffffff) - quad_value; // make sure this won't overflow - uint32_t quad_accumulator_right = (4 * quad_accumulator_left) + quad_value; - - uint32_t left_idx = builder.add_variable(uint256_t(quad_accumulator_left)); - uint32_t right_idx = builder.add_variable(uint256_t(quad_accumulator_right)); - - uint32_t input = engine.get_random_uint32(); - uint32_t output = input + (quad_value > 1 ? 1 : 0); - - builder.create_big_add_gate_with_bit_extraction({ builder.add_variable(uint256_t(input)), - builder.add_variable(uint256_t(output)), - right_idx, - left_idx, - fr(6), - -fr(6), - fr::zero(), - fr::zero(), - fr::zero() }); - }; - - generate_constraints(0); - generate_constraints(1); - generate_constraints(2); - generate_constraints(3); - - auto prover = composer.create_prover(builder); - - auto verifier = composer.create_verifier(builder); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - - EXPECT_EQ(result, true); -} - -TEST(turbo_plonk_composer, validate_copy_constraints) -{ - for (size_t m = 0; m < 2; ++m) { - for (size_t k = 0; k < 4; ++k) { - for (size_t j = 0; j < 4; ++j) { - if (m == 0 && (j > 0 || k > 0)) { - continue; - } - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - - barretenberg::fr variables[4]{ - barretenberg::fr::random_element(), - barretenberg::fr::random_element(), - barretenberg::fr::random_element(), - barretenberg::fr::random_element(), - }; - - uint32_t indices[4]{ - builder.add_variable(variables[0]), - builder.add_variable(variables[1]), - builder.add_variable(variables[2]), - builder.add_variable(variables[3]), - }; - - for (size_t i = 0; i < 4; ++i) { - builder.create_big_add_gate({ - indices[0], - indices[1], - indices[2], - indices[3], - barretenberg::fr(0), - barretenberg::fr(0), - barretenberg::fr(0), - barretenberg::fr(0), - barretenberg::fr(0), - }); - - builder.create_big_add_gate({ - indices[3], - indices[2], - indices[1], - indices[0], - barretenberg::fr(0), - barretenberg::fr(0), - barretenberg::fr(0), - barretenberg::fr(0), - barretenberg::fr(0), - }); - } - - auto prover = composer.create_prover(builder); - - if (m > 0) { - prover.key->polynomial_store.get("w_" + std::to_string(k + 1) + "_lagrange")[j] = - barretenberg::fr::random_element(); - } - - auto verifier = composer.create_verifier(builder); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - - bool expected = (m == 0); - EXPECT_EQ(result, expected); - } - } - } -} - -TEST(turbo_plonk_composer, test_check_circuit_add_gate_proofs_correct) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - fr a = fr::one(); - fr b = fr::one(); - fr c = a + b; - fr d = a + c; - uint32_t a_idx = builder.add_variable(a); - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c); - uint32_t d_idx = builder.add_variable(d); - - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ d_idx, c_idx, a_idx, fr::one(), fr::neg_one(), fr::neg_one(), fr::zero() }); - - // TODO: proof fails if one wire contains all zeros. Should we support this? - uint32_t zero_idx = builder.add_variable(fr::zero()); - - builder.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, a_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - bool result = builder.check_circuit(); - EXPECT_EQ(result, true); -} - -TEST(turbo_plonk_composer, test_check_circuit_add_gate_proofs_broken) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - fr a = fr::one(); - fr b = fr::one(); - fr c = a + b; - fr d = a + c; - uint32_t a_idx = builder.add_variable(a); - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c + 1); - uint32_t d_idx = builder.add_variable(d); - - builder.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - builder.create_add_gate({ d_idx, c_idx, a_idx, fr::one(), fr::neg_one(), fr::neg_one(), fr::zero() }); - - // TODO: proof fails if one wire contains all zeros. Should we support this? - uint32_t zero_idx = builder.add_variable(fr::zero()); - - builder.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, a_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - bool result = builder.check_circuit(); - EXPECT_EQ(result, false); -} -TEST(turbo_plonk_composer, test_check_circuit_mul_gate_proofs_correct) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - fr q[7]{ fr::random_element(), fr::random_element(), fr::random_element(), fr::random_element(), - fr::random_element(), fr::random_element(), fr::random_element() }; - fr q_inv[7]{ - q[0].invert(), q[1].invert(), q[2].invert(), q[3].invert(), q[4].invert(), q[5].invert(), q[6].invert(), - }; - - fr a = fr::random_element(); - fr b = fr::random_element(); - fr c = -((((q[0] * a) + (q[1] * b)) + q[3]) * q_inv[2]); - fr d = -((((q[4] * (a * b)) + q[6]) * q_inv[5])); - - uint32_t a_idx = builder.add_public_variable(a); - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c); - uint32_t d_idx = builder.add_variable(d); - - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - - uint32_t zero_idx = builder.add_variable(fr::zero()); - uint32_t one_idx = builder.add_variable(fr::one()); - builder.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, one_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - uint32_t e_idx = builder.add_variable(a - fr::one()); - builder.create_add_gate({ e_idx, b_idx, c_idx, q[0], q[1], q[2], (q[3] + q[0]) }); - - bool result = builder.check_circuit(); - - EXPECT_EQ(result, true); -} - -TEST(turbo_plonk_composer, test_check_circuit_mul_gate_proofs_broken) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - fr q[7]{ fr::random_element(), fr::random_element(), fr::random_element(), fr::random_element(), - fr::random_element(), fr::random_element(), fr::random_element() }; - fr q_inv[7]{ - q[0].invert(), q[1].invert(), q[2].invert(), q[3].invert(), q[4].invert(), q[5].invert(), q[6].invert(), - }; - - fr a = fr::random_element(); - fr b = fr::random_element(); - fr c = -((((q[0] * a) + (q[1] * b)) + q[3]) * q_inv[2]); - fr d = -((((q[4] * (a * b)) + q[6]) * q_inv[5])); - - uint32_t a_idx = builder.add_public_variable(a); - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c + 1); - uint32_t d_idx = builder.add_variable(d); - - builder.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - builder.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - - uint32_t zero_idx = builder.add_variable(fr::zero()); - uint32_t one_idx = builder.add_variable(fr::one()); - builder.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, one_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - uint32_t e_idx = builder.add_variable(a - fr::one()); - builder.create_add_gate({ e_idx, b_idx, c_idx, q[0], q[1], q[2], (q[3] + q[0]) }); - - bool result = builder.check_circuit(); - - EXPECT_EQ(result, false); -} -TEST(turbo_plonk_composer, test_check_circuit_fixed_group) -{ - constexpr size_t num_bits = 254; - constexpr size_t num_quads_base = (num_bits - 1) >> 1; - constexpr size_t num_quads = ((num_quads_base << 1) + 1 < num_bits) ? num_quads_base + 1 : num_quads_base; - constexpr size_t num_wnaf_bits = (num_quads << 1) + 1; - - constexpr size_t initial_exponent = num_bits; // ((num_bits & 1) == 1) ? num_bits - 1 : num_bits; - auto gen_data = crypto::generators::get_generator_data(DEFAULT_GEN_1); - const crypto::generators::fixed_base_ladder* ladder = gen_data.get_ladder(num_bits); - grumpkin::g1::affine_element generator = gen_data.generator; - - grumpkin::g1::element origin_points[2]; - origin_points[0] = grumpkin::g1::element(ladder[0].one); - origin_points[1] = origin_points[0] + generator; - origin_points[1] = origin_points[1].normalize(); - - grumpkin::fr scalar_multiplier_base = grumpkin::fr::random_element(); - - grumpkin::fr scalar_multiplier = scalar_multiplier_base.from_montgomery_form(); - - if ((scalar_multiplier.data[0] & 1) == 0) { - grumpkin::fr two = grumpkin::fr::one() + grumpkin::fr::one(); - scalar_multiplier_base = scalar_multiplier_base - two; - } - scalar_multiplier_base = scalar_multiplier_base.from_montgomery_form(); - uint64_t wnaf_entries[num_quads + 1] = { 0 }; - - bool skew = false; - barretenberg::wnaf::fixed_wnaf(&scalar_multiplier_base.data[0], &wnaf_entries[0], skew, 0); - - fr accumulator_offset = (fr::one() + fr::one()).pow(static_cast(initial_exponent)).invert(); - fr origin_accumulators[2]{ fr::one(), accumulator_offset + fr::one() }; - - grumpkin::g1::element* multiplication_transcript = - static_cast(aligned_alloc(64, sizeof(grumpkin::g1::element) * (num_quads + 1))); - fr* accumulator_transcript = static_cast(aligned_alloc(64, sizeof(fr) * (num_quads + 1))); - - if (skew) { - multiplication_transcript[0] = origin_points[1]; - accumulator_transcript[0] = origin_accumulators[1]; - } else { - multiplication_transcript[0] = origin_points[0]; - accumulator_transcript[0] = origin_accumulators[0]; - } - - fr one = fr::one(); - fr three = ((one + one) + one); - for (size_t i = 0; i < num_quads; ++i) { - uint64_t entry = wnaf_entries[i + 1] & 0xffffff; - fr prev_accumulator = accumulator_transcript[i] + accumulator_transcript[i]; - prev_accumulator = prev_accumulator + prev_accumulator; - - grumpkin::g1::affine_element point_to_add = (entry == 1) ? ladder[i + 1].three : ladder[i + 1].one; - fr scalar_to_add = (entry == 1) ? three : one; - uint64_t predicate = (wnaf_entries[i + 1] >> 31U) & 1U; - if (predicate) { - point_to_add = -point_to_add; - scalar_to_add.self_neg(); - } - accumulator_transcript[i + 1] = prev_accumulator + scalar_to_add; - multiplication_transcript[i + 1] = multiplication_transcript[i] + point_to_add; - } - grumpkin::g1::element::batch_normalize(&multiplication_transcript[0], num_quads + 1); - - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - - fr x_alpha = accumulator_offset; - for (size_t i = 0; i < num_quads; ++i) { - fixed_group_add_quad_ round_quad; - round_quad.d = builder.add_variable(accumulator_transcript[i]); - round_quad.a = builder.add_variable(multiplication_transcript[i].x); - round_quad.b = builder.add_variable(multiplication_transcript[i].y); - round_quad.c = builder.add_variable(x_alpha); - if ((wnaf_entries[i + 1] & 0xffffffU) == 0) { - x_alpha = ladder[i + 1].one.x; - } else { - x_alpha = ladder[i + 1].three.x; - } - round_quad.q_x_1 = ladder[i + 1].q_x_1; - round_quad.q_x_2 = ladder[i + 1].q_x_2; - round_quad.q_y_1 = ladder[i + 1].q_y_1; - round_quad.q_y_2 = ladder[i + 1].q_y_2; - - if (i > 0) { - builder.create_fixed_group_add_gate(round_quad); - } else { - builder.create_fixed_group_add_gate_with_init(round_quad, - { origin_points[0].x, - (origin_points[0].x - origin_points[1].x), - origin_points[0].y, - (origin_points[0].y - origin_points[1].y) }); - } - } - - builder.create_big_add_gate({ builder.add_variable(multiplication_transcript[num_quads].x), - builder.add_variable(multiplication_transcript[num_quads].y), - builder.add_variable(x_alpha), - builder.add_variable(accumulator_transcript[num_quads]), - fr::zero(), - fr::zero(), - fr::zero(), - fr::zero(), - fr::zero() }); - - grumpkin::g1::element expected_point = - grumpkin::g1::element(generator * scalar_multiplier.to_montgomery_form()).normalize(); - EXPECT_EQ((multiplication_transcript[num_quads].x == expected_point.x), true); - EXPECT_EQ((multiplication_transcript[num_quads].y == expected_point.y), true); - - fr result_accumulator = (accumulator_transcript[num_quads]); - fr expected_accumulator = - fr{ scalar_multiplier.data[0], scalar_multiplier.data[1], scalar_multiplier.data[2], scalar_multiplier.data[3] } - .to_montgomery_form(); - EXPECT_EQ((result_accumulator == expected_accumulator), true); - - bool result = builder.check_circuit(); - - EXPECT_EQ(result, true); - - free(multiplication_transcript); - free(accumulator_transcript); -} - -TEST(turbo_plonk_composer, test_check_circuit_range_constraint) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - - for (size_t i = 0; i < 10; ++i) { - uint32_t value = engine.get_random_uint32(); - fr witness_value = fr{ value, 0, 0, 0 }.to_montgomery_form(); - uint32_t witness_index = builder.add_variable(witness_value); - - // include non-nice numbers of bits, that will bleed over gate boundaries - size_t extra_bits = 2 * (i % 4); - - std::vector accumulators = builder.decompose_into_base4_accumulators( - witness_index, 32 + extra_bits, "range constraint fails in test_check_circuit_range_constraint"); - } - - uint32_t zero_idx = builder.add_variable(fr::zero()); - uint32_t one_idx = builder.add_variable(fr::one()); - builder.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, one_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - bool result = builder.check_circuit(); - - EXPECT_EQ(result, true); -} - -TEST(turbo_plonk_composer, test_check_circuit_xor) -{ - auto builder = TurboCircuitBuilder(); - auto composer = TurboComposer(); - - for (size_t i = 0; i < /*10*/ 1; ++i) { - uint32_t left_value = engine.get_random_uint32(); - - fr left_witness_value = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t left_witness_index = builder.add_variable(left_witness_value); - - uint32_t right_value = engine.get_random_uint32(); - fr right_witness_value = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t right_witness_index = builder.add_variable(right_witness_value); - - // include non-nice numbers of bits, that will bleed over gate boundaries - size_t extra_bits = 2 * (i % 4); - - auto accumulators = builder.create_xor_constraint(left_witness_index, right_witness_index, 32 + extra_bits); - } - - uint32_t zero_idx = builder.add_variable(fr::zero()); - uint32_t one_idx = builder.add_variable(fr::one()); - builder.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, one_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - bool result = builder.check_circuit(); - - EXPECT_EQ(result, true); -} -} // namespace proof_system::plonk::test_turbo_plonk_composer \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.test.cpp b/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.test.cpp index 99b3b8232d3..e1c932c6a92 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.test.cpp @@ -276,53 +276,50 @@ TYPED_TEST(ultra_plonk_composer, non_trivial_tag_permutation_and_cycles) TYPED_TEST(ultra_plonk_composer, bad_tag_permutation) { - auto builder = UltraCircuitBuilder(); - auto composer = UltraComposer(); - fr a = fr::random_element(); - fr b = -a; - - auto a_idx = builder.add_variable(a); - auto b_idx = builder.add_variable(b); - auto c_idx = builder.add_variable(b); - auto d_idx = builder.add_variable(a + 1); + { + auto builder = UltraCircuitBuilder(); + auto composer = UltraComposer(); + fr a = fr::random_element(); + fr b = -a; - builder.create_add_gate({ a_idx, b_idx, builder.zero_idx, 1, 1, 0, 0 }); - builder.create_add_gate({ c_idx, d_idx, builder.zero_idx, 1, 1, 0, -1 }); + auto a_idx = builder.add_variable(a); + auto b_idx = builder.add_variable(b); + auto c_idx = builder.add_variable(b); + auto d_idx = builder.add_variable(a + 1); - builder.create_tag(1, 2); - builder.create_tag(2, 1); + builder.create_add_gate({ a_idx, b_idx, builder.zero_idx, 1, 1, 0, 0 }); + builder.create_add_gate({ c_idx, d_idx, builder.zero_idx, 1, 1, 0, -1 }); - builder.assign_tag(a_idx, 1); - builder.assign_tag(b_idx, 1); - builder.assign_tag(c_idx, 2); - builder.assign_tag(d_idx, 2); + builder.create_tag(1, 2); + builder.create_tag(2, 1); - TestFixture::prove_and_verify(builder, composer, /*expected_result=*/false); -} + builder.assign_tag(a_idx, 1); + builder.assign_tag(b_idx, 1); + builder.assign_tag(c_idx, 2); + builder.assign_tag(d_idx, 2); -// same as above but with turbocomposer to check reason of failue is really tag mismatch -TYPED_TEST(ultra_plonk_composer, bad_tag_turbo_permutation) -{ - auto builder = UltraCircuitBuilder(); - auto composer = UltraComposer(); - fr a = fr::random_element(); - fr b = -a; + TestFixture::prove_and_verify(builder, composer, /*expected_result=*/false); + } + // Same as above but without tag creation to check reason of failure is really tag mismatch + { + auto builder = UltraCircuitBuilder(); + auto composer = UltraComposer(); + fr a = fr::random_element(); + fr b = -a; - auto a_idx = builder.add_variable(a); - auto b_idx = builder.add_variable(b); - auto c_idx = builder.add_variable(b); - auto d_idx = builder.add_variable(a + 1); + auto a_idx = builder.add_variable(a); + auto b_idx = builder.add_variable(b); + auto c_idx = builder.add_variable(b); + auto d_idx = builder.add_variable(a + 1); - builder.create_add_gate({ a_idx, b_idx, builder.zero_idx, 1, 1, 0, 0 }); - builder.create_add_gate({ c_idx, d_idx, builder.zero_idx, 1, 1, 0, -1 }); + builder.create_add_gate({ a_idx, b_idx, builder.zero_idx, 1, 1, 0, 0 }); + builder.create_add_gate({ c_idx, d_idx, builder.zero_idx, 1, 1, 0, -1 }); - // builder.create_add_gate({ a_idx, b_idx, builder.zero_idx, fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); - // builder.create_add_gate({ a_idx, b_idx, builder.zero_idx, fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); - // builder.create_add_gate({ a_idx, b_idx, builder.zero_idx, fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); - auto prover = composer.create_prover(builder); - auto verifier = composer.create_verifier(builder); + auto prover = composer.create_prover(builder); + auto verifier = composer.create_verifier(builder); - TestFixture::prove_and_verify(builder, composer, /*expected_result=*/true); + TestFixture::prove_and_verify(builder, composer, /*expected_result=*/true); + } } TYPED_TEST(ultra_plonk_composer, sort_widget) diff --git a/barretenberg/cpp/src/barretenberg/plonk/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/plonk/flavor/flavor.hpp index 87e22689d45..967b0c1539a 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/flavor/flavor.hpp @@ -1,7 +1,6 @@ #pragma once #include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" #include "barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp" -#include "barretenberg/proof_system/circuit_builder/turbo_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" #include "barretenberg/proof_system/flavor/flavor.hpp" @@ -18,18 +17,6 @@ class Standard { static constexpr bool has_zero_row = false; }; -class Turbo { - public: - using CircuitBuilder = proof_system::TurboCircuitBuilder; - using ProvingKey = plonk::proving_key; - using Curve = curve::BN254; - using FF = Curve::ScalarField; - using Polynomial = barretenberg::Polynomial; - static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES; - // Whether or not the first row of the execution trace is reserved for 0s to enable shifts - static constexpr bool has_zero_row = false; -}; - class Ultra { public: using CircuitBuilder = proof_system::UltraCircuitBuilder; diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/commitment_scheme.test.cpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/commitment_scheme.test.cpp index e874cb7b5e9..cfc63adf8cd 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/commitment_scheme.test.cpp +++ b/barretenberg/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/commitment_scheme.test.cpp @@ -33,7 +33,7 @@ TEST(commitment_scheme, kate_open) // compute opening polynomial W(X), and evaluation f = F(z) transcript::StandardTranscript inp_tx = transcript::StandardTranscript(transcript::Manifest()); - plonk::KateCommitmentScheme newKate; + plonk::KateCommitmentScheme newKate; // std::shared_ptr> crs_factory = (new // FileReferenceStringFactory("../srs_db/ignition")); @@ -92,7 +92,7 @@ TEST(commitment_scheme, kate_batch_open) // setting up the Kate commitment scheme class transcript::StandardTranscript inp_tx = transcript::StandardTranscript(transcript::Manifest()); - plonk::KateCommitmentScheme newKate; + plonk::KateCommitmentScheme newKate; auto file_crs = std::make_shared>("../srs_db/ignition"); auto crs = file_crs->get_prover_crs(n); diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.cpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.cpp index ccdf2eb4c1e..46a0507a52d 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.cpp +++ b/barretenberg/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.cpp @@ -39,7 +39,7 @@ void KateCommitmentScheme::compute_opening_polynomial(const fr* src, // We assume that the commitment is well-formed and that there is no remainder term. // Under these conditions we can perform this polynomial division in linear time with good constants. - // Note that the opening polynomial always has (n+1) coefficients for Standard/Turbo/Ultra due to + // Note that the opening polynomial always has (n+1) coefficients for Standard/Ultra due to // the blinding of the quotient polynomial parts. fr f = polynomial_arithmetic::evaluate(src, z_point, n + 1); @@ -200,7 +200,7 @@ void KateCommitmentScheme::batch_open(const transcript::StandardTransc } ITERATE_OVER_DOMAIN_END; - // Adjust the (n + 1)th coefficient of t_{0,1,2}(X) or r(X) (Note: t_4 (Turbo/Ultra) has only n coefficients) + // Adjust the (n + 1)th coefficient of t_{0,1,2}(X) or r(X) (Note: t_4 (Ultra) has only n coefficients) opening_poly[input_key->circuit_size] = 0; const fr zeta_pow_n = zeta.pow(static_cast(input_key->circuit_size)); @@ -388,7 +388,6 @@ void KateCommitmentScheme::add_opening_evaluations_to_transcript( } template class KateCommitmentScheme; -template class KateCommitmentScheme; template class KateCommitmentScheme; template class KateCommitmentScheme; template class KateCommitmentScheme; diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.hpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.hpp index 0ddebc4271a..49a44df984f 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.hpp @@ -40,7 +40,6 @@ template class KateCommitmentScheme : public CommitmentSchem }; extern template class KateCommitmentScheme; -extern template class KateCommitmentScheme; extern template class KateCommitmentScheme; extern template class KateCommitmentScheme; extern template class KateCommitmentScheme; diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/prover/prover.cpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/prover/prover.cpp index 6d1b9de2ad9..227a0679197 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/prover/prover.cpp +++ b/barretenberg/cpp/src/barretenberg/plonk/proof_system/prover/prover.cpp @@ -127,7 +127,7 @@ template void ProverBase::compute_quotient_commitm // // NOTE: If in future there is a need to cut off more zeros off the vanishing polynomial, the degree of // the quotient polynomial t(X) will increase, so the degrees of t_{high}, t_{mid}, t_{low} could also - // increase according to the type of the composer type we are using. Currently, for TurboPLONK and Ultra- + // increase according to the type of the composer type we are using. Currently, for Ultra- // PLONK, the degree of t(X) is (4n - 1) and hence each t_{low}, t_{mid}, t_{high}, t_{higher} each is of // degree (n - 1) (and thus contains n coefficients). Therefore, we are on the brink! // If we need to cut out more zeros off the vanishing polynomial, sizes of coefficients of individual @@ -138,7 +138,7 @@ template void ProverBase::compute_quotient_commitm auto coefficients = key->quotient_polynomial_parts[i].data(); std::string quotient_tag = "T_" + std::to_string(i + 1); // Set flag that determines domain size (currently n or n+1) in pippenger (see process_queue()). - // Note: After blinding, all t_i have size n+1 representation (degree n) except t_4 in Turbo/Ultra. + // Note: After blinding, all t_i have size n+1 representation (degree n) except t_4 in Ultra. fr domain_size_flag = i > 2 ? key->circuit_size : (key->circuit_size + 1); commitment_scheme->commit(coefficients, quotient_tag, domain_size_flag, queue); } @@ -191,7 +191,7 @@ template void ProverBase::execute_preamble_round() // Why do we need 2 random scalars in witness polynomials? The reason is: our witness polynomials are // evaluated at only 1 point (\scripted{z}), so adding a random degree-1 polynomial suffices. // - // NOTE: In TurboPlonk and UltraPlonk, the witness polynomials are evaluated at 2 points and thus + // NOTE: In UltraPlonk, the witness polynomials are evaluated at 2 points and thus // we need to add 3 random scalars in them. // // We start adding random scalars in `wire` polynomials from index (n - k) upto (n - k + 2). @@ -573,7 +573,6 @@ template void ProverBase::add_plookup_memory_recor } template class ProverBase; -template class ProverBase; template class ProverBase; template class ProverBase; template class ProverBase; diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/prover/prover.hpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/prover/prover.hpp index 166bcbdb145..76295aafc72 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/prover/prover.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/proof_system/prover/prover.hpp @@ -99,12 +99,10 @@ template class ProverBase { plonk::proof proof; }; extern template class ProverBase; -extern template class ProverBase; extern template class ProverBase; extern template class ProverBase; typedef ProverBase Prover; -typedef ProverBase TurboProver; typedef ProverBase UltraProver; // TODO(Mike): maybe just return a templated proverbase so that I don't // need separate cases for ultra vs ultra_to_standard...??? // TODO(Cody): Make this into an issue? diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/polynomial_manifest.hpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/polynomial_manifest.hpp index b4115ce9a50..d4148be017b 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/polynomial_manifest.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/polynomial_manifest.hpp @@ -105,30 +105,6 @@ static constexpr PolynomialDescriptor standard_polynomial_manifest[STANDARD_MANI PolynomialDescriptor("SIGMA_3", "sigma_3", false, PERMUTATION, SIGMA_3), // }; -static constexpr size_t TURBO_MANIFEST_SIZE = 20; -static constexpr PolynomialDescriptor turbo_polynomial_manifest[TURBO_MANIFEST_SIZE]{ - PolynomialDescriptor("W_1", "w_1", true, WITNESS, W_1), // - PolynomialDescriptor("W_2", "w_2", true, WITNESS, W_2), // - PolynomialDescriptor("W_3", "w_3", true, WITNESS, W_3), // - PolynomialDescriptor("W_4", "w_4", true, WITNESS, W_4), // - PolynomialDescriptor("Z_PERM", "z_perm", true, WITNESS, Z), // - PolynomialDescriptor("Q_1", "q_1", false, SELECTOR, Q_1), // - PolynomialDescriptor("Q_2", "q_2", false, SELECTOR, Q_2), // - PolynomialDescriptor("Q_3", "q_3", false, SELECTOR, Q_3), // - PolynomialDescriptor("Q_4", "q_4", false, SELECTOR, Q_4), // - PolynomialDescriptor("Q_5", "q_5", false, SELECTOR, Q_5), // - PolynomialDescriptor("Q_M", "q_m", false, SELECTOR, Q_M), // - PolynomialDescriptor("Q_C", "q_c", false, SELECTOR, Q_C), // - PolynomialDescriptor("Q_ARITHMETIC", "q_arith", false, SELECTOR, Q_ARITHMETIC), // - PolynomialDescriptor("Q_RANGE", "q_range", false, SELECTOR, Q_RANGE), // - PolynomialDescriptor("Q_FIXED_BASE", "q_fixed_base", false, SELECTOR, Q_FIXED_BASE), // - PolynomialDescriptor("Q_LOGIC", "q_logic", false, SELECTOR, Q_LOGIC), // - PolynomialDescriptor("SIGMA_1", "sigma_1", false, PERMUTATION, SIGMA_1), // - PolynomialDescriptor("SIGMA_2", "sigma_2", false, PERMUTATION, SIGMA_2), // - PolynomialDescriptor("SIGMA_3", "sigma_3", false, PERMUTATION, SIGMA_3), // - PolynomialDescriptor("SIGMA_4", "sigma_4", false, PERMUTATION, SIGMA_4), // -}; - static constexpr size_t ULTRA_MANIFEST_SIZE = 30; static constexpr PolynomialDescriptor ultra_polynomial_manifest[ULTRA_MANIFEST_SIZE]{ PolynomialDescriptor("W_1", "w_1", true, WITNESS, W_1), // @@ -181,12 +157,6 @@ class PolynomialManifest { std::back_inserter(manifest)); break; }; - case CircuitType::TURBO: { - std::copy(turbo_polynomial_manifest, - turbo_polynomial_manifest + TURBO_MANIFEST_SIZE, - std::back_inserter(manifest)); - break; - }; case CircuitType::ULTRA: { std::copy(ultra_polynomial_manifest, ultra_polynomial_manifest + ULTRA_MANIFEST_SIZE, diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/program_settings.hpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/program_settings.hpp index ea450a11b9e..20ff3a92085 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/program_settings.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/program_settings.hpp @@ -10,11 +10,9 @@ #include "../widgets/transition_widgets/elliptic_widget.hpp" #include "../widgets/transition_widgets/fixed_base_widget.hpp" #include "../widgets/transition_widgets/genperm_sort_widget.hpp" +#include "../widgets/transition_widgets/logic_widget.hpp" #include "../widgets/transition_widgets/plookup_arithmetic_widget.hpp" #include "../widgets/transition_widgets/plookup_auxiliary_widget.hpp" -#include "../widgets/transition_widgets/turbo_arithmetic_widget.hpp" -#include "../widgets/transition_widgets/turbo_logic_widget.hpp" -#include "../widgets/transition_widgets/turbo_range_widget.hpp" #include "./prover_settings.hpp" namespace proof_system::plonk { @@ -59,61 +57,6 @@ class standard_verifier_settings : public standard_settings { } }; -class turbo_verifier_settings : public turbo_settings { - public: - typedef barretenberg::fr fr; - typedef barretenberg::g1 g1; - typedef transcript::StandardTranscript Transcript; - typedef VerifierTurboArithmeticWidget TurboArithmeticWidget; - typedef VerifierTurboFixedBaseWidget TurboFixedBaseWidget; - typedef VerifierTurboRangeWidget TurboRangeWidget; - typedef VerifierTurboLogicWidget TurboLogicWidget; - typedef VerifierPermutationWidget PermutationWidget; - - static constexpr size_t num_challenge_bytes = - 16; // Challenges are only 128-bits (16-bytes) to reduce the number of constraints required in the verification - // circuit. 128-bits is ample security, given the security of altBN254 snarks is in the low-100-bits. - static constexpr transcript::HashType hash_type = transcript::HashType::PedersenBlake3s; - static constexpr bool idpolys = false; - - static fr append_scalar_multiplication_inputs(verification_key* key, - const fr& alpha_base, - const Transcript& transcript, - std::map& scalars) - { - auto updated_alpha = PermutationWidget::append_scalar_multiplication_inputs(key, alpha_base, transcript); - - updated_alpha = - TurboArithmeticWidget::append_scalar_multiplication_inputs(key, updated_alpha, transcript, scalars); - updated_alpha = - TurboFixedBaseWidget::append_scalar_multiplication_inputs(key, updated_alpha, transcript, scalars); - updated_alpha = TurboRangeWidget::append_scalar_multiplication_inputs(key, updated_alpha, transcript, scalars); - updated_alpha = TurboLogicWidget::append_scalar_multiplication_inputs(key, updated_alpha, transcript, scalars); - - return updated_alpha; - } - - static barretenberg::fr compute_quotient_evaluation_contribution(verification_key* key, - const barretenberg::fr& alpha_base, - const Transcript& transcript, - barretenberg::fr& quotient_numerator_eval) - { - auto updated_alpha_base = PermutationWidget::compute_quotient_evaluation_contribution( - key, alpha_base, transcript, quotient_numerator_eval, idpolys); - - updated_alpha_base = TurboArithmeticWidget::compute_quotient_evaluation_contribution( - key, updated_alpha_base, transcript, quotient_numerator_eval); - updated_alpha_base = TurboFixedBaseWidget::compute_quotient_evaluation_contribution( - key, updated_alpha_base, transcript, quotient_numerator_eval); - updated_alpha_base = TurboRangeWidget::compute_quotient_evaluation_contribution( - key, updated_alpha_base, transcript, quotient_numerator_eval); - updated_alpha_base = TurboLogicWidget::compute_quotient_evaluation_contribution( - key, updated_alpha_base, transcript, quotient_numerator_eval); - - return updated_alpha_base; - } -}; - class ultra_verifier_settings : public ultra_settings { public: typedef barretenberg::fr fr; @@ -121,7 +64,7 @@ class ultra_verifier_settings : public ultra_settings { typedef transcript::StandardTranscript Transcript; typedef VerifierPlookupArithmeticWidget PlookupArithmeticWidget; typedef VerifierGenPermSortWidget GenPermSortWidget; - typedef VerifierTurboLogicWidget TurboLogicWidget; + typedef VerifierLogicWidget LogicWidget; typedef VerifierPermutationWidget PermutationWidget; typedef VerifierPlookupWidget PlookupWidget; typedef VerifierEllipticWidget EllipticWidget; @@ -177,7 +120,7 @@ class ultra_to_standard_verifier_settings : public ultra_verifier_settings { typedef VerifierPlookupArithmeticWidget PlookupArithmeticWidget; typedef VerifierGenPermSortWidget GenPermSortWidget; - typedef VerifierTurboLogicWidget TurboLogicWidget; + typedef VerifierLogicWidget LogicWidget; typedef VerifierPermutationWidget PermutationWidget; typedef VerifierPlookupWidget PlookupWidget; typedef VerifierEllipticWidget EllipticWidget; @@ -193,7 +136,7 @@ class ultra_with_keccak_verifier_settings : public ultra_verifier_settings { typedef VerifierPlookupArithmeticWidget PlookupArithmeticWidget; typedef VerifierGenPermSortWidget GenPermSortWidget; - typedef VerifierTurboLogicWidget TurboLogicWidget; + typedef VerifierLogicWidget LogicWidget; typedef VerifierPermutationWidget PermutationWidget; typedef VerifierPlookupWidget PlookupWidget; typedef VerifierEllipticWidget EllipticWidget; diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp index 67d77015d8d..47fffbf8280 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp @@ -24,19 +24,6 @@ class standard_settings : public settings_base { static constexpr bool is_plookup = false; }; -class turbo_settings : public settings_base { - public: - static constexpr size_t num_challenge_bytes = 16; - static constexpr transcript::HashType hash_type = transcript::HashType::PedersenBlake3s; - static constexpr size_t program_width = 4; - static constexpr size_t num_shifted_wire_evaluations = 4; - static constexpr uint64_t wire_shift_settings = 0b1111; - static constexpr uint32_t permutation_shift = 30; - static constexpr uint32_t permutation_mask = 0xC0000000; - static constexpr size_t num_roots_cut_out_of_vanishing_polynomial = 4; - static constexpr bool is_plookup = false; -}; - class ultra_settings : public settings_base { public: static constexpr size_t num_challenge_bytes = 16; diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/utils/kate_verification.hpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/utils/kate_verification.hpp index b5bd03fed89..fe40c41f202 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/utils/kate_verification.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/proof_system/utils/kate_verification.hpp @@ -106,45 +106,4 @@ void populate_kate_element_map(verification_key* key, } } -/** - * Debug method for Turbo plonk proofs - prints verification key in the format required by our smart contracts - **/ -inline void print_turbo_verification_key(verification_key* key) -{ - const auto print_fr = [](const std::string& name, const barretenberg::fr& element) { - std::cerr << "vk." << name << " = PairingsBn254.new_fr(" << std::endl; - std::cerr << " " << element << std::endl; - std::cerr << ");" << std::endl; - }; - const auto print_g1 = [](const std::string& name, const barretenberg::g1::affine_element& element) { - std::cerr << "vk." << name << " = PairingsBn254.new_g1(" << std::endl; - std::cerr << " " << element.x << "," << std::endl; - std::cerr << " " << element.y << std::endl; - std::cerr << ");" << std::endl; - }; - std::cerr << "### vk" << std::endl; - std::cerr << "vk.circuit_size = " << key->domain.size << ";" << std::endl; - std::cerr << "vk.num_inputs = " << key->num_public_inputs << ";" << std::endl; - print_fr("work_root", key->domain.root); - print_fr("domain_inverse", key->domain.domain_inverse); - print_fr("work_root_inverse", key->domain.root_inverse); - print_g1("Q1", key->commitments.at("Q_1")); - print_g1("Q2", key->commitments.at("Q_2")); - print_g1("Q3", key->commitments.at("Q_3")); - print_g1("Q4", key->commitments.at("Q_4")); - print_g1("Q5", key->commitments.at("Q_5")); - print_g1("QM", key->commitments.at("Q_M")); - print_g1("QC", key->commitments.at("Q_C")); - print_g1("QARITH", key->commitments.at("Q_ARITHMETIC")); - print_g1("QFIXEDBASE", key->commitments.at("Q_FIXED_BASE")); - print_g1("QRANGE", key->commitments.at("Q_RANGE")); - print_g1("QLOGIC", key->commitments.at("Q_LOGIC")); - print_g1("sigma_commitments[0]", key->commitments.at("SIGMA_1")); - print_g1("sigma_commitments[1]", key->commitments.at("SIGMA_2")); - print_g1("sigma_commitments[2]", key->commitments.at("SIGMA_3")); - print_g1("sigma_commitments[3]", key->commitments.at("SIGMA_4")); - print_fr("permutation_non_residues[0]", 5); - print_fr("permutation_non_residues[1]", 6); - print_fr("permutation_non_residues[2]", 7); -} } // namespace proof_system::plonk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/verification_key/sol_gen.hpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/verification_key/sol_gen.hpp index d4759a94cad..2f5822fec2b 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/verification_key/sol_gen.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/proof_system/verification_key/sol_gen.hpp @@ -149,10 +149,6 @@ inline void output_vk_sol(std::ostream& os, std::shared_ptr bool VerifierBase::verify } template class VerifierBase; -template class VerifierBase; template class VerifierBase; template class VerifierBase; template class VerifierBase; diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/verifier/verifier.hpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/verifier/verifier.hpp index 568fac727aa..b39f1a97c4d 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/verifier/verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/proof_system/verifier/verifier.hpp @@ -29,13 +29,11 @@ template class VerifierBase { }; extern template class VerifierBase; -extern template class VerifierBase; extern template class VerifierBase; extern template class VerifierBase; extern template class VerifierBase; typedef VerifierBase Verifier; -typedef VerifierBase TurboVerifier; typedef VerifierBase UltraVerifier; typedef VerifierBase UltraToStandardVerifier; typedef VerifierBase UltraWithKeccakVerifier; diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/random_widgets/permutation_widget_impl.hpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/random_widgets/permutation_widget_impl.hpp index b38ae3c3b17..0209756a25f 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/random_widgets/permutation_widget_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/random_widgets/permutation_widget_impl.hpp @@ -276,7 +276,7 @@ void ProverPermutationWidget class FixedBaseKernel { +template class FixedBaseKernel { public: // UltraPlonkComposer only needs 6 independent relations, (α^5 is not added), but we accept the tiny inefficiency // of computing and storing an extra power of α (we use power 0,1,2,3,4 and 6) to minimize code changes. @@ -151,21 +151,12 @@ template class Field q_5_multiplicand; - if constexpr (turbo) { // α^5 terms not present in UltraPlonK - q_4_multiplicand = w_3 * q_fixed_base * q_c * challenges.alpha_powers[5]; - q_5_multiplicand = (Field(1) - w_4) * q_fixed_base * q_c * challenges.alpha_powers[5]; - } - Field q_m_multiplicand = w_3 * q_fixed_base * q_c * challenges.alpha_powers[6]; - linear_terms[0] = q_m_multiplicand; // α^6 q_fixed_base q_c w_3 - linear_terms[1] = q_1_multiplicand; // α q_fixed_base δ^2 - linear_terms[2] = q_2_multiplicand; // α q_fixed_base - linear_terms[3] = q_3_multiplicand; // α^3 q_fixed_base δ * (w_1,ω - w_1) * w_3,ω - if constexpr (turbo) { // α^5 terms not present in UltraPlonK - linear_terms[4] = q_4_multiplicand; // α^5 q_fixed_base q_c w_3 - linear_terms[5] = q_5_multiplicand; // α^5 q_fixed_base q_c (1 - w_4) - } + linear_terms[0] = q_m_multiplicand; // α^6 q_fixed_base q_c w_3 + linear_terms[1] = q_1_multiplicand; // α q_fixed_base δ^2 + linear_terms[2] = q_2_multiplicand; // α q_fixed_base + linear_terms[3] = q_3_multiplicand; // α^3 q_fixed_base δ * (w_1,ω - w_1) * w_3,ω } inline static Field sum_linear_terms(PolyContainer& polynomials, @@ -188,12 +179,6 @@ template class result += (linear_terms[1] * q_1); result += (linear_terms[2] * q_2); result += (linear_terms[3] * q_3); - if constexpr (turbo) { - const Field& q_5 = - Getters::template get_value(polynomials, i); - result += (linear_terms[4] * q_4); - result += (linear_terms[5] * q_5); - } return result; } @@ -270,10 +255,6 @@ template class Field accumulator_init_identity = T0 * T1 * challenges.alpha_powers[4]; Field x_init_identity; - if constexpr (turbo) { // α^5 terms not present in UltraPlonK - // x_init_identity = -α^5 * w_1 * w_3 - x_init_identity = -(w_1 * w_3) * challenges.alpha_powers[5]; - } // y_init_identity = α^6 * (q_c * (1 - w_4) - w_2 * w_3) T0 = Field(1) - w_4; @@ -282,9 +263,6 @@ template class Field y_init_identity = (T0 - T1) * challenges.alpha_powers[6]; Field gate_identity = accumulator_init_identity + y_init_identity; - if constexpr (turbo) { // α^5 terms not present in UltraPlonK - gate_identity += x_init_identity; - } gate_identity = gate_identity * q_c; gate_identity = gate_identity + accumulator_identity + x_alpha_identity + x_accumulator_identity + y_accumulator_identity; @@ -301,30 +279,16 @@ template class scalars["Q_1"] += linear_terms[1]; scalars["Q_2"] += linear_terms[2]; scalars["Q_3"] += linear_terms[3]; - if constexpr (turbo) { // α^5 terms not present in UltraPlonK - scalars["Q_4"] += linear_terms[4]; - scalars["Q_5"] += linear_terms[5]; - } } }; template -using TurboFixedBaseKernel = FixedBaseKernel; - -template -using UltraFixedBaseKernel = FixedBaseKernel; +using UltraFixedBaseKernel = FixedBaseKernel; } // namespace widget -template -using ProverTurboFixedBaseWidget = widget::TransitionWidget; - template using ProverUltraFixedBaseWidget = widget::TransitionWidget; -template -using VerifierTurboFixedBaseWidget = - widget::GenericVerifierWidget; - template using VerifierUltraFixedBaseWidget = widget::GenericVerifierWidget; diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/turbo_logic_widget.hpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/logic_widget.hpp similarity index 96% rename from barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/turbo_logic_widget.hpp rename to barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/logic_widget.hpp index 95ade04896a..6edc1c1f432 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/turbo_logic_widget.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/logic_widget.hpp @@ -5,7 +5,7 @@ namespace proof_system::plonk { namespace widget { -template class TurboLogicKernel { +template class LogicKernel { public: static constexpr size_t num_independent_relations = 4; // We state the challenges required for linear/nonlinear terms computation @@ -228,9 +228,9 @@ template class TurboLogicKe } // namespace widget template -using ProverTurboLogicWidget = widget::TransitionWidget; +using ProverLogicWidget = widget::TransitionWidget; template -using VerifierTurboLogicWidget = widget::GenericVerifierWidget; +using VerifierLogicWidget = widget::GenericVerifierWidget; } // namespace proof_system::plonk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/plookup_arithmetic_widget.hpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/plookup_arithmetic_widget.hpp index 3a10bb97876..c22caccd58f 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/plookup_arithmetic_widget.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/plookup_arithmetic_widget.hpp @@ -6,7 +6,7 @@ namespace proof_system::plonk { namespace widget { /** - * @brief Core class implementing the arithmetic gate in Turbo plonk + * @brief Core class implementing the arithmetic gate in Ultra plonk * * @details ArithmethicKernel provides the logic that can implement one of several transitions. The whole formula * without alpha scaling is: diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/turbo_arithmetic_widget.hpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/turbo_arithmetic_widget.hpp deleted file mode 100644 index 5b46fb8b809..00000000000 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/turbo_arithmetic_widget.hpp +++ /dev/null @@ -1,307 +0,0 @@ -#pragma once - -#include "./transition_widget.hpp" - -namespace proof_system::plonk { -namespace widget { - -/** - * @brief Core class implementing the arithmetic gate in Turbo plonk - * - * @details ArithmethicKernel provides the logic that implements the standard arithmetic transition (the following - * doens't represent the whole arithmetic transition formula) - * q_arith * (q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_5 *(w_4 - 2) * (w_4 - 1) * w_4 + q_c) - * = 0 - * - * So it extends beyond standard plonk and is enabled by the arithmetic selector. The q_5 selector is used to ensure the - * value at wire w_4 is in range {0, 1, 2}. - * - * Additionally, the gadget contains a nonlinear term, which is enabled by setting q_arith to 2. This gadget is used to - * emit the highest bit of the difference (w_3 - 4 * w_4) and is supposed to be used in conjunction with TurboPlonk base - * 4 decomposition. - * - * @tparam Field The basic field in which the elements operates - * @tparam Getters The class providing functions that access evaluations of polynomials at indices - * @tparam PolyContainer Container for the polynomials or their simulation - */ -template class TurboArithmeticKernel { - public: - static constexpr size_t num_independent_relations = 2; - // We state the challenges required for linear/nonlinear terms computation - static constexpr uint8_t quotient_required_challenges = CHALLENGE_BIT_ALPHA; - // We state the challenges required for updating kate opening scalars - static constexpr uint8_t update_required_challenges = CHALLENGE_BIT_ALPHA; - - private: - // A structure with various challenges, even though only alpha is used here. - typedef containers::challenge_array challenge_array; - // Type for the linear terms of the transition - typedef containers::coefficient_array coefficient_array; - - public: - /** - * @brief Quickly checks if the result of all computation will be zero because of the selector or not - * - * @param polynomials Polynomial or simulated container - * @param i Gate index - * @return q_arith[i] != 0 - */ - inline static bool gate_enabled(PolyContainer& polynomials, const size_t i = 0) - { - const Field& q_arith = - Getters::template get_value(polynomials, i); - return !q_arith.is_zero(); - } - - inline static std::set const& get_required_polynomial_ids() - { - static const std::set required_polynomial_ids = { - PolynomialIndex::Q_1, PolynomialIndex::Q_2, PolynomialIndex::Q_3, PolynomialIndex::Q_4, - PolynomialIndex::Q_5, PolynomialIndex::Q_M, PolynomialIndex::Q_C, PolynomialIndex::Q_ARITHMETIC, - PolynomialIndex::W_1, PolynomialIndex::W_2, PolynomialIndex::W_3, PolynomialIndex::W_4 - }; - return required_polynomial_ids; - } - - /** - * @brief Computes the linear terms. - * - * @details Multiplies the values at the first and second wire, puts the product and all the wires into the - * linear terms multiplied by appropriate selector values, the fifth linear term is polynomial vanishing on - * values {0, 1, 2} for w_4 - * - * Uses only the alpha challenge - * - * @param polynomials Polynomials from which the values of wires are obtained - * @param challenges Challenge array, but only alpha challenge is used - * @param linear_terms Container for results of computation - * @param i Index at which the wire values are sampled. - */ - inline static void compute_linear_terms(PolyContainer& polynomials, - const challenge_array& challenges, - coefficient_array& linear_terms, - const size_t i = 0) - { - constexpr barretenberg::fr minus_two(-2); - const Field& alpha = challenges.elements[ChallengeIndex::ALPHA]; - const Field& w_1 = - Getters::template get_value(polynomials, i); - const Field& w_2 = - Getters::template get_value(polynomials, i); - const Field& w_3 = - Getters::template get_value(polynomials, i); - const Field& w_4 = - Getters::template get_value(polynomials, i); - - const Field& q_arith = - Getters::template get_value(polynomials, i); - - Field T0; - Field T1; - Field T2; - Field T3; - Field T4; - Field T5; - Field T6; - - T0 = q_arith * w_1 * w_2; - T1 = q_arith * w_1; - T2 = q_arith * w_2; - T3 = q_arith * w_3; - T4 = q_arith * w_4; - - // T5 imposes w_4 lies in {0, 1, 2} - T5 = w_4.sqr(); - T5 -= w_4; - T6 = w_4 + minus_two; - T5 *= T6; - T5 *= q_arith; - T5 *= alpha; - - linear_terms[0] = T0; - linear_terms[1] = T1; - linear_terms[2] = T2; - linear_terms[3] = T3; - linear_terms[4] = T4; - linear_terms[5] = T5; - linear_terms[6] = q_arith; - } - - /** - * @brief Compute the non-linear term that is enabled by q_arith==2 and allows getting information about whether the - * highest bit is set in w_3 - 4*w_4 - * - * @param polynomials Containers with polynomials or their simulation - * @param challenges Challenge arrey (we are only using alpha) - * @param quotient Reference to quotient, which will be updated with the non-linear term - * @param i Index at which the wires/seclectors are evaluated - */ - inline static void compute_non_linear_terms(PolyContainer& polynomials, - const challenge_array& challenges, - Field& quotient, - const size_t i = 0) - { - constexpr barretenberg::fr minus_seven(-7); - - const Field& w_3 = - Getters::template get_value(polynomials, i); - const Field& w_4 = - Getters::template get_value(polynomials, i); - const Field& q_arith = - Getters::template get_value(polynomials, i); - const Field& alpha_base = challenges.alpha_powers[0]; - - Field T1; - Field T2; - Field T3; - Field T4; - Field T5; - - /** - * Quad extraction term. This term is only active when q_arith is set to 2. - * - * We evaluate ranges using the turbo_range_widget, which generates a sequence - * of accumulating sums - each sum aggregates a base-4 value. - * - * We sometimes need to extract individual bits from our quads, the following - * term will extract the high bit b from two accumulators, and add 6b into the - * arithmetic identity. - * - * In more detail, a quad will be represented using accumulators stored in - * wires w_3, w_4 via the formula - * Δ = w_3 - 4.w_4. - * We'd like to construct the high bit of Δ in each of the four possible cases - * Δ = 0, 1, 2, 3. We could do this via Lagrange interpolation of the points - * {(0, 0), (1, 0), (2, 1), (3, 1)} over the domain {0, 1, 2, 3}, leading to - * the polynomial - * - * Δ(Δ-1)(Δ-3) Δ(Δ-1)(Δ-2) - * l_2 + l_3 = ---------- + ----------- . - * 2.1.-1 3.2.1 - * - * Clearing the denominators, we find that - * 9.Δ^2 - 2.Δ^3 - 7.Δ interpolates {(0, 0), (1, 0), (2, 6), (3, 6)}, - * so we instead treat 6 as the indicator that the high bit of Δ is 1. - **/ - - // T1 = q_arith^2 - q_arith. - T1 = q_arith.sqr(); - T1 -= q_arith; - - // T2 = Δ - T2 = w_4 + w_4; - T2 += T2; - T2 = w_3 - T2; - - // T3 = 2Δ^2 - T3 = T2.sqr(); - T3 += T3; - - // T4 = 9.Δ - T4 = T2 + T2; - T4 += T2; - // // T5 = 6.Δ - T5 = T4 + T4; - T4 += T5; - - // T4 = 9.Δ - 2.Δ^2 - 7 - T4 -= T3; - T4 += minus_seven; - - // T2 = 9.Δ^2 - 2.Δ^3 - 7.Δ - T2 *= T4; - - // T1 = (q_arith^2 - q_arith).(9.Δ^2 - 2.Δ^3 - 7.Δ) - // Note that, when q_arith = 2, q_arith^2 - q_arith = q_arith - T1 *= T2; - - T1 *= alpha_base; - - quotient += T1; - } - - /** - * @brief Scales all the linear terms by appropriate selectors, sums the, scales by alpha and returns the result - * - * @param polynomials Container with polynomials or their simulation - * @param challenges A structure with various challenges - * @param linear_terms Precomputed linear terms to be scaled and summed - * @param i The index at which selector/witness values are sampled - * @return Field Scaled sum of values - * - */ - inline static Field sum_linear_terms(PolyContainer& polynomials, - const challenge_array& challenges, - coefficient_array& linear_terms, - const size_t i = 0) - { - const Field& alpha_base = challenges.alpha_powers[0]; - const Field& q_1 = - Getters::template get_value(polynomials, i); - const Field& q_2 = - Getters::template get_value(polynomials, i); - const Field& q_3 = - Getters::template get_value(polynomials, i); - const Field& q_4 = - Getters::template get_value(polynomials, i); - const Field& q_5 = - Getters::template get_value(polynomials, i); - const Field& q_m = - Getters::template get_value(polynomials, i); - const Field& q_c = - Getters::template get_value(polynomials, i); - - Field result = linear_terms[0] * q_m; - result += (linear_terms[1] * q_1); - result += (linear_terms[2] * q_2); - result += (linear_terms[3] * q_3); - result += (linear_terms[4] * q_4); - result += (linear_terms[5] * q_5); - result += (linear_terms[6] * q_c); - result *= alpha_base; - return result; - } - - /** - * @brief Compute the scaled values of openings - * - * @param linear_terms The original computed linear terms of the product and wires - * @param scalars A map where we put the values - * @param challenges Challenges where we get the alpha - */ - inline static void update_kate_opening_scalars(coefficient_array& linear_terms, - std::map& scalars, - const challenge_array& challenges) - { - const Field& alpha = challenges.alpha_powers[0]; - const Field challenge_product = alpha; - scalars["Q_M"] += linear_terms[0] * challenge_product; - scalars["Q_1"] += linear_terms[1] * challenge_product; - scalars["Q_2"] += linear_terms[2] * challenge_product; - scalars["Q_3"] += linear_terms[3] * challenge_product; - scalars["Q_4"] += linear_terms[4] * challenge_product; - scalars["Q_5"] += linear_terms[5] * challenge_product; - scalars["Q_C"] += linear_terms[6] * challenge_product; - } -}; - -} // namespace widget - -/** - * @brief Turbo plonk arithmetic widget for the prover. Provides standard plonk gate transition - * - * @tparam Settings - */ -template -using ProverTurboArithmeticWidget = widget::TransitionWidget; - -/** - * @brief Turbo plonk arithmetic widget for the verifier. Provides standard plonk gate transition - * - * @tparam Settings - */ -template -using VerifierTurboArithmeticWidget = - widget::GenericVerifierWidget; - -} // namespace proof_system::plonk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/turbo_range_widget.hpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/turbo_range_widget.hpp deleted file mode 100644 index ffa9852c116..00000000000 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/widgets/transition_widgets/turbo_range_widget.hpp +++ /dev/null @@ -1,212 +0,0 @@ -#pragma once - -#include "./transition_widget.hpp" - -namespace proof_system::plonk { -namespace widget { - -/* - * The range constraint accumulates base 4 values into a sum. - * We do this by evaluating a kind of 'raster scan', where we compare adjacent elements - * and validate that their differences map to a base for value * - * Let's say that we want to perform a 32-bit range constraint in 'x'. - * We can represent x via 16 constituent base-4 'quads' {q_0, ..., q_15}: - * - * 15 - * === - * \ i - * x = / q . 4 - * === i - * i = 0 - * - * In program memory, we place an accumulating base-4 sum of x {a_0, ..., a_15}, where - * - * i | - * === | a_0 = q_15 - * \ i - j | a_1 = q_15 . 4 + q_14 - * a = / q . 4 | a_2 = q_15 . 4^2 + q_14 . 4 + q_13 - * i === (15 - j) | ... - * j = 0 | a_15 = x - * - * - * From this, we can use our range transition constraint to validate that - * - * - * a - 4 . a ϵ {0, 1, 2, 3} (for the a_i above, we have - * i + 1 i a_{i+1} - 4.a_i = q_{14-i}, for i = 0, ..., 15), - * - * setting a_{-1} = 0. - * - * We place our accumulating sums in program memory in the following sequence: - * - * +-----+-----+-----+-----+ - * | A | B | C | D | - * +-----+-----+-----+-----+ - * | a2 | a1 | a0 | 0 | - * | a6 | a5 | a4 | a3 | - * | a10 | a9 | a8 | a7 | - * | a14 | a13 | a12 | a11 | - * | --- | --- | --- | a15 | - * +-----+-----+-----+-----+ - * - * Our range transition constraint on row 'i' - * performs our base-4 range check on the follwing pairs: - * - * (D_{i}, C_{i}), (C_{i}, B_{i}), (B_{i}, A_{i}), (A_{i}, D_{i+1}) - * - * We need to start our raster scan at zero, so we simplify matters and just force the first value - * to be zero. - * - * The output will be in the 4th column of an otherwise unused row. Assuming this row can - * be used for a width-3 standard gate, the total number of gates for an n-bit range constraint - * is (n / 8) gates - * - **/ -template class TurboRangeKernel { - public: - static constexpr size_t num_independent_relations = 4; - // We state the challenges required for linear/nonlinear terms computation - static constexpr uint8_t quotient_required_challenges = CHALLENGE_BIT_ALPHA; - // We state the challenges required for updating kate opening scalars - static constexpr uint8_t update_required_challenges = CHALLENGE_BIT_ALPHA; - - private: - typedef containers::challenge_array challenge_array; - typedef containers::coefficient_array coefficient_array; - - public: - /** - * @brief Quickly checks if the result of all computation will be zero because of the selector or not - * - * @param polynomials Polynomial or simulated container - * @param i Gate index - * @return q_range[i] != 0 - */ - inline static bool gate_enabled(PolyContainer& polynomials, const size_t i = 0) - { - const Field& q_range = - Getters::template get_value(polynomials, i); - return !q_range.is_zero(); - } - - inline static std::set const& get_required_polynomial_ids() - { - static const std::set required_polynomial_ids = { PolynomialIndex::Q_RANGE, - PolynomialIndex::W_1, - PolynomialIndex::W_2, - PolynomialIndex::W_3, - PolynomialIndex::W_4 }; - return required_polynomial_ids; - } - - inline static void compute_linear_terms(PolyContainer& polynomials, - const challenge_array& challenges, - coefficient_array& linear_terms, - const size_t i = 0) - { - constexpr barretenberg::fr minus_two(-2); - constexpr barretenberg::fr minus_three(-3); - - const Field& alpha_base = challenges.alpha_powers[0]; - const Field& alpha = challenges.elements[ChallengeIndex::ALPHA]; - const Field& w_1 = - Getters::template get_value(polynomials, i); - const Field& w_2 = - Getters::template get_value(polynomials, i); - const Field& w_3 = - Getters::template get_value(polynomials, i); - const Field& w_4 = - Getters::template get_value(polynomials, i); - const Field& w_4_omega = - Getters::template get_value(polynomials, i); - - Field alpha_a = alpha_base; - Field alpha_b = alpha_a * alpha; - Field alpha_c = alpha_b * alpha; - Field alpha_d = alpha_c * alpha; - - Field delta_1 = w_4 + w_4; - delta_1 += delta_1; - delta_1 = w_3 - delta_1; - - Field delta_2 = w_3 + w_3; - delta_2 += delta_2; - delta_2 = w_2 - delta_2; - - Field delta_3 = w_2 + w_2; - delta_3 += delta_3; - delta_3 = w_1 - delta_3; - - Field delta_4 = w_1 + w_1; - delta_4 += delta_4; - delta_4 = w_4_omega - delta_4; - - // D(D - 1)(D - 2)(D - 3).alpha - Field T0 = delta_1.sqr(); - T0 -= delta_1; - Field T1 = delta_1 + minus_two; - T0 *= T1; - T1 = delta_1 + minus_three; - T0 *= T1; - Field range_accumulator = T0 * alpha_a; - - T0 = delta_2.sqr(); - T0 -= delta_2; - T1 = delta_2 + minus_two; - T0 *= T1; - T1 = delta_2 + minus_three; - T0 *= T1; - T0 *= alpha_b; - range_accumulator += T0; - - T0 = delta_3.sqr(); - T0 -= delta_3; - T1 = delta_3 + minus_two; - T0 *= T1; - T1 = delta_3 + minus_three; - T0 *= T1; - T0 *= alpha_c; - range_accumulator += T0; - - T0 = delta_4.sqr(); - T0 -= delta_4; - T1 = delta_4 + minus_two; - T0 *= T1; - T1 = delta_4 + minus_three; - T0 *= T1; - T0 *= alpha_d; - range_accumulator += T0; - - linear_terms[0] = range_accumulator; - } - - inline static void compute_non_linear_terms(PolyContainer&, const challenge_array&, Field&, const size_t = 0) {} - - inline static Field sum_linear_terms(PolyContainer& polynomials, - const challenge_array&, - coefficient_array& linear_terms, - const size_t i = 0) - { - const Field& q_range = - Getters::template get_value(polynomials, i); - - return linear_terms[0] * q_range; - } - - inline static void update_kate_opening_scalars(coefficient_array& linear_terms, - std::map& scalars, - const challenge_array&) - { - scalars["Q_RANGE"] += linear_terms[0]; - } -}; - -} // namespace widget - -template -using ProverTurboRangeWidget = widget::TransitionWidget; - -template -using VerifierTurboRangeWidget = widget::GenericVerifierWidget; - -} // namespace proof_system::plonk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp b/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp index 671ab2e4304..3c0b6ba8769 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp @@ -81,50 +81,6 @@ template class Standard : public Arithmetization class Turbo : public Arithmetization { - public: - using FF = _FF; - struct Selectors : SelectorsBase { - std::vector>& q_m = std::get<0>(this->_data); - std::vector>& q_c = std::get<1>(this->_data); - std::vector>& q_1 = std::get<2>(this->_data); - std::vector>& q_2 = std::get<3>(this->_data); - std::vector>& q_3 = std::get<4>(this->_data); - std::vector>& q_4 = std::get<5>(this->_data); - std::vector>& q_5 = std::get<6>(this->_data); - std::vector>& q_arith = std::get<7>(this->_data); - std::vector>& q_fixed_base = std::get<8>(this->_data); - std::vector>& q_range = std::get<9>(this->_data); - std::vector>& q_logic = std::get<10>(this->_data); - Selectors() - : SelectorsBase(){}; - Selectors(const Selectors& other) - : SelectorsBase(other) - {} - Selectors(Selectors&& other) - { - this->_data = std::move(other._data); - this->q_m = std::get<0>(this->_data); - this->q_c = std::get<1>(this->_data); - this->q_1 = std::get<2>(this->_data); - this->q_2 = std::get<3>(this->_data); - this->q_3 = std::get<4>(this->_data); - this->q_4 = std::get<5>(this->_data); - this->q_5 = std::get<6>(this->_data); - this->q_arith = std::get<7>(this->_data); - this->q_fixed_base = std::get<8>(this->_data); - this->q_range = std::get<9>(this->_data); - this->q_logic = std::get<10>(this->_data); - }; - Selectors& operator=(Selectors&& other) - { - SelectorsBase::operator=(other); - return *this; - } - ~Selectors() = default; - }; -}; - template class Ultra : public Arithmetization { public: using FF = _FF; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.cpp index a50396869eb..b919594528e 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.cpp @@ -47,5 +47,4 @@ template class CircuitBuilderBase>; template class CircuitBuilderBase>; template class CircuitBuilderBase>; template class CircuitBuilderBase; -template class CircuitBuilderBase>; } // namespace proof_system diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.cpp deleted file mode 100644 index ba7a5d213ce..00000000000 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.cpp +++ /dev/null @@ -1,1519 +0,0 @@ -#include "turbo_circuit_builder.hpp" -#include "barretenberg/common/slab_allocator.hpp" -#include "barretenberg/numeric/bitop/get_msb.hpp" - -using namespace barretenberg; - -namespace proof_system { - -/** - * Turbo circuit initialization, where you can specify the probable number of gates in your circuit. - * - * @param size_hint Assumed number of gates. Used to allocate space for various member - * vectors during initialization. - * */ -template -TurboCircuitBuilder_::TurboCircuitBuilder_(const size_t size_hint) - : CircuitBuilderBase>(turbo_selector_names(), size_hint) -{ - w_l.reserve(size_hint); - w_r.reserve(size_hint); - w_o.reserve(size_hint); - w_4.reserve(size_hint); - - this->zero_idx = put_constant_variable(FF::zero()); -} - -/** - * Create an addition gate. - * The q_m, q_4, q_5, q_fixed_base, q_range, q_logic are zero. - * q_artith is one. w_4 is set to 0-variable index. - * Other parameters are received from the argument. - * - * @param in Specifies addition gate parameters: - * w_l, w_r, w_o, q_1, q_2, q_3, q_c. - * */ -template void TurboCircuitBuilder_::create_add_gate(const add_triple_& in) -{ - this->assert_valid_variables({ in.a, in.b, in.c }); - - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - w_4.emplace_back(this->zero_idx); - q_m.emplace_back(FF::zero()); - q_1.emplace_back(in.a_scaling); - q_2.emplace_back(in.b_scaling); - q_3.emplace_back(in.c_scaling); - q_c.emplace_back(in.const_scaling); - q_arith.emplace_back(FF::one()); - q_4.emplace_back(FF::zero()); - q_5.emplace_back(FF::zero()); - q_fixed_base.emplace_back(FF::zero()); - q_range.emplace_back(FF::zero()); - q_logic.emplace_back(FF::zero()); - ++this->num_gates; -} - -/** - * Create an addition gate that adds 4 variables. - * The q_m, q_5, q_fixed_base, q_range, q_logic are zero. - * q_arith is one. - * Other parameters are received from the argument. - * - * @param in Specifies addition gate parameters: - * w_l, w_r, w_o, w_4, q_1, q_2, q_3, q_4, q_c. - * */ -template void TurboCircuitBuilder_::create_big_add_gate(const add_quad_& in) -{ - this->assert_valid_variables({ in.a, in.b, in.c, in.d }); - - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - w_4.emplace_back(in.d); - q_m.emplace_back(FF::zero()); - q_1.emplace_back(in.a_scaling); - q_2.emplace_back(in.b_scaling); - q_3.emplace_back(in.c_scaling); - q_c.emplace_back(in.const_scaling); - q_arith.emplace_back(FF::one()); - q_4.emplace_back(in.d_scaling); - q_5.emplace_back(FF::zero()); - q_fixed_base.emplace_back(FF::zero()); - q_range.emplace_back(FF::zero()); - q_logic.emplace_back(FF::zero()); - ++this->num_gates; -} - -/** - * @brief Create an addition gate that adds 4 variables with bit extraction. - * The q_m, q_5, q_fixed_base, q_range, q_logic are zero. - * q_arith is 2, so an additional constraint is imposed in the nonlinear terms. - * Other parameters are received from the argument. - * - * @param in Specifies addition gate parameters: - * w_l, w_r, w_o, w_4, q_1, q_2, q_3, q_4, q_c. - * - * @details Impose the constraint - * a_scaling . a + b_scaling . b + c_scaling . c + d_scaling . d - * + 6 * (high bit of c - 4d) == 0. - * @warning This function assumes that c - 4d lies in the set {0, 1, 2, 3}. The circuit writer should take care to - * ensure this assumption is backed by a constraint (e.g., c and d could be accumulators produced using the TurboPLONK - * function `decompose_into_base4_accumulators`). - * */ -template void TurboCircuitBuilder_::create_big_add_gate_with_bit_extraction(const add_quad_& in) -{ - this->assert_valid_variables({ in.a, in.b, in.c, in.d }); - - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - w_4.emplace_back(in.d); - q_m.emplace_back(FF::zero()); - q_1.emplace_back(in.a_scaling); - q_2.emplace_back(in.b_scaling); - q_3.emplace_back(in.c_scaling); - q_c.emplace_back(in.const_scaling); - q_arith.emplace_back(FF::one() + FF::one()); - q_4.emplace_back(in.d_scaling); - q_5.emplace_back(FF::zero()); - q_fixed_base.emplace_back(FF::zero()); - q_range.emplace_back(FF::zero()); - q_logic.emplace_back(FF::zero()); - ++this->num_gates; -} - -template void TurboCircuitBuilder_::create_big_mul_gate(const mul_quad_& in) -{ - this->assert_valid_variables({ in.a, in.b, in.c, in.d }); - - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - w_4.emplace_back(in.d); - q_m.emplace_back(in.mul_scaling); - q_1.emplace_back(in.a_scaling); - q_2.emplace_back(in.b_scaling); - q_3.emplace_back(in.c_scaling); - q_c.emplace_back(in.const_scaling); - q_arith.emplace_back(FF::one()); - q_4.emplace_back(in.d_scaling); - q_5.emplace_back(FF::zero()); - q_fixed_base.emplace_back(FF::zero()); - q_range.emplace_back(FF::zero()); - q_logic.emplace_back(FF::zero()); - ++this->num_gates; -} - -/** - * @brief Create an addition constraint with a range constraint on the fourth witness. - * - * @details The constraints imposed by this: - * q_1 * w_l + q_2 * w_r + q_3 * w_o + q_4 * w_4 + q_c == 0 - * and - * w_4 * (w_4 - 1) * (w_4 - 2) == 0 (i.e., w_4 is in {0, 1, 2}). - * - * We use this gate to evaluate additions/subtractions of bounded integers. The purpose is to ensure the prover can use - * the output witness in constraints that require the input to be bounded. For a typical example, look at the function, - * uint::operator+, which calculates addition modulo some number 2**w. This function must - * calculate a long divison by 2**w and return the remainder. Without the constraint on w_4, the prover could lie about - * the remainder. - * - * @warning Even with the constraint on w_3, it is typically necessary to range constrain the wire value that will be - * returned. - */ -template void TurboCircuitBuilder_::create_balanced_add_gate(const add_quad_& in) -{ - this->assert_valid_variables({ in.a, in.b, in.c, in.d }); - - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - w_4.emplace_back(in.d); - q_m.emplace_back(FF::zero()); - q_1.emplace_back(in.a_scaling); - q_2.emplace_back(in.b_scaling); - q_3.emplace_back(in.c_scaling); - q_c.emplace_back(in.const_scaling); - q_arith.emplace_back(FF::one()); - q_4.emplace_back(in.d_scaling); - q_5.emplace_back(FF::one()); - q_fixed_base.emplace_back(FF::zero()); - q_range.emplace_back(FF::zero()); - q_logic.emplace_back(FF::zero()); - ++this->num_gates; -} - -/** - * Create multiplication gate. - * w_4 is set to the index of zero variable. - * q_1, q_2, q_4, q_4, q_fixed_base, q_range and q_logic are set to zero. - * q_arith is set to 1. - * - * @param in Contains the values for w_l, w_r, w_o, - * q_m, q_3, q_c. - * */ -template void TurboCircuitBuilder_::create_mul_gate(const mul_triple_& in) -{ - this->assert_valid_variables({ in.a, in.b, in.c }); - - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - w_4.emplace_back(this->zero_idx); - q_m.emplace_back(in.mul_scaling); - q_1.emplace_back(FF::zero()); - q_2.emplace_back(FF::zero()); - q_3.emplace_back(in.c_scaling); - q_c.emplace_back(in.const_scaling); - q_arith.emplace_back(FF::one()); - q_4.emplace_back(FF::zero()); - q_5.emplace_back(FF::zero()); - q_fixed_base.emplace_back(FF::zero()); - q_range.emplace_back(FF::zero()); - q_logic.emplace_back(FF::zero()); - ++this->num_gates; -} - -/** - * Create a gate contraining the variable to 0 or 1. - * We set selectors in such a way that we get the - * equation x^2-x=0. - * - * @param variable_index The index of the variable. - * */ -template void TurboCircuitBuilder_::create_bool_gate(const uint32_t variable_index) -{ - this->assert_valid_variables({ variable_index }); - - w_l.emplace_back(variable_index); - w_r.emplace_back(variable_index); - w_o.emplace_back(variable_index); - w_4.emplace_back(this->zero_idx); - q_arith.emplace_back(FF::one()); - q_4.emplace_back(FF::zero()); - q_5.emplace_back(FF::zero()); - q_fixed_base.emplace_back(FF::zero()); - q_range.emplace_back(FF::zero()); - - q_m.emplace_back(FF::one()); - q_1.emplace_back(FF::zero()); - q_2.emplace_back(FF::zero()); - q_3.emplace_back(FF::neg_one()); - q_c.emplace_back(FF::zero()); - q_logic.emplace_back(FF::zero()); - ++this->num_gates; -} - -/** - * Create poly gate as in standard composer. - * w_4 is set to zero variable. - * q_range, q_logic, q_4, q_5, q_fixed_base are set to 0. - * q_arith is set to 1. - * - * @param in Contains the values for - * w_l, w_r, w_o, q_m, q_1, q_2, q_3, q_c. - * */ -template void TurboCircuitBuilder_::create_poly_gate(const poly_triple_& in) -{ - this->assert_valid_variables({ in.a, in.b, in.c }); - - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - w_4.emplace_back(this->zero_idx); - q_m.emplace_back(in.q_m); - q_1.emplace_back(in.q_l); - q_2.emplace_back(in.q_r); - q_3.emplace_back(in.q_o); - q_c.emplace_back(in.q_c); - q_range.emplace_back(FF::zero()); - q_logic.emplace_back(FF::zero()); - - q_arith.emplace_back(FF::one()); - q_4.emplace_back(FF::zero()); - q_5.emplace_back(FF::zero()); - q_fixed_base.emplace_back(FF::zero()); - ++this->num_gates; -} - -/** - * Add a grumpkin point, from a 2-bit lookup table, into an accumulator point. - * - * @param in Witnesses and values of two points. - * */ -template void TurboCircuitBuilder_::create_fixed_group_add_gate(const fixed_group_add_quad_& in) -{ - this->assert_valid_variables({ in.a, in.b, in.c, in.d }); - - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - w_4.emplace_back(in.d); - - q_arith.emplace_back(FF::zero()); - q_4.emplace_back(FF::zero()); - q_5.emplace_back(FF::zero()); - q_m.emplace_back(FF::zero()); - q_c.emplace_back(FF::zero()); - q_range.emplace_back(FF::zero()); - q_logic.emplace_back(FF::zero()); - - q_1.emplace_back(in.q_x_1); - q_2.emplace_back(in.q_x_2); - q_3.emplace_back(in.q_y_1); - q_fixed_base.emplace_back(in.q_y_2); - ++this->num_gates; -} - -/** - * Add a grumpkin point into an accumulator, while also initializing the accumulator. - * - * @param in Addition parameters (points and coefficients). - * @param init Initialization parameters (points). - * */ -template -void TurboCircuitBuilder_::create_fixed_group_add_gate_with_init(const fixed_group_add_quad_& in, - const fixed_group_init_quad_& init) -{ - this->assert_valid_variables({ in.a, in.b, in.c, in.d }); - - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - w_4.emplace_back(in.d); - - q_arith.emplace_back(FF::zero()); - q_4.emplace_back(init.q_x_1); - q_5.emplace_back(init.q_x_2); - q_m.emplace_back(init.q_y_1); - q_c.emplace_back(init.q_y_2); - q_range.emplace_back(FF::zero()); - q_logic.emplace_back(FF::zero()); - - q_1.emplace_back(in.q_x_1); - q_2.emplace_back(in.q_x_2); - q_3.emplace_back(in.q_y_1); - q_fixed_base.emplace_back(in.q_y_2); - ++this->num_gates; -} - -template void TurboCircuitBuilder_::create_fixed_group_add_gate_final(const add_quad_& in) -{ - create_big_add_gate(in); -} - -/** - * Add a gate that will fix the witness (make it public). - * - * @param witness_index Witness variable index. - * @param witness_value Witness variable value. - * */ -template void TurboCircuitBuilder_::fix_witness(const uint32_t witness_index, const FF& witness_value) -{ - this->assert_valid_variables({ witness_index }); - - w_l.emplace_back(witness_index); - w_r.emplace_back(this->zero_idx); - w_o.emplace_back(this->zero_idx); - w_4.emplace_back(this->zero_idx); - q_m.emplace_back(FF::zero()); - q_1.emplace_back(FF::one()); - q_2.emplace_back(FF::zero()); - q_3.emplace_back(FF::zero()); - q_c.emplace_back(-witness_value); - q_arith.emplace_back(FF::one()); - q_4.emplace_back(FF::zero()); - q_5.emplace_back(FF::zero()); - q_fixed_base.emplace_back(FF::zero()); - q_range.emplace_back(FF::zero()); - q_logic.emplace_back(FF::zero()); - ++this->num_gates; -} - -/** - * Create a constraint placing the witness in 2^{num_bits} range. - * - * @param witness_index The index of the witness variable to constrain. - * @param num_bits Constraint size. - * - * @return Vector of variable indexes for accumulator variables used in - * the constraint. - * */ -template -std::vector TurboCircuitBuilder_::decompose_into_base4_accumulators(const uint32_t witness_index, - const size_t num_bits, - std::string const& msg) -{ - this->assert_valid_variables({ witness_index }); - - ASSERT(num_bits > 0); - - /* - * The range constraint accumulates base 4 values into a sum. - * We do this by evaluating a kind of 'raster scan', where we compare adjacent elements - * and validate that their weighted differences lie in a base for value expansion in powers of 4. - * Let's say that we want to perform a 32-bit range constraint on a field element x. - * We can expand x to the desired length via 16 constituent base-4 'quads' {q_0, ..., q_15}: - * - * 15 - * === - * \ i - * x = / q . 4 - * === i - * i = 0 - * - * In program memory, we place an accumulating base-4 sum of x {a_0, ..., a_15}, where - * - * - * i | - * === | a_0 = q_15 - * \ i - j | a_1 = q_15 . 4 + q_14 - * a = / q . 4 | a_2 = q_15 . 4^2 + q_14 . 4 + q_13 - * i === (15 - j) | ... - * j = 0 | a_15 = x - * - * - * From this, we can use our range transition constraint to validate that - * - * - * a - 4 . a ϵ {0, 1, 2, 3} (for the a_i above, we have - * i + 1 i a_{i+1} - 4.a_i = q_{14-i}, for i = 0, ..., 15), - * - * setting a_{-1} = 0. - * - * We place our accumulating sums in program memory in the following sequence: - * - * +-----+-----+-----+-----+ - * | A | B | C | D | - * +-----+-----+-----+-----+ - * | a2 | a1 | a0 | 0 | - * | a6 | a5 | a4 | a3 | - * | a10 | a9 | a8 | a7 | - * | a14 | a13 | a12 | a11 | - * | --- | --- | --- | a15 | - * +-----+-----+-----+-----+ - * - * Our range transition constraint on row 'i' - * performs our base-4 range check on the follwing pairs: - * - * (D_{i}, C_{i}), (C_{i}, B_{i}), (B_{i}, A_{i}), (A_{i}, D_{i+1}) - * - * We need to start our raster scan at zero, so we simplify matters and just force the first value - * to be zero. - * - * We will prepend 0 quads to our sequence of accumulator values so that the final accumulator value (equal to the - * witness value if the range constraint holds) will be in the 4th column of an otherwise unused row. More - * explicitly, in general (num_bits > 0), a_0 will be placed in column: - * - C if num_bits = 7, 8 mod 8 - * - D if num_bits = 1, 2 mod 8 - * - A if num_bits = 3, 4 mod 8 - * - B if num_bits = 5, 6 mod 8 - * - * Examples: - * 7,8-bit 9,10-bit 11,12-bit 13,14-bit - * +-----+-----+-----+-----+ +-----+-----+-----+-----+ +-----+-----+-----+-----+ +-----+-----+-----+-----+ - * | A | B | C | D | | A | B | C | D | | A | B | C | D | | A | B | C | D | - * +-----+-----+-----+-----+ +-----+-----+-----+-----+ +-----+-----+-----+-----+ +-----+-----+-----+-----+ - * | a2 | a1 | a0 | 0 | | 0 | 0 | 0 | 0 | | a0 | 0 | 0 | 0 | | a1 | a0 | 0 | 0 | - * | 0 | 0 | 0 | a3 | | a3 | a2 | a1 | a0 | | a4 | a3 | a2 | a1 | | a5 | a4 | a3 | a2 | - * | --- | --- | --- | --- | | 0 | 0 | 0 | a4 | | 0 | 0 | 0 | a5 | | 0 | 0 | 0 | a6 | - * +-----+-----+-----+-----+ +-----+-----+-----+-----+ +-----+-----+-----+-----+ +-----+-----+-----+-----+ - * - * - **/ - - const uint256_t witness_value(this->get_variable(witness_index)); - - if (witness_value.get_msb() >= num_bits && !this->failed()) { - this->failure(msg); - } - /* num_quad_gates is the minimum number of gates needed to record num_bits-many bits in a table, putting two-bits (a - * quad) at each position. Since our table has width 4, we can fit 8 bits on a row, hence num_quad_gates is - * num_bits/8 when num_bits is a multiple of 8, and otherwise it is 1 + (num_bits/8). Because we will always pre-pad - * with 0 quads to ensure that the final accumulator is in the fourth column, num_quad_gates is also equal to one - * less than the total number of rows that will be used to record the accumulator values. */ - size_t num_quad_gates = (num_bits >> 3); - num_quad_gates = (num_quad_gates << 3 == num_bits) ? num_quad_gates : num_quad_gates + 1; - - std::vector>* wires[4]{ &w_4, &w_o, &w_r, &w_l }; - - // num_quads = the number of accumulators used in the table, not including the output row. - const size_t num_quads = (num_quad_gates << 2); - // (num_quads << 1) is the number of bits in the non-output row, including 0 quads. - // ((num_quads << 1) - num_bits) >> 1 is the number of padding 0 quads. - const size_t forced_zero_threshold = 1 + (((num_quads << 1) - num_bits) >> 1); - - std::vector accumulators; - FF accumulator(0); - uint32_t most_significant_segment = 0; - // iterate through entries of all but final row - for (size_t i = 0; i < num_quads + 1; ++i) { - uint32_t accumulator_index; - // prepend padding 0 quads - if (i < forced_zero_threshold) { - accumulator_index = this->zero_idx; - } else { - // accumulate quad - const size_t bit_index = (num_quads - i) << 1; - const uint64_t quad = static_cast(witness_value.get_bit(bit_index)) + - 2ULL * static_cast(witness_value.get_bit(bit_index + 1)); - const FF quad_element = fr{ quad, 0, 0, 0 }.to_montgomery_form(); - accumulator += accumulator; - accumulator += accumulator; - accumulator += quad_element; - - accumulator_index = this->add_variable(accumulator); - accumulators.emplace_back(accumulator_index); - - if (i == forced_zero_threshold) { - // mark this to constrain top bit to 0 in case num_bits is odd - most_significant_segment = accumulator_index; - } - } - - (*(wires + (i & 3)))->emplace_back(accumulator_index); - } - - // we use one additional gate to record the final accumulator value. - size_t used_gates = 1 + num_quad_gates; - for (size_t i = 0; i < used_gates; ++i) { - q_m.emplace_back(0); - q_1.emplace_back(0); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(0); - q_4.emplace_back(0); - q_5.emplace_back(0); - q_fixed_base.emplace_back(0); - q_logic.emplace_back(0); - q_range.emplace_back(1); - } - - // switch off range widget for final row; fill wire values not in use with zeros - q_range[q_range.size() - 1] = 0; - w_l.emplace_back(this->zero_idx); - w_r.emplace_back(this->zero_idx); - w_o.emplace_back(this->zero_idx); - - this->assert_equal(witness_index, accumulators[accumulators.size() - 1], msg); - - accumulators[accumulators.size() - 1] = witness_index; - - this->num_gates += used_gates; - - // constrain top bit of top quad to zero in case num_bits is odd - if ((num_bits & 1ULL) == 1ULL) { - create_bool_gate(most_significant_segment); - } - return accumulators; -} - -/** - * @brief Implements AND and XOR. - * - * @returns A triple of vectors of accumulator values. - * - * @details If T is the returned triple, then the last element of T.left is guaranteed to be - * our input a, regardless of a's relation with the rest of T.left. For instance, if num_bits is - * smaller than the bit length of a, then the constraint that a is reproduced by T.left will fail: - * for u = T.left[T.left.size()-2], u will be too small to express a in the form a = 4u + quad. - * The same holds, mutatis mutandis, for T.right. - */ -template -accumulator_triple_ TurboCircuitBuilder_::create_logic_constraint(const uint32_t a, - const uint32_t b, - const size_t num_bits, - const bool is_xor_gate) -{ - this->assert_valid_variables({ a, b }); - - ASSERT(((num_bits >> 1U) << 1U) == num_bits); // Do not allow constraint for an odd number of bits. - - // one gate accmulates 1 quads, or 2 bits. - // # gates = (bits / 2) - const size_t num_quads = (num_bits >> 1); - - /* - * The LOGIC constraint accumulates 3 base-4 values (a, b, c) into a sum, where c = a & b OR c = a ^ b - * - * In program memory, we place an accumulating base-4 sum of a, b, c {a_0, ..., a_{(num_bits/2)-1}}, where - * i - * === - * \ i - j - * a = / q . 4 - * i === (num_bits/2 - 1 - j) - * j = 0 - * - * Note that a_0 = q_15, a_1 = 4.q_15 + q_14 = 4.a_0 + q_14, and, in general, we have the - * accumulator relation - * - * a = 4 a + q (for i > 0). - * i + 1 i num_bits/2 - 1 -i - * - * We can use our logic transition constraint to validate that - * - * - * a - 4 . a ϵ [0, 1, 2, 3] - * i + 1 i - * - * - * - * - * b - 4 . b ϵ [0, 1, 2, 3] - * i + 1 i - * - * - * - * / \ / \ - * c - 4 . c = | a - 4 . a | (& OR ^) | b - 4 . b | - * i + 1 i \ i + 1 i / \ i + 1 i / - * - * - * We also need the following temporary, w, stored in program memory: - * - * / \ / \ - * w = | a - 4 . a | * | b - 4 . b | - * i \ i + 1 i / \ i + 1 i / - * - * - * w is needed to prevent the degree of our quotient polynomial from blowing up - * - * We place our accumulating sums in program memory in the following sequence: - * - * +-----+-----+-----+-----+ - * | A | B | C | D | - * +-----+-----+-----+-----+ - * | 0 | 0 | w0 | 0 | - * | a0 | b0 | w1 | c0 | - * | a1 | b1 | w2 | c1 | - * | : | : | : | : | - * | aN | bN | 0 | cN | where N = num_bits/2 - 1 (num_bits is assumed even) - * +-----+-----+-----+-----+ - * - * Typically we will set num_bits = max(num_bits(a), num_bits(b)), so that c computes the AND or XOR - * of a and b, depending on the value of is_xor_gate. - * - * Our transition constraint extracts quads by taking the difference between two accumulating sums, - * so we need to start the chain with a row of zeroes - * - * One additional benefit of this constraint, is that both our inputs and output are in 'native' uint32 form. - * This means we *never* have to decompose a uint32 into bits and back in order to chain together - * addition and logic operations. - **/ - - const uint256_t left_witness_value(this->get_variable(a)); - const uint256_t right_witness_value(this->get_variable(b)); - - accumulator_triple_ accumulators; - FF left_accumulator = FF::zero(); - FF right_accumulator = FF::zero(); - FF out_accumulator = FF::zero(); - - // Step 1: populate 1st row accumulators with zero - w_l.emplace_back(this->zero_idx); - w_r.emplace_back(this->zero_idx); - w_4.emplace_back(this->zero_idx); - - // w_l, w_r, w_4 now point to 1 gate ahead of w_o - for (size_t j = 0; j < num_quads; ++j) { - uint32_t left_accumulator_index; - uint32_t right_accumulator_index; - uint32_t out_accumulator_index; - uint32_t product_index; - - const size_t bit_index = (num_quads - 1 - j) << 1; // subscript of q as defined above - // get quad coeffs of 4^{num_quads - 1 - j} in a and b, respectively - const uint64_t left_quad = static_cast(left_witness_value.get_bit(bit_index)) + - 2ULL * static_cast(left_witness_value.get_bit(bit_index + 1)); - const uint64_t right_quad = static_cast(right_witness_value.get_bit(bit_index)) + - 2ULL * static_cast(right_witness_value.get_bit(bit_index + 1)); - - const FF left_quad_element = fr{ left_quad, 0, 0, 0 }.to_montgomery_form(); - const FF right_quad_element = fr{ right_quad, 0, 0, 0 }.to_montgomery_form(); - FF out_quad_element; - if (is_xor_gate) { - out_quad_element = fr{ left_quad ^ right_quad, 0, 0, 0 }.to_montgomery_form(); - } else { - out_quad_element = fr{ left_quad & right_quad, 0, 0, 0 }.to_montgomery_form(); - } - - const FF product_quad_element = fr{ left_quad * right_quad, 0, 0, 0 }.to_montgomery_form(); - - // replace accumulator by 4.accumulator + quad for a, b and c - left_accumulator += left_accumulator; - left_accumulator += left_accumulator; - left_accumulator += left_quad_element; - - right_accumulator += right_accumulator; - right_accumulator += right_accumulator; - right_accumulator += right_quad_element; - - out_accumulator += out_accumulator; - out_accumulator += out_accumulator; - out_accumulator += out_quad_element; - - left_accumulator_index = this->add_variable(left_accumulator); - accumulators.left.emplace_back(left_accumulator_index); - - right_accumulator_index = this->add_variable(right_accumulator); - accumulators.right.emplace_back(right_accumulator_index); - - out_accumulator_index = this->add_variable(out_accumulator); - accumulators.out.emplace_back(out_accumulator_index); - - product_index = this->add_variable(product_quad_element); - - w_l.emplace_back(left_accumulator_index); - w_r.emplace_back(right_accumulator_index); - w_4.emplace_back(out_accumulator_index); - w_o.emplace_back(product_index); - } - w_o.emplace_back(this->zero_idx); - - for (size_t i = 0; i < num_quads + 1; ++i) { - q_m.emplace_back(FF::zero()); - q_1.emplace_back(FF::zero()); - q_2.emplace_back(FF::zero()); - q_3.emplace_back(FF::zero()); - q_arith.emplace_back(FF::zero()); - q_4.emplace_back(FF::zero()); - q_5.emplace_back(FF::zero()); - q_fixed_base.emplace_back(FF::zero()); - q_range.emplace_back(FF::zero()); - if (is_xor_gate) { - q_c.emplace_back(FF::neg_one()); - q_logic.emplace_back(FF::neg_one()); - } else { - q_c.emplace_back(FF::one()); - q_logic.emplace_back(FF::one()); - } - } - - q_c[q_c.size() - 1] = FF::zero(); // last gate is a noop - q_logic[q_logic.size() - 1] = FF::zero(); // last gate is a noop - - this->assert_equal( - a, accumulators.left[accumulators.left.size() - 1], "cannot reproduce `a` value using accumulator."); - - accumulators.left[accumulators.left.size() - 1] = a; - - this->assert_equal( - b, accumulators.right[accumulators.right.size() - 1], "cannot reproduce `b` value using accumulator."); - - accumulators.right[accumulators.right.size() - 1] = b; - - this->num_gates += (num_quads + 1); - - return accumulators; -} - -template -accumulator_triple_ TurboCircuitBuilder_::create_and_constraint(const uint32_t a, - const uint32_t b, - const size_t num_bits) -{ - return create_logic_constraint(a, b, num_bits, false); -} - -template -accumulator_triple_ TurboCircuitBuilder_::create_xor_constraint(const uint32_t a, - const uint32_t b, - const size_t num_bits) -{ - return create_logic_constraint(a, b, num_bits, true); -} - -template uint32_t TurboCircuitBuilder_::put_constant_variable(const FF& variable) -{ - if (constant_variable_indices.contains(variable)) { - return constant_variable_indices.at(variable); - } else { - uint32_t variable_index = this->add_variable(variable); - fix_witness(variable_index, variable); - constant_variable_indices.insert({ variable, variable_index }); - return variable_index; - } -} -/** - * @brief Just an arithemtic gate zero-equality test, but with base set to 1 - * - * @param gate_index - * @return true Evaluation is zero - * @return false Evaluation is not zero - */ -template inline bool TurboCircuitBuilder_::lazy_arithmetic_gate_check(const size_t gate_index) -{ - return arithmetic_gate_evaluation(gate_index, FF::one()).is_zero(); -} - -/** - * @brief Separately checks individual conditions that make up the fixed base gate - * - * @param gate_index Gate index - * @return bool - * TODO(luke/kesha): Add some comments explaining in what sense each of these checks are "lazy" - */ -template inline bool TurboCircuitBuilder_::lazy_fixed_base_gate_check(const size_t gate_index) -{ - ASSERT(gate_index < this->num_gates); - - constexpr FF grumpkin_curve_b(-17); - constexpr FF nine(9); - - // Get witness values - FF wire_1_shifted; - FF wire_2_shifted; - FF wire_3_shifted; - FF wire_4_shifted; - const FF wire_1_value = this->get_variable(w_l[gate_index]); - const FF wire_2_value = this->get_variable(w_r[gate_index]); - const FF wire_3_value = this->get_variable(w_o[gate_index]); - const FF wire_4_value = this->get_variable(w_4[gate_index]); - if ((gate_index + 1) < this->num_gates) { - wire_1_shifted = this->get_variable(w_l[gate_index + 1]); - wire_2_shifted = this->get_variable(w_r[gate_index + 1]); - wire_3_shifted = this->get_variable(w_o[gate_index + 1]); - wire_4_shifted = this->get_variable(w_4[gate_index + 1]); - } else { - wire_1_shifted = FF::zero(); - wire_2_shifted = FF::zero(); - wire_3_shifted = FF::zero(); - wire_4_shifted = FF::zero(); - } - - // Get selector values - const FF q_c_value = q_c[gate_index]; - const FF q_fixed_base_value = q_fixed_base[gate_index]; - const FF q_m_value = q_m[gate_index]; - const FF q_1_value = q_1[gate_index]; - const FF q_2_value = q_2[gate_index]; - const FF q_3_value = q_3[gate_index]; - const FF q_4_value = q_4[gate_index]; - const FF q_5_value = q_5[gate_index]; - - // Compute, optimizing multiplications (different fromt the way we used in widgets, since the linearization - // trick is no more) - - FF delta = wire_4_shifted - (wire_4_value + wire_4_value + wire_4_value + wire_4_value); - FF delta_squared = delta.sqr(); - - // accumulator_identity = (δ + 3)(δ + 1)(δ - 1)(δ - 3) - if (delta_squared != nine && delta_squared != FF::one()) { - return false; - } - - // Check x_alpha_identity - if (!(delta_squared * q_1_value + q_2_value - wire_3_shifted).is_zero()) { - return false; - } - - FF T0 = wire_1_shifted + wire_1_value + wire_3_shifted; - FF T1 = (wire_3_shifted - wire_1_value).sqr(); - T0 = T0 * T1; - - T1 = wire_3_shifted.sqr() * wire_3_shifted; - FF T2 = wire_2_value.sqr(); - T1 = T1 + T2; - T1 = -(T1 + grumpkin_curve_b); - - T2 = delta * wire_2_value * q_fixed_base_value; - T2 = T2 + T2; - FF T3_part = delta * wire_3_shifted * q_3_value; - FF T3 = T3_part * wire_2_value; - T3 = T3 + T3; - - // x_accumulator_identity = α^2 * - // [(w_1,ω + w_1 + w_3,ω) * (w_3,ω - w_1)^2 - (b + w_3,ω^3 + w_2^2) + 2δ * w_2 * q_fixed_base] - if (!(T0 + T1 + T2 + T3).is_zero()) { - return false; - } - T0 = (wire_2_shifted + wire_2_value) * (wire_3_shifted - wire_1_value); - T1 = wire_1_value - wire_1_shifted; - T2 = wire_2_value - (q_fixed_base_value * delta); - T1 = T1 * (T2 - T3_part); - - // y_accumulator_identity = α^3 * - // [(w_2,ω + w_2) * (w_3,ω - w_1) + (w_1 - w_1,ω) * (w_2 - q_fixed_base * δ)] - - if (!(T0 + T1).is_zero()) { - return false; - } - - if (!q_c_value.is_zero()) { - T0 = wire_4_value - FF::one(); - T1 = T0 - wire_3_value; - - if (!T0.is_zero() && !T1.is_zero()) { - return false; - } - T0 = wire_3_value * (q_4_value - wire_1_value) + (FF::one() - wire_4_value) * q_5_value; - if (!T0.is_zero()) { - return false; - } - T0 = q_c_value * (FF::one() - wire_4_value); - T1 = wire_2_value * wire_3_value; - FF y_init_identity = (T0 - T1 + q_m_value * wire_3_value); - if (!y_init_identity.is_zero()) { - return false; - } - } - return true; -} - -/** - * @brief Check if the logic gate should pass. (Checks xor or and of values) - * - * @param gate_index Gate index - * @return fr - */ -template inline bool TurboCircuitBuilder_::lazy_logic_gate_check(const size_t gate_index) -{ - - ASSERT(gate_index < this->num_gates); - - FF wire_1_shifted; - FF wire_2_shifted; - FF wire_4_shifted; - const FF wire_1_value = this->get_variable(w_l[gate_index]); - const FF wire_2_value = this->get_variable(w_r[gate_index]); - const FF wire_4_value = this->get_variable(w_4[gate_index]); - if ((gate_index + 1) < this->num_gates) { - wire_1_shifted = this->get_variable(w_l[gate_index + 1]); - wire_2_shifted = this->get_variable(w_r[gate_index + 1]); - wire_4_shifted = this->get_variable(w_4[gate_index + 1]); - } else { - wire_1_shifted = FF::zero(); - wire_2_shifted = FF::zero(); - wire_4_shifted = FF::zero(); - } - - // Get selector values - const FF q_c_value = q_c[gate_index]; - const FF q_logic_value = q_logic[gate_index]; - constexpr FF two(2); - constexpr FF three(3); - constexpr FF minus_one = -FF::one(); - - FF T0; - FF T1; - FF T2; - - // T0 = a - T0 = wire_1_value + wire_1_value; - T0 += T0; - T0 = wire_1_shifted - T0; - - if (!T0.is_zero() && T0 != FF::one() && T0 != two && T0 != three) { - return false; - } - // T1 = b - T1 = wire_2_value + wire_2_value; - T1 += T1; - T1 = wire_2_shifted - T1; - - if (!T1.is_zero() && T1 != FF::one() && T1 != two && T1 != three) { - return false; - } - - // T2 = c - T2 = wire_4_value + wire_4_value; - T2 += T2; - T2 = wire_4_shifted - T2; - - if (!T2.is_zero() && T2 != FF::one() && T2 != two && T2 != three) { - return false; - } - uint64_t a = uint256_t(T0).data[0]; - uint64_t b = uint256_t(T1).data[0]; - uint64_t c = uint256_t(T2).data[0]; - - if (q_c_value == FF::one() && q_logic_value == FF::one()) { - return (a & b) == c; - } - - if (q_c_value == minus_one && q_logic_value == minus_one) { - return (a ^ b) == c; - } - return false; -} -/** - * @brief Check if the range gate should pass (checks that all the differences are 0,1,2 or 3) - * - * @param gate_index Gate index - * @return bool - */ -template inline bool TurboCircuitBuilder_::lazy_range_gate_check(const size_t gate_index) -{ - - ASSERT(gate_index < this->num_gates); - - FF wire_4_shifted; - const FF wire_1_value = this->get_variable(w_l[gate_index]); - const FF wire_2_value = this->get_variable(w_r[gate_index]); - const FF wire_3_value = this->get_variable(w_o[gate_index]); - const FF wire_4_value = this->get_variable(w_4[gate_index]); - if ((gate_index + 1) < this->num_gates) { - wire_4_shifted = this->get_variable(w_4[gate_index + 1]); - } else { - wire_4_shifted = FF::zero(); - } - constexpr FF two(2); - constexpr FF three(3); - - FF delta_1 = wire_4_value + wire_4_value; - delta_1 += delta_1; - delta_1 = (wire_3_value - delta_1).reduce_once(); - if (!delta_1.is_zero() && delta_1 != FF::one() && delta_1 != two && delta_1 != three) { - return false; - } - - FF delta_2 = wire_3_value + wire_3_value; - delta_2 += delta_2; - delta_2 = wire_2_value - delta_2; - - if (!delta_2.is_zero() && delta_2 != FF::one() && delta_2 != two && delta_2 != three) { - return false; - } - FF delta_3 = wire_2_value + wire_2_value; - delta_3 += delta_3; - delta_3 = wire_1_value - delta_3; - - if (!delta_3.is_zero() && delta_3 != FF::one() && delta_3 != two && delta_3 != three) { - return false; - } - FF delta_4 = wire_1_value + wire_1_value; - delta_4 += delta_4; - delta_4 = wire_4_shifted - delta_4; - - if (!delta_4.is_zero() && delta_4 != FF::one() && delta_4 != two && delta_4 != three) { - return false; - } - - return true; -} -/** - * @brief Evaluate the contribution of the arithmetic gate constraint - * - * @param gate_index Gate index - * @param alpha_base The base value that the whole evaluation is multiplied by - * @return fr - */ -template -inline FF TurboCircuitBuilder_::arithmetic_gate_evaluation(const size_t gate_index, const FF alpha_base) -{ - ASSERT(gate_index < this->num_gates); - - constexpr FF minus_seven(-7); - - constexpr FF two = FF::one() + FF::one(); - const FF wire_1_value = this->get_variable(w_l[gate_index]); - const FF wire_2_value = this->get_variable(w_r[gate_index]); - const FF wire_3_value = this->get_variable(w_o[gate_index]); - const FF wire_4_value = this->get_variable(w_4[gate_index]); - - // T2 = Δ - FF T2 = wire_4_value + wire_4_value; - T2 += T2; - T2 = wire_3_value - T2; - - // T3 = 2Δ^2 - FF T3 = T2.sqr(); - T3 += T3; - - // T4 = 9.Δ - FF T4 = T2 + T2; - T4 += T2; - // // T5 = 6.Δ - FF T5 = T4 + T4; - T4 += T5; - - // T4 = 9.Δ - 2.Δ^2 - 7 - T4 -= T3; - T4 += minus_seven; - - // T2 = 9.Δ^2 - 2.Δ^3 - 7.Δ - T2 *= T4; - - return alpha_base * q_arith[gate_index] * - (wire_1_value * (q_m[gate_index] * wire_2_value + q_1[gate_index]) + q_2[gate_index] * wire_2_value + - q_3[gate_index] * wire_3_value + - wire_4_value * (q_4[gate_index] + q_5[gate_index] * (wire_4_value - two) * (wire_4_value - FF::one())) + - q_c[gate_index] + (q_arith[gate_index] - 1) * T2); -} -/** - * @brief Evaluate the contribution of the range gate constraint - * - * @param gate_index Gate index - * @param alpha_base The base value that the whole evaluation is multiplied by - * @param alpha An element used as a separator of individual subrelations - * @return fr - */ -template -inline FF TurboCircuitBuilder_::range_gate_evaluation(const size_t gate_index, const FF alpha_base, const FF alpha) -{ - - ASSERT(gate_index < this->num_gates); - - FF wire_4_shifted; - const FF wire_1_value = this->get_variable(w_l[gate_index]); - const FF wire_2_value = this->get_variable(w_r[gate_index]); - const FF wire_3_value = this->get_variable(w_o[gate_index]); - const FF wire_4_value = this->get_variable(w_4[gate_index]); - if ((gate_index + 1) < this->num_gates) { - wire_4_shifted = this->get_variable(w_4[gate_index + 1]); - } else { - wire_4_shifted = FF::zero(); - } - constexpr FF minus_two(-2); - constexpr FF minus_three(-3); - FF alpha_a = alpha_base; - FF alpha_b = alpha_a * alpha; - FF alpha_c = alpha_b * alpha; - FF alpha_d = alpha_c * alpha; - - FF delta_1 = wire_4_value + wire_4_value; - delta_1 += delta_1; - delta_1 = wire_3_value - delta_1; - - FF delta_2 = wire_3_value + wire_3_value; - delta_2 += delta_2; - delta_2 = wire_2_value - delta_2; - - FF delta_3 = wire_2_value + wire_2_value; - delta_3 += delta_3; - delta_3 = wire_1_value - delta_3; - - FF delta_4 = wire_1_value + wire_1_value; - delta_4 += delta_4; - delta_4 = wire_4_shifted - delta_4; - - // D(D - 1)(D - 2)(D - 3).alpha - FF T0 = delta_1.sqr(); - T0 -= delta_1; - FF T1 = delta_1 + minus_two; - T0 *= T1; - T1 = delta_1 + minus_three; - T0 *= T1; - FF range_accumulator = T0 * alpha_a; - - T0 = delta_2.sqr(); - T0 -= delta_2; - T1 = delta_2 + minus_two; - T0 *= T1; - T1 = delta_2 + minus_three; - T0 *= T1; - T0 *= alpha_b; - range_accumulator += T0; - - T0 = delta_3.sqr(); - T0 -= delta_3; - T1 = delta_3 + minus_two; - T0 *= T1; - T1 = delta_3 + minus_three; - T0 *= T1; - T0 *= alpha_c; - range_accumulator += T0; - - T0 = delta_4.sqr(); - T0 -= delta_4; - T1 = delta_4 + minus_two; - T0 *= T1; - T1 = delta_4 + minus_three; - T0 *= T1; - T0 *= alpha_d; - range_accumulator += T0; - - return q_range[gate_index] * range_accumulator; -} -/** - * @brief Evaluate the contribution of the logic gate constraint - * - * @param gate_index Gate index - * @param alpha_base The base value the whole evaluation is multiplied by - * @param alpha The element used as separator for individual subrelations - * @return fr - */ -template -inline FF TurboCircuitBuilder_::logic_gate_evaluation(const size_t gate_index, const FF alpha_base, const FF alpha) -{ - - ASSERT(gate_index < this->num_gates); - - FF wire_1_shifted; - FF wire_2_shifted; - FF wire_4_shifted; - const FF wire_1_value = this->get_variable(w_l[gate_index]); - const FF wire_2_value = this->get_variable(w_r[gate_index]); - const FF wire_3_value = this->get_variable(w_o[gate_index]); - const FF wire_4_value = this->get_variable(w_4[gate_index]); - if ((gate_index + 1) < this->num_gates) { - wire_1_shifted = this->get_variable(w_l[gate_index + 1]); - wire_2_shifted = this->get_variable(w_r[gate_index + 1]); - wire_4_shifted = this->get_variable(w_4[gate_index + 1]); - } else { - wire_1_shifted = FF::zero(); - wire_2_shifted = FF::zero(); - wire_4_shifted = FF::zero(); - } - - // Get selector values - const FF q_c_value = q_c[gate_index]; - constexpr FF six(6); - constexpr FF eighty_one(81); - constexpr FF eighty_three(83); - - FF delta_sum; - FF delta_squared_sum; - FF T0; - FF T1; - FF T2; - FF T3; - FF T4; - FF identity; - - T0 = wire_1_value + wire_1_value; - T0 += T0; - T0 = wire_1_shifted - T0; - - // T1 = b - T1 = wire_2_value + wire_2_value; - T1 += T1; - T1 = wire_2_shifted - T1; - - // delta_sum = a + b - delta_sum = T0 + T1; - - // T2 = a^2, T3 = b^2 - T2 = T0.sqr(); - T3 = T1.sqr(); - - delta_squared_sum = T2 + T3; - - // identity = a^2 + b^2 + 2ab - identity = delta_sum.sqr(); - // identity = 2ab - identity -= delta_squared_sum; - - // identity = 2(ab - w) - T4 = wire_3_value + wire_3_value; - identity -= T4; - identity *= alpha; - - // T4 = 4w - T4 += T4; - - // T2 = a^2 - a - T2 -= T0; - - // T0 = a^2 - 5a + 6 - T0 += T0; - T0 += T0; - T0 = T2 - T0; - T0 += six; - - // identity = (identity + a(a - 1)(a - 2)(a - 3)) * alpha - T0 *= T2; - identity += T0; - identity *= alpha; - - // T3 = b^2 - b - T3 -= T1; - - // T1 = b^2 - 5b + 6 - T1 += T1; - T1 += T1; - T1 = T3 - T1; - T1 += six; - - // identity = (identity + b(b - 1)(b - 2)(b - 3)) * alpha - T1 *= T3; - identity += T1; - identity *= alpha; - - // T0 = 3(a + b) - T0 = delta_sum + delta_sum; - T0 += delta_sum; - - // T1 = 9(a + b) - T1 = T0 + T0; - T1 += T0; - - // delta_sum = 18(a + b) - delta_sum = T1 + T1; - - // T1 = 81(a + b) - T2 = delta_sum + delta_sum; - T2 += T2; - T1 += T2; - - // delta_squared_sum = 18(a^2 + b^2) - T2 = delta_squared_sum + delta_squared_sum; - T2 += delta_squared_sum; - delta_squared_sum = T2 + T2; - delta_squared_sum += T2; - delta_squared_sum += delta_squared_sum; - - // delta_sum = w(4w - 18(a + b) + 81) - delta_sum = T4 - delta_sum; - delta_sum += eighty_one; - delta_sum *= wire_3_value; - - // T1 = 18(a^2 + b^2) - 81(a + b) + 83 - T1 = delta_squared_sum - T1; - T1 += eighty_three; - - // delta_sum = w ( w ( 4w - 18(a + b) + 81) + 18(a^2 + b^2) - 81(a + b) + 83) - delta_sum += T1; - delta_sum *= wire_3_value; - - // T2 = 3c - T2 = wire_4_value + wire_4_value; - T2 += T2; - T2 = wire_4_shifted - T2; - T3 = T2 + T2; - T2 += T3; - - // T3 = 9c - T3 = T2 + T2; - T3 += T2; - - // T3 = q_c * (9c - 3(a + b)) - T3 -= T0; - T3 *= q_c_value; - - // T2 = 3c + 3(a + b) - 2 * delta_sum - T2 += T0; - delta_sum += delta_sum; - T2 -= delta_sum; - - // T2 = T2 + T3 - T2 += T3; - - // identity = q_logic * alpha_base * (identity + T2) - identity += T2; - identity *= alpha_base; - return identity * q_logic[gate_index]; -} - -/** - * @brief Evaluates the contribution of the fixed_base constraint - * - * @param gate_index Gate index - * @param alpha_powers A vector with alpha_base and alpha_base*α^{i} for enough i - * @return fr - */ -template -inline FF TurboCircuitBuilder_::fixed_base_gate_evaluation(const size_t gate_index, - const std::vector& alpha_powers) -{ - ASSERT(gate_index < this->num_gates); - - constexpr FF grumpkin_curve_b(-17); - constexpr FF three(3); - - // Get witness values - FF wire_1_shifted; - FF wire_2_shifted; - FF wire_3_shifted; - FF wire_4_shifted; - const FF wire_1_value = this->get_variable(w_l[gate_index]); - const FF wire_2_value = this->get_variable(w_r[gate_index]); - const FF wire_3_value = this->get_variable(w_o[gate_index]); - const FF wire_4_value = this->get_variable(w_4[gate_index]); - if ((gate_index + 1) < this->num_gates) { - wire_1_shifted = this->get_variable(w_l[gate_index + 1]); - wire_2_shifted = this->get_variable(w_r[gate_index + 1]); - wire_3_shifted = this->get_variable(w_o[gate_index + 1]); - wire_4_shifted = this->get_variable(w_4[gate_index + 1]); - } else { - wire_1_shifted = FF::zero(); - wire_2_shifted = FF::zero(); - wire_3_shifted = FF::zero(); - wire_4_shifted = FF::zero(); - } - - // Get selector values - const FF q_c_value = q_c[gate_index]; - const FF q_fixed_base_value = q_fixed_base[gate_index]; - const FF q_m_value = q_m[gate_index]; - const FF q_1_value = q_1[gate_index]; - const FF q_2_value = q_2[gate_index]; - const FF q_3_value = q_3[gate_index]; - const FF q_4_value = q_4[gate_index]; - const FF q_5_value = q_5[gate_index]; - - // Compute, optimizing multiplications (different from the way we used in widgets, since the linearization - // trick is no more) - - FF delta = wire_4_shifted - (wire_4_value + wire_4_value + wire_4_value + wire_4_value); - FF delta_squared = delta.sqr(); - - // accumulator_identity = (δ + 3)(δ + 1)(δ - 1)(δ - 3) - FF result = (delta - three) * (delta - FF::one()) * (delta + FF::one()) * (delta + three) * alpha_powers[0]; - - // Originaly q_1 and q_2 multiplicands with x_alpha_identity - result += (delta_squared * q_1_value + q_2_value - wire_3_shifted) * alpha_powers[1]; - FF T1_part = wire_2_value * alpha_powers[2]; - // Added q_3 multiplicand - result += - ((T1_part + T1_part) + (wire_1_shifted - wire_1_value) * alpha_powers[3]) * delta * wire_3_shifted * q_3_value; - - FF T0 = wire_1_shifted + wire_1_value + wire_3_shifted; - FF T1 = (wire_3_shifted - wire_1_value).sqr(); - T0 = T0 * T1; - - T1 = wire_3_shifted.sqr() * wire_3_shifted; - FF T2 = wire_2_value.sqr(); - T1 = T1 + T2; - T1 = -(T1 + grumpkin_curve_b); - - T2 = delta * wire_2_value * q_fixed_base_value; - T2 = T2 + T2; - - // x_accumulator_identity = α^2 * - // [(w_1,ω + w_1 + w_3,ω) * (w_3,ω - w_1)^2 - (b + w_3,ω^3 + w_2^2) + 2δ * w_2 * q_fixed_base] - result += (T0 + T1 + T2) * alpha_powers[2]; - - T0 = (wire_2_shifted + wire_2_value) * (wire_3_shifted - wire_1_value); - T1 = wire_1_value - wire_1_shifted; - T2 = wire_2_value - (q_fixed_base_value * delta); - T1 = T1 * T2; - - // y_accumulator_identity = α^3 * - // [(w_2,ω + w_2) * (w_3,ω - w_1) + (w_1 - w_1,ω) * (w_2 - q_fixed_base * δ)] - - result += (T0 + T1) * alpha_powers[3]; - - T0 = wire_4_value - FF::one(); - T1 = T0 - wire_3_value; - FF accumulator_init_identity = T0 * T1 * alpha_powers[4]; - - // q_4 and q_5 - result += (((wire_3_value * q_4_value + (FF::one() - wire_4_value) * q_5_value) * alpha_powers[5]) + - (q_m_value * wire_3_value * alpha_powers[6])) * - q_c_value; - - // x_init_identity = -α^5 * w_1 * w_3 - FF x_init_identity = -(wire_1_value * wire_3_value) * alpha_powers[5]; - - // y_init_identity = α^6 * (q_c * (1 - w_4) - w_2 * w_3) - T0 = FF::one() - wire_4_value; - T0 = T0 * q_c_value; - T1 = wire_2_value * wire_3_value; - FF y_init_identity = (T0 - T1) * alpha_powers[6]; - - result += (accumulator_init_identity + x_init_identity + y_init_identity) * q_c_value; - return result * q_fixed_base_value; -} -/** - * Check if the circuit constraints hold. - * - * @return true if circuit is correct, false if not. - * */ -template bool TurboCircuitBuilder_::check_circuit() -{ -// #define LAZY_CIRCUIT_CHECKS -#ifdef LAZY_CIRCUIT_CHECKS - for (size_t i = 0; i < this->num_gates; i++) { - if (!q_arith[i].is_zero() && !lazy_arithmetic_gate_check(i)) { - return false; - } - if (!q_fixed_base[i].is_zero() && !lazy_fixed_base_gate_check(i)) { - return false; - } - if (!q_range[i].is_zero() && !lazy_range_gate_check(i)) { - return false; - } - if (!q_logic[i].is_zero() && !lazy_logic_gate_check(i)) { - return false; - } - } - return true; -#else - // Initialize each of the kernels - const FF alpha_base = FF::random_element(); - const FF alpha = FF::random_element(); - std::vector alpha_powers; - alpha_powers.push_back(alpha_base); - for (size_t i = 1; i < 7; i++) { - alpha_powers.push_back(alpha_powers[i - 1] * alpha); - } - - for (size_t i = 0; i < this->get_num_gates(); i++) { - if (!arithmetic_gate_evaluation(i, alpha_base).is_zero()) { -#ifndef FUZZING - info("Arithmetic gate ", i, " failed"); -#endif - return false; - } - - if (!logic_gate_evaluation(i, alpha_base, alpha).is_zero()) { -#ifndef FUZZING - info("Logic gate ", i, " failed"); -#endif - return false; - } - - if (!range_gate_evaluation(i, alpha_base, alpha).is_zero()) { -#ifndef FUZZING - info("Range gate ", i, " failed"); -#endif - return false; - } - - if (!fixed_base_gate_evaluation(i, alpha_powers).is_zero()) { -#ifndef FUZZING - info("Arithmetic gate ", i, " failed"); -#endif - return false; - } - } - return true; - -#endif -} -template class TurboCircuitBuilder_; -} // namespace proof_system diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.hpp deleted file mode 100644 index 7ab81feef2d..00000000000 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.hpp +++ /dev/null @@ -1,128 +0,0 @@ -#pragma once -#include "barretenberg/ecc/curves/bn254/bn254.hpp" -#include "barretenberg/proof_system/types/circuit_type.hpp" -#include "barretenberg/proof_system/types/merkle_hash_type.hpp" -#include "barretenberg/proof_system/types/pedersen_commitment_type.hpp" -#include "circuit_builder_base.hpp" -#include - -namespace proof_system { - -inline std::vector turbo_selector_names() -{ - std::vector result{ "q_m", "q_c", "q_1", "q_2", "q_3", "q_4", - "q_5", "q_arith", "q_fixed_base", "q_range", "q_logic" }; - return result; -} -template class TurboCircuitBuilder_ : public CircuitBuilderBase> { - - public: - static constexpr std::string_view NAME_STRING = "TurboArithmetization"; - static constexpr CircuitType CIRCUIT_TYPE = CircuitType::TURBO; - // TODO(#563): make issue; these belong in plonk::flavor::Turbo. - static constexpr merkle::HashType merkle_hash_type = merkle::HashType::FIXED_BASE_PEDERSEN; - static constexpr pedersen::CommitmentType commitment_type = pedersen::CommitmentType::FIXED_BASE_PEDERSEN; - static constexpr size_t UINT_LOG2_BASE = 2; - - using WireVector = std::vector>; - using SelectorVector = std::vector>; - - WireVector& w_l = std::get<0>(this->wires); - WireVector& w_r = std::get<1>(this->wires); - WireVector& w_o = std::get<2>(this->wires); - WireVector& w_4 = std::get<3>(this->wires); - - SelectorVector& q_m = this->selectors.q_m; - SelectorVector& q_c = this->selectors.q_c; - SelectorVector& q_1 = this->selectors.q_1; - SelectorVector& q_2 = this->selectors.q_2; - SelectorVector& q_3 = this->selectors.q_3; - SelectorVector& q_4 = this->selectors.q_4; - SelectorVector& q_5 = this->selectors.q_5; - SelectorVector& q_arith = this->selectors.q_arith; - SelectorVector& q_fixed_base = this->selectors.q_fixed_base; - SelectorVector& q_range = this->selectors.q_range; - SelectorVector& q_logic = this->selectors.q_logic; - - TurboCircuitBuilder_(const size_t size_hint = 0); - TurboCircuitBuilder_(TurboCircuitBuilder_&& other) = default; - TurboCircuitBuilder_& operator=(TurboCircuitBuilder_&& other) - { - CircuitBuilderBase>::operator=(std::move(other)); - constant_variable_indices = other.constant_variable_indices; - return *this; - }; - ~TurboCircuitBuilder_() {} - - void create_add_gate(const add_triple_& in); - - void create_big_add_gate(const add_quad_& in); - void create_big_add_gate_with_bit_extraction(const add_quad_& in); - void create_big_mul_gate(const mul_quad_& in); - void create_balanced_add_gate(const add_quad_& in); - - void create_mul_gate(const mul_triple_& in); - void create_bool_gate(const uint32_t a); - void create_poly_gate(const poly_triple_& in); - void create_fixed_group_add_gate(const fixed_group_add_quad_& in); - void create_fixed_group_add_gate_with_init(const fixed_group_add_quad_& in, - const fixed_group_init_quad_& init); - void create_fixed_group_add_gate_final(const add_quad_& in); - void fix_witness(const uint32_t witness_index, const FF& witness_value); - - FF arithmetic_gate_evaluation(const size_t index, const FF alpha_base); - FF fixed_base_gate_evaluation(const size_t index, const std::vector& alpha_powers); - FF logic_gate_evaluation(const size_t index, const FF alpha_bas, const FF alpha); - FF range_gate_evaluation(const size_t index, const FF alpha_bas, const FF alpha); - - bool lazy_arithmetic_gate_check(const size_t gate_index); - bool lazy_fixed_base_gate_check(const size_t gate_index); - bool lazy_logic_gate_check(const size_t gate_index); - bool lazy_range_gate_check(const size_t gate_index); - - bool check_circuit(); - - std::vector decompose_into_base4_accumulators(const uint32_t witness_index, - const size_t num_bits, - std::string const& msg); - - void create_range_constraint(const uint32_t variable_index, const size_t num_bits, std::string const& msg) - { - decompose_into_base4_accumulators(variable_index, num_bits, msg); - } - - accumulator_triple_ create_logic_constraint(const uint32_t a, - const uint32_t b, - const size_t num_bits, - bool is_xor_gate); - accumulator_triple_ create_and_constraint(const uint32_t a, const uint32_t b, const size_t num_bits); - accumulator_triple_ create_xor_constraint(const uint32_t a, const uint32_t b, const size_t num_bits); - - uint32_t put_constant_variable(const FF& variable); - - size_t get_num_constant_gates() const { return 0; } - - void assert_equal_constant(const uint32_t a_idx, const FF& b, std::string const& msg = "assert_equal_constant") - { - if (this->variables[a_idx] != b && !this->failed()) { - this->failure(msg); - } - auto b_idx = put_constant_variable(b); - this->assert_equal(a_idx, b_idx, msg); - } - - /** - * For any type other than uint32_t (presumed to be a witness index), we call normalize first. - */ - template - void assert_equal_constant(T const& in, const FF& b, std::string const& msg = "assert_equal_constant") - { - assert_equal_constant(in.normalize().witness_index, b, msg); - } - - // these are variables that we have used a gate on, to enforce that they are equal to a defined value - std::map constant_variable_indices; -}; -extern template class TurboCircuitBuilder_; -using TurboCircuitBuilder = TurboCircuitBuilder_; -} // namespace proof_system diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.test.cpp deleted file mode 100644 index e06220338fa..00000000000 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.test.cpp +++ /dev/null @@ -1,684 +0,0 @@ -#include "turbo_circuit_builder.hpp" -#include "barretenberg/crypto/generators/fixed_base_scalar_mul.hpp" -#include "barretenberg/crypto/generators/generator_data.hpp" -#include - -using namespace barretenberg; -using namespace crypto::generators; - -namespace { -auto& engine = numeric::random::get_debug_engine(); -} -namespace proof_system { -TEST(turbo_circuit_constructor, base_case) -{ - TurboCircuitBuilder circuit_constructor = TurboCircuitBuilder(); - fr a = fr::one(); - circuit_constructor.add_public_variable(a); - bool result = circuit_constructor.check_circuit(); - EXPECT_EQ(result, true); -} - -TEST(turbo_circuit_constructor, test_add_gate_proofs) -{ - TurboCircuitBuilder circuit_constructor = TurboCircuitBuilder(); - fr a = fr::one(); - fr b = fr::one(); - fr c = a + b; - fr d = a + c; - uint32_t a_idx = circuit_constructor.add_variable(a); - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - uint32_t d_idx = circuit_constructor.add_variable(d); - - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ d_idx, c_idx, a_idx, fr::one(), fr::neg_one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ b_idx, a_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - - // TODO: proof fails if one wire contains all zeros. Should we support this? - uint32_t zero_idx = circuit_constructor.add_variable(fr::zero()); - - circuit_constructor.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, a_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - bool result = circuit_constructor.check_circuit(); - EXPECT_EQ(result, true); -} - -TEST(turbo_circuit_constructor, test_mul_gate_proofs) -{ - TurboCircuitBuilder circuit_constructor = TurboCircuitBuilder(); - fr q[7]{ fr::random_element(), fr::random_element(), fr::random_element(), fr::random_element(), - fr::random_element(), fr::random_element(), fr::random_element() }; - fr q_inv[7]{ - q[0].invert(), q[1].invert(), q[2].invert(), q[3].invert(), q[4].invert(), q[5].invert(), q[6].invert(), - }; - - fr a = fr::random_element(); - fr b = fr::random_element(); - fr c = -((((q[0] * a) + (q[1] * b)) + q[3]) * q_inv[2]); - fr d = -((((q[4] * (a * b)) + q[6]) * q_inv[5])); - - uint32_t a_idx = circuit_constructor.add_public_variable(a); - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - uint32_t d_idx = circuit_constructor.add_variable(d); - - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, q[0], q[1], q[2], q[3] }); - circuit_constructor.create_mul_gate({ a_idx, b_idx, d_idx, q[4], q[5], q[6] }); - - uint32_t zero_idx = circuit_constructor.add_variable(fr::zero()); - uint32_t one_idx = circuit_constructor.add_variable(fr::one()); - circuit_constructor.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, one_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - uint32_t e_idx = circuit_constructor.add_variable(a - fr::one()); - circuit_constructor.create_add_gate({ e_idx, b_idx, c_idx, q[0], q[1], q[2], (q[3] + q[0]) }); - - bool result = circuit_constructor.check_circuit(); - EXPECT_EQ(result, true); -} - -TEST(turbo_circuit_constructor, small_scalar_multipliers) -{ - constexpr size_t num_bits = 63; - constexpr size_t num_quads_base = (num_bits - 1) >> 1; - constexpr size_t num_quads = ((num_quads_base << 1) + 1 < num_bits) ? num_quads_base + 1 : num_quads_base; - constexpr size_t num_wnaf_bits = (num_quads << 1) + 1; - constexpr size_t initial_exponent = ((num_bits & 1) == 1) ? num_bits - 1 : num_bits; - constexpr uint64_t bit_mask = (1ULL << num_bits) - 1UL; - auto gen_data = crypto::generators::get_generator_data(DEFAULT_GEN_1); - const crypto::generators::fixed_base_ladder* ladder = gen_data.get_ladder(num_bits); - grumpkin::g1::affine_element generator = gen_data.generator; - - grumpkin::g1::element origin_points[2]; - origin_points[0] = grumpkin::g1::element(ladder[0].one); - origin_points[1] = origin_points[0] + generator; - origin_points[1] = origin_points[1].normalize(); - - grumpkin::fr scalar_multiplier_entropy = grumpkin::fr::random_element(); - grumpkin::fr scalar_multiplier_base{ scalar_multiplier_entropy.data[0] & bit_mask, 0, 0, 0 }; - // scalar_multiplier_base.data[0] = scalar_multiplier_base.data[0] | (1ULL); - scalar_multiplier_base.data[0] = scalar_multiplier_base.data[0] & (~1ULL); - grumpkin::fr scalar_multiplier = scalar_multiplier_base; - - uint64_t wnaf_entries[num_quads + 1] = { 0 }; - if ((scalar_multiplier_base.data[0] & 1) == 0) { - scalar_multiplier_base.data[0] -= 2; - } - bool skew = false; - barretenberg::wnaf::fixed_wnaf(&scalar_multiplier_base.data[0], &wnaf_entries[0], skew, 0); - - fr accumulator_offset = (fr::one() + fr::one()).pow(static_cast(initial_exponent)).invert(); - fr origin_accumulators[2]{ fr::one(), accumulator_offset + fr::one() }; - - grumpkin::g1::element* multiplication_transcript = - static_cast(aligned_alloc(64, sizeof(grumpkin::g1::element) * (num_quads + 1))); - fr* accumulator_transcript = static_cast(aligned_alloc(64, sizeof(fr) * (num_quads + 1))); - - if (skew) { - multiplication_transcript[0] = origin_points[1]; - accumulator_transcript[0] = origin_accumulators[1]; - } else { - multiplication_transcript[0] = origin_points[0]; - accumulator_transcript[0] = origin_accumulators[0]; - } - - fr one = fr::one(); - fr three = ((one + one) + one); - for (size_t i = 0; i < num_quads; ++i) { - uint64_t entry = wnaf_entries[i + 1] & crypto::generators::WNAF_MASK; - fr prev_accumulator = accumulator_transcript[i] + accumulator_transcript[i]; - prev_accumulator = prev_accumulator + prev_accumulator; - - grumpkin::g1::affine_element point_to_add = (entry == 1) ? ladder[i + 1].three : ladder[i + 1].one; - fr scalar_to_add = (entry == 1) ? three : one; - uint64_t predicate = (wnaf_entries[i + 1] >> 31U) & 1U; - if (predicate) { - point_to_add = -point_to_add; - scalar_to_add.self_neg(); - } - accumulator_transcript[i + 1] = prev_accumulator + scalar_to_add; - multiplication_transcript[i + 1] = multiplication_transcript[i] + point_to_add; - } - grumpkin::g1::element::batch_normalize(&multiplication_transcript[0], num_quads + 1); - - TurboCircuitBuilder circuit_constructor = TurboCircuitBuilder(); - - fr x_alpha = accumulator_offset; - for (size_t i = 0; i < num_quads; ++i) { - fixed_group_add_quad_ round_quad; - round_quad.d = circuit_constructor.add_variable(accumulator_transcript[i]); - round_quad.a = circuit_constructor.add_variable(multiplication_transcript[i].x); - round_quad.b = circuit_constructor.add_variable(multiplication_transcript[i].y); - round_quad.c = circuit_constructor.add_variable(x_alpha); - if ((wnaf_entries[i + 1] & 0xffffffU) == 0) { - x_alpha = ladder[i + 1].one.x; - } else { - x_alpha = ladder[i + 1].three.x; - } - round_quad.q_x_1 = ladder[i + 1].q_x_1; - round_quad.q_x_2 = ladder[i + 1].q_x_2; - round_quad.q_y_1 = ladder[i + 1].q_y_1; - round_quad.q_y_2 = ladder[i + 1].q_y_2; - - if (i > 0) { - circuit_constructor.create_fixed_group_add_gate(round_quad); - } else { - circuit_constructor.create_fixed_group_add_gate_with_init(round_quad, - { origin_points[0].x, - (origin_points[0].x - origin_points[1].x), - origin_points[0].y, - (origin_points[0].y - origin_points[1].y) }); - } - } - - circuit_constructor.create_big_add_gate({ circuit_constructor.add_variable(multiplication_transcript[num_quads].x), - circuit_constructor.add_variable(multiplication_transcript[num_quads].y), - circuit_constructor.add_variable(x_alpha), - circuit_constructor.add_variable(accumulator_transcript[num_quads]), - fr::zero(), - fr::zero(), - fr::zero(), - fr::zero(), - fr::zero() }); - - grumpkin::g1::element expected_point = - grumpkin::g1::element(generator * scalar_multiplier.to_montgomery_form()).normalize(); - EXPECT_EQ((multiplication_transcript[num_quads].x == expected_point.x), true); - EXPECT_EQ((multiplication_transcript[num_quads].y == expected_point.y), true); - - uint64_t result_accumulator = accumulator_transcript[num_quads].from_montgomery_form().data[0]; - uint64_t expected_accumulator = scalar_multiplier.data[0]; - EXPECT_EQ(result_accumulator, expected_accumulator); - - bool result = circuit_constructor.check_circuit(); - - EXPECT_EQ(result, true); - - free(multiplication_transcript); - free(accumulator_transcript); -} - -TEST(turbo_circuit_constructor, large_scalar_multipliers) -{ - constexpr size_t num_bits = 254; - constexpr size_t num_quads_base = (num_bits - 1) >> 1; - constexpr size_t num_quads = ((num_quads_base << 1) + 1 < num_bits) ? num_quads_base + 1 : num_quads_base; - constexpr size_t num_wnaf_bits = (num_quads << 1) + 1; - - constexpr size_t initial_exponent = num_bits; // ((num_bits & 1) == 1) ? num_bits - 1 : num_bits; - auto gen_data = crypto::generators::get_generator_data(DEFAULT_GEN_1); - const crypto::generators::fixed_base_ladder* ladder = gen_data.get_ladder(num_bits); - grumpkin::g1::affine_element generator = gen_data.generator; - - grumpkin::g1::element origin_points[2]; - origin_points[0] = grumpkin::g1::element(ladder[0].one); - origin_points[1] = origin_points[0] + generator; - origin_points[1] = origin_points[1].normalize(); - - grumpkin::fr scalar_multiplier_base = grumpkin::fr::random_element(); - - grumpkin::fr scalar_multiplier = scalar_multiplier_base.from_montgomery_form(); - - if ((scalar_multiplier.data[0] & 1) == 0) { - grumpkin::fr two = grumpkin::fr::one() + grumpkin::fr::one(); - scalar_multiplier_base = scalar_multiplier_base - two; - } - scalar_multiplier_base = scalar_multiplier_base.from_montgomery_form(); - uint64_t wnaf_entries[num_quads + 1] = { 0 }; - - bool skew = false; - barretenberg::wnaf::fixed_wnaf(&scalar_multiplier_base.data[0], &wnaf_entries[0], skew, 0); - - fr accumulator_offset = (fr::one() + fr::one()).pow(static_cast(initial_exponent)).invert(); - fr origin_accumulators[2]{ fr::one(), accumulator_offset + fr::one() }; - - grumpkin::g1::element* multiplication_transcript = - static_cast(aligned_alloc(64, sizeof(grumpkin::g1::element) * (num_quads + 1))); - fr* accumulator_transcript = static_cast(aligned_alloc(64, sizeof(fr) * (num_quads + 1))); - - if (skew) { - multiplication_transcript[0] = origin_points[1]; - accumulator_transcript[0] = origin_accumulators[1]; - } else { - multiplication_transcript[0] = origin_points[0]; - accumulator_transcript[0] = origin_accumulators[0]; - } - - fr one = fr::one(); - fr three = ((one + one) + one); - for (size_t i = 0; i < num_quads; ++i) { - uint64_t entry = wnaf_entries[i + 1] & crypto::generators::WNAF_MASK; - fr prev_accumulator = accumulator_transcript[i] + accumulator_transcript[i]; - prev_accumulator = prev_accumulator + prev_accumulator; - - grumpkin::g1::affine_element point_to_add = (entry == 1) ? ladder[i + 1].three : ladder[i + 1].one; - fr scalar_to_add = (entry == 1) ? three : one; - uint64_t predicate = (wnaf_entries[i + 1] >> 31U) & 1U; - if (predicate) { - point_to_add = -point_to_add; - scalar_to_add.self_neg(); - } - accumulator_transcript[i + 1] = prev_accumulator + scalar_to_add; - multiplication_transcript[i + 1] = multiplication_transcript[i] + point_to_add; - } - grumpkin::g1::element::batch_normalize(&multiplication_transcript[0], num_quads + 1); - - TurboCircuitBuilder circuit_constructor = TurboCircuitBuilder(); - - fr x_alpha = accumulator_offset; - for (size_t i = 0; i < num_quads; ++i) { - fixed_group_add_quad_ round_quad; - round_quad.d = circuit_constructor.add_variable(accumulator_transcript[i]); - round_quad.a = circuit_constructor.add_variable(multiplication_transcript[i].x); - round_quad.b = circuit_constructor.add_variable(multiplication_transcript[i].y); - round_quad.c = circuit_constructor.add_variable(x_alpha); - if ((wnaf_entries[i + 1] & 0xffffffU) == 0) { - x_alpha = ladder[i + 1].one.x; - } else { - x_alpha = ladder[i + 1].three.x; - } - round_quad.q_x_1 = ladder[i + 1].q_x_1; - round_quad.q_x_2 = ladder[i + 1].q_x_2; - round_quad.q_y_1 = ladder[i + 1].q_y_1; - round_quad.q_y_2 = ladder[i + 1].q_y_2; - - if (i > 0) { - circuit_constructor.create_fixed_group_add_gate(round_quad); - } else { - circuit_constructor.create_fixed_group_add_gate_with_init(round_quad, - { origin_points[0].x, - (origin_points[0].x - origin_points[1].x), - origin_points[0].y, - (origin_points[0].y - origin_points[1].y) }); - } - } - - circuit_constructor.create_big_add_gate({ circuit_constructor.add_variable(multiplication_transcript[num_quads].x), - circuit_constructor.add_variable(multiplication_transcript[num_quads].y), - circuit_constructor.add_variable(x_alpha), - circuit_constructor.add_variable(accumulator_transcript[num_quads]), - fr::zero(), - fr::zero(), - fr::zero(), - fr::zero(), - fr::zero() }); - - grumpkin::g1::element expected_point = - grumpkin::g1::element(generator * scalar_multiplier.to_montgomery_form()).normalize(); - EXPECT_EQ((multiplication_transcript[num_quads].x == expected_point.x), true); - EXPECT_EQ((multiplication_transcript[num_quads].y == expected_point.y), true); - - fr result_accumulator = (accumulator_transcript[num_quads]); - fr expected_accumulator = - fr{ scalar_multiplier.data[0], scalar_multiplier.data[1], scalar_multiplier.data[2], scalar_multiplier.data[3] } - .to_montgomery_form(); - EXPECT_EQ((result_accumulator == expected_accumulator), true); - - bool result = circuit_constructor.check_circuit(); - EXPECT_EQ(result, true); - - free(multiplication_transcript); - free(accumulator_transcript); -} - -TEST(turbo_circuit_constructor, range_constraint) -{ - TurboCircuitBuilder circuit_constructor = TurboCircuitBuilder(); - - for (size_t i = 0; i < 10; ++i) { - uint32_t value = engine.get_random_uint32(); - fr witness_value = fr{ value, 0, 0, 0 }.to_montgomery_form(); - uint32_t witness_index = circuit_constructor.add_variable(witness_value); - - // include non-nice numbers of bits, that will bleed over gate boundaries - size_t extra_bits = 2 * (i % 4); - - std::vector accumulators = circuit_constructor.decompose_into_base4_accumulators( - witness_index, 32 + extra_bits, "constraint in test range_constraint fails"); - - for (uint32_t j = 0; j < 16; ++j) { - uint32_t result = (value >> (30U - (2 * j))); - fr source = circuit_constructor.get_variable(accumulators[j + (extra_bits >> 1)]).from_montgomery_form(); - uint32_t expected = static_cast(source.data[0]); - EXPECT_EQ(result, expected); - } - for (uint32_t j = 1; j < 16; ++j) { - uint32_t left = (value >> (30U - (2 * j))); - uint32_t right = (value >> (30U - (2 * (j - 1)))); - EXPECT_EQ(left - 4 * right < 4, true); - } - } - - uint32_t zero_idx = circuit_constructor.add_variable(fr::zero()); - uint32_t one_idx = circuit_constructor.add_variable(fr::one()); - circuit_constructor.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, one_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - bool result = circuit_constructor.check_circuit(); - - EXPECT_EQ(result, true); -} - -TEST(turbo_circuit_constructor, range_constraint_fail) -{ - TurboCircuitBuilder circuit_constructor = TurboCircuitBuilder(); - - uint64_t value = 0xffffff; - uint32_t witness_index = circuit_constructor.add_variable(fr(value)); - - circuit_constructor.decompose_into_base4_accumulators(witness_index, 23, "yay, range constraint fails"); - - bool result = circuit_constructor.check_circuit(); - - EXPECT_EQ(result, false); -} - -/** - * @brief Test that the `AND` constraint fails when constraining too few bits. - * - */ -TEST(turbo_circuit_constructor, and_constraint_failure) -{ - TurboCircuitBuilder circuit_constructor = TurboCircuitBuilder(); - - uint32_t left_value = 4; - fr left_witness_value = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t left_witness_index = circuit_constructor.add_variable(left_witness_value); - - uint32_t right_value = 5; - fr right_witness_value = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t right_witness_index = circuit_constructor.add_variable(right_witness_value); - - // 4 && 5 is 4, so 3 bits are needed, but we only constrain 2 - auto accumulators = circuit_constructor.create_and_constraint(left_witness_index, right_witness_index, 2); - - bool result = circuit_constructor.check_circuit(); - - if (circuit_constructor.failed()) { - info("circuit_constructor failed; ", circuit_constructor.err()); - } - - EXPECT_EQ(result, false); -} - -TEST(turbo_circuit_constructor, and_constraint) -{ - TurboCircuitBuilder circuit_constructor = TurboCircuitBuilder(); - - for (size_t i = 0; i < /*10*/ 1; ++i) { - uint32_t left_value = engine.get_random_uint32(); - - fr left_witness_value = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t left_witness_index = circuit_constructor.add_variable(left_witness_value); - - uint32_t right_value = engine.get_random_uint32(); - fr right_witness_value = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t right_witness_index = circuit_constructor.add_variable(right_witness_value); - - uint32_t out_value = left_value & right_value; - // include non-nice numbers of bits, that will bleed over gate boundaries - size_t extra_bits = 2 * (i % 4); - - auto accumulators = - circuit_constructor.create_and_constraint(left_witness_index, right_witness_index, 32 + extra_bits); - // circuit_constructor.create_and_constraint(left_witness_index, right_witness_index, 32 + extra_bits); - - for (uint32_t j = 0; j < 16; ++j) { - uint32_t left_expected = (left_value >> (30U - (2 * j))); - uint32_t right_expected = (right_value >> (30U - (2 * j))); - uint32_t out_expected = left_expected & right_expected; - - fr left_source = - circuit_constructor.get_variable(accumulators.left[j + (extra_bits >> 1)]).from_montgomery_form(); - uint32_t left_result = static_cast(left_source.data[0]); - - fr right_source = - circuit_constructor.get_variable(accumulators.right[j + (extra_bits >> 1)]).from_montgomery_form(); - uint32_t right_result = static_cast(right_source.data[0]); - - fr out_source = - circuit_constructor.get_variable(accumulators.out[j + (extra_bits >> 1)]).from_montgomery_form(); - uint32_t out_result = static_cast(out_source.data[0]); - - EXPECT_EQ(left_result, left_expected); - EXPECT_EQ(right_result, right_expected); - EXPECT_EQ(out_result, out_expected); - } - for (uint32_t j = 1; j < 16; ++j) { - uint32_t left = (left_value >> (30U - (2 * j))); - uint32_t right = (left_value >> (30U - (2 * (j - 1)))); - EXPECT_EQ(left - 4 * right < 4, true); - - left = (right_value >> (30U - (2 * j))); - right = (right_value >> (30U - (2 * (j - 1)))); - EXPECT_EQ(left - 4 * right < 4, true); - - left = (out_value >> (30U - (2 * j))); - right = (out_value >> (30U - (2 * (j - 1)))); - EXPECT_EQ(left - 4 * right < 4, true); - } - } - - uint32_t zero_idx = circuit_constructor.add_variable(fr::zero()); - uint32_t one_idx = circuit_constructor.add_variable(fr::one()); - circuit_constructor.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, one_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - bool result = circuit_constructor.check_circuit(); - - EXPECT_EQ(result, true); -} - -/** - * @brief Test that the `XOR` constraint fails when constraining too few bits. - * - */ -TEST(turbo_circuit_constructor, xor_constraint_failure) -{ - TurboCircuitBuilder circuit_constructor = TurboCircuitBuilder(); - - uint32_t left_value = 4; - fr left_witness_value = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t left_witness_index = circuit_constructor.add_variable(left_witness_value); - - uint32_t right_value = 1; - fr right_witness_value = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t right_witness_index = circuit_constructor.add_variable(right_witness_value); - - // 4 && 1 is 5, so 3 bits are needed, but we only constrain 2 - auto accumulators = circuit_constructor.create_and_constraint(left_witness_index, right_witness_index, 2); - - bool result = circuit_constructor.check_circuit(); - - if (circuit_constructor.failed()) { - info("circuit_constructor failed; ", circuit_constructor.err()); - } - - EXPECT_EQ(result, false); -} - -TEST(turbo_circuit_constructor, xor_constraint) -{ - TurboCircuitBuilder circuit_constructor = TurboCircuitBuilder(); - - for (size_t i = 0; i < /*10*/ 1; ++i) { - uint32_t left_value = engine.get_random_uint32(); - - fr left_witness_value = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t left_witness_index = circuit_constructor.add_variable(left_witness_value); - - uint32_t right_value = engine.get_random_uint32(); - fr right_witness_value = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t right_witness_index = circuit_constructor.add_variable(right_witness_value); - - uint32_t out_value = left_value ^ right_value; - // include non-nice numbers of bits, that will bleed over gate boundaries - size_t extra_bits = 2 * (i % 4); - - auto accumulators = - circuit_constructor.create_xor_constraint(left_witness_index, right_witness_index, 32 + extra_bits); - - for (uint32_t j = 0; j < 16; ++j) { - uint32_t left_expected = (left_value >> (30U - (2 * j))); - uint32_t right_expected = (right_value >> (30U - (2 * j))); - uint32_t out_expected = left_expected ^ right_expected; - - fr left_source = - circuit_constructor.get_variable(accumulators.left[j + (extra_bits >> 1)]).from_montgomery_form(); - uint32_t left_result = static_cast(left_source.data[0]); - - fr right_source = - circuit_constructor.get_variable(accumulators.right[j + (extra_bits >> 1)]).from_montgomery_form(); - uint32_t right_result = static_cast(right_source.data[0]); - - fr out_source = - circuit_constructor.get_variable(accumulators.out[j + (extra_bits >> 1)]).from_montgomery_form(); - uint32_t out_result = static_cast(out_source.data[0]); - - EXPECT_EQ(left_result, left_expected); - EXPECT_EQ(right_result, right_expected); - EXPECT_EQ(out_result, out_expected); - } - for (uint32_t j = 1; j < 16; ++j) { - uint32_t left = (left_value >> (30U - (2 * j))); - uint32_t right = (left_value >> (30U - (2 * (j - 1)))); - EXPECT_EQ(left - 4 * right < 4, true); - - left = (right_value >> (30U - (2 * j))); - right = (right_value >> (30U - (2 * (j - 1)))); - EXPECT_EQ(left - 4 * right < 4, true); - - left = (out_value >> (30U - (2 * j))); - right = (out_value >> (30U - (2 * (j - 1)))); - EXPECT_EQ(left - 4 * right < 4, true); - } - } - - uint32_t zero_idx = circuit_constructor.add_variable(fr::zero()); - uint32_t one_idx = circuit_constructor.add_variable(fr::one()); - circuit_constructor.create_big_add_gate( - { zero_idx, zero_idx, zero_idx, one_idx, fr::one(), fr::one(), fr::one(), fr::one(), fr::neg_one() }); - - bool result = circuit_constructor.check_circuit(); - - EXPECT_EQ(result, true); -} - -TEST(turbo_circuit_constructor, big_add_gate_with_bit_extract) -{ - TurboCircuitBuilder circuit_constructor = TurboCircuitBuilder(); - - const auto generate_constraints = [&circuit_constructor](uint32_t quad_value) { - uint32_t quad_accumulator_left = - (engine.get_random_uint32() & 0x3fffffff) - quad_value; // make sure this won't overflow - uint32_t quad_accumulator_right = (4 * quad_accumulator_left) + quad_value; - - uint32_t left_idx = circuit_constructor.add_variable(uint256_t(quad_accumulator_left)); - uint32_t right_idx = circuit_constructor.add_variable(uint256_t(quad_accumulator_right)); - - uint32_t input = engine.get_random_uint32(); - uint32_t output = input + (quad_value > 1 ? 1 : 0); - - circuit_constructor.create_big_add_gate_with_bit_extraction( - { circuit_constructor.add_variable(uint256_t(input)), - circuit_constructor.add_variable(uint256_t(output)), - right_idx, - left_idx, - fr(6), - -fr(6), - fr::zero(), - fr::zero(), - fr::zero() }); - }; - - generate_constraints(0); - generate_constraints(1); - generate_constraints(2); - generate_constraints(3); - - bool result = circuit_constructor.check_circuit(); - - EXPECT_EQ(result, true); -} - -} // namespace proof_system diff --git a/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp index c97c9e3c125..093f5ab8123 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp @@ -266,7 +266,6 @@ template class GoblinUltraRecursive_; // Forward declare plonk flavors namespace proof_system::plonk::flavor { class Standard; -class Turbo; class Ultra; } // namespace proof_system::plonk::flavor @@ -281,7 +280,7 @@ namespace proof_system { // clang-format off template -concept IsPlonkFlavor = IsAnyOf; +concept IsPlonkFlavor = IsAnyOf; template concept IsHonkFlavor = IsAnyOf; 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 d134af16715..f1fb50c3627 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,8 @@ #include namespace proof_system { -enum class CircuitType : uint32_t { STANDARD, TURBO, ULTRA, UNDEFINED }; +// 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 concept IsAnyOf = (std::same_as || ...); diff --git a/barretenberg/cpp/src/barretenberg/solidity_helpers/circuits/recursive_circuit.hpp b/barretenberg/cpp/src/barretenberg/solidity_helpers/circuits/recursive_circuit.hpp index b3fb91baf64..cb635c11500 100644 --- a/barretenberg/cpp/src/barretenberg/solidity_helpers/circuits/recursive_circuit.hpp +++ b/barretenberg/cpp/src/barretenberg/solidity_helpers/circuits/recursive_circuit.hpp @@ -47,7 +47,7 @@ template class RecursiveCircuit { static circuit_outputs create_outer_circuit(InnerBuilder& inner_circuit, OuterComposer& outer_composer) { // These constexpr definitions are to allow for the following: - // An Ultra Pedersen hash evaluates to a different value from the Turbo/Standard versions of the Pedersen hash. + // An Ultra Pedersen hash evaluates to a different value from the Standard version of the Pedersen hash. // Therefore, the fiat-shamir challenges generated by the prover and verifier _could_ accidentally be different // if an ultra proof is generated using ultra-pedersen challenges, but is being verified within a non-ultra // circuit which uses non-ultra-pedersen challenges. We need the prover and verifier hashes to be the same. The diff --git a/barretenberg/cpp/src/barretenberg/stdlib/commitment/pedersen/pedersen.bench.cpp b/barretenberg/cpp/src/barretenberg/stdlib/commitment/pedersen/pedersen.bench.cpp index 723a291a90a..170e324b52d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/commitment/pedersen/pedersen.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/commitment/pedersen/pedersen.bench.cpp @@ -1,7 +1,7 @@ #include "barretenberg/crypto/pedersen_commitment/pedersen.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" -#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/plonk/composer/ultra_composer.hpp" #include "barretenberg/srs/factories/file_crs_factory.hpp" #include "barretenberg/stdlib/primitives/field/field.hpp" #include "pedersen.hpp" @@ -12,8 +12,8 @@ using namespace benchmark; using namespace proof_system::plonk; -using Builder = proof_system::TurboCircuitBuilder; -using Composer = proof_system::plonk::TurboComposer; +using Builder = proof_system::UltraCircuitBuilder; +using Composer = proof_system::plonk::UltraComposer; constexpr size_t NUM_CIRCUITS = 10; @@ -49,8 +49,8 @@ void generate_test_pedersen_circuit(Builder& builder, size_t num_repetitions) } } -plonk::TurboProver pedersen_provers[NUM_CIRCUITS]; -plonk::TurboVerifier pedersen_verifiers[NUM_CIRCUITS]; +plonk::UltraProver pedersen_provers[NUM_CIRCUITS]; +plonk::UltraVerifier pedersen_verifiers[NUM_CIRCUITS]; plonk::proof pedersen_proofs[NUM_CIRCUITS]; grumpkin::fq pedersen_function(const size_t count) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/commitment/pedersen/pedersen.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/commitment/pedersen/pedersen.test.cpp index b14a4beabf0..90d871ed195 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/commitment/pedersen/pedersen.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/commitment/pedersen/pedersen.test.cpp @@ -387,9 +387,7 @@ template class stdlib_pedersen : public testing::Test { } }; -typedef testing:: - Types - CircuitTypes; +typedef testing::Types CircuitTypes; TYPED_TEST_SUITE(stdlib_pedersen, CircuitTypes); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.cpp b/barretenberg/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.cpp index 52f7e698d4f..349765fb44a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.cpp @@ -20,8 +20,6 @@ namespace schnorr { * @warning While it is possible to express any 129-bit value in this form, this function only works correctly * on 128-bit values, since the same is true for fixed_wnaf<129, 1, 1>. This is illusrated in the tests. * - * - * TurboPLONK: ~260 gates. */ template wnaf_record convert_field_into_wnaf(C* context, const field_t& limb) { @@ -269,7 +267,6 @@ point variable_base_mul(const point& pub_key, const point& current_accu * e' = hash(([s]g + [e]pub).x | message) and return e'. * - * @details TurboPlonk: ~10850 gates (~4k for variable_base_mul, ~6k for blake2s) for a string of length < 32. */ template std::array, 2> verify_signature_internal(const byte_array& message, diff --git a/barretenberg/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.test.cpp index a5eca30695e..fa61baaf068 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.test.cpp @@ -178,8 +178,8 @@ TEST(stdlib_schnorr, test_scalar_mul_low_high) /** * @test Test circuit verifying a Schnorr signature generated by \see{crypto::schnorr::verify_signature}. - * We only test: messages signed and verified using Grumpkin and the BLAKE2s hash function. We only test - * TurboPLONK. We test strings of lengths 0, 1, ..., 33. + * We only test: messages signed and verified using Grumpkin and the BLAKE2s hash function. We test strings of lengths + * 0, 1, ..., 33. */ TEST(stdlib_schnorr, verify_signature) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake_util.hpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake_util.hpp index be960fe45fd..3eadd6ac106 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake_util.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake_util.hpp @@ -65,7 +65,7 @@ template field_t add_normalize(const field_t state[BLAKE3_STATE_SIZE], } /* - * This is the round function used in Blake2s and Blake3s for TurboPlonk. + * This is the round function used in Blake2s and Blake3s. * Inputs: - 16-word state * - 16-word msg * - round numbe diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/blake3s/blake3s.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/blake3s/blake3s.test.cpp index 06ec006981c..c06f47566dd 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/blake3s/blake3s.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/blake3s/blake3s.test.cpp @@ -7,15 +7,16 @@ using namespace barretenberg; using namespace proof_system::plonk; -typedef proof_system::TurboCircuitBuilder Builder; -typedef stdlib::byte_array byte_array; -typedef stdlib::byte_array byte_array_plookup; -typedef stdlib::public_witness_t public_witness_t; -typedef stdlib::public_witness_t public_witness_t_plookup; +using byte_array = stdlib::byte_array; +using public_witness_t = stdlib::public_witness_t; +using byte_array_plookup = stdlib::byte_array; +using public_witness_t_plookup = stdlib::public_witness_t; +using StandardBuilder = proof_system::StandardCircuitBuilder; +using UltraBuilder = proof_system::UltraCircuitBuilder; TEST(stdlib_blake3s, test_single_block) { - Builder builder = Builder(); + auto builder = StandardBuilder(); std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01"; std::vector input_v(input.begin(), input.end()); @@ -34,12 +35,12 @@ TEST(stdlib_blake3s, test_single_block) TEST(stdlib_blake3s, test_single_block_plookup) { - proof_system::UltraCircuitBuilder builder = proof_system::UltraCircuitBuilder(); + auto builder = UltraBuilder(); std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01"; std::vector input_v(input.begin(), input.end()); byte_array_plookup input_arr(&builder, input_v); - byte_array_plookup output = stdlib::blake3s(input_arr); + byte_array_plookup output = stdlib::blake3s(input_arr); std::vector expected = blake3::blake3s(input_v); @@ -53,7 +54,7 @@ TEST(stdlib_blake3s, test_single_block_plookup) TEST(stdlib_blake3s, test_double_block) { - Builder builder = Builder(); + auto builder = StandardBuilder(); std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789"; std::vector input_v(input.begin(), input.end()); @@ -72,7 +73,7 @@ TEST(stdlib_blake3s, test_double_block) TEST(stdlib_blake3s, test_double_block_plookup) { - proof_system::UltraCircuitBuilder builder = proof_system::UltraCircuitBuilder(); + auto builder = UltraBuilder(); std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789"; std::vector input_v(input.begin(), input.end()); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen.cpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen.cpp index a85e7d9177e..34dce73adb3 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen.cpp @@ -207,10 +207,10 @@ point pedersen_hash::hash_single_internal(const field_t& in, } else { if constexpr (HasPlookup && (C::merkle_hash_type == merkle::HashType::FIXED_BASE_PEDERSEN || C::commitment_type == pedersen::CommitmentType::FIXED_BASE_PEDERSEN)) { - /* In TurboBuilder, the selector q_5 is used to show that w_1 and w_2 are properly initialized to - * the coordinates of P_s = (-s + 4^n)[g]. In UltraPlonK, we have removed q_5 for overall efficiency (it - * would only be used here in this gate), but this presents us a cost in the present circuit: we must - * use an additional gate to perform part of the initialization. Since q_5 is only involved in the + /* In TurboBuilder, the selector q_5 was used to show that w_1 and w_2 were properly initialized + * to the coordinates of P_s = (-s + 4^n)[g]. In UltraPlonK, we have removed q_5 for overall efficiency + * (it would only be used here in this gate), but this presents us a cost in the present circuit: we + * must use an additional gate to perform part of the initialization. Since q_5 is only involved in the * x-coordinate initialization (in the notation of the widget, Constraint 5), we only perform that part * of the initialization with additional gates, letting Constraints 4 and 6 be handled in the Ultra * version of the widget as in the Turbo verison. @@ -242,8 +242,7 @@ point pedersen_hash::hash_single_internal(const field_t& in, accumulator_witnesses.push_back(round_quad.d); } - // In Turbo PLONK, this effectively just adds the last row of the table as witnesses. - // In Standard PLONK, this also creates the constraint involving the final two rows. + // In Standard PLONK, this creates the constraint involving the final two rows. add_quad_ add_quad{ ctx->add_variable(multiplication_transcript[num_quads].x), ctx->add_variable(multiplication_transcript[num_quads].y), ctx->add_variable(x_alpha), diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen_gates.hpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen_gates.hpp index e105d7e321c..4484492c6ac 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen_gates.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen_gates.hpp @@ -36,279 +36,247 @@ template class pedersen_gates { void create_fixed_group_add_gate(const fixed_group_add_quad& in) { - if constexpr (std::same_as) { - context->create_fixed_group_add_gate(in); - } else { - - // TODO: not supported by honk builder? - // context->assert_valid_variables({ in.a, in.b, in.c, in.d }); - - auto row_1 = previous_add_quad; - auto row_2 = in; - previous_add_quad = in; - - fr a_1 = context->get_variable(row_1.d); - fr a_2 = context->get_variable(row_2.d); - fr x_1 = context->get_variable(row_1.a); - fr y_1 = context->get_variable(row_1.b); - fr x_2 = context->get_variable(row_2.a); - fr y_2 = context->get_variable(row_2.b); - fr x_alpha = context->get_variable(row_2.c); - - fr q_x_alpha_1 = row_1.q_x_1; - fr q_x_alpha_2 = row_1.q_x_2; - fr q_y_alpha_1 = row_1.q_y_1; - fr q_y_alpha_2 = row_1.q_y_2; - - uint32_t a_1_idx = row_1.d; - uint32_t a_2_idx = row_2.d; - uint32_t x_1_idx = row_1.a; - uint32_t y_1_idx = row_1.b; - uint32_t x_2_idx = row_2.a; - uint32_t y_2_idx = row_2.b; - uint32_t x_alpha_idx = row_2.c; - - // add variable δ = a_2 - 4a_1 - fr delta = a_2 - (a_1 + a_1 + a_1 + a_1); - uint32_t delta_idx = context->add_variable(delta); - context->create_add_gate({ .a = a_2_idx, - .b = a_1_idx, - .c = delta_idx, - .a_scaling = 1, - .b_scaling = -4, - .c_scaling = -1, - .const_scaling = 0 }); - - // constraint: (δ + 3)(δ + 1)(δ - 1)(δ - 3) - // (δ + 3)(δ + 1)(δ - 1)(δ - 3) = (δ^2 - 9)(δ^2 - 1)=0 - // // first: (δ^2 - δ_sqr = 0) - fr delta_sqr = delta * delta; - uint32_t delta_sqr_idx = context->add_variable(delta_sqr); - context->create_mul_gate({ .a = delta_idx, - .b = delta_idx, - .c = delta_sqr_idx, - .mul_scaling = 1, - .c_scaling = -1, - .const_scaling = 0 }); - // // next (δ^2 - 9)( δ^2 - 1) = δ^2*δ^2 - 10 * δ^2 + 9 = 0 - context->create_mul_gate({ .a = delta_sqr_idx, - .b = delta_sqr_idx, - .c = delta_sqr_idx, - .mul_scaling = 1, - .c_scaling = -10, - .const_scaling = 9 }); - - // validate correctness of x_ɑ - // constraint: (δ^2) * q_x_ɑ,1 + q_x_ɑ,2 - x,ɑ = 0 - context->create_add_gate({ .a = delta_sqr_idx, + // TODO: not supported by honk composer? + // context->assert_valid_variables({ in.a, in.b, in.c, in.d }); + + auto row_1 = previous_add_quad; + auto row_2 = in; + previous_add_quad = in; + + fr a_1 = context->get_variable(row_1.d); + fr a_2 = context->get_variable(row_2.d); + fr x_1 = context->get_variable(row_1.a); + fr y_1 = context->get_variable(row_1.b); + fr x_2 = context->get_variable(row_2.a); + fr y_2 = context->get_variable(row_2.b); + fr x_alpha = context->get_variable(row_2.c); + + fr q_x_alpha_1 = row_1.q_x_1; + fr q_x_alpha_2 = row_1.q_x_2; + fr q_y_alpha_1 = row_1.q_y_1; + fr q_y_alpha_2 = row_1.q_y_2; + + uint32_t a_1_idx = row_1.d; + uint32_t a_2_idx = row_2.d; + uint32_t x_1_idx = row_1.a; + uint32_t y_1_idx = row_1.b; + uint32_t x_2_idx = row_2.a; + uint32_t y_2_idx = row_2.b; + uint32_t x_alpha_idx = row_2.c; + + // add variable δ = a_2 - 4a_1 + fr delta = a_2 - (a_1 + a_1 + a_1 + a_1); + uint32_t delta_idx = context->add_variable(delta); + context->create_add_gate({ .a = a_2_idx, + .b = a_1_idx, + .c = delta_idx, + .a_scaling = 1, + .b_scaling = -4, + .c_scaling = -1, + .const_scaling = 0 }); + + // constraint: (δ + 3)(δ + 1)(δ - 1)(δ - 3) + // (δ + 3)(δ + 1)(δ - 1)(δ - 3) = (δ^2 - 9)(δ^2 - 1)=0 + // // first: (δ^2 - δ_sqr = 0) + fr delta_sqr = delta * delta; + uint32_t delta_sqr_idx = context->add_variable(delta_sqr); + context->create_mul_gate({ .a = delta_idx, + .b = delta_idx, + .c = delta_sqr_idx, + .mul_scaling = 1, + .c_scaling = -1, + .const_scaling = 0 }); + // // next (δ^2 - 9)( δ^2 - 1) = δ^2*δ^2 - 10 * δ^2 + 9 = 0 + context->create_mul_gate({ .a = delta_sqr_idx, + .b = delta_sqr_idx, + .c = delta_sqr_idx, + .mul_scaling = 1, + .c_scaling = -10, + .const_scaling = 9 }); + + // validate correctness of x_ɑ + // constraint: (δ^2) * q_x_ɑ,1 + q_x_ɑ,2 - x,ɑ = 0 + context->create_add_gate({ .a = delta_sqr_idx, + .b = x_alpha_idx, + .c = context->zero_idx, + .a_scaling = q_x_alpha_1, + .b_scaling = -1, + .c_scaling = 0, + .const_scaling = q_x_alpha_2 }); + + // compute y_alpha using lookup formula, instantiate as witness and validate + fr y_alpha = (x_alpha * q_y_alpha_1 + q_y_alpha_2) * delta; + uint32_t y_alpha_idx = context->add_variable(y_alpha); + context->create_poly_gate({ .a = delta_idx, + .b = x_alpha_idx, + .c = y_alpha_idx, + .q_m = q_y_alpha_1, + .q_l = q_y_alpha_2, + .q_r = 0, + .q_o = -1, + .q_c = 0 }); + + // show that (x_1, y_1) + (x_ɑ, y_ɑ) = (x_2, y_2) in 11 gates + // // 4 gates to compute commonly used expressions + // // // 2 differences: + fr diff_x_alpha_x_1 = x_alpha - x_1; + uint32_t diff_x_alpha_x_1_idx = context->add_variable(diff_x_alpha_x_1); + context->create_add_gate({ .a = diff_x_alpha_x_1_idx, + .b = x_1_idx, + .c = x_alpha_idx, + .a_scaling = 1, + .b_scaling = 1, + .c_scaling = -1, + .const_scaling = 0 }); + + fr diff_y_alpha_y_1 = y_alpha - y_1; + uint32_t diff_y_alpha_y_1_idx = context->add_variable(diff_y_alpha_y_1); + context->create_add_gate({ .a = diff_y_alpha_y_1_idx, + .b = y_1_idx, + .c = y_alpha_idx, + .a_scaling = 1, + .b_scaling = 1, + .c_scaling = -1, + .const_scaling = 0 }); + + // // // now the squares of these 2 differences + fr diff_x_alpha_x_1_sqr = diff_x_alpha_x_1 * diff_x_alpha_x_1; + uint32_t diff_x_alpha_x_1_sqr_idx = context->add_variable(diff_x_alpha_x_1_sqr); + context->create_mul_gate({ .a = diff_x_alpha_x_1_idx, + .b = diff_x_alpha_x_1_idx, + .c = diff_x_alpha_x_1_sqr_idx, + .mul_scaling = 1, + .c_scaling = -1, + .const_scaling = 0 }); + + fr diff_y_alpha_y_1_sqr = diff_y_alpha_y_1 * diff_y_alpha_y_1; + uint32_t diff_y_alpha_y_1_sqr_idx = context->add_variable(diff_y_alpha_y_1_sqr); + context->create_mul_gate({ .a = diff_y_alpha_y_1_idx, + .b = diff_y_alpha_y_1_idx, + .c = diff_y_alpha_y_1_sqr_idx, + .mul_scaling = 1, + .c_scaling = -1, + .const_scaling = 0 }); + + // // 3 gates to build identity for x_2 + // // // compute x_2 + x_ɑ + x_1 using 2 poly_gates via create_big_add_gate + fr sum_x_1_2_alpha = x_2 + x_alpha + x_1; + uint32_t sum_x_1_2_alpha_idx = context->add_variable(sum_x_1_2_alpha); + context->create_big_add_gate({ .a = x_2_idx, .b = x_alpha_idx, - .c = context->zero_idx, - .a_scaling = q_x_alpha_1, - .b_scaling = -1, - .c_scaling = 0, - .const_scaling = q_x_alpha_2 }); - - // compute y_alpha using lookup formula, instantiate as witness and validate - fr y_alpha = (x_alpha * q_y_alpha_1 + q_y_alpha_2) * delta; - uint32_t y_alpha_idx = context->add_variable(y_alpha); - context->create_poly_gate({ .a = delta_idx, - .b = x_alpha_idx, - .c = y_alpha_idx, - .q_m = q_y_alpha_1, - .q_l = q_y_alpha_2, - .q_r = 0, - .q_o = -1, - .q_c = 0 }); - - // show that (x_1, y_1) + (x_ɑ, y_ɑ) = (x_2, y_2) in 11 gates - // // 4 gates to compute commonly used expressions - // // // 2 differences: - fr diff_x_alpha_x_1 = x_alpha - x_1; - uint32_t diff_x_alpha_x_1_idx = context->add_variable(diff_x_alpha_x_1); - context->create_add_gate({ .a = diff_x_alpha_x_1_idx, - .b = x_1_idx, - .c = x_alpha_idx, - .a_scaling = 1, - .b_scaling = 1, - .c_scaling = -1, - .const_scaling = 0 }); - - fr diff_y_alpha_y_1 = y_alpha - y_1; - uint32_t diff_y_alpha_y_1_idx = context->add_variable(diff_y_alpha_y_1); - context->create_add_gate({ .a = diff_y_alpha_y_1_idx, - .b = y_1_idx, - .c = y_alpha_idx, - .a_scaling = 1, - .b_scaling = 1, - .c_scaling = -1, - .const_scaling = 0 }); - - // // // now the squares of these 2 differences - fr diff_x_alpha_x_1_sqr = diff_x_alpha_x_1 * diff_x_alpha_x_1; - uint32_t diff_x_alpha_x_1_sqr_idx = context->add_variable(diff_x_alpha_x_1_sqr); - context->create_mul_gate({ .a = diff_x_alpha_x_1_idx, - .b = diff_x_alpha_x_1_idx, - .c = diff_x_alpha_x_1_sqr_idx, - .mul_scaling = 1, - .c_scaling = -1, - .const_scaling = 0 }); - - fr diff_y_alpha_y_1_sqr = diff_y_alpha_y_1 * diff_y_alpha_y_1; - uint32_t diff_y_alpha_y_1_sqr_idx = context->add_variable(diff_y_alpha_y_1_sqr); - context->create_mul_gate({ .a = diff_y_alpha_y_1_idx, - .b = diff_y_alpha_y_1_idx, - .c = diff_y_alpha_y_1_sqr_idx, - .mul_scaling = 1, - .c_scaling = -1, - .const_scaling = 0 }); - - // // 3 gates to build identity for x_2 - // // // compute x_2 + x_ɑ + x_1 using 2 poly_gates via create_big_add_gate - fr sum_x_1_2_alpha = x_2 + x_alpha + x_1; - uint32_t sum_x_1_2_alpha_idx = context->add_variable(sum_x_1_2_alpha); - context->create_big_add_gate({ .a = x_2_idx, - .b = x_alpha_idx, - .c = x_1_idx, - .d = sum_x_1_2_alpha_idx, - .a_scaling = 1, - .b_scaling = 1, - .c_scaling = 1, - .d_scaling = -1, - .const_scaling = 0 }); - - // // // constraint: identity for x_2 - context->create_poly_gate({ .a = sum_x_1_2_alpha_idx, - .b = diff_x_alpha_x_1_sqr_idx, - .c = diff_y_alpha_y_1_sqr_idx, - .q_m = 1, - .q_l = 0, - .q_r = 0, - .q_o = -1, - .q_c = 0 }); - - // // 4 gates to build identity for y_2: - // // // 3 auxiliary - fr sum_y_1_y_2 = y_1 + y_2; - uint32_t sum_y_1_y_2_idx = context->add_variable(sum_y_1_y_2); - context->create_add_gate({ .a = y_1_idx, - .b = y_2_idx, - .c = sum_y_1_y_2_idx, - .a_scaling = 1, - .b_scaling = 1, - .c_scaling = -1, - .const_scaling = 0 }); - - fr diff_x_1_x_2 = x_1 - x_2; - uint32_t diff_x_1_x_2_idx = context->add_variable(diff_x_1_x_2); - context->create_add_gate({ .a = diff_x_1_x_2_idx, - .b = x_2_idx, .c = x_1_idx, + .d = sum_x_1_2_alpha_idx, .a_scaling = 1, .b_scaling = 1, - .c_scaling = -1, + .c_scaling = 1, + .d_scaling = -1, .const_scaling = 0 }); - fr prod_y_diff_x_diff = diff_y_alpha_y_1 * diff_x_1_x_2; - uint32_t prod_y_diff_x_diff_idx = context->add_variable(prod_y_diff_x_diff); - context->create_mul_gate({ .a = diff_y_alpha_y_1_idx, - .b = diff_x_1_x_2_idx, - .c = prod_y_diff_x_diff_idx, - .mul_scaling = 1, - .c_scaling = -1, - .const_scaling = 0 }); - - // // // identity for y_2 - context->create_mul_gate({ .a = sum_y_1_y_2_idx, - .b = diff_x_alpha_x_1_idx, - .c = prod_y_diff_x_diff_idx, - .mul_scaling = 1, - .c_scaling = -1, - .const_scaling = 0 }); - } + // // // constraint: identity for x_2 + context->create_poly_gate({ .a = sum_x_1_2_alpha_idx, + .b = diff_x_alpha_x_1_sqr_idx, + .c = diff_y_alpha_y_1_sqr_idx, + .q_m = 1, + .q_l = 0, + .q_r = 0, + .q_o = -1, + .q_c = 0 }); + + // // 4 gates to build identity for y_2: + // // // 3 auxiliary + fr sum_y_1_y_2 = y_1 + y_2; + uint32_t sum_y_1_y_2_idx = context->add_variable(sum_y_1_y_2); + context->create_add_gate({ .a = y_1_idx, + .b = y_2_idx, + .c = sum_y_1_y_2_idx, + .a_scaling = 1, + .b_scaling = 1, + .c_scaling = -1, + .const_scaling = 0 }); + + fr diff_x_1_x_2 = x_1 - x_2; + uint32_t diff_x_1_x_2_idx = context->add_variable(diff_x_1_x_2); + context->create_add_gate({ .a = diff_x_1_x_2_idx, + .b = x_2_idx, + .c = x_1_idx, + .a_scaling = 1, + .b_scaling = 1, + .c_scaling = -1, + .const_scaling = 0 }); + + fr prod_y_diff_x_diff = diff_y_alpha_y_1 * diff_x_1_x_2; + uint32_t prod_y_diff_x_diff_idx = context->add_variable(prod_y_diff_x_diff); + context->create_mul_gate({ .a = diff_y_alpha_y_1_idx, + .b = diff_x_1_x_2_idx, + .c = prod_y_diff_x_diff_idx, + .mul_scaling = 1, + .c_scaling = -1, + .const_scaling = 0 }); + + // // // identity for y_2 + context->create_mul_gate({ .a = sum_y_1_y_2_idx, + .b = diff_x_alpha_x_1_idx, + .c = prod_y_diff_x_diff_idx, + .mul_scaling = 1, + .c_scaling = -1, + .const_scaling = 0 }); } void create_fixed_group_add_gate_with_init(const fixed_group_add_quad& in, const fixed_group_init_quad& init) { - if constexpr (std::same_as) { - context->create_fixed_group_add_gate_with_init(in, init); - } else { - uint32_t x_0_idx = in.a; - uint32_t y_0_idx = in.b; - uint32_t x_alpha_idx = in.c; - uint32_t a_0_idx = in.d; - - fr x_alpha = context->get_variable(x_alpha_idx); - fr a_0 = context->get_variable(a_0_idx); - - // weird names here follow the Turbo notation - fr q_4 = init.q_x_1; - fr q_5 = init.q_x_2; - fr q_m = init.q_y_1; - fr q_c = init.q_y_2; - - // We will think of s = 1-a_0 as an auxiliary "switch" which is equal to either -x_alpha or 0 - // during the initialization step, but we will not add this variable to the builder for reasons of - // efficiency. - - // (ɑ^4 identity) impose 1-a_0 = 0 or -x_alpha - // // first check formula for sx_alpha - fr sx_alpha = (fr(1) - a_0) * x_alpha; - uint32_t sx_alpha_idx = context->add_variable(sx_alpha); - context->create_poly_gate({ .a = a_0_idx, - .b = x_alpha_idx, - .c = sx_alpha_idx, - .q_m = 1, - .q_l = 0, - .q_r = -1, - .q_o = 1, - .q_c = 0 }); - - // // now add the desired constraint on sx_alpha - // // s(s + x_alpha) = s*s + s*x_alpha = 0 - context->create_poly_gate( - { .a = a_0_idx, .b = a_0_idx, .c = sx_alpha_idx, .q_m = 1, .q_l = -2, .q_r = 0, .q_o = 1, .q_c = 1 }); - - // (ɑ^5 identity) - context->create_poly_gate({ .a = x_0_idx, - .b = x_alpha_idx, - .c = a_0_idx, - .q_m = -1, - .q_l = 0, - .q_r = q_4, - .q_o = -q_5, - .q_c = q_5 }); - - // (ɑ^6 identity) - context->create_poly_gate({ .a = y_0_idx, - .b = x_alpha_idx, - .c = a_0_idx, - .q_m = -1, - .q_l = 0, - .q_r = q_m, - .q_o = -q_c, - .q_c = q_c }); - - // There is no previous add quad. - previous_add_quad = in; - } + uint32_t x_0_idx = in.a; + uint32_t y_0_idx = in.b; + uint32_t x_alpha_idx = in.c; + uint32_t a_0_idx = in.d; + + fr x_alpha = context->get_variable(x_alpha_idx); + fr a_0 = context->get_variable(a_0_idx); + + // weird names here follow the Turbo notation + fr q_4 = init.q_x_1; + fr q_5 = init.q_x_2; + fr q_m = init.q_y_1; + fr q_c = init.q_y_2; + + // We will think of s = 1-a_0 as an auxiliary "switch" which is equal to either -x_alpha or 0 + // during the initialization step, but we will not add this variable to the composer for reasons of + // efficiency. + + // (ɑ^4 identity) impose 1-a_0 = 0 or -x_alpha + // // first check formula for sx_alpha + fr sx_alpha = (fr(1) - a_0) * x_alpha; + uint32_t sx_alpha_idx = context->add_variable(sx_alpha); + context->create_poly_gate( + { .a = a_0_idx, .b = x_alpha_idx, .c = sx_alpha_idx, .q_m = 1, .q_l = 0, .q_r = -1, .q_o = 1, .q_c = 0 }); + + // // now add the desired constraint on sx_alpha + // // s(s + x_alpha) = s*s + s*x_alpha = 0 + context->create_poly_gate( + { .a = a_0_idx, .b = a_0_idx, .c = sx_alpha_idx, .q_m = 1, .q_l = -2, .q_r = 0, .q_o = 1, .q_c = 1 }); + + // (ɑ^5 identity) + context->create_poly_gate( + { .a = x_0_idx, .b = x_alpha_idx, .c = a_0_idx, .q_m = -1, .q_l = 0, .q_r = q_4, .q_o = -q_5, .q_c = q_5 }); + + // (ɑ^6 identity) + context->create_poly_gate( + { .a = y_0_idx, .b = x_alpha_idx, .c = a_0_idx, .q_m = -1, .q_l = 0, .q_r = q_m, .q_o = -q_c, .q_c = q_c }); + + // There is no previous add quad. + previous_add_quad = in; } void create_fixed_group_add_gate_final(const add_quad& in) { - if constexpr (std::same_as) { - context->create_fixed_group_add_gate_final(in); - } else { - - fixed_group_add_quad final_round_quad{ .a = in.a, - .b = in.b, - .c = in.c, - .d = in.d, - .q_x_1 = fr::zero(), - .q_x_2 = fr::zero(), - .q_y_1 = fr::zero(), - .q_y_2 = fr::zero() }; - create_fixed_group_add_gate(final_round_quad); - } + fixed_group_add_quad final_round_quad{ .a = in.a, + .b = in.b, + .c = in.c, + .d = in.d, + .q_x_1 = fr::zero(), + .q_x_2 = fr::zero(), + .q_y_1 = fr::zero(), + .q_y_2 = fr::zero() }; + create_fixed_group_add_gate(final_round_quad); } }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield.test.cpp index 4db4fe6068c..8637ccbff91 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield.test.cpp @@ -847,9 +847,7 @@ template class stdlib_bigfield : public testing::Test { }; // Define types for which the above tests will be constructed. -typedef testing:: - Types - CircuitTypes; +typedef testing::Types CircuitTypes; // Define the suite of tests. TYPED_TEST_SUITE(stdlib_bigfield, CircuitTypes); TYPED_TEST(stdlib_bigfield, badmul) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_all.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_all.fuzzer.cpp index 2d16b31f7e5..a20a1ee5f96 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_all.fuzzer.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_all.fuzzer.cpp @@ -1,3 +1,3 @@ #include "barretenberg/common/fuzzer_constants.hpp" -constexpr uint64_t FuzzerCircuitTypes = CircuitType::Standard | CircuitType::Turbo; +constexpr uint64_t FuzzerCircuitTypes = CircuitType::Standard; #include "bigfield.fuzzer.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_impl.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_impl.hpp index 72330802d0a..42177e199bb 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_impl.hpp @@ -79,8 +79,7 @@ bigfield::bigfield(const field_t& low_bits_in, low_accumulator = context->decompose_into_base4_accumulators( low_bits_in.witness_index, static_cast(NUM_LIMB_BITS * 2), "bigfield: low_bits_in too large."); mid_index = static_cast((NUM_LIMB_BITS / 2) - 1); - // Turbo plonk range constraint returns an array of partial sums, midpoint will happen to hold the big limb - // value + // Range constraint returns an array of partial sums, midpoint will happen to hold the big limb value limb_1.witness_index = low_accumulator[mid_index]; // We can get the first half bits of low_bits_in from the variables we already created limb_0 = (low_bits_in - (limb_1 * shift_1)); @@ -862,7 +861,7 @@ bigfield bigfield::div_check_denominator_nonzero(const s /** * Compute a * a = c mod p * - * Slightly cheaper than operator* for StandardPlonk and TurboPlonk + * Slightly cheaper than operator* for StandardPlonk **/ template bigfield bigfield::sqr() const { @@ -2560,7 +2559,7 @@ void bigfield::unsafe_evaluate_multiple_multiply_add(const std::vect * We store these values in an "accumulator" vector in order to efficiently add them into a sum. * i.e. limb_0 =- field_t::accumulate(limb_0_accumulator) * This costs us fewer gates than addition operations because we can add 2 values into a sum in a single - *TurboPlonk gate. + * custom gate. **/ std::vector> limb_0_accumulator; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_turbo.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_turbo.fuzzer.cpp deleted file mode 100644 index ed967b0021f..00000000000 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield_turbo.fuzzer.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "barretenberg/common/fuzzer_constants.hpp" -constexpr uint64_t FuzzerCircuitTypes = CircuitType::Turbo; -#include "bigfield.fuzzer.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp index 65823a98302..ee2a04f956a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp @@ -717,7 +717,6 @@ template class element { /** * Helper class to split a set of points into lookup table subsets * - * TurboPlonk version **/ struct batch_lookup_table_base { batch_lookup_table_base(const std::vector& points) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp index 0eb8bcbf09b..3e02c3cb6b0 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp @@ -903,7 +903,7 @@ HEAVY_TYPED_TEST(stdlib_biggroup, wnaf_batch_mul) } } -/* the following test was only developed as a test of Ultra Circuit Constructor. It fails for Turbo and Standard in the +/* the following test was only developed as a test of Ultra Circuit Constructor. It fails for Standard in the case where Fr is a bigfield. */ HEAVY_TYPED_TEST(stdlib_biggroup, compute_wnaf) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_bn254.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_bn254.hpp index 21c91f0306c..1384bc2813c 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_bn254.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_bn254.hpp @@ -293,7 +293,7 @@ element element::bn254_endo_batch_mul(const std::vec * * batch_lookup_table implements a lookup table for a vector of points. * - * For TurboPlonk, we subdivide `batch_lookup_table` into a set of 3-bit lookup tables, + * We subdivide `batch_lookup_table` into a set of 3-bit lookup tables, * (using 2-bit and 1-bit tables if points.size() is not a multiple of 8) * * We index the lookup table using a vector of NAF values for each point diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_impl.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_impl.hpp index 1ca76538963..013f57fef74 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_impl.hpp @@ -661,7 +661,7 @@ element element::operator*(const Fr& scalar) const * * Now lets say we are constructing a SNARK circuit over another curve E2, whose order is r. * - * All of our addition / multiplication / turbo gates are going to be evaluating low degree multivariate + * All of our addition / multiplication / custom gates are going to be evaluating low degree multivariate * polynomials modulo r. * * E.g. our addition/mul gate (for wires a, b, c and selectors q_m, q_l, q_r, q_o, q_c) is: diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_array/bit_array.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_array/bit_array.test.cpp index 1d4bfa2f0a8..d31f7dfc45c 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_array/bit_array.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_array/bit_array.test.cpp @@ -28,8 +28,7 @@ auto& engine = numeric::random::get_debug_engine(); template class BitArrayTest : public ::testing::Test {}; -using CircuitTypes = ::testing:: - Types; +using CircuitTypes = ::testing::Types; TYPED_TEST_SUITE(BitArrayTest, CircuitTypes); TYPED_TEST(BitArrayTest, test_uint32_input_output_consistency) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_array/bit_array_all.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_array/bit_array_all.fuzzer.cpp index bd2611c3373..6f0571100d3 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_array/bit_array_all.fuzzer.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_array/bit_array_all.fuzzer.cpp @@ -1,3 +1,3 @@ #include "barretenberg/common/fuzzer_constants.hpp" -constexpr uint64_t FuzzerCircuitTypes = CircuitType::Standard | CircuitType::Turbo; +constexpr uint64_t FuzzerCircuitTypes = CircuitType::Standard; #include "bit_array.fuzzer.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_array/bit_array_turbo.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_array/bit_array_turbo.fuzzer.cpp deleted file mode 100644 index 28a266c3bf2..00000000000 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_array/bit_array_turbo.fuzzer.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "barretenberg/common/fuzzer_constants.hpp" -constexpr uint64_t FuzzerCircuitTypes = CircuitType::Turbo; -#include "bit_array.fuzzer.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool.test.cpp index ffc856ca210..4a26bd7300e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool.test.cpp @@ -18,8 +18,7 @@ auto& engine = numeric::random::get_debug_engine(); template class BoolTest : public ::testing::Test {}; -using CircuitTypes = ::testing:: - Types; +using CircuitTypes = ::testing::Types; TYPED_TEST_SUITE(BoolTest, CircuitTypes); TYPED_TEST(BoolTest, TestBasicOperations) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool_all.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool_all.fuzzer.cpp index 6c11d2a5804..577f8c147d2 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool_all.fuzzer.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool_all.fuzzer.cpp @@ -1,3 +1,3 @@ #include "barretenberg/common/fuzzer_constants.hpp" -constexpr uint64_t FuzzerCircuitTypes = CircuitType::Standard | CircuitType::Turbo; +constexpr uint64_t FuzzerCircuitTypes = CircuitType::Standard; #include "bool.fuzzer.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool_turbo.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool_turbo.fuzzer.cpp deleted file mode 100644 index b73e7430796..00000000000 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool_turbo.fuzzer.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "barretenberg/common/fuzzer_constants.hpp" -constexpr uint64_t FuzzerCircuitTypes = CircuitType::Turbo; -#include "bool.fuzzer.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array.test.cpp index 26c83cb2023..e9ad658d75a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array.test.cpp @@ -22,8 +22,7 @@ template class ByteArrayTest : public ::testing::Test {}; template using byte_array_ct = byte_array; -using CircuitTypes = ::testing:: - Types; +using CircuitTypes = ::testing::Types; TYPED_TEST_SUITE(ByteArrayTest, CircuitTypes); TYPED_TEST(ByteArrayTest, test_reverse) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array_all.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array_all.fuzzer.cpp index f563bba1ac6..39eafcc443a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array_all.fuzzer.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array_all.fuzzer.cpp @@ -1,3 +1,3 @@ #include "barretenberg/common/fuzzer_constants.hpp" -constexpr uint64_t FuzzerCircuitTypes = CircuitType::Standard | CircuitType::Turbo; +constexpr uint64_t FuzzerCircuitTypes = CircuitType::Standard; #include "byte_array.fuzzer.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array_turbo.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array_turbo.fuzzer.cpp deleted file mode 100644 index 3fad3654c37..00000000000 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array_turbo.fuzzer.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "barretenberg/common/fuzzer_constants.hpp" -constexpr uint64_t FuzzerCircuitTypes = CircuitType::Turbo; -#include "byte_array.fuzzer.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders.hpp index 8fbac8a643b..d748baa72a8 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders.hpp @@ -5,7 +5,6 @@ #pragma once #include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp" -#include "barretenberg/proof_system/circuit_builder/turbo_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" template @@ -17,29 +16,23 @@ concept IsGoblinBuilder = proof_system::IsAnyOf; \ - template class stdlib_type; \ template class stdlib_type; \ template class stdlib_type; #define INSTANTIATE_STDLIB_TYPE_VA(stdlib_type, ...) \ template class stdlib_type; \ - template class stdlib_type; \ template class stdlib_type; \ template class stdlib_type; -#define INSTANTIATE_STDLIB_BASIC_TYPE(stdlib_type) \ - template class stdlib_type; \ - template class stdlib_type; +#define INSTANTIATE_STDLIB_BASIC_TYPE(stdlib_type) template class stdlib_type; #define INSTANTIATE_STDLIB_BASIC_TYPE_VA(stdlib_type, ...) \ - template class stdlib_type; \ - template class stdlib_type; + template class stdlib_type; #define INSTANTIATE_STDLIB_ULTRA_METHOD(stdlib_method) \ template stdlib_method(proof_system::UltraCircuitBuilder); \ diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp index 9069cf1d992..01bc6a21a10 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp @@ -25,8 +25,6 @@ namespace proof_system { template class StandardCircuitBuilder_; using StandardCircuitBuilder = StandardCircuitBuilder_>; using StandardGrumpkinCircuitBuilder = StandardCircuitBuilder_>; -template class TurboCircuitBuilder_; -using TurboCircuitBuilder = TurboCircuitBuilder_>; template class UltraCircuitBuilder_; using UltraCircuitBuilder = UltraCircuitBuilder_>; template class GoblinUltraCircuitBuilder_; @@ -35,29 +33,23 @@ using GoblinUltraCircuitBuilder = GoblinUltraCircuitBuilder_; \ - extern template class stdlib_type; \ extern template class stdlib_type; \ extern template class stdlib_type; #define EXTERN_STDLIB_METHOD(stdlib_method) \ extern template stdlib_method(proof_system::StandardCircuitBuilder); \ - extern template stdlib_method(proof_system::TurboCircuitBuilder); \ extern template stdlib_method(proof_system::UltraCircuitBuilder); \ extern template stdlib_method(proof_system::GoblinUltraCircuitBuilder); #define EXTERN_STDLIB_TYPE_VA(stdlib_type, ...) \ extern template class stdlib_type; \ - extern template class stdlib_type; \ extern template class stdlib_type; \ extern template class stdlib_type; -#define EXTERN_STDLIB_BASIC_TYPE(stdlib_type) \ - extern template class stdlib_type; \ - extern template class stdlib_type; +#define EXTERN_STDLIB_BASIC_TYPE(stdlib_type) extern template class stdlib_type; #define EXTERN_STDLIB_BASIC_TYPE_VA(stdlib_type, ...) \ - extern template class stdlib_type; \ - extern template class stdlib_type; + extern template class stdlib_type; #define EXTERN_STDLIB_ULTRA_TYPE(stdlib_type) \ extern template class stdlib_type; \ diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/array.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/array.test.cpp index f0fcab3cdf7..c94152d63e3 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/array.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/array.test.cpp @@ -595,9 +595,7 @@ template class stdlib_array : public testing::Test { } }; -typedef testing:: - Types - CircuitTypes; +typedef testing::Types CircuitTypes; TYPED_TEST_SUITE(stdlib_array, CircuitTypes); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.cpp index 01a98593090..4e525e2fa5d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.cpp @@ -1010,18 +1010,6 @@ template field_t field_t::accumulate(const accumulating_total = witness_t(ctx, new_total); } return total.normalize(); - } else if constexpr (std::same_as) { - - field_t total(0); - bool odd_number = (input.size() & 0x01UL) == 0x01ULL; - size_t end = input.size() - (odd_number ? 2 : 0); - for (size_t i = 0; i < end; i += 2) { - total = total.add_two(input[(size_t)i], input[(size_t)i + 1]); - } - if (odd_number) { - total += input[input.size() - 1]; - } - return total.normalize(); } field_t total; for (const auto& item : input) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.hpp index f4fafa515fa..cd73554418e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.hpp @@ -212,11 +212,11 @@ template class field_t { /** * multiply *this by `to_mul` and add `to_add` - * One `madd` call costs 1 constraint for Turbo plonk and Ultra plonk + * One `madd` call costs 1 constraint for Ultra plonk * */ field_t madd(const field_t& to_mul, const field_t& to_add) const; - // add_two costs 1 constraint for turbo/ultra plonk + // add_two costs 1 constraint for ultra plonk field_t add_two(const field_t& add_a, const field_t& add_b) const; bool_t operator==(const field_t& other) const; bool_t operator!=(const field_t& other) const; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp index f539ef5d883..9ed50192778 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp @@ -304,7 +304,7 @@ template class stdlib_field : public testing::Test { EXPECT_EQ(x, fr(1)); // This logic requires on madd in field, which creates a big mul gate. - // This gate is implemented in standard by create 2 actual gates, while in turbo and ultra there are 2 + // This gate is implemented in standard by create 2 actual gates, while in ultra there are 2 if constexpr (std::same_as) { EXPECT_EQ(gates_after - gates_before, 6UL); } else { @@ -332,7 +332,7 @@ template class stdlib_field : public testing::Test { EXPECT_EQ(x, fr(0)); // This logic requires on madd in field, which creates a big mul gate. - // This gate is implemented in standard by create 2 actual gates, while in turbo and ultra there are 2 + // This gate is implemented in standard by create 2 actual gates, while in ultra there are 2 if constexpr (std::same_as) { EXPECT_EQ(gates_after - gates_before, 6UL); } else { @@ -361,7 +361,7 @@ template class stdlib_field : public testing::Test { EXPECT_EQ(x, fr(1)); // This logic requires on madd in field, which creates a big mul gate. - // This gate is implemented in standard by create 2 actual gates, while in turbo and ultra there are 2 + // This gate is implemented in standard by create 2 actual gates, while in ultra there are 2 if constexpr (std::same_as) { EXPECT_EQ(gates_after - gates_before, 11UL); } else { @@ -910,9 +910,7 @@ template class stdlib_field : public testing::Test { } }; -typedef testing:: - Types - CircuitTypes; +typedef testing::Types CircuitTypes; TYPED_TEST_SUITE(stdlib_field, CircuitTypes); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field_all.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field_all.fuzzer.cpp index a73287e412f..950dc6fa15e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field_all.fuzzer.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field_all.fuzzer.cpp @@ -1,3 +1,3 @@ #include "barretenberg/common/fuzzer_constants.hpp" -constexpr uint64_t FuzzerCircuitTypes = CircuitType::Standard | CircuitType::Turbo; +constexpr uint64_t FuzzerCircuitTypes = CircuitType::Standard; #include "field.fuzzer.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field_turbo.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field_turbo.fuzzer.cpp deleted file mode 100644 index fc42377ac5d..00000000000 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field_turbo.fuzzer.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "barretenberg/common/fuzzer_constants.hpp" -constexpr uint64_t FuzzerCircuitTypes = CircuitType::Turbo; -#include "field.fuzzer.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/group.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/group.test.cpp index c8931bff21a..752f4f3b80e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/group.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/group.test.cpp @@ -20,8 +20,7 @@ auto& engine = numeric::random::get_debug_engine(); template class GroupTest : public ::testing::Test {}; -using CircuitTypes = ::testing:: - Types; +using CircuitTypes = ::testing::Types; TYPED_TEST_SUITE(GroupTest, CircuitTypes); TYPED_TEST(GroupTest, TestFixedBaseScalarMul) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/logic/logic.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/logic/logic.test.cpp index 11a8f6277fa..1c3ab427b90 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/logic/logic.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/logic/logic.test.cpp @@ -29,8 +29,7 @@ using namespace proof_system::plonk; template class LogicTest : public testing::Test {}; -using CircuitTypes = ::testing:: - Types; +using CircuitTypes = ::testing::Types; TYPED_TEST_SUITE(LogicTest, CircuitTypes); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.test.cpp index 763d98fae46..cabe42dfeda 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.test.cpp @@ -21,8 +21,7 @@ auto& engine = numeric::random::get_debug_engine(); template class PackedByteArrayTest : public ::testing::Test {}; -using CircuitTypes = ::testing:: - Types; +using CircuitTypes = ::testing::Types; TYPED_TEST_SUITE(PackedByteArrayTest, CircuitTypes); TYPED_TEST(PackedByteArrayTest, string_constructor_and_get_value_consistency) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint.test.cpp index ad9913aeb17..33a8a374375 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint.test.cpp @@ -30,8 +30,7 @@ template void ignore_unused(T&) {} // use to ignore unused variables i template class SafeUintTest : public ::testing::Test {}; -using CircuitTypes = ::testing:: - Types; +using CircuitTypes = ::testing::Types; TYPED_TEST_SUITE(SafeUintTest, CircuitTypes); // CONSTRUCTOR diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint_all.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint_all.fuzzer.cpp index 086c36bb1a8..4e35aeb3654 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint_all.fuzzer.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint_all.fuzzer.cpp @@ -1,3 +1,3 @@ #include "barretenberg/common/fuzzer_constants.hpp" -constexpr uint64_t FuzzerCircuitTypes = CircuitType::Standard | CircuitType::Turbo; +constexpr uint64_t FuzzerCircuitTypes = CircuitType::Standard; #include "safe_uint.fuzzer.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint_turbo.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint_turbo.fuzzer.cpp deleted file mode 100644 index c51d1c7138b..00000000000 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint_turbo.fuzzer.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "barretenberg/common/fuzzer_constants.hpp" -constexpr uint64_t FuzzerCircuitTypes = CircuitType::Turbo; -#include "safe_uint.fuzzer.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/logic.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/logic.cpp index 40c4dfb7b3c..72cc1dee046 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/logic.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/logic.cpp @@ -75,12 +75,12 @@ uint uint::operator>>(const size_t shift) cons * * Our range constraint will represent A via its accumulating sums (A_0, ..., A_{w-1}), where * - * i | ~NOTE~ : i - * === | this is equivalent : === - * \ j | to the formula : \ i - j - * A = / a . 4 | given in : a = / a . 4 - * i === (w - 1 - i + j) | turbo_plonk_composer.cpp : i === (15 - j) - * j = 0 | when width = 32 : j = 0 + * i + * === + * \ j + * A = / a . 4 + * i === (w - 1 - i + j) + * j = 0 * * * Write x = 2y + z with z in {0,1}. Let diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/uint.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/uint.cpp index 0d48d22759a..887a80fd01b 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/uint.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/uint.cpp @@ -8,7 +8,7 @@ namespace proof_system::plonk { namespace stdlib { /** - * @brief In the case of TurboPLONK, range constrain the given witness. + * @brief Constrain accumulators */ template std::vector uint::constrain_accumulators(Builder* context, @@ -251,14 +251,6 @@ template uint uint class stdlib_uint : public testing::Test { * * @details Notes that the static casts have to be there becuase of -Wc++11-narrowing flag. * - * TurboPLONK: 19896 gates * StandardPLONK: 210363 gates */ static void test_hash_rounds() @@ -1740,9 +1739,7 @@ template class stdlib_uint : public testing::Test { } }; -typedef testing:: - Types - CircuitTypes; +typedef testing::Types CircuitTypes; TYPED_TEST_SUITE(stdlib_uint, CircuitTypes); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/uint_all.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/uint_all.fuzzer.cpp index 9c9034e7462..236586701ee 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/uint_all.fuzzer.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/uint_all.fuzzer.cpp @@ -1,3 +1,3 @@ #include "barretenberg/common/fuzzer_constants.hpp" -constexpr uint64_t FuzzerCircuitTypes = CircuitType::Standard | CircuitType::Turbo; +constexpr uint64_t FuzzerCircuitTypes = CircuitType::Standard; #include "uint.fuzzer.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/uint_turbo.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/uint_turbo.fuzzer.cpp deleted file mode 100644 index fd94f4223cc..00000000000 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/uint_turbo.fuzzer.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "barretenberg/common/fuzzer_constants.hpp" -constexpr uint64_t FuzzerCircuitTypes = CircuitType::Turbo; -#include "uint.fuzzer.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp index fedf66d6cd1..386f6d0e032 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp @@ -3,7 +3,6 @@ #include "barretenberg/common/test.hpp" #include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp" #include "barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp" -#include "barretenberg/proof_system/circuit_builder/turbo_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" #include "barretenberg/srs/factories/file_crs_factory.hpp" @@ -45,8 +44,7 @@ template class VerificationKeyFixture : public testing::Test } }; -using CircuitTypes = testing:: - Types; +using CircuitTypes = testing::Types; TYPED_TEST_SUITE(VerificationKeyFixture, CircuitTypes); TYPED_TEST(VerificationKeyFixture, vk_data_vs_recursion_compress_native) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/verifier/program_settings.hpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/verifier/program_settings.hpp index dbccf2f49dd..3c091b010f2 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/verifier/program_settings.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/verifier/program_settings.hpp @@ -21,7 +21,7 @@ template class recursive_ultra_verifier_settings : public plonk typedef proof_system::plonk::VerifierPlookupArithmeticWidget PlookupArithmeticWidget; - typedef proof_system::plonk::VerifierTurboLogicWidget TurboLogicWidget; + typedef proof_system::plonk::VerifierLogicWidget LogicWidget; typedef proof_system::plonk::VerifierGenPermSortWidget GenPermSortWidget; typedef proof_system::plonk::VerifierEllipticWidget EllipticWidget; typedef proof_system::plonk::VerifierPlookupAuxiliaryWidget @@ -99,7 +99,7 @@ class recursive_ultra_to_standard_verifier_settings : public recursive_ultra_ver typedef proof_system::plonk::VerifierPlookupArithmeticWidget PlookupArithmeticWidget; - typedef proof_system::plonk::VerifierTurboLogicWidget TurboLogicWidget; + typedef proof_system::plonk::VerifierLogicWidget LogicWidget; typedef proof_system::plonk::VerifierGenPermSortWidget GenPermSortWidget; typedef proof_system::plonk::VerifierEllipticWidget EllipticWidget; typedef proof_system::plonk::VerifierPlookupAuxiliaryWidget @@ -108,64 +108,6 @@ class recursive_ultra_to_standard_verifier_settings : public recursive_ultra_ver static constexpr transcript::HashType hash_type = transcript::HashType::PedersenBlake3s; }; -template class recursive_turbo_verifier_settings : public plonk::turbo_settings { - public: - typedef typename Curve::ScalarField fr_ct; - typedef typename Curve::GroupNative::affine_element g1; - typedef typename Curve::Builder Builder; - typedef Transcript Transcript_pt; - typedef proof_system::plonk::VerifierPermutationWidget PermutationWidget; - - typedef proof_system::plonk::turbo_settings base_settings; - - typedef proof_system::plonk::VerifierTurboFixedBaseWidget - TurboFixedBaseWidget; - typedef proof_system::plonk::VerifierTurboArithmeticWidget - TurboArithmeticWidget; - typedef proof_system::plonk::VerifierTurboRangeWidget TurboRangeWidget; - typedef proof_system::plonk::VerifierTurboLogicWidget TurboLogicWidget; - - static constexpr size_t num_challenge_bytes = 16; - static constexpr transcript::HashType hash_type = transcript::HashType::PedersenBlake3s; - - static fr_ct append_scalar_multiplication_inputs(typename Transcript_pt::Key* key, - const fr_ct& alpha_base, - const Transcript_pt& transcript, - std::map& scalars) - { - auto updated_alpha = PermutationWidget::append_scalar_multiplication_inputs(key, alpha_base, transcript); - - updated_alpha = - TurboArithmeticWidget::append_scalar_multiplication_inputs(key, updated_alpha, transcript, scalars); - - updated_alpha = - TurboFixedBaseWidget::append_scalar_multiplication_inputs(key, updated_alpha, transcript, scalars); - - updated_alpha = TurboRangeWidget::append_scalar_multiplication_inputs(key, updated_alpha, transcript, scalars); - - updated_alpha = TurboLogicWidget::append_scalar_multiplication_inputs(key, updated_alpha, transcript, scalars); - return updated_alpha; - } - - static fr_ct compute_quotient_evaluation_contribution(typename Transcript_pt::Key* key, - const fr_ct& alpha_base, - const Transcript_pt& transcript, - fr_ct& quotient_numerator_eval) - { - auto updated_alpha_base = PermutationWidget::compute_quotient_evaluation_contribution( - key, alpha_base, transcript, quotient_numerator_eval); - updated_alpha_base = TurboArithmeticWidget::compute_quotient_evaluation_contribution( - key, updated_alpha_base, transcript, quotient_numerator_eval); - updated_alpha_base = TurboFixedBaseWidget::compute_quotient_evaluation_contribution( - key, updated_alpha_base, transcript, quotient_numerator_eval); - updated_alpha_base = TurboRangeWidget::compute_quotient_evaluation_contribution( - key, updated_alpha_base, transcript, quotient_numerator_eval); - updated_alpha_base = TurboLogicWidget::compute_quotient_evaluation_contribution( - key, updated_alpha_base, transcript, quotient_numerator_eval); - return updated_alpha_base; - } -}; - } // namespace recursion } // namespace stdlib } // namespace proof_system::plonk diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/verifier/verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/verifier/verifier.test.cpp index 86936023fb9..3d20c547285 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/verifier/verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/verifier/verifier.test.cpp @@ -5,7 +5,6 @@ #include "barretenberg/ecc/curves/bn254/fq12.hpp" #include "barretenberg/ecc/curves/bn254/pairing.hpp" #include "barretenberg/plonk/composer/standard_composer.hpp" -#include "barretenberg/plonk/composer/turbo_composer.hpp" #include "barretenberg/plonk/composer/ultra_composer.hpp" #include "barretenberg/plonk/proof_system/proving_key/serialize.hpp" #include "barretenberg/stdlib/hash/blake3s/blake3s.hpp" @@ -40,7 +39,7 @@ template class stdlib_verifier : public testing::Test { using pairing_target_field = barretenberg::fq12; // These constexpr definitions are to allow for the following: An Ultra Pedersen hash evaluates to a - // different value from the Turbo/Standard versions of the Pedersen hash. Therefore, the fiat-shamir + // different value from the Standard version of the Pedersen hash. Therefore, the fiat-shamir // challenges generated by the prover and verifier _could_ accidentally be different if an ultra proof is // generated using ultra-pedersen challenges, but is being verified within a non-ultra circuit which uses // non-ultra-pedersen challenges. We need the prover and verifier hashes to be the same. The solution is to @@ -565,7 +564,7 @@ template class stdlib_verifier : public testing::Test { } }; -typedef testing::Types OuterCircuitTypes; +typedef testing::Types OuterCircuitTypes; TYPED_TEST_SUITE(stdlib_verifier, OuterCircuitTypes); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/verifier/verifier_turbo.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/verifier/verifier_turbo.test.cpp deleted file mode 100644 index 0256210509d..00000000000 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/verifier/verifier_turbo.test.cpp +++ /dev/null @@ -1,537 +0,0 @@ -#include "program_settings.hpp" -#include "verifier.hpp" - -#include "barretenberg/common/test.hpp" -#include "barretenberg/ecc/curves/bn254/fq12.hpp" -#include "barretenberg/ecc/curves/bn254/pairing.hpp" -#include "barretenberg/plonk/composer/standard_composer.hpp" -#include "barretenberg/plonk/composer/turbo_composer.hpp" -#include "barretenberg/plonk/proof_system/proving_key/serialize.hpp" -#include "barretenberg/stdlib/hash/blake3s/blake3s.hpp" -#include "barretenberg/stdlib/hash/pedersen/pedersen.hpp" -#include "barretenberg/stdlib/primitives/curves/bn254.hpp" -#include "barretenberg/transcript/transcript.hpp" - -namespace proof_system::plonk::stdlib { - -template class stdlib_verifier_turbo : public testing::Test { - - using InnerComposer = proof_system::plonk::TurboComposer; - using InnerBuilder = typename InnerComposer::CircuitBuilder; - - using OuterBuilder = typename OuterComposer::CircuitBuilder; - - using inner_curve = bn254; - using outer_curve = bn254; - - using verification_key_pt = recursion::verification_key; - using recursive_settings = recursion::recursive_turbo_verifier_settings; - - using inner_scalar_field_ct = inner_curve::ScalarField; - using inner_ground_field_ct = inner_curve::BaseField; - using public_witness_ct = inner_curve::public_witness_ct; - using witness_ct = inner_curve::witness_ct; - using byte_array_ct = inner_curve::byte_array_ct; - - using inner_scalar_field = typename inner_curve::ScalarFieldNative; - using outer_scalar_field = typename outer_curve::BaseFieldNative; - using pairing_target_field = barretenberg::fq12; - - using ProverOfInnerCircuit = plonk::TurboProver; - using VerifierOfInnerProof = plonk::TurboVerifier; - using RecursiveSettings = recursive_settings; - - struct circuit_outputs { - recursion::aggregation_state aggregation_state; - std::shared_ptr verification_key; - }; - - static void create_inner_circuit(InnerBuilder& builder, const std::vector& public_inputs) - { - inner_scalar_field_ct a(public_witness_ct(&builder, public_inputs[0])); - inner_scalar_field_ct b(public_witness_ct(&builder, public_inputs[1])); - inner_scalar_field_ct c(public_witness_ct(&builder, public_inputs[2])); - - for (size_t i = 0; i < 32; ++i) { - a = (a * b) + b + a; - a = a.madd(b, c); - } - pedersen_commitment::compress(a, b); - byte_array_ct to_hash(&builder, "nonsense test data"); - blake3s(to_hash); - - inner_scalar_field bigfield_data = fr::random_element(); - inner_scalar_field bigfield_data_a{ bigfield_data.data[0], bigfield_data.data[1], 0, 0 }; - inner_scalar_field bigfield_data_b{ bigfield_data.data[2], bigfield_data.data[3], 0, 0 }; - - inner_ground_field_ct big_a(inner_scalar_field_ct(witness_ct(&builder, bigfield_data_a.to_montgomery_form())), - inner_scalar_field_ct(witness_ct(&builder, 0))); - inner_ground_field_ct big_b(inner_scalar_field_ct(witness_ct(&builder, bigfield_data_b.to_montgomery_form())), - inner_scalar_field_ct(witness_ct(&builder, 0))); - - big_a* big_b; - }; - static void create_alternate_inner_circuit(InnerBuilder& builder, - const std::vector& public_inputs) - { - inner_scalar_field_ct a(public_witness_ct(&builder, public_inputs[0])); - inner_scalar_field_ct b(public_witness_ct(&builder, public_inputs[1])); - inner_scalar_field_ct c(public_witness_ct(&builder, public_inputs[2])); - - for (size_t i = 0; i < 32; ++i) { - a = (a * b) + b + a; - a = c.madd(b, a); - } - pedersen_commitment::compress(a, a); - byte_array_ct to_hash(&builder, "different nonsense test data"); - blake3s(to_hash); - - inner_scalar_field bigfield_data = fr::random_element(); - inner_scalar_field bigfield_data_a{ bigfield_data.data[0], bigfield_data.data[1], 0, 0 }; - inner_scalar_field bigfield_data_b{ bigfield_data.data[2], bigfield_data.data[3], 0, 0 }; - - inner_ground_field_ct big_a(inner_scalar_field_ct(witness_ct(&builder, bigfield_data_a.to_montgomery_form())), - inner_scalar_field_ct(witness_ct(&builder, 0))); - inner_ground_field_ct big_b(inner_scalar_field_ct(witness_ct(&builder, bigfield_data_b.to_montgomery_form())), - inner_scalar_field_ct(witness_ct(&builder, 0))); - ((big_a * big_b) + big_a) * big_b; - } - - static circuit_outputs create_outer_circuit(InnerBuilder& inner_circuit, OuterBuilder& outer_builder) - { - info("Creating turbo (inner) prover..."); - ProverOfInnerCircuit prover; - InnerComposer inner_composer; - prover = inner_composer.create_prover(inner_circuit); - - info("Computing verification key..."); - const auto verification_key_native = inner_composer.compute_verification_key(inner_circuit); - // Convert the verification key's elements into _circuit_ types, using the OUTER composer. - std::shared_ptr verification_key = - verification_key_pt::from_witness(&outer_builder, verification_key_native); - - info("Constructing the turbo (inner) proof ..."); - plonk::proof proof_to_recursively_verify = prover.construct_proof(); - - { - // Native check is mainly for comparison vs circuit version of the verifier. - info("Creating a native turbo (inner) verifier..."); - VerifierOfInnerProof native_verifier; - native_verifier = inner_composer.create_verifier(inner_circuit); - - info("Verifying the turbo (inner) proof natively..."); - auto native_result = native_verifier.verify_proof(proof_to_recursively_verify); - - info("Native result: ", native_result); - } - - transcript::Manifest recursive_manifest = InnerComposer::create_manifest(prover.key->num_public_inputs); - - auto output = recursion::verify_proof( - &outer_builder, verification_key, recursive_manifest, proof_to_recursively_verify); - - return { output, verification_key }; - }; - - static circuit_outputs create_double_outer_circuit(InnerBuilder& inner_circuit_a, - InnerBuilder& inner_circuit_b, - OuterBuilder& outer_circuit) - { - ProverOfInnerCircuit prover; - InnerComposer inner_composer_a; - prover = inner_composer_a.create_prover(inner_circuit_a); - - const auto verification_key_native = inner_composer_a.compute_verification_key(inner_circuit_a); - std::shared_ptr verification_key = - verification_key_pt::from_witness(&outer_circuit, verification_key_native); - - plonk::proof proof_to_recursively_verify_a = prover.construct_proof(); - - transcript::Manifest recursive_manifest = InnerComposer::create_manifest(prover.key->num_public_inputs); - - auto previous_output = recursion::verify_proof( - &outer_circuit, verification_key, recursive_manifest, proof_to_recursively_verify_a); - - InnerComposer inner_composer_b; - prover = inner_composer_b.create_prover(inner_circuit_b); - - const auto verification_key_b_raw = inner_composer_b.compute_verification_key(inner_circuit_b); - std::shared_ptr verification_key_b = - verification_key_pt::from_witness(&outer_circuit, verification_key_b_raw); - - plonk::proof proof_to_recursively_verify_b = prover.construct_proof(); - - auto output = proof_system::plonk::stdlib::recursion::verify_proof( - &outer_circuit, verification_key_b, recursive_manifest, proof_to_recursively_verify_b, previous_output); - - verification_key_b->compress(); - verification_key->compress(); - return { output, verification_key }; - } - - // creates a cicuit that verifies either a proof from composer a, or from composer b - static circuit_outputs create_outer_circuit_with_variable_inner_circuit(InnerBuilder& inner_circuit_a, - InnerBuilder& inner_circuit_b, - OuterBuilder& outer_circuit, - const bool proof_type, - const bool create_failing_proof = false, - const bool use_constant_key = false) - { - ProverOfInnerCircuit prover_a; - ProverOfInnerCircuit prover_b; - InnerComposer inner_composer_a; - InnerComposer inner_composer_b; - prover_a = inner_composer_a.create_prover(inner_circuit_a); - prover_b = inner_composer_b.create_prover(inner_circuit_b); - - const auto verification_key_raw_a = inner_composer_a.compute_verification_key(inner_circuit_a); - const auto verification_key_raw_b = inner_composer_b.compute_verification_key(inner_circuit_b); - - std::shared_ptr verification_key; - if (use_constant_key) { - verification_key = proof_type ? verification_key_pt::from_constants(&outer_circuit, verification_key_raw_a) - : verification_key_pt::from_constants(&outer_circuit, verification_key_raw_b); - - } else { - verification_key = proof_type ? verification_key_pt::from_witness(&outer_circuit, verification_key_raw_a) - : verification_key_pt::from_witness(&outer_circuit, verification_key_raw_b); - } - - if (!use_constant_key) { - if (create_failing_proof) { - verification_key->validate_key_is_in_set({ verification_key_raw_b, verification_key_raw_b }); - } else { - verification_key->validate_key_is_in_set({ verification_key_raw_a, verification_key_raw_b }); - } - } - - plonk::proof recursive_proof = proof_type ? prover_a.construct_proof() : prover_b.construct_proof(); - - transcript::Manifest recursive_manifest = InnerComposer::create_manifest(prover_a.key->num_public_inputs); - - proof_system::plonk::stdlib::recursion::aggregation_state output = - proof_system::plonk::stdlib::recursion::verify_proof( - &outer_circuit, verification_key, recursive_manifest, recursive_proof); - - return { output, verification_key }; - } - - // /** - // * @brief Check the correctness of the recursive proof public inputs - // * - // * @details Circuit constructors have no notion of SRS and any proof-related stuff except for the existence of - // * recursive proof-specific public inputs, so we can't check the recursive proof fully in check_circuit. So we - // * use this additional function to check that the recursive proof points work. - // * - // * @return boolean result - // */ - - static bool check_recursive_proof_public_inputs(OuterBuilder& builder, - const barretenberg::pairing::miller_lines* lines) - { - if (builder.contains_recursive_proof && builder.recursive_proof_public_input_indices.size() == 16) { - const auto& inputs = builder.public_inputs; - const auto recover_fq_from_public_inputs = - [&inputs, &builder](const size_t idx0, const size_t idx1, const size_t idx2, const size_t idx3) { - const uint256_t l0 = builder.get_variable(inputs[idx0]); - const uint256_t l1 = builder.get_variable(inputs[idx1]); - const uint256_t l2 = builder.get_variable(inputs[idx2]); - const uint256_t l3 = builder.get_variable(inputs[idx3]); - - const uint256_t limb = l0 + (l1 << NUM_LIMB_BITS_IN_FIELD_SIMULATION) + - (l2 << (NUM_LIMB_BITS_IN_FIELD_SIMULATION * 2)) + - (l3 << (NUM_LIMB_BITS_IN_FIELD_SIMULATION * 3)); - return outer_scalar_field(limb); - }; - - const auto x0 = recover_fq_from_public_inputs(builder.recursive_proof_public_input_indices[0], - builder.recursive_proof_public_input_indices[1], - builder.recursive_proof_public_input_indices[2], - builder.recursive_proof_public_input_indices[3]); - const auto y0 = recover_fq_from_public_inputs(builder.recursive_proof_public_input_indices[4], - builder.recursive_proof_public_input_indices[5], - builder.recursive_proof_public_input_indices[6], - builder.recursive_proof_public_input_indices[7]); - const auto x1 = recover_fq_from_public_inputs(builder.recursive_proof_public_input_indices[8], - builder.recursive_proof_public_input_indices[9], - builder.recursive_proof_public_input_indices[10], - builder.recursive_proof_public_input_indices[11]); - const auto y1 = recover_fq_from_public_inputs(builder.recursive_proof_public_input_indices[12], - builder.recursive_proof_public_input_indices[13], - builder.recursive_proof_public_input_indices[14], - builder.recursive_proof_public_input_indices[15]); - g1::affine_element P_affine[2]{ - { x0, y0 }, - { x1, y1 }, - }; - - pairing_target_field result = - barretenberg::pairing::reduced_ate_pairing_batch_precomputed(P_affine, lines, 2); - - return (result == pairing_target_field::one()); - } - return true; - } - - static void check_pairing(const circuit_outputs& circuit_output) - { - auto g2_lines = barretenberg::srs::get_crs_factory()->get_verifier_crs()->get_precomputed_g2_lines(); - g1::affine_element P[2]; - P[0].x = outer_scalar_field(circuit_output.aggregation_state.P0.x.get_value().lo); - P[0].y = outer_scalar_field(circuit_output.aggregation_state.P0.y.get_value().lo); - P[1].x = outer_scalar_field(circuit_output.aggregation_state.P1.x.get_value().lo); - P[1].y = outer_scalar_field(circuit_output.aggregation_state.P1.y.get_value().lo); - pairing_target_field inner_proof_result = - barretenberg::pairing::reduced_ate_pairing_batch_precomputed(P, g2_lines, 2); - EXPECT_EQ(inner_proof_result, pairing_target_field::one()); - } - - static void check_recursive_verification_circuit(OuterBuilder& outer_circuit, bool expected_result) - { - info("number of gates in recursive verification circuit = ", outer_circuit.get_num_gates()); - bool result = outer_circuit.check_circuit(); - EXPECT_EQ(result, expected_result); - auto g2_lines = barretenberg::srs::get_crs_factory()->get_verifier_crs()->get_precomputed_g2_lines(); - EXPECT_EQ(check_recursive_proof_public_inputs(outer_circuit, g2_lines), true); - } - - public: - static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../srs_db/ignition"); } - - static void test_inner_circuit() - { - InnerBuilder builder; - std::vector inputs{ inner_scalar_field::random_element(), - inner_scalar_field::random_element(), - inner_scalar_field::random_element() }; - - create_inner_circuit(builder, inputs); - - bool result = builder.check_circuit(); - EXPECT_EQ(result, true); - } - - static void test_recursive_proof_composition() - { - InnerBuilder inner_circuit; - OuterBuilder outer_circuit; - - std::vector inner_public_inputs{ inner_scalar_field::random_element(), - inner_scalar_field::random_element(), - inner_scalar_field::random_element() }; - - create_inner_circuit(inner_circuit, inner_public_inputs); - - auto circuit_output = create_outer_circuit(inner_circuit, outer_circuit); - EXPECT_EQ(circuit_output.aggregation_state.public_inputs[0].get_value(), inner_public_inputs[0]); - EXPECT_EQ(circuit_output.aggregation_state.public_inputs[1].get_value(), inner_public_inputs[1]); - - circuit_output.aggregation_state.assign_object_to_proof_outputs(); - EXPECT_EQ(outer_circuit.failed(), false); - - check_pairing(circuit_output); - check_recursive_verification_circuit(outer_circuit, true); - } - - static void test_double_verification() - { - InnerBuilder inner_circuit_a; - InnerBuilder inner_circuit_b; - - OuterBuilder mid_circuit_a; - OuterBuilder mid_circuit_b; - - OuterBuilder outer_circuit; - - std::vector inner_inputs{ inner_scalar_field::random_element(), - inner_scalar_field::random_element(), - inner_scalar_field::random_element() }; - - create_inner_circuit(inner_circuit_a, inner_inputs); - create_inner_circuit(inner_circuit_b, inner_inputs); - - auto circuit_output_a = create_outer_circuit(inner_circuit_a, mid_circuit_a); - - uint256_t a0 = circuit_output_a.aggregation_state.P0.x.binary_basis_limbs[1].element.get_value(); - uint256_t a1 = circuit_output_a.aggregation_state.P0.y.binary_basis_limbs[1].element.get_value(); - uint256_t a2 = circuit_output_a.aggregation_state.P1.x.binary_basis_limbs[1].element.get_value(); - uint256_t a3 = circuit_output_a.aggregation_state.P1.y.binary_basis_limbs[1].element.get_value(); - - ASSERT(a0.get_msb() <= 68); - ASSERT(a1.get_msb() <= 68); - ASSERT(a2.get_msb() <= 68); - ASSERT(a3.get_msb() <= 68); - - circuit_output_a.aggregation_state.assign_object_to_proof_outputs(); - - auto circuit_output_b = create_outer_circuit(inner_circuit_b, mid_circuit_b); - - circuit_output_b.aggregation_state.assign_object_to_proof_outputs(); - - auto circuit_output = create_double_outer_circuit(mid_circuit_a, mid_circuit_b, outer_circuit); - circuit_output.aggregation_state.assign_object_to_proof_outputs(); - EXPECT_EQ(circuit_output_a.aggregation_state.public_inputs[0].get_value(), inner_inputs[0]); - EXPECT_EQ(circuit_output_a.aggregation_state.public_inputs[1].get_value(), inner_inputs[1]); - - check_pairing(circuit_output); - check_recursive_verification_circuit(outer_circuit, true); - } - - // verifies a proof of a circuit that verifies one of two proofs. Test 'a' uses a proof over the first of the - // two variable circuits - static void test_recursive_proof_composition_with_variable_verification_key_a() - { - InnerBuilder inner_circuit_a; - InnerBuilder inner_circuit_b; - OuterBuilder outer_circuit; - - std::vector inner_inputs_a{ inner_scalar_field::random_element(), - inner_scalar_field::random_element(), - inner_scalar_field::random_element() }; - - std::vector inner_inputs_b{ inner_scalar_field::random_element(), - inner_scalar_field::random_element(), - inner_scalar_field::random_element() }; - - create_inner_circuit(inner_circuit_a, inner_inputs_a); - create_alternate_inner_circuit(inner_circuit_b, inner_inputs_b); - - auto circuit_output = - create_outer_circuit_with_variable_inner_circuit(inner_circuit_a, inner_circuit_b, outer_circuit, true); - EXPECT_EQ(circuit_output.aggregation_state.public_inputs[0].get_value(), inner_inputs_a[0]); - EXPECT_EQ(circuit_output.aggregation_state.public_inputs[1].get_value(), inner_inputs_a[1]); - EXPECT_EQ(circuit_output.aggregation_state.public_inputs[2].get_value(), inner_inputs_a[2]); - - check_pairing(circuit_output); - check_recursive_verification_circuit(outer_circuit, true); - } - - // verifies a proof of a circuit that verifies one of two proofs. Test 'b' uses a proof over the second of the - // two variable circuits - static void test_recursive_proof_composition_with_variable_verification_key_b() - { - InnerBuilder inner_circuit_a; - InnerBuilder inner_circuit_b; - OuterBuilder outer_circuit; - - std::vector inner_inputs_a{ inner_scalar_field::random_element(), - inner_scalar_field::random_element(), - inner_scalar_field::random_element() }; - - std::vector inner_inputs_b{ inner_scalar_field::random_element(), - inner_scalar_field::random_element(), - inner_scalar_field::random_element() }; - - create_inner_circuit(inner_circuit_a, inner_inputs_a); - create_alternate_inner_circuit(inner_circuit_b, inner_inputs_b); - - auto circuit_output = - create_outer_circuit_with_variable_inner_circuit(inner_circuit_a, inner_circuit_b, outer_circuit, false); - EXPECT_EQ(circuit_output.aggregation_state.public_inputs[0].get_value(), inner_inputs_b[0]); - EXPECT_EQ(circuit_output.aggregation_state.public_inputs[1].get_value(), inner_inputs_b[1]); - EXPECT_EQ(circuit_output.aggregation_state.public_inputs[2].get_value(), inner_inputs_b[2]); - - check_pairing(circuit_output); - check_recursive_verification_circuit(outer_circuit, true); - } - - static void test_recursive_proof_composition_with_variable_verification_key_failure_case() - { - InnerBuilder inner_circuit_a; - InnerBuilder inner_circuit_b; - OuterBuilder outer_circuit; - - std::vector inner_inputs_a{ inner_scalar_field::random_element(), - inner_scalar_field::random_element(), - inner_scalar_field::random_element() }; - - std::vector inner_inputs_b{ inner_scalar_field::random_element(), - inner_scalar_field::random_element(), - inner_scalar_field::random_element() }; - - create_inner_circuit(inner_circuit_a, inner_inputs_a); - create_alternate_inner_circuit(inner_circuit_b, inner_inputs_b); - - auto circuit_output = create_outer_circuit_with_variable_inner_circuit( - inner_circuit_a, inner_circuit_b, outer_circuit, true, true); - EXPECT_EQ(circuit_output.aggregation_state.public_inputs[0].get_value(), inner_inputs_a[0]); - EXPECT_EQ(circuit_output.aggregation_state.public_inputs[1].get_value(), inner_inputs_a[1]); - EXPECT_EQ(circuit_output.aggregation_state.public_inputs[2].get_value(), inner_inputs_a[2]); - - check_pairing(circuit_output); - check_recursive_verification_circuit(outer_circuit, false); - } - - static void test_recursive_proof_composition_with_constant_verification_key() - { - InnerBuilder inner_circuit_a; - InnerBuilder inner_circuit_b; - OuterBuilder outer_circuit; - - std::vector inner_inputs_a{ inner_scalar_field::random_element(), - inner_scalar_field::random_element(), - inner_scalar_field::random_element() }; - - std::vector inner_inputs_b{ inner_scalar_field::random_element(), - inner_scalar_field::random_element(), - inner_scalar_field::random_element() }; - - create_inner_circuit(inner_circuit_a, inner_inputs_a); - create_alternate_inner_circuit(inner_circuit_b, inner_inputs_b); - - auto circuit_output = create_outer_circuit_with_variable_inner_circuit( - inner_circuit_a, inner_circuit_b, outer_circuit, true, false, true); - EXPECT_EQ(circuit_output.aggregation_state.public_inputs[0].get_value(), inner_inputs_a[0]); - EXPECT_EQ(circuit_output.aggregation_state.public_inputs[1].get_value(), inner_inputs_a[1]); - EXPECT_EQ(circuit_output.aggregation_state.public_inputs[2].get_value(), inner_inputs_a[2]); - - check_pairing(circuit_output); - check_recursive_verification_circuit(outer_circuit, true); - } -}; - -typedef testing::Types OuterCircuitTypes; - -TYPED_TEST_SUITE(stdlib_verifier_turbo, OuterCircuitTypes); - -HEAVY_TYPED_TEST(stdlib_verifier_turbo, test_inner_circuit) -{ - TestFixture::test_inner_circuit(); -} - -HEAVY_TYPED_TEST(stdlib_verifier_turbo, recursive_proof_composition) -{ - TestFixture::test_recursive_proof_composition(); -}; - -HEAVY_TYPED_TEST(stdlib_verifier_turbo, double_verification) -{ - if constexpr (std::same_as) { - TestFixture::test_double_verification(); - } else { - // Test doesn't compile. - GTEST_SKIP(); - } -}; - -HEAVY_TYPED_TEST(stdlib_verifier_turbo, recursive_proof_composition_with_variable_verification_key_a) -{ - TestFixture::test_recursive_proof_composition_with_variable_verification_key_a(); -} - -HEAVY_TYPED_TEST(stdlib_verifier_turbo, recursive_proof_composition_with_variable_verification_key_b) -{ - TestFixture::test_recursive_proof_composition_with_variable_verification_key_b(); -} - -HEAVY_TYPED_TEST(stdlib_verifier_turbo, recursive_proof_composition_var_verif_key_fail) -{ - TestFixture::test_recursive_proof_composition_with_variable_verification_key_failure_case(); -} - -HEAVY_TYPED_TEST(stdlib_verifier_turbo, recursive_proof_composition_const_verif_key) -{ - TestFixture::test_recursive_proof_composition_with_constant_verification_key(); -} - -} // namespace proof_system::plonk::stdlib \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/types/turbo.hpp b/barretenberg/cpp/src/barretenberg/stdlib/types/turbo.hpp deleted file mode 100644 index 6ec21e69555..00000000000 --- a/barretenberg/cpp/src/barretenberg/stdlib/types/turbo.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once -#include "barretenberg/plonk/composer/turbo_composer.hpp" -#include "barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.hpp" -#include "barretenberg/plonk/proof_system/prover/prover.hpp" -#include "barretenberg/plonk/proof_system/types/prover_settings.hpp" -#include "barretenberg/stdlib/commitment/pedersen/pedersen.hpp" -#include "barretenberg/stdlib/encryption/schnorr/schnorr.hpp" -#include "barretenberg/stdlib/merkle_tree/hash_path.hpp" -#include "barretenberg/stdlib/primitives/bigfield/bigfield.hpp" -#include "barretenberg/stdlib/primitives/biggroup/biggroup.hpp" -#include "barretenberg/stdlib/primitives/bit_array/bit_array.hpp" -#include "barretenberg/stdlib/primitives/bool/bool.hpp" -#include "barretenberg/stdlib/primitives/byte_array/byte_array.hpp" -#include "barretenberg/stdlib/primitives/curves/bn254.hpp" -#include "barretenberg/stdlib/primitives/curves/secp256k1.hpp" -#include "barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.hpp" -#include "barretenberg/stdlib/primitives/uint/uint.hpp" -#include "barretenberg/stdlib/primitives/witness/witness.hpp" -#include "barretenberg/stdlib/recursion/verifier/program_settings.hpp" - -namespace proof_system::plonk::stdlib::types { - -using namespace proof_system::plonk; - -using Builder = proof_system::TurboCircuitBuilder; - -using Composer = plonk::TurboComposer; - -using Prover = plonk::TurboProver; - -using Verifier = plonk::TurboVerifier; - -using settings = plonk::turbo_settings; - -using kate_commitment_scheme = plonk::KateCommitmentScheme; - -using witness_ct = stdlib::witness_t; -using public_witness_ct = stdlib::public_witness_t; -using bool_ct = stdlib::bool_t; -using byte_array_ct = stdlib::byte_array; -using packed_byte_array_ct = stdlib::packed_byte_array; -using field_ct = stdlib::field_t; -using suint_ct = stdlib::safe_uint_t; -using uint8_ct = stdlib::uint8; -using uint16_ct = stdlib::uint16; -using uint32_ct = stdlib::uint32; -using uint64_ct = stdlib::uint64; -using bit_array_ct = stdlib::bit_array; -using fq_ct = stdlib::bigfield; -using biggroup_ct = stdlib::element; -using point_ct = stdlib::point; -using pedersen_commitment = stdlib::pedersen_commitment; -using group_ct = stdlib::group; -using bn254 = stdlib::bn254; -using secp256k1_ct = stdlib::secp256k1; - -namespace merkle_tree { -using namespace stdlib::merkle_tree; -using hash_path = stdlib::merkle_tree::hash_path; -} // namespace merkle_tree - -namespace schnorr { -using signature_bits = stdlib::schnorr::signature_bits; -} // namespace schnorr - -using recursive_inner_verifier_settings = recursion::recursive_turbo_verifier_settings; - -} // namespace proof_system::plonk::stdlib::types diff --git a/barretenberg/cpp/src/barretenberg/transcript/transcript.cpp b/barretenberg/cpp/src/barretenberg/transcript/transcript.cpp index 89eea69a9d2..ff4abf73113 100644 --- a/barretenberg/cpp/src/barretenberg/transcript/transcript.cpp +++ b/barretenberg/cpp/src/barretenberg/transcript/transcript.cpp @@ -187,7 +187,7 @@ void Transcript::add_element(const std::string& element_name, const std::vector< void Transcript::apply_fiat_shamir(const std::string& challenge_name /*, const bool info_togglable*/) { // For reference, see the relevant manifest, which is defined in - // plonk/composer/[standard/turbo/ultra]_composer.hpp + // plonk/composer/[standard/ultra]_composer.hpp ASSERT(current_round <= manifest.get_num_rounds()); // TODO(Cody): Coupling: this line insists that the challenges in the manifest // are encountered in the order that matches the order of the proof construction functions. diff --git a/barretenberg/sol/README.md b/barretenberg/sol/README.md index d0ae9ffa1b5..061a39c6e9e 100644 --- a/barretenberg/sol/README.md +++ b/barretenberg/sol/README.md @@ -1,11 +1,10 @@ # Solidity Verifier contracts and tests -**Note:** ONLY Ultra verifier as rolled versions were removed. [aztec-verifier-contracts](https://github.com/AztecProtocol/aztec-verifier-contracts) contains old code with rolled standard verifier and tests. - +**Note:** ONLY Ultra verifier as rolled versions were removed. [aztec-verifier-contracts](https://github.com/AztecProtocol/aztec-verifier-contracts) contains old code with rolled standard verifier and tests. This folder contains verifier contracts and testing harnesses that are used by [Noir, our Zero-Knowledge Programming Language](https://github.com/noir-lang/noir). -The implementations maintain the same interface, regardless of the verifier flavour (Standard, Turbo, Ultra), this should enable upstream implementations to be "plug-and-play". +The implementations maintain the same interface, regardless of the verifier flavour (Standard, Ultra), this should enable upstream implementations to be "plug-and-play". The verifier will follow an overall architecture below, consisting of 3 contracts/libraries. Namely, the verifier algorithm (stable across circuits), the verification key (circuit dependent) and then the "verifier instance", a base that reads from the verification key and uses the key's values in the verification algorithm. The main advantage of this design is that we can generate verification key's per circuit and plug them into a general verification algorithm. @@ -56,13 +55,16 @@ forge test --match-contract StandardTest --match-test testValidProof -vvvv ## Debugging in assembly Debugging from inside the assembly can be pretty inconvenient. The quickest way to get going is to add a custom error: + ```solidity bytes4 internal constant ERR_S = 0xf7b44074; error ERR(bytes32,bytes32,bytes32); ``` + Where `ERR_S` is the selector (first 4 bytes of keccak256(function signature)). To revert the contract, and print values, you can then do as + ```solidity mstore(0x00, ERR_S) // put the selector in memory mstore(0x04, val_1) // add first value after selector @@ -70,11 +72,14 @@ mstore(0x24, val_2) // add second value after first mstore(0x44, val_3) // add third value after second revert(0x00, 0x64) // revert with a message containing 0x64 bytes defined above ``` + When running a test, you will then see the three values `val_1, val_2, val_3` in the console. # Docker + To run the docker image, which will build keygen and proofgen and then run tests, run the following from root: + ```bash -# From root +# From root docker build . -f sol/Dockerfile ``` diff --git a/barretenberg/sol/test/base/DifferentialFuzzer.sol b/barretenberg/sol/test/base/DifferentialFuzzer.sol index 3f6ee18e1d7..451fc8ee21b 100644 --- a/barretenberg/sol/test/base/DifferentialFuzzer.sol +++ b/barretenberg/sol/test/base/DifferentialFuzzer.sol @@ -11,7 +11,6 @@ contract DifferentialFuzzer is TestBase { enum PlonkFlavour { Invalid, Standard, - Turbo, Ultra } enum CircuitFlavour { @@ -50,8 +49,6 @@ contract DifferentialFuzzer is TestBase { function get_plonk_flavour() internal view returns (string memory) { if (plonkFlavour == PlonkFlavour.Standard) { return "standard"; - } else if (plonkFlavour == PlonkFlavour.Turbo) { - return "turbo"; } else if (plonkFlavour == PlonkFlavour.Ultra) { return "ultra"; } else { diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/utils.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/utils.cpp index a22535a3577..3c4e8c3501b 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/utils.cpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/private/utils.cpp @@ -91,7 +91,7 @@ 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(proof_system::CircuitType::TURBO), + NT::VKData vk_data = { .circuit_type = static_cast(CircuitType::ULTRA), .circuit_size = 2048, .num_public_inputs = 116, .commitments = commitments, diff --git a/yarn-project/circuits.js/src/structs/shared.ts b/yarn-project/circuits.js/src/structs/shared.ts index 473db51ee7b..50375a8a58b 100644 --- a/yarn-project/circuits.js/src/structs/shared.ts +++ b/yarn-project/circuits.js/src/structs/shared.ts @@ -32,8 +32,7 @@ export type UInt32 = number; */ export enum CircuitType { STANDARD = 0, - TURBO = 1, - ULTRA = 2, + ULTRA = 1, } /** diff --git a/yarn-project/circuits.js/src/structs/verification_key.ts b/yarn-project/circuits.js/src/structs/verification_key.ts index 28135bb2ce5..7e24f9ba644 100644 --- a/yarn-project/circuits.js/src/structs/verification_key.ts +++ b/yarn-project/circuits.js/src/structs/verification_key.ts @@ -140,75 +140,14 @@ export class VerificationKey { /** * Builds a fake verification key that should be accepted by circuits. - * @returns A turbo verification key. + * @returns A fake verification key. */ static makeFake(): VerificationKey { return new VerificationKey( - CircuitType.TURBO, + CircuitType.ULTRA, // This is entirely arbitrary 2048, 116, - { - Q_1: new G1AffineElement( - 0x09623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128dn, - 0x1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f9n, - ), - Q_2: new G1AffineElement( - 0x2bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a09n, - 0x2a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa948n, - ), - Q_3: new G1AffineElement( - 0x2729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6dn, - 0x0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a301n, - ), - Q_4: new G1AffineElement( - 0x2be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a8n, - 0x2a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a1n, - ), - Q_5: new G1AffineElement( - 0x1f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c0n, - 0x00c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e17n, - ), - Q_ARITHMETIC: new G1AffineElement( - 0x0d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e042n, - 0x13f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff434n, - ), - Q_C: new G1AffineElement( - 0x224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e9n, - 0x0f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa013n, - ), - Q_FIXED_BASE: new G1AffineElement( - 0x060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8dn, - 0x2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3an, - ), - Q_LOGIC: new G1AffineElement( - 0x0721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec199696n, - 0x1a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c7n, - ), - Q_M: new G1AffineElement( - 0x05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b40n, - 0x1b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed8n, - ), - Q_RANGE: new G1AffineElement( - 0x04b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9adn, - 0x07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2bn, - ), - SIGMA_1: new G1AffineElement( - 0x25001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d31n, - 0x2c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47cn, - ), - SIGMA_2: new G1AffineElement( - 0x23994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15adn, - 0x11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7bebn, - ), - SIGMA_3: new G1AffineElement( - 0x00cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d8n, - 0x29639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fban, - ), - SIGMA_4: new G1AffineElement( - 0x2d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fcn, - 0x2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5cn, - ), - }, + {}, // Empty set of commitments false, times(16, i => i), );