From 6a7ebb60e4ecf0ae0d047814e22ecd88c9c7528f Mon Sep 17 00:00:00 2001 From: Cody Gunton Date: Wed, 22 Nov 2023 15:04:28 -0500 Subject: [PATCH] feat: Goblin proof construction (#3332) The last PR that splits out and completes work from https://github.com/AztecProtocol/aztec-packages/pull/3022 We add composer, prover and verifier classes for the Goblin Translator VM. We also further flesh out the full Goblin composer tests. Modulo some missing challenge generation, we have our first Goblin proofs (i.e., something worth measuring)! Spawned issues https://github.com/AztecProtocol/barretenberg/issues/783 https://github.com/AztecProtocol/barretenberg/issues/784 https://github.com/AztecProtocol/barretenberg/issues/785 https://github.com/AztecProtocol/barretenberg/issues/786 https://github.com/AztecProtocol/barretenberg/issues/787 --- barretenberg/cpp/scripts/bb-tests.sh | 1 + barretenberg/cpp/src/CMakeLists.txt | 1 + .../relations_bench/relations.bench.cpp | 89 ++-- .../zeromorph/zeromorph.hpp | 4 +- .../zeromorph/zeromorph.test.cpp | 15 +- .../cpp/src/barretenberg/common/benchmark.hpp | 2 + .../src/barretenberg/eccvm/eccvm_prover.cpp | 37 +- .../src/barretenberg/eccvm/eccvm_prover.hpp | 6 + .../eccvm/eccvm_transcript.test.cpp | 9 +- .../src/barretenberg/eccvm/eccvm_verifier.cpp | 2 +- .../src/barretenberg/flavor/flavor.test.cpp | 4 - .../barretenberg/flavor/goblin_translator.hpp | 283 ++----------- .../src/barretenberg/flavor/goblin_ultra.hpp | 4 +- .../cpp/src/barretenberg/flavor/ultra.hpp | 2 +- .../src/barretenberg/goblin/CMakeLists.txt | 2 +- .../goblin/full_goblin_composer.test.cpp | 139 +++---- .../goblin/translation_evaluations.hpp | 8 + .../honk/proof_system/permutation_library.hpp | 28 +- .../barretenberg/polynomials/polynomial.hpp | 4 +- .../eccvm/eccvm_circuit_builder.hpp | 26 +- .../goblin_translator_circuit_builder.cpp | 10 +- .../goblin_translator_circuit_builder.hpp | 7 +- ...goblin_translator_circuit_builder.test.cpp | 14 +- .../relations/ecc_vm/ecc_lookup_relation.cpp | 1 - .../srs/factories/file_crs_factory.hpp | 2 +- .../src/barretenberg/sumcheck/sumcheck.hpp | 4 - .../barretenberg/sumcheck/sumcheck_round.hpp | 2 - .../barretenberg/translator_vm/CMakeLists.txt | 1 + .../goblin_translator_composer.cpp | 312 ++++++++++++++ .../goblin_translator_composer.hpp | 68 ++++ .../goblin_translator_composer.test.cpp | 81 ++++ .../goblin_translator_prover.cpp | 385 ++++++++++++++++++ .../goblin_translator_prover.hpp | 57 +++ .../goblin_translator_verifier.cpp | 312 ++++++++++++++ .../goblin_translator_verifier.hpp | 39 ++ .../ultra_honk/relation_correctness.test.cpp | 26 +- .../ultra_honk/ultra_composer.hpp | 8 +- 37 files changed, 1534 insertions(+), 461 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/goblin/translation_evaluations.hpp create mode 100644 barretenberg/cpp/src/barretenberg/translator_vm/CMakeLists.txt create mode 100644 barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.cpp create mode 100644 barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.hpp create mode 100644 barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.test.cpp create mode 100644 barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.cpp create mode 100644 barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.hpp create mode 100644 barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_verifier.cpp create mode 100644 barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_verifier.hpp diff --git a/barretenberg/cpp/scripts/bb-tests.sh b/barretenberg/cpp/scripts/bb-tests.sh index d0ca404757e..0c16f66e55b 100755 --- a/barretenberg/cpp/scripts/bb-tests.sh +++ b/barretenberg/cpp/scripts/bb-tests.sh @@ -35,6 +35,7 @@ TESTS=( srs_tests sumcheck_tests transcript_tests + translator_vm_tests ultra_honk_tests ) TESTS_STR="${TESTS[@]}" diff --git a/barretenberg/cpp/src/CMakeLists.txt b/barretenberg/cpp/src/CMakeLists.txt index 43e5b66200f..b74bc2f99b5 100644 --- a/barretenberg/cpp/src/CMakeLists.txt +++ b/barretenberg/cpp/src/CMakeLists.txt @@ -74,6 +74,7 @@ add_subdirectory(barretenberg/srs) add_subdirectory(barretenberg/stdlib) add_subdirectory(barretenberg/sumcheck) add_subdirectory(barretenberg/transcript) +add_subdirectory(barretenberg/translator_vm) add_subdirectory(barretenberg/ultra_honk) add_subdirectory(barretenberg/wasi) diff --git a/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp index 3300fb4bf8e..d27dc35f9bc 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp @@ -1,3 +1,4 @@ +#include "barretenberg/flavor/ecc_vm.hpp" #include "barretenberg/flavor/goblin_translator.hpp" #include "barretenberg/flavor/goblin_ultra.hpp" #include "barretenberg/flavor/ultra.hpp" @@ -7,12 +8,16 @@ namespace { auto& engine = numeric::random::get_debug_engine(); } +using namespace proof_system::honk::sumcheck; + namespace proof_system::benchmark::relations { -using FF = barretenberg::fr; +using Fr = barretenberg::fr; +using Fq = grumpkin::fr; template void execute_relation(::benchmark::State& state) { + using FF = typename Flavor::FF; using AllValues = typename Flavor::AllValues; using SumcheckArrayOfValuesOverSubrelations = typename Relation::SumcheckArrayOfValuesOverSubrelations; @@ -29,82 +34,118 @@ template void execute_relation(::benchmark: } } -void auxiliary_relation(::benchmark::State& state) noexcept +void ultra_auxiliary_relation(::benchmark::State& state) noexcept { - execute_relation>(state); + execute_relation>(state); } -BENCHMARK(auxiliary_relation); +BENCHMARK(ultra_auxiliary_relation); -void elliptic_relation(::benchmark::State& state) noexcept +void ultra_elliptic_relation(::benchmark::State& state) noexcept { - execute_relation>(state); + execute_relation>(state); } -BENCHMARK(elliptic_relation); +BENCHMARK(ultra_elliptic_relation); -void ecc_op_queue_relation(::benchmark::State& state) noexcept +void ultra_ecc_op_queue_relation(::benchmark::State& state) noexcept { - execute_relation>(state); + execute_relation>(state); } -BENCHMARK(ecc_op_queue_relation); +BENCHMARK(ultra_ecc_op_queue_relation); -void gen_perm_sort_relation(::benchmark::State& state) noexcept +void ultra_gen_perm_sort_relation(::benchmark::State& state) noexcept { - execute_relation>(state); + execute_relation>(state); } -BENCHMARK(gen_perm_sort_relation); +BENCHMARK(ultra_gen_perm_sort_relation); -void lookup_relation(::benchmark::State& state) noexcept +void ultralookup_relation(::benchmark::State& state) noexcept { - execute_relation>(state); + execute_relation>(state); } -BENCHMARK(lookup_relation); +BENCHMARK(ultralookup_relation); void ultra_permutation_relation(::benchmark::State& state) noexcept { - execute_relation>(state); + execute_relation>(state); } BENCHMARK(ultra_permutation_relation); void ultra_arithmetic_relation(::benchmark::State& state) noexcept { - execute_relation>(state); + execute_relation>(state); } BENCHMARK(ultra_arithmetic_relation); void translator_decomposition_relation(::benchmark::State& state) noexcept { - execute_relation>(state); + execute_relation>(state); } BENCHMARK(translator_decomposition_relation); void translator_opcode_constraint_relation(::benchmark::State& state) noexcept { - execute_relation>(state); + execute_relation>(state); } BENCHMARK(translator_opcode_constraint_relation); void translator_accumulator_transfer_relation(::benchmark::State& state) noexcept { - execute_relation>(state); + execute_relation>(state); } BENCHMARK(translator_accumulator_transfer_relation); void translator_gen_perm_sort_relation(::benchmark::State& state) noexcept { - execute_relation>(state); + execute_relation>(state); } BENCHMARK(translator_gen_perm_sort_relation); void translator_non_native_field_relation(::benchmark::State& state) noexcept { - execute_relation>(state); + execute_relation>(state); } BENCHMARK(translator_non_native_field_relation); void translator_permutation_relation(::benchmark::State& state) noexcept { - execute_relation>(state); + execute_relation>(state); } BENCHMARK(translator_permutation_relation); +void eccvm_lookup_relation(::benchmark::State& state) noexcept +{ + execute_relation>(state); +} +BENCHMARK(eccvm_lookup_relation); + +void eccvm_msm_relation(::benchmark::State& state) noexcept +{ + execute_relation>(state); +} +BENCHMARK(eccvm_msm_relation); + +void eccvm_point_table_relation(::benchmark::State& state) noexcept +{ + execute_relation>(state); +} +BENCHMARK(eccvm_point_table_relation); + +void eccvm_set_relation(::benchmark::State& state) noexcept +{ + execute_relation>(state); +} +BENCHMARK(eccvm_set_relation); + +void eccvm_transcript_relation(::benchmark::State& state) noexcept +{ + execute_relation>(state); +} +BENCHMARK(eccvm_transcript_relation); + +void eccvm_wnaf_relation(::benchmark::State& state) noexcept +{ + execute_relation>(state); +} +BENCHMARK(eccvm_wnaf_relation); + } // namespace proof_system::benchmark::relations diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp index 93ec07ec533..1cd359ebe69 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp @@ -319,9 +319,9 @@ template class ZeroMorphProver_ { auto& multilinear_challenge, auto& commitment_key, auto& transcript, - const std::vector& concatenated_polynomials = {}, + const std::vector>& concatenated_polynomials = {}, const std::vector& concatenated_evaluations = {}, - const std::vector>& concatenation_groups = {}) + const std::vector>>& concatenation_groups = {}) { // Generate batching challenge \rho and powers 1,...,\rho^{m-1} FF rho = transcript.get_challenge("rho"); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp index 270f236ad68..30876c73e50 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp @@ -225,6 +225,17 @@ template class ZeroMorphWithConcatenationTest : public CommitmentT // Initialize an empty BaseTranscript auto prover_transcript = BaseTranscript::prover_init_empty(); + std::vector> concatenated_polynomials_views; + for (auto& poly : concatenated_polynomials) { + concatenated_polynomials_views.emplace_back(poly); + } + + std::vector>> concatenation_groups_views(concatenation_groups.size()); + for (auto [group_of_polys, group_of_views] : zip_view(concatenation_groups, concatenation_groups_views)) { + for (auto& poly : group_of_polys) { + group_of_views.emplace_back(poly); + } + } // Execute Prover protocol ZeroMorphProver::prove(f_polynomials, // unshifted g_polynomials, // to-be-shifted @@ -233,9 +244,9 @@ template class ZeroMorphWithConcatenationTest : public CommitmentT u_challenge, this->commitment_key, prover_transcript, - concatenated_polynomials, + concatenated_polynomials_views, c_evaluations, - concatenation_groups); + concatenation_groups_views); auto verifier_transcript = BaseTranscript::verifier_init_empty(prover_transcript); diff --git a/barretenberg/cpp/src/barretenberg/common/benchmark.hpp b/barretenberg/cpp/src/barretenberg/common/benchmark.hpp index 5d3034bbe6f..98715635c92 100644 --- a/barretenberg/cpp/src/barretenberg/common/benchmark.hpp +++ b/barretenberg/cpp/src/barretenberg/common/benchmark.hpp @@ -8,6 +8,8 @@ #include #include +#pragma GCC diagnostic ignored "-Wunused-result" // GCC13 hits this + namespace { /** * If user provides the env var BENCHMARK_FD write benchmarks to this fd, otherwise default to -1 (disable). diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index cd819f5c6ac..d757c37c5ed 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -320,35 +320,38 @@ template void ECCVMProver_::execute_transcript_cons transcript.send_to_verifier("Translation:hack_commitment", commitment_key->commit(hack)); // Get the challenge at which we evaluate the polynomials as univariates - FF evaluation_challenge_x = transcript.get_challenge("Translation:evaluation_challenge_x"); + evaluation_challenge_x = transcript.get_challenge("Translation:evaluation_challenge_x"); - // Collect the polynomials and evaluations to be batched - const size_t NUM_UNIVARIATES = 6; // 5 transcript polynomials plus the constant hack poly - std::array univariate_polynomials = { key->transcript_op, key->transcript_Px, - key->transcript_Py, key->transcript_z1, - key->transcript_z2, hack }; - std::array univariate_evaluations; - for (auto [eval, polynomial] : zip_view(univariate_evaluations, univariate_polynomials)) { - eval = polynomial.evaluate(evaluation_challenge_x); - } + translation_evaluations.op = key->transcript_op.evaluate(evaluation_challenge_x); + translation_evaluations.Px = key->transcript_Px.evaluate(evaluation_challenge_x); + translation_evaluations.Py = key->transcript_Py.evaluate(evaluation_challenge_x); + translation_evaluations.z1 = key->transcript_z1.evaluate(evaluation_challenge_x); + translation_evaluations.z2 = key->transcript_z2.evaluate(evaluation_challenge_x); // Add the univariate evaluations to the transcript - transcript.send_to_verifier("Translation:op", univariate_evaluations[0]); - transcript.send_to_verifier("Translation:Px", univariate_evaluations[1]); - transcript.send_to_verifier("Translation:Py", univariate_evaluations[2]); - transcript.send_to_verifier("Translation:z1", univariate_evaluations[3]); - transcript.send_to_verifier("Translation:z2", univariate_evaluations[4]); - transcript.send_to_verifier("Translation:hack_evaluation", univariate_evaluations[5]); + transcript.send_to_verifier("Translation:op", translation_evaluations.op); + transcript.send_to_verifier("Translation:Px", translation_evaluations.Px); + transcript.send_to_verifier("Translation:Py", translation_evaluations.Py); + transcript.send_to_verifier("Translation:z1", translation_evaluations.z1); + transcript.send_to_verifier("Translation:z2", translation_evaluations.z2); + transcript.send_to_verifier("Translation:hack_evaluation", hack.evaluate(evaluation_challenge_x)); // Get another challenge for batching the univariate claims FF batching_challenge = transcript.get_challenge("Translation:batching_challenge"); + // Collect the polynomials and evaluations to be batched + const size_t NUM_UNIVARIATES = 6; // 5 transcript polynomials plus the constant hack poly + std::array univariate_polynomials = { &key->transcript_op, &key->transcript_Px, + &key->transcript_Py, &key->transcript_z1, + &key->transcript_z2, &hack }; + std::array univariate_evaluations; + // Constuct the batched polynomial and batched evaluation Polynomial batched_univariate{ key->circuit_size }; FF batched_evaluation{ 0 }; auto batching_scalar = FF(1); for (auto [eval, polynomial] : zip_view(univariate_evaluations, univariate_polynomials)) { - batched_univariate.add_scaled(polynomial, batching_scalar); + batched_univariate.add_scaled(*polynomial, batching_scalar); batched_evaluation += eval * batching_scalar; batching_scalar *= batching_challenge; } diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp index 7bbf8f2de8a..3cd07fb9414 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp @@ -2,6 +2,7 @@ #include "barretenberg/commitment_schemes/gemini/gemini.hpp" #include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" #include "barretenberg/flavor/ecc_vm.hpp" +#include "barretenberg/goblin/translation_evaluations.hpp" #include "barretenberg/plonk/proof_system/types/proof.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/sumcheck/sumcheck_output.hpp" @@ -22,6 +23,7 @@ template class ECCVMProver_ { using CommitmentLabels = typename Flavor::CommitmentLabels; using Curve = typename Flavor::Curve; using Transcript = typename Flavor::Transcript; + using TranslationEvaluations = barretenberg::TranslationEvaluations; public: explicit ECCVMProver_(std::shared_ptr input_key, std::shared_ptr commitment_key); @@ -43,6 +45,8 @@ template class ECCVMProver_ { Transcript transcript; + TranslationEvaluations translation_evaluations; + std::vector public_inputs; proof_system::RelationParameters relation_parameters; @@ -62,6 +66,8 @@ template class ECCVMProver_ { Polynomial quotient_W; + FF evaluation_challenge_x; + sumcheck::SumcheckOutput sumcheck_output; pcs::gemini::ProverOutput gemini_output; pcs::shplonk::ProverOutput shplonk_output; diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp index 2b11b0b64c3..8af4c20cca0 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp @@ -227,7 +227,8 @@ TYPED_TEST_SUITE(ECCVMTranscriptTests, FlavorTypes); */ TYPED_TEST(ECCVMTranscriptTests, ProverManifestConsistency) { - GTEST_SKIP() << "WORKTODO: update and reinstate after the protocol is finalized."; + GTEST_SKIP() << "TODO(https://github.com/AztecProtocol/barretenberg/issues/782): update and reinstate after the " + "protocol is finalized."; using Flavor = TypeParam; // Construct a simple circuit @@ -256,7 +257,8 @@ TYPED_TEST(ECCVMTranscriptTests, ProverManifestConsistency) */ TYPED_TEST(ECCVMTranscriptTests, VerifierManifestConsistency) { - GTEST_SKIP() << "WORKTODO: update and reinstate after the protocol is finalized."; + GTEST_SKIP() << "TODO(https://github.com/AztecProtocol/barretenberg/issues/782): update and reinstate after the " + "protocol is finalized."; using Flavor = TypeParam; @@ -310,7 +312,8 @@ TYPED_TEST(ECCVMTranscriptTests, ChallengeGenerationTest) TYPED_TEST(ECCVMTranscriptTests, StructureTest) { - GTEST_SKIP() << "WORKTODO: update and reinstate after the protocol is finalized."; + GTEST_SKIP() << "TODO(https://github.com/AztecProtocol/barretenberg/issues/782): update and reinstate after the " + "protocol is finalized."; using Flavor = TypeParam; diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index 7959b5bfdb9..01aea6e673a 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -270,7 +270,7 @@ template bool ECCVMVerifier_::verify_proof(const plonk univariate_opening_verified = PCS::verify(pcs_verification_key, batched_univariate_claim, transcript); } - return multivariate_opening_verified && univariate_opening_verified; + return sumcheck_verified.value() && multivariate_opening_verified && univariate_opening_verified; } template class ECCVMVerifier_; diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor.test.cpp b/barretenberg/cpp/src/barretenberg/flavor/flavor.test.cpp index 92d5c2a980c..8e99d56e397 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor.test.cpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor.test.cpp @@ -4,9 +4,6 @@ #include #include -#pragma GCC diagnostic ignored "-Wunused-local-typedefs" -#pragma GCC diagnostic ignored "-Wunused-variable" - namespace proof_system::test_flavor { TEST(Flavor, Getters) { @@ -139,7 +136,6 @@ TEST(Flavor, GetRow) return std::vector({ FF::random_element(), FF::random_element() }); }); Flavor::ProverPolynomials prover_polynomials; - size_t poly_idx = 0; for (auto [poly, entry] : zip_view(prover_polynomials.pointer_view(), data)) { *poly = entry; } diff --git a/barretenberg/cpp/src/barretenberg/flavor/goblin_translator.hpp b/barretenberg/cpp/src/barretenberg/flavor/goblin_translator.hpp index 0bd927302ff..454bbf85b67 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/goblin_translator.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/goblin_translator.hpp @@ -1,10 +1,7 @@ #pragma once #include "barretenberg/commitment_schemes/commitment_key.hpp" #include "barretenberg/commitment_schemes/kzg/kzg.hpp" -#include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/flavor/flavor.hpp" -#include "barretenberg/polynomials/univariate.hpp" -#include "barretenberg/proof_system/arithmetization/arithmetization.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/relations/translator_vm/translator_decomposition_relation.hpp" @@ -13,248 +10,16 @@ #include "barretenberg/relations/translator_vm/translator_non_native_field_relation.hpp" #include "barretenberg/relations/translator_vm/translator_permutation_relation.hpp" #include "relation_definitions_fwd.hpp" -#include -#include -#include -#include -#include -#include namespace proof_system::honk::flavor { -template class GoblinTranslator_ { +class GoblinTranslator { public: - /** - * @brief Enum containing IDs of all the polynomials used in Goblin Translator - * - * @details We use the enum for easier updates of structure sizes and for cases where we need to get a particular - * polynomial programmatically - */ - enum ALL_ENTITIES_IDS : size_t { - /*The first 4 wires contain the standard values from the EccOpQueue*/ - OP, - X_LO_Y_HI, - X_HI_Z_1, - Y_LO_Z_2, - /*P.xₗₒ split into 2 NUM_LIMB_BITS bit limbs*/ - P_X_LOW_LIMBS, - /*Low limbs split further into smaller chunks for range constraints*/ - P_X_LOW_LIMBS_RANGE_CONSTRAINT_0, - P_X_LOW_LIMBS_RANGE_CONSTRAINT_1, - P_X_LOW_LIMBS_RANGE_CONSTRAINT_2, - P_X_LOW_LIMBS_RANGE_CONSTRAINT_3, - P_X_LOW_LIMBS_RANGE_CONSTRAINT_4, - P_X_LOW_LIMBS_RANGE_CONSTRAINT_TAIL, - /*P.xₕᵢ split into 2 NUM_LIMB_BITS bit limbs*/ - P_X_HIGH_LIMBS, - /*High limbs split into chunks for range constraints*/ - P_X_HIGH_LIMBS_RANGE_CONSTRAINT_0, - P_X_HIGH_LIMBS_RANGE_CONSTRAINT_1, - P_X_HIGH_LIMBS_RANGE_CONSTRAINT_2, - P_X_HIGH_LIMBS_RANGE_CONSTRAINT_3, - P_X_HIGH_LIMBS_RANGE_CONSTRAINT_4, - P_X_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL, // The tail also contains some leftover values from relation wide limb - // range cosntraints - /*P.yₗₒ split into 2 NUM_LIMB_BITS bit limbs*/ - P_Y_LOW_LIMBS, - /*Low limbs split into chunks for range constraints*/ - P_Y_LOW_LIMBS_RANGE_CONSTRAINT_0, - P_Y_LOW_LIMBS_RANGE_CONSTRAINT_1, - P_Y_LOW_LIMBS_RANGE_CONSTRAINT_2, - P_Y_LOW_LIMBS_RANGE_CONSTRAINT_3, - P_Y_LOW_LIMBS_RANGE_CONSTRAINT_4, - P_Y_LOW_LIMBS_RANGE_CONSTRAINT_TAIL, - /*P.yₕᵢ split into 2 NUM_LIMB_BITS bit limbs*/ - P_Y_HIGH_LIMBS, - /*High limbs split into chunks for range constraints*/ - P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_0, - P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_1, - P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_2, - P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_3, - P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_4, - P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL, // The tail also contains some leftover values from relation wide limb - // range cosntraints - /*Low limbs of z_1 and z_2*/ - Z_LOW_LIMBS, - /*Range constraints for low limbs of z_1 and z_2*/ - Z_LOW_LIMBS_RANGE_CONSTRAINT_0, - Z_LOW_LIMBS_RANGE_CONSTRAINT_1, - Z_LOW_LIMBS_RANGE_CONSTRAINT_2, - Z_LOW_LIMBS_RANGE_CONSTRAINT_3, - Z_LOW_LIMBS_RANGE_CONSTRAINT_4, - Z_LOW_LIMBS_RANGE_CONSTRAINT_TAIL, - /*High Limbs of z_1 and z_2*/ - Z_HIGH_LIMBS, - /*Range constraints for high limbs of z_1 and z_2*/ - Z_HIGH_LIMBS_RANGE_CONSTRAINT_0, - Z_HIGH_LIMBS_RANGE_CONSTRAINT_1, - Z_HIGH_LIMBS_RANGE_CONSTRAINT_2, - Z_HIGH_LIMBS_RANGE_CONSTRAINT_3, - Z_HIGH_LIMBS_RANGE_CONSTRAINT_4, - Z_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL, - /* Contain NUM_LIMB_BITS-bit limbs of current and previous accumulator (previous at higher indices because of - the nuances of KZG commitment) */ - ACCUMULATORS_BINARY_LIMBS_0, - ACCUMULATORS_BINARY_LIMBS_1, - ACCUMULATORS_BINARY_LIMBS_2, - ACCUMULATORS_BINARY_LIMBS_3, - ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_0, // Range constraints for the current accumulator limbs (no need to - // redo previous accumulator) - ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_1, - ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_2, - ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_3, - ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_4, - ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_TAIL, - ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_0, - ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_1, - ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_2, - ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_3, - ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_4, - ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL, // The tail also contains some leftover values from relation wide - // limb range constraints - - /* Quotient limbs*/ - QUOTIENT_LOW_BINARY_LIMBS, - QUOTIENT_HIGH_BINARY_LIMBS, - /* Range constraints for quotient */ - QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_0, - QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_1, - QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_2, - QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_3, - QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_4, - QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_TAIL, - QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_0, - QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_1, - QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_2, - QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_3, - QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_4, - QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL, // The tail also contains some leftover values from relation wide - // limb range constraints - - /* Limbs for checking the correctness of mod 2²⁷² relations*/ - RELATION_WIDE_LIMBS, - RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_0, - RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_1, - RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_2, - RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_3, - /*Concatenations of various range constraint wires*/ - CONCATENATED_RANGE_CONSTRAINTS_0, - CONCATENATED_RANGE_CONSTRAINTS_1, - CONCATENATED_RANGE_CONSTRAINTS_2, - CONCATENATED_RANGE_CONSTRAINTS_3, - /*Values from concatenated range constraints + some additional ones*/ - ORDERED_RANGE_CONSTRAINTS_0, - ORDERED_RANGE_CONSTRAINTS_1, - ORDERED_RANGE_CONSTRAINTS_2, - ORDERED_RANGE_CONSTRAINTS_3, - ORDERED_RANGE_CONSTRAINTS_4, - /*Grand Product Polynomial*/ - Z_PERM, - /*Shifted versions of polynomials*/ - X_LO_Y_HI_SHIFT, - X_HI_Z_1_SHIFT, - Y_LO_Z_2_SHIFT, - P_X_LOW_LIMBS_SHIFT, - P_X_LOW_LIMBS_RANGE_CONSTRAINT_0_SHIFT, - P_X_LOW_LIMBS_RANGE_CONSTRAINT_1_SHIFT, - P_X_LOW_LIMBS_RANGE_CONSTRAINT_2_SHIFT, - P_X_LOW_LIMBS_RANGE_CONSTRAINT_3_SHIFT, - P_X_LOW_LIMBS_RANGE_CONSTRAINT_4_SHIFT, - P_X_LOW_LIMBS_RANGE_CONSTRAINT_TAIL_SHIFT, - P_X_HIGH_LIMBS_SHIFT, - P_X_HIGH_LIMBS_RANGE_CONSTRAINT_0_SHIFT, - P_X_HIGH_LIMBS_RANGE_CONSTRAINT_1_SHIFT, - P_X_HIGH_LIMBS_RANGE_CONSTRAINT_2_SHIFT, - P_X_HIGH_LIMBS_RANGE_CONSTRAINT_3_SHIFT, - P_X_HIGH_LIMBS_RANGE_CONSTRAINT_4_SHIFT, - P_X_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL_SHIFT, - P_Y_LOW_LIMBS_SHIFT, - P_Y_LOW_LIMBS_RANGE_CONSTRAINT_0_SHIFT, - P_Y_LOW_LIMBS_RANGE_CONSTRAINT_1_SHIFT, - P_Y_LOW_LIMBS_RANGE_CONSTRAINT_2_SHIFT, - P_Y_LOW_LIMBS_RANGE_CONSTRAINT_3_SHIFT, - P_Y_LOW_LIMBS_RANGE_CONSTRAINT_4_SHIFT, - P_Y_LOW_LIMBS_RANGE_CONSTRAINT_TAIL_SHIFT, - P_Y_HIGH_LIMBS_SHIFT, - P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_0_SHIFT, - P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_1_SHIFT, - P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_2_SHIFT, - P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_3_SHIFT, - P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_4_SHIFT, - P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL_SHIFT, - Z_LOW_LIMBS_SHIFT, - Z_LOW_LIMBS_RANGE_CONSTRAINT_0_SHIFT, - Z_LOW_LIMBS_RANGE_CONSTRAINT_1_SHIFT, - Z_LOW_LIMBS_RANGE_CONSTRAINT_2_SHIFT, - Z_LOW_LIMBS_RANGE_CONSTRAINT_3_SHIFT, - Z_LOW_LIMBS_RANGE_CONSTRAINT_4_SHIFT, - Z_LOW_LIMBS_RANGE_CONSTRAINT_TAIL_SHIFT, - Z_HIGH_LIMBS_SHIFT, - Z_HIGH_LIMBS_RANGE_CONSTRAINT_0_SHIFT, - Z_HIGH_LIMBS_RANGE_CONSTRAINT_1_SHIFT, - Z_HIGH_LIMBS_RANGE_CONSTRAINT_2_SHIFT, - Z_HIGH_LIMBS_RANGE_CONSTRAINT_3_SHIFT, - Z_HIGH_LIMBS_RANGE_CONSTRAINT_4_SHIFT, - Z_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL_SHIFT, - ACCUMULATORS_BINARY_LIMBS_0_SHIFT, - ACCUMULATORS_BINARY_LIMBS_1_SHIFT, - ACCUMULATORS_BINARY_LIMBS_2_SHIFT, - ACCUMULATORS_BINARY_LIMBS_3_SHIFT, - ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_0_SHIFT, - ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_1_SHIFT, - ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_2_SHIFT, - ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_3_SHIFT, - ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_4_SHIFT, - ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_TAIL_SHIFT, - ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_0_SHIFT, - ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_1_SHIFT, - ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_2_SHIFT, - ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_3_SHIFT, - ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_4_SHIFT, - ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL_SHIFT, - QUOTIENT_LOW_BINARY_LIMBS_SHIFT, - QUOTIENT_HIGH_BINARY_LIMBS_SHIFT, - QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_0_SHIFT, - QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_1_SHIFT, - QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_2_SHIFT, - QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_3_SHIFT, - QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_4_SHIFT, - QUOTIENT_LOW_LIMBS_RANGE_CONSTRAINT_TAIL_SHIFT, - QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_0_SHIFT, - QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_1_SHIFT, - QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_2_SHIFT, - QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_3_SHIFT, - QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_4_SHIFT, - QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL_SHIFT, - RELATION_WIDE_LIMBS_SHIFT, - RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_0_SHIFT, - RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_1_SHIFT, - RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_2_SHIFT, - RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_3_SHIFT, - ORDERED_RANGE_CONSTRAINTS_0_SHIFT, - ORDERED_RANGE_CONSTRAINTS_1_SHIFT, - ORDERED_RANGE_CONSTRAINTS_2_SHIFT, - ORDERED_RANGE_CONSTRAINTS_3_SHIFT, - ORDERED_RANGE_CONSTRAINTS_4_SHIFT, - - Z_PERM_SHIFT, - /*All precomputed polynomials*/ - LAGRANGE_FIRST, - LAGRANGE_LAST, - LAGRANGE_ODD_IN_MINICIRCUIT, - LAGRANGE_EVEN_IN_MINICIRCUIT, - LAGRANGE_SECOND, - LAGRANGE_SECOND_TO_LAST_IN_MINICIRCUIT, - ORDERED_EXTRA_RANGE_CONSTRAINTS_NUMERATOR, - /*Utility value*/ - TOTAL_COUNT - - }; - + static constexpr size_t mini_circuit_size = 2048; using CircuitBuilder = GoblinTranslatorCircuitBuilder; - using PCS = pcs::kzg::KZG; using Curve = curve::BN254; + using PCS = pcs::kzg::KZG; using GroupElement = Curve::Element; using Commitment = Curve::AffineElement; using CommitmentHandle = Curve::AffineElement; @@ -300,13 +65,12 @@ template class GoblinTranslator_ { // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`. // Note: this number does not include the individual sorted list polynomials. - static constexpr size_t NUM_ALL_ENTITIES = ALL_ENTITIES_IDS::TOTAL_COUNT; + static constexpr size_t NUM_ALL_ENTITIES = 184; // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying // assignment of witnesses. We again choose a neutral name. - static constexpr size_t NUM_PRECOMPUTED_ENTITIES = ALL_ENTITIES_IDS::TOTAL_COUNT - ALL_ENTITIES_IDS::Z_PERM_SHIFT; + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 7; // The total number of witness entities not including shifts. - static constexpr size_t NUM_WITNESS_ENTITIES = - ALL_ENTITIES_IDS::TOTAL_COUNT - (ALL_ENTITIES_IDS::Z_PERM_SHIFT - ALL_ENTITIES_IDS::Z_PERM); + static constexpr size_t NUM_WITNESS_ENTITIES = 91; using GrandProductRelations = std::tuple>; // define the tuple of Relations that comprise the Sumcheck relation @@ -328,7 +92,13 @@ template class GoblinTranslator_ { static constexpr size_t NUM_RELATIONS = std::tuple_size_v; // define the containers for storing the contributions from each relation in Sumcheck - using SumcheckTupleOfTuplesOfUnivariates = decltype(create_sumcheck_tuple_of_tuples_of_univariates()); + using SumcheckTupleOfTuplesOfUnivariates = + std::tuple::SumcheckTupleOfUnivariatesOverSubrelations, + typename GoblinTranslatorGenPermSortRelation::SumcheckTupleOfUnivariatesOverSubrelations, + typename GoblinTranslatorOpcodeConstraintRelation::SumcheckTupleOfUnivariatesOverSubrelations, + typename GoblinTranslatorAccumulatorTransferRelation::SumcheckTupleOfUnivariatesOverSubrelations, + typename GoblinTranslatorDecompositionRelation::SumcheckTupleOfUnivariatesOverSubrelations, + typename GoblinTranslatorNonNativeFieldRelation::SumcheckTupleOfUnivariatesOverSubrelations>; using TupleOfArraysOfValues = decltype(create_tuple_of_arrays_of_values()); private: @@ -355,6 +125,7 @@ template class GoblinTranslator_ { &lagrange_second, &lagrange_second_to_last_in_minicircuit, &ordered_extra_range_constraints_numerator); + std::vector get_selectors() { return {}; }; std::vector get_sigma_polynomials() { return {}; }; std::vector get_id_polynomials() { return {}; }; @@ -550,7 +321,7 @@ template class GoblinTranslator_ { &ordered_range_constraints_2, &ordered_range_constraints_3, &ordered_range_constraints_4, - &z_perm, ) + &z_perm) std::vector get_wires() override { @@ -935,7 +706,6 @@ template class GoblinTranslator_ { DataType lagrange_second; // column 181 DataType lagrange_second_to_last_in_minicircuit; // column 182 DataType ordered_extra_range_constraints_numerator; // column 183 - // defines a method pointer_view that returns the following, with const and non-const variants DEFINE_POINTER_VIEW(NUM_ALL_ENTITIES, &op, @@ -1122,7 +892,6 @@ template class GoblinTranslator_ { &lagrange_second, &lagrange_second_to_last_in_minicircuit, &ordered_extra_range_constraints_numerator) - std::vector get_wires() override { @@ -1688,7 +1457,6 @@ template class GoblinTranslator_ { public: using Base = AllEntities; using Base::Base; - AllValues(std::array _data_in) { this->_data = _data_in; } }; /** * @brief A container for the prover polynomials handles; only stores spans. @@ -1728,13 +1496,11 @@ template class GoblinTranslator_ { */ class AllPolynomials : public AllEntities { public: - AllValues get_row(const size_t row_idx) const + [[nodiscard]] AllValues get_row(const size_t row_idx) const { AllValues result; - size_t column_idx = 0; // // TODO(https://github.com/AztecProtocol/barretenberg/issues/391) zip - for (auto& column : this->_data) { - result[column_idx] = column[row_idx]; - column_idx++; + for (auto [result_field, polynomial] : zip_view(result.pointer_view(), this->pointer_view())) { + *result_field = (*polynomial)[row_idx]; } return result; } @@ -1755,8 +1521,8 @@ template class GoblinTranslator_ { PartiallyEvaluatedMultivariates(const size_t circuit_size) { // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) - for (auto& poly : this->_data) { - poly = Polynomial(circuit_size / 2); + for (auto* poly : this->pointer_view()) { + *poly = Polynomial(circuit_size / 2); } } }; @@ -1782,7 +1548,6 @@ template class GoblinTranslator_ { public: CommitmentLabels() { - this->op = "OP"; this->x_lo_y_hi = "X_LO_Y_HI"; this->x_hi_z_1 = "X_HI_Z_1"; @@ -1882,10 +1647,9 @@ template class GoblinTranslator_ { class VerifierCommitments : public AllEntities { public: - VerifierCommitments(std::shared_ptr verification_key, + VerifierCommitments([[maybe_unused]] std::shared_ptr verification_key, [[maybe_unused]] const BaseTranscript& transcript) { - static_cast(transcript); this->lagrange_first = verification_key->lagrange_first; this->lagrange_last = verification_key->lagrange_last; this->lagrange_odd_in_minicircuit = verification_key->lagrange_odd_in_minicircuit; @@ -1896,10 +1660,9 @@ template class GoblinTranslator_ { verification_key->ordered_extra_range_constraints_numerator; } }; -}; - -using GoblinTranslator = GoblinTranslator_<2048>; + using Transcript = BaseTranscript; +}; } // namespace proof_system::honk::flavor namespace proof_system { diff --git a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp index ad3b536ed47..66127524328 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp @@ -438,7 +438,7 @@ class GoblinUltra { PartiallyEvaluatedMultivariates(const size_t circuit_size) { // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) - for (auto* poly : pointer_view()) { + for (auto* poly : this->pointer_view()) { *poly = Polynomial(circuit_size / 2); } } @@ -475,7 +475,7 @@ class GoblinUltra { [[nodiscard]] AllValues get_row(size_t row_idx) const { AllValues result; - for (auto [result_field, polynomial] : zip_view(result.pointer_view(), pointer_view())) { + for (auto [result_field, polynomial] : zip_view(result.pointer_view(), this->pointer_view())) { *result_field = (*polynomial)[row_idx]; } return result; diff --git a/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp b/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp index 414b08e13e6..da12a3994ef 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp @@ -374,7 +374,7 @@ class Ultra { PartiallyEvaluatedMultivariates(const size_t circuit_size) { // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) - for (auto* poly : pointer_view()) { + for (auto* poly : this->pointer_view()) { *poly = Polynomial(circuit_size / 2); } } diff --git a/barretenberg/cpp/src/barretenberg/goblin/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/goblin/CMakeLists.txt index f0316f56dcc..248b05c02e6 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/goblin/CMakeLists.txt @@ -1 +1 @@ -barretenberg_module(goblin ultra_honk eccvm) \ No newline at end of file +barretenberg_module(goblin ultra_honk eccvm translator_vm) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp index 0c675939b0c..e263cb329a4 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp @@ -1,14 +1,14 @@ -#include -#include -#include - -#include "barretenberg/common/log.hpp" #include "barretenberg/eccvm/eccvm_composer.hpp" +#include "barretenberg/goblin/translation_evaluations.hpp" #include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" +#include "barretenberg/translator_vm/goblin_translator_composer.hpp" #include "barretenberg/ultra_honk/ultra_composer.hpp" -#include "barretenberg/ultra_honk/ultra_prover.hpp" + +#include + +using namespace proof_system::honk; namespace test_full_goblin_composer { @@ -26,22 +26,27 @@ class FullGoblinComposerTests : public ::testing::Test { using Curve = curve::BN254; using FF = Curve::ScalarField; + using Fbase = Curve::BaseField; using Point = Curve::AffineElement; - using CommitmentKey = proof_system::honk::pcs::CommitmentKey; + using CommitmentKey = pcs::CommitmentKey; + using OpQueue = proof_system::ECCOpQueue; using GoblinUltraBuilder = proof_system::GoblinUltraCircuitBuilder; - using GoblinUltraComposer = proof_system::honk::GoblinUltraComposer; - using ECCVMFlavor = proof_system::honk::flavor::ECCVM; + using ECCVMFlavor = flavor::ECCVM; using ECCVMBuilder = proof_system::ECCVMCircuitBuilder; - using ECCVMComposer = proof_system::honk::ECCVMComposer_; - using VMOp = proof_system_eccvm::VMOperation; - static constexpr size_t NUM_OP_QUEUE_COLUMNS = proof_system::honk::flavor::GoblinUltra::NUM_WIRES; + using ECCVMComposer = ECCVMComposer_; + using TranslatorFlavor = flavor::GoblinTranslator; + using TranslatorBuilder = proof_system::GoblinTranslatorCircuitBuilder; + using TranslatorComposer = GoblinTranslatorComposer; + using TranslatorConsistencyData = barretenberg::TranslationEvaluations; + + static constexpr size_t NUM_OP_QUEUE_COLUMNS = flavor::GoblinUltra::NUM_WIRES; /** * @brief Generate a simple test circuit with some ECC op gates and conventional arithmetic gates * * @param builder */ - void generate_test_circuit(auto& builder) + static void generate_test_circuit(GoblinUltraBuilder& builder) { // Add some arbitrary ecc op gates for (size_t i = 0; i < 3; ++i) { @@ -50,7 +55,8 @@ class FullGoblinComposerTests : public ::testing::Test { builder.queue_ecc_add_accum(point); builder.queue_ecc_mul_accum(point, scalar); } - builder.queue_ecc_eq(); + // queues the result of the preceding ECC + builder.queue_ecc_eq(); // should be eq and reset // Add some conventional gates that utilize public inputs for (size_t i = 0; i < 10; ++i) { @@ -75,6 +81,8 @@ class FullGoblinComposerTests : public ::testing::Test { * protocol can proceed nominally. The mock data is valid in the sense that it can be processed by all stages of * Goblin as if it came from a genuine circuit. * + * @todo WOKTODO: this is a zero commitments issue + * * @param op_queue */ static void perform_op_queue_interactions_for_mock_first_circuit( @@ -106,7 +114,7 @@ class FullGoblinComposerTests : public ::testing::Test { * @brief Construct and a verify a Honk proof * */ - bool construct_and_verify_honk_proof(auto& composer, auto& builder) + static bool construct_and_verify_honk_proof(GoblinUltraComposer& composer, GoblinUltraBuilder& builder) { auto instance = composer.create_instance(builder); auto prover = composer.create_prover(instance); @@ -121,29 +129,15 @@ class FullGoblinComposerTests : public ::testing::Test { * @brief Construct and verify a Goblin ECC op queue merge proof * */ - bool construct_and_verify_merge_proof(auto& composer, auto& op_queue) + static bool construct_and_verify_merge_proof(GoblinUltraComposer& composer, std::shared_ptr& op_queue) { auto merge_prover = composer.create_merge_prover(op_queue); - auto merge_verifier = composer.create_merge_verifier(10); + auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); auto merge_proof = merge_prover.construct_proof(); bool verified = merge_verifier.verify_proof(merge_proof); return verified; } - - /** - * @brief Construct and verify a Goblin ECC op queue merge proof - * - */ - bool construct_and_verify_eccvm_proof(auto& composer, auto& builder) - { - auto prover = composer.create_prover(builder); - auto proof = prover.construct_proof(); - auto verifier = composer.create_verifier(builder); - bool verified = verifier.verify_proof(proof); - - return verified; - } }; /** @@ -171,69 +165,36 @@ TEST_F(FullGoblinComposerTests, SimpleCircuit) auto composer = GoblinUltraComposer(); // Construct and verify Ultra Goblin Honk proof - auto honk_verified = construct_and_verify_honk_proof(composer, builder); + bool honk_verified = construct_and_verify_honk_proof(composer, builder); EXPECT_TRUE(honk_verified); // Construct and verify op queue merge proof - auto merge_verified = construct_and_verify_merge_proof(composer, op_queue); + bool merge_verified = construct_and_verify_merge_proof(composer, op_queue); EXPECT_TRUE(merge_verified); } - // Construct an ECCVM circuit then generate and verify its proof - { - // Instantiate an ECCVM builder with the vm ops stored in the op queue - auto builder = ECCVMBuilder(op_queue->raw_ops); - - // Construct and verify ECCVM proof - auto composer = ECCVMComposer(); - auto eccvm_verified = construct_and_verify_eccvm_proof(composer, builder); - EXPECT_TRUE(eccvm_verified); - } + // Execute the ECCVM + // TODO(https://github.com/AztecProtocol/barretenberg/issues/785) Properly initialize transcript + auto eccvm_builder = ECCVMBuilder(op_queue); + auto eccvm_composer = ECCVMComposer(); + auto eccvm_prover = eccvm_composer.create_prover(eccvm_builder); + auto eccvm_verifier = eccvm_composer.create_verifier(eccvm_builder); + auto eccvm_proof = eccvm_prover.construct_proof(); + bool eccvm_verified = eccvm_verifier.verify_proof(eccvm_proof); + EXPECT_TRUE(eccvm_verified); + + // Execute the Translator + // TODO(https://github.com/AztecProtocol/barretenberg/issues/786) Properly derive batching_challenge + auto batching_challenge = Fbase::random_element(); + auto evaluation_input = eccvm_prover.evaluation_challenge_x; + auto translator_builder = TranslatorBuilder(batching_challenge, evaluation_input, op_queue); + auto translator_composer = TranslatorComposer(); + auto translator_prover = translator_composer.create_prover(translator_builder); + auto translator_verifier = translator_composer.create_verifier(translator_builder); + auto translator_proof = translator_prover.construct_proof(); + bool accumulator_construction_verified = translator_verifier.verify_proof(translator_proof); + bool translation_verified = translator_verifier.verify_translation(eccvm_prover.translation_evaluations); + EXPECT_TRUE(accumulator_construction_verified && translation_verified); } - -/** - * @brief Check that ECCVM verification fails if ECC op queue operands are tampered with - * - */ -TEST_F(FullGoblinComposerTests, SimpleCircuitFailureCase) -{ - auto op_queue = std::make_shared(); - - // Add mock data to op queue to simulate interaction with a "first" circuit - perform_op_queue_interactions_for_mock_first_circuit(op_queue); - - // Construct a series of simple Goblin circuits; generate and verify their proofs - size_t NUM_CIRCUITS = 3; - for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { - auto builder = GoblinUltraBuilder{ op_queue }; - - generate_test_circuit(builder); - - // The same composer is used to manage Honk and Merge prover/verifier - auto composer = GoblinUltraComposer(); - - // Construct and verify Ultra Goblin Honk proof - auto honk_verified = construct_and_verify_honk_proof(composer, builder); - EXPECT_TRUE(honk_verified); - - // Construct and verify op queue merge proof - auto merge_verified = construct_and_verify_merge_proof(composer, op_queue); - EXPECT_TRUE(merge_verified); - } - - // Construct an ECCVM circuit then generate and verify its proof - { - // Instantiate an ECCVM builder with the vm ops stored in the op queue - auto builder = ECCVMBuilder(op_queue->raw_ops); - - // Fiddle with one of the operands to trigger a failure - builder.vm_operations[0].z1 += 1; - - // Construct and verify ECCVM proof - auto composer = ECCVMComposer(); - auto eccvm_verified = construct_and_verify_eccvm_proof(composer, builder); - EXPECT_FALSE(eccvm_verified); - } -} - +// TODO(https://github.com/AztecProtocol/barretenberg/issues/787) Expand these tests. } // namespace test_full_goblin_composer diff --git a/barretenberg/cpp/src/barretenberg/goblin/translation_evaluations.hpp b/barretenberg/cpp/src/barretenberg/goblin/translation_evaluations.hpp new file mode 100644 index 00000000000..4a0e6d5d835 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/goblin/translation_evaluations.hpp @@ -0,0 +1,8 @@ +#pragma once +#include "barretenberg/ecc/curves/bn254/fq.hpp" + +namespace barretenberg { +struct TranslationEvaluations { + fq op, Px, Py, z1, z2; +}; +} // namespace barretenberg \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp index 0471f818ca6..b4f4573c6f8 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp @@ -1,7 +1,6 @@ #pragma once #include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" #include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/sumcheck/sumcheck.hpp" #include namespace proof_system::honk::permutation_library { @@ -401,4 +400,31 @@ template inline void compute_extra_range_constraint_numerator( parallel_for(num_concatenated_wires + 1, fill_with_shift); } +/** + * @brief Compute odd and even largrange polynomials (up to mini_circuit length) and put them in the polynomial cache + * + * @param key Proving key where we will save the polynomials + */ +template inline void compute_lagrange_polynomials_for_goblin_translator(auto proving_key) + +{ + const size_t n = proving_key->circuit_size; + typename Flavor::Polynomial lagrange_polynomial_odd_in_minicircuit(n); + typename Flavor::Polynomial lagrange_polynomial_even_in_minicircut(n); + typename Flavor::Polynomial lagrange_polynomial_second(n); + typename Flavor::Polynomial lagrange_polynomial_second_to_last_in_minicircuit(n); + + for (size_t i = 1; i < Flavor::MINI_CIRCUIT_SIZE - 1; i += 2) { + lagrange_polynomial_odd_in_minicircuit[i] = 1; + lagrange_polynomial_even_in_minicircut[i + 1] = 1; + } + proving_key->lagrange_odd_in_minicircuit = lagrange_polynomial_odd_in_minicircuit; + + proving_key->lagrange_even_in_minicircuit = lagrange_polynomial_even_in_minicircut; + lagrange_polynomial_second[1] = 1; + lagrange_polynomial_second_to_last_in_minicircuit[Flavor::MINI_CIRCUIT_SIZE - 2] = 1; + proving_key->lagrange_second_to_last_in_minicircuit = lagrange_polynomial_second_to_last_in_minicircuit; + proving_key->lagrange_second = lagrange_polynomial_second; +} + } // namespace proof_system::honk::permutation_library \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp b/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp index 63caded798a..caf74ad39dc 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp @@ -105,8 +105,8 @@ template class Polynomial { return coefficients_.get()[i]; }; - Fr evaluate(const Fr& z, const size_t target_size) const; - Fr evaluate(const Fr& z) const; + [[nodiscard]] Fr evaluate(const Fr& z, const size_t target_size) const; + [[nodiscard]] Fr evaluate(const Fr& z) const; Fr compute_barycentric_evaluation(const Fr& z, const EvaluationDomain& domain) requires polynomial_arithmetic::SupportsFFT; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp index 765d3f0841e..6bee55c0d4c 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp @@ -9,6 +9,7 @@ #include "barretenberg/flavor/ecc_vm.hpp" #include "barretenberg/honk/proof_system/lookup_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" +#include "barretenberg/proof_system/op_queue/ecc_op_queue.hpp" #include "barretenberg/relations/relation_parameters.hpp" namespace proof_system { @@ -36,19 +37,20 @@ template class ECCVMCircuitBuilder { using MSM = proof_system_eccvm::MSM; using VMOperation = proof_system_eccvm::VMOperation; - std::vector vm_operations; + std::shared_ptr op_queue; using ScalarMul = proof_system_eccvm::ScalarMul; using AllPolynomials = typename Flavor::AllPolynomials; - ECCVMCircuitBuilder() = default; + ECCVMCircuitBuilder() + : op_queue(std::make_shared()){}; - ECCVMCircuitBuilder(std::vector vm_operations) - : vm_operations(vm_operations){}; + ECCVMCircuitBuilder(std::shared_ptr& op_queue) + : op_queue(op_queue){}; [[nodiscard]] uint32_t get_number_of_muls() const { uint32_t num_muls = 0; - for (auto& op : vm_operations) { + for (auto& op : op_queue->raw_ops) { if (op.mul) { if (op.z1 != 0) { num_muls++; @@ -144,7 +146,7 @@ template class ECCVMCircuitBuilder { } }; - for (auto& op : vm_operations) { + for (auto& op : op_queue->raw_ops) { if (op.mul) { process_mul(op.z1, op.base_point); process_mul(op.z2, AffineElement{ op.base_point.x * FF::cube_root_of_unity(), -op.base_point.y }); @@ -177,7 +179,7 @@ template class ECCVMCircuitBuilder { void add_accumulate(const AffineElement& to_add) { - vm_operations.emplace_back(VMOperation{ + op_queue->raw_ops.emplace_back(VMOperation{ .add = true, .mul = false, .eq = false, @@ -197,7 +199,7 @@ template class ECCVMCircuitBuilder { CycleScalar::split_into_endomorphism_scalars(converted, z1, z2); z1 = z1.to_montgomery_form(); z2 = z2.to_montgomery_form(); - vm_operations.emplace_back(VMOperation{ + op_queue->raw_ops.emplace_back(VMOperation{ .add = false, .mul = true, .eq = false, @@ -211,7 +213,7 @@ template class ECCVMCircuitBuilder { void eq_and_reset(const AffineElement& expected) { - vm_operations.emplace_back(VMOperation{ + op_queue->raw_ops.emplace_back(VMOperation{ .add = false, .mul = false, .eq = true, @@ -225,7 +227,7 @@ template class ECCVMCircuitBuilder { void empty_row() { - vm_operations.emplace_back(VMOperation{ + op_queue->raw_ops.emplace_back(VMOperation{ .add = false, .mul = false, .eq = false, @@ -322,7 +324,7 @@ template class ECCVMCircuitBuilder { std::array, 2> point_table_read_counts; const auto transcript_state = - ECCVMTranscriptBuilder::compute_transcript_state(vm_operations, get_number_of_muls()); + ECCVMTranscriptBuilder::compute_transcript_state(op_queue->raw_ops, get_number_of_muls()); const auto precompute_table_state = ECCVMPrecomputedTablesBuilder::compute_precompute_state(flattened_muls); const auto msm_state = @@ -575,7 +577,7 @@ template class ECCVMCircuitBuilder { std::array, 2> point_table_read_counts; const auto transcript_state = - ECCVMTranscriptBuilder::compute_transcript_state(vm_operations, get_number_of_muls()); + ECCVMTranscriptBuilder::compute_transcript_state(op_queue->raw_ops, get_number_of_muls()); const auto precompute_table_state = ECCVMPrecomputedTablesBuilder::compute_precompute_state(flattened_muls); const auto msm_state = diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.cpp index 9384ef1f86d..ee95fd30105 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.cpp @@ -599,12 +599,12 @@ GoblinTranslatorCircuitBuilder::AccumulationInput compute_witness_values_for_one batching_challenge_v, evaluation_input_x); } -void GoblinTranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(ECCOpQueue& ecc_op_queue) +void GoblinTranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(std::shared_ptr ecc_op_queue) { using Fq = barretenberg::fq; std::vector accumulator_trace; Fq current_accumulator(0); - if (ecc_op_queue.raw_ops.empty()) { + if (ecc_op_queue->raw_ops.empty()) { return; } // Rename for ease of use @@ -613,8 +613,8 @@ void GoblinTranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(ECCOpQueue& // We need to precompute the accumulators at each step, because in the actual circuit we compute the values starting // from the later indices. We need to know the previous accumulator to create the gate - for (size_t i = 0; i < ecc_op_queue.raw_ops.size(); i++) { - auto& ecc_op = ecc_op_queue.raw_ops[ecc_op_queue.raw_ops.size() - 1 - i]; + for (size_t i = 0; i < ecc_op_queue->raw_ops.size(); i++) { + auto& ecc_op = ecc_op_queue->raw_ops[ecc_op_queue->raw_ops.size() - 1 - i]; current_accumulator *= x; current_accumulator += (Fq(ecc_op.get_opcode_value()) + @@ -625,7 +625,7 @@ void GoblinTranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(ECCOpQueue& // We don't care about the last value since we'll recompute it during witness generation anyway accumulator_trace.pop_back(); - for (auto& raw_op : ecc_op_queue.raw_ops) { + for (auto& raw_op : ecc_op_queue->raw_ops) { Fq previous_accumulator = 0; // Pop the last value from accumulator trace and use it as previous accumulator if (!accumulator_trace.empty()) { diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp index 2235a934345..92164873e44 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp @@ -94,7 +94,6 @@ class GoblinTranslatorCircuitBuilder : public CircuitBuilderBase op_queue) : GoblinTranslatorCircuitBuilder(batching_challenge_v_, evaluation_input_x_) { feed_ecc_op_queue_into_circuit(op_queue); @@ -447,7 +448,7 @@ class GoblinTranslatorCircuitBuilder : public CircuitBuilderBase ecc_op_queue); /** * @brief Check the witness satisifies the circuit diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.test.cpp index 6c3b10b33c4..cd019284069 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.test.cpp @@ -87,9 +87,9 @@ TEST(GoblinTranslatorCircuitBuilder, SeveralOperationCorrectness) auto z = scalar::random_element(); // Add the same operations to the ECC op queue; the native computation is performed under the hood. - ECCOpQueue op_queue; - op_queue.add_accumulate(P1); - op_queue.mul_accumulate(P2, z); + auto op_queue = std::make_shared(); + op_queue->add_accumulate(P1); + op_queue->mul_accumulate(P2, z); Fq op_accumulator = 0; Fq p_x_accumulator = 0; Fq p_y_accumulator = 0; @@ -97,22 +97,22 @@ TEST(GoblinTranslatorCircuitBuilder, SeveralOperationCorrectness) Fq z_2_accumulator = 0; Fq batching_challenge = fq::random_element(); - op_queue.eq(); - op_queue.empty_row(); + op_queue->eq(); + op_queue->empty_row(); // Sample the evaluation input x Fq x = Fq::random_element(); // Get an inverse Fq x_inv = x.invert(); // Compute the batched evaluation of polynomials (multiplying by inverse to go from lower to higher) - for (auto& ecc_op : op_queue.raw_ops) { + for (auto& ecc_op : op_queue->raw_ops) { op_accumulator = op_accumulator * x_inv + ecc_op.get_opcode_value(); p_x_accumulator = p_x_accumulator * x_inv + ecc_op.base_point.x; p_y_accumulator = p_y_accumulator * x_inv + ecc_op.base_point.y; z_1_accumulator = z_1_accumulator * x_inv + ecc_op.z1; z_2_accumulator = z_2_accumulator * x_inv + ecc_op.z2; } - Fq x_pow = x.pow(op_queue.raw_ops.size() - 1); + Fq x_pow = x.pow(op_queue->raw_ops.size() - 1); // Multiply by an appropriate power of x to get rid of the inverses Fq result = ((((z_2_accumulator * batching_challenge + z_1_accumulator) * batching_challenge + p_y_accumulator) * diff --git a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.cpp b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.cpp index b3cae2f8e6b..1daf3469bc7 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.cpp +++ b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.cpp @@ -29,7 +29,6 @@ void ECCVMLookupRelationImpl::accumulate(ContainerOverSubrelations& accumula accumulator, in, params, scaling_factor); } -template class ECCVMLookupRelationImpl; template class ECCVMLookupRelationImpl; DEFINE_SUMCHECK_RELATION_CLASS(ECCVMLookupRelationImpl, flavor::ECCVM); diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.hpp b/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.hpp index 3a925e2ccf9..e165c15c671 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.hpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.hpp @@ -42,7 +42,7 @@ template class FileProverCrs : public ProverCrs { typename Curve::AffineElement* get_monomial_points() { return monomials_.get(); } - size_t get_monomial_size() const { return num_points; } + [[nodiscard]] size_t get_monomial_size() const { return num_points; } private: size_t num_points; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index c8d1ecaeca0..eb98b7898a7 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -1,9 +1,5 @@ #pragma once -#include "barretenberg/common/serialize.hpp" -#include "barretenberg/common/throw_or_abort.hpp" -#include "barretenberg/polynomials/univariate.hpp" #include "barretenberg/proof_system/library/grand_product_delta.hpp" -#include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/sumcheck/instance/prover_instance.hpp" #include "barretenberg/sumcheck/sumcheck_output.hpp" #include "barretenberg/transcript/transcript.hpp" diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index b25956c9f27..66ceeedcf52 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -1,9 +1,7 @@ #pragma once -#include "barretenberg/common/log.hpp" #include "barretenberg/common/thread.hpp" #include "barretenberg/common/thread_utils.hpp" #include "barretenberg/flavor/flavor.hpp" -#include "barretenberg/polynomials/barycentric.hpp" #include "barretenberg/polynomials/pow.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/relations/relation_types.hpp" diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/translator_vm/CMakeLists.txt new file mode 100644 index 00000000000..c5740c436fc --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/translator_vm/CMakeLists.txt @@ -0,0 +1 @@ +barretenberg_module(translator_vm honk sumcheck) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.cpp new file mode 100644 index 00000000000..7ecf87adaf5 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.cpp @@ -0,0 +1,312 @@ +/** + * @file goblin_translator_composer.cpp + * @brief Contains the logic for transfroming a Goblin Translator Circuit Builder object into a witness and methods to + * create prover and verifier objects + * @date 2023-10-05 + */ +#include "goblin_translator_composer.hpp" +#include "barretenberg/flavor/goblin_translator.hpp" +#include "barretenberg/honk/proof_system/permutation_library.hpp" +#include "barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp" +#include "barretenberg/proof_system/composer/composer_lib.hpp" +#include "barretenberg/proof_system/composer/permutation_lib.hpp" + +namespace proof_system::honk { +using Flavor = honk::flavor::GoblinTranslator; +using Curve = typename Flavor::Curve; +using CircuitBuilder = typename Flavor::CircuitBuilder; +using ProvingKey = typename Flavor::ProvingKey; +using VerificationKey = typename Flavor::VerificationKey; +using PCS = typename Flavor::PCS; +using CommitmentKey = typename Flavor::CommitmentKey; +using VerifierCommitmentKey = typename Flavor::VerifierCommitmentKey; +using Polynomial = typename Flavor::Polynomial; + +/** + * @brief Helper method to compute quantities like total number of gates and dyadic circuit size + * + * @tparam Flavor + * @param circuit_builder + */ + +void GoblinTranslatorComposer::compute_circuit_size_parameters(CircuitBuilder& circuit_builder) +{ + const size_t num_gates = circuit_builder.num_gates; + + // number of populated rows in the execution trace + size_t num_rows_populated_in_execution_trace = num_gates; + + // Goblin translator circuits always have a predefined size and are structured as a VM (no concept of selectors) + ASSERT(MINI_CIRCUIT_SIZE >= num_rows_populated_in_execution_trace); + + total_num_gates = std::max(MINI_CIRCUIT_SIZE, num_rows_populated_in_execution_trace); + + // Next power of 2 + mini_circuit_dyadic_size = circuit_builder.get_circuit_subgroup_size(total_num_gates); + + // The actual circuit size is several times bigger than the trace in the builder, because we use concatenation to + // bring the degree of relations down, while extending the length. + dyadic_circuit_size = mini_circuit_dyadic_size * Flavor::CONCATENATION_INDEX; +} + +/** + * @brief Construct the witness polynomials from the witness vectors in the circuit constructor. + * + * @details In goblin translator wires come as is, since they have to reflect the structure of polynomials in the first + * 4 wires, which we've commited to + * + * @tparam Flavor provides the circuit constructor type and the number of wires. + * @param circuit_builder + * @param dyadic_circuit_size Power of 2 circuit size + * @todo TODO(https://github.com/AztecProtocol/barretenberg/issues/783) Optimize memory operations. + * @return std::vector + * */ + +std::vector construct_wire_polynomials_base_goblin_translator(const CircuitBuilder& circuit_builder, + const size_t dyadic_circuit_size) +{ + const size_t num_gates = circuit_builder.num_gates; + + std::vector wire_polynomials; + // Populate the wire polynomials with values from conventional wires + for (size_t wire_idx = 0; wire_idx < Flavor::NUM_WIRES; ++wire_idx) { + // Expect all values to be set to 0 initially + Polynomial w_lagrange(dyadic_circuit_size); + + // Insert conventional gate wire values into the wire polynomial + for (size_t i = 0; i < num_gates; ++i) { + auto& wire = circuit_builder.wires[wire_idx]; + w_lagrange[i] = circuit_builder.get_variable(wire[i]); + } + + wire_polynomials.push_back(std::move(w_lagrange)); + } + return wire_polynomials; +} + +/** + * @brief Compute witness polynomials + * + */ +void GoblinTranslatorComposer::compute_witness(CircuitBuilder& circuit_builder) +{ + if (computed_witness) { + return; + } + + // Construct the conventional wire polynomials + auto wire_polynomials = construct_wire_polynomials_base_goblin_translator(circuit_builder, dyadic_circuit_size); + + // Most of the witness polynomials are the original wire polynomials + proving_key->op = wire_polynomials[0]; + proving_key->x_lo_y_hi = wire_polynomials[1]; + proving_key->x_hi_z_1 = wire_polynomials[2]; + proving_key->y_lo_z_2 = wire_polynomials[3]; + proving_key->p_x_low_limbs = wire_polynomials[4]; + proving_key->p_x_low_limbs_range_constraint_0 = wire_polynomials[5]; + proving_key->p_x_low_limbs_range_constraint_1 = wire_polynomials[6]; + proving_key->p_x_low_limbs_range_constraint_2 = wire_polynomials[7]; + proving_key->p_x_low_limbs_range_constraint_3 = wire_polynomials[8]; + proving_key->p_x_low_limbs_range_constraint_4 = wire_polynomials[9]; + proving_key->p_x_low_limbs_range_constraint_tail = wire_polynomials[10]; + proving_key->p_x_high_limbs = wire_polynomials[11]; + proving_key->p_x_high_limbs_range_constraint_0 = wire_polynomials[12]; + proving_key->p_x_high_limbs_range_constraint_1 = wire_polynomials[13]; + proving_key->p_x_high_limbs_range_constraint_2 = wire_polynomials[14]; + proving_key->p_x_high_limbs_range_constraint_3 = wire_polynomials[15]; + proving_key->p_x_high_limbs_range_constraint_4 = wire_polynomials[16]; + proving_key->p_x_high_limbs_range_constraint_tail = wire_polynomials[17]; + proving_key->p_y_low_limbs = wire_polynomials[18]; + proving_key->p_y_low_limbs_range_constraint_0 = wire_polynomials[19]; + proving_key->p_y_low_limbs_range_constraint_1 = wire_polynomials[20]; + proving_key->p_y_low_limbs_range_constraint_2 = wire_polynomials[21]; + proving_key->p_y_low_limbs_range_constraint_3 = wire_polynomials[22]; + proving_key->p_y_low_limbs_range_constraint_4 = wire_polynomials[23]; + proving_key->p_y_low_limbs_range_constraint_tail = wire_polynomials[24]; + proving_key->p_y_high_limbs = wire_polynomials[25]; + proving_key->p_y_high_limbs_range_constraint_0 = wire_polynomials[26]; + proving_key->p_y_high_limbs_range_constraint_1 = wire_polynomials[27]; + proving_key->p_y_high_limbs_range_constraint_2 = wire_polynomials[28]; + proving_key->p_y_high_limbs_range_constraint_3 = wire_polynomials[29]; + proving_key->p_y_high_limbs_range_constraint_4 = wire_polynomials[30]; + proving_key->p_y_high_limbs_range_constraint_tail = wire_polynomials[31]; + proving_key->z_low_limbs = wire_polynomials[32]; + proving_key->z_low_limbs_range_constraint_0 = wire_polynomials[33]; + proving_key->z_low_limbs_range_constraint_1 = wire_polynomials[34]; + proving_key->z_low_limbs_range_constraint_2 = wire_polynomials[35]; + proving_key->z_low_limbs_range_constraint_3 = wire_polynomials[36]; + proving_key->z_low_limbs_range_constraint_4 = wire_polynomials[37]; + proving_key->z_low_limbs_range_constraint_tail = wire_polynomials[38]; + proving_key->z_high_limbs = wire_polynomials[39]; + proving_key->z_high_limbs_range_constraint_0 = wire_polynomials[40]; + proving_key->z_high_limbs_range_constraint_1 = wire_polynomials[41]; + proving_key->z_high_limbs_range_constraint_2 = wire_polynomials[42]; + proving_key->z_high_limbs_range_constraint_3 = wire_polynomials[43]; + proving_key->z_high_limbs_range_constraint_4 = wire_polynomials[44]; + proving_key->z_high_limbs_range_constraint_tail = wire_polynomials[45]; + proving_key->accumulators_binary_limbs_0 = wire_polynomials[46]; + proving_key->accumulators_binary_limbs_1 = wire_polynomials[47]; + proving_key->accumulators_binary_limbs_2 = wire_polynomials[48]; + proving_key->accumulators_binary_limbs_3 = wire_polynomials[49]; + proving_key->accumulator_low_limbs_range_constraint_0 = wire_polynomials[50]; + proving_key->accumulator_low_limbs_range_constraint_1 = wire_polynomials[51]; + proving_key->accumulator_low_limbs_range_constraint_2 = wire_polynomials[52]; + proving_key->accumulator_low_limbs_range_constraint_3 = wire_polynomials[53]; + proving_key->accumulator_low_limbs_range_constraint_4 = wire_polynomials[54]; + proving_key->accumulator_low_limbs_range_constraint_tail = wire_polynomials[55]; + proving_key->accumulator_high_limbs_range_constraint_0 = wire_polynomials[56]; + proving_key->accumulator_high_limbs_range_constraint_1 = wire_polynomials[57]; + proving_key->accumulator_high_limbs_range_constraint_2 = wire_polynomials[58]; + proving_key->accumulator_high_limbs_range_constraint_3 = wire_polynomials[59]; + proving_key->accumulator_high_limbs_range_constraint_4 = wire_polynomials[60]; + proving_key->accumulator_high_limbs_range_constraint_tail = wire_polynomials[61]; + proving_key->quotient_low_binary_limbs = wire_polynomials[62]; + proving_key->quotient_high_binary_limbs = wire_polynomials[63]; + proving_key->quotient_low_limbs_range_constraint_0 = wire_polynomials[64]; + proving_key->quotient_low_limbs_range_constraint_1 = wire_polynomials[65]; + proving_key->quotient_low_limbs_range_constraint_2 = wire_polynomials[66]; + proving_key->quotient_low_limbs_range_constraint_3 = wire_polynomials[67]; + proving_key->quotient_low_limbs_range_constraint_4 = wire_polynomials[68]; + proving_key->quotient_low_limbs_range_constraint_tail = wire_polynomials[69]; + proving_key->quotient_high_limbs_range_constraint_0 = wire_polynomials[70]; + proving_key->quotient_high_limbs_range_constraint_1 = wire_polynomials[71]; + proving_key->quotient_high_limbs_range_constraint_2 = wire_polynomials[72]; + proving_key->quotient_high_limbs_range_constraint_3 = wire_polynomials[73]; + proving_key->quotient_high_limbs_range_constraint_4 = wire_polynomials[74]; + proving_key->quotient_high_limbs_range_constraint_tail = wire_polynomials[75]; + proving_key->relation_wide_limbs = wire_polynomials[76]; + proving_key->relation_wide_limbs_range_constraint_0 = wire_polynomials[77]; + proving_key->relation_wide_limbs_range_constraint_1 = wire_polynomials[78]; + proving_key->relation_wide_limbs_range_constraint_2 = wire_polynomials[79]; + proving_key->relation_wide_limbs_range_constraint_3 = wire_polynomials[80]; + + // We construct concatenated versions of range constraint polynomials, where several polynomials are concatenated + // into one. These polynomials are not commited to. + proof_system::honk::permutation_library::compute_concatenated_polynomials(proving_key.get()); + + // We also contruct ordered polynomials, which have the same values as concatenated ones + enough values to bridge + // the range from 0 to maximum range defined by the range constraint. + proof_system::honk::permutation_library::compute_goblin_translator_range_constraint_ordered_polynomials( + proving_key.get()); + + computed_witness = true; +} + +/** + * @brief Create a prover object (used to create the proof) + * + * @tparam Flavor + * @param circuit_builder + * @return GoblinTranslatorProver + */ + +GoblinTranslatorProver GoblinTranslatorComposer::create_prover(CircuitBuilder& circuit_builder) +{ + + // Compute total number of gates, dyadic circuit size, etc. + compute_circuit_size_parameters(circuit_builder); + + // Compute non-witness polynomials + compute_proving_key(circuit_builder); + + compute_witness(circuit_builder); + + compute_commitment_key(proving_key->circuit_size); + + GoblinTranslatorProver output_state(proving_key, commitment_key); + + return output_state; +} + +/** + * @brief Create verifier: compute verification key, + * initialize verifier with it and an initial manifest and initialize commitment_scheme. + * + * @tparam Flavor + * @param circuit_builder + * @return GoblinTranslatorVerifier + */ + +GoblinTranslatorVerifier GoblinTranslatorComposer::create_verifier(const CircuitBuilder& circuit_builder) +{ + auto verification_key = compute_verification_key(circuit_builder); + + GoblinTranslatorVerifier output_state(verification_key); + + auto pcs_verification_key = std::make_unique(verification_key->circuit_size, crs_factory_); + output_state.pcs_verification_key = std::move(pcs_verification_key); + + return output_state; +} + +/** + * @brief Move goblin translator specific inputs from circuit builder and compute all the constant polynomials used by + * the prover + * + * @tparam Flavor + * @param circuit_builder + * @return std::shared_ptr + */ + +std::shared_ptr GoblinTranslatorComposer::compute_proving_key( + const CircuitBuilder& circuit_builder) +{ + if (proving_key) { + return proving_key; + } + + proving_key = std::make_shared(dyadic_circuit_size); + + // The input/challenge that we are evaluating all polynomials at + proving_key->evaluation_input_x = circuit_builder.evaluation_input_x; + + // The challenge for batching polynomials + proving_key->batching_challenge_v = circuit_builder.batching_challenge_v; + + // First and last lagrange polynomials (in the full circuit size) + compute_first_and_last_lagrange_polynomials(proving_key.get()); + + // Compute polynomials with odd and even indices set to 1 up to the minicircuit margin + lagrange polynomials at + // second and second to last indices in the minicircuit + proof_system::honk::permutation_library::compute_lagrange_polynomials_for_goblin_translator( + proving_key.get()); + + // Compute the numerator for the permutation argument with several repetitions of steps bridging 0 and maximum range + // constraint + proof_system::honk::permutation_library::compute_extra_range_constraint_numerator(proving_key.get()); + + return proving_key; +} + +/** + * Compute verification key consisting of non-changing polynomials' precommitments. + * + * @return Pointer to created circuit verification key. + * */ + +std::shared_ptr GoblinTranslatorComposer::compute_verification_key( + const CircuitBuilder& circuit_builder) +{ + if (verification_key) { + return verification_key; + } + + if (!proving_key) { + compute_proving_key(circuit_builder); + } + + verification_key = std::make_shared(proving_key->circuit_size, proving_key->num_public_inputs); + + verification_key->lagrange_first = commitment_key->commit(proving_key->lagrange_first); + verification_key->lagrange_last = commitment_key->commit(proving_key->lagrange_last); + verification_key->lagrange_odd_in_minicircuit = commitment_key->commit(proving_key->lagrange_odd_in_minicircuit); + verification_key->lagrange_even_in_minicircuit = commitment_key->commit(proving_key->lagrange_even_in_minicircuit); + verification_key->lagrange_second = commitment_key->commit(proving_key->lagrange_second); + verification_key->lagrange_second_to_last_in_minicircuit = + commitment_key->commit(proving_key->lagrange_second_to_last_in_minicircuit); + verification_key->ordered_extra_range_constraints_numerator = + commitment_key->commit(proving_key->ordered_extra_range_constraints_numerator); + + return verification_key; +} +} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.hpp new file mode 100644 index 00000000000..749151b3ebe --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include "barretenberg/flavor/goblin_translator.hpp" +#include "barretenberg/proof_system/composer/composer_lib.hpp" +#include "barretenberg/srs/factories/file_crs_factory.hpp" +#include "barretenberg/srs/global_crs.hpp" +#include "barretenberg/translator_vm/goblin_translator_prover.hpp" +#include "barretenberg/translator_vm/goblin_translator_verifier.hpp" + +namespace proof_system::honk { +class GoblinTranslatorComposer { + public: + using Flavor = honk::flavor::GoblinTranslator; + using Curve = typename Flavor::Curve; + using CircuitBuilder = typename Flavor::CircuitBuilder; + using ProvingKey = typename Flavor::ProvingKey; + using VerificationKey = typename Flavor::VerificationKey; + using PCS = typename Flavor::PCS; + using CommitmentKey = typename Flavor::CommitmentKey; + using VerifierCommitmentKey = typename Flavor::VerifierCommitmentKey; + using Polynomial = typename Flavor::Polynomial; + static constexpr size_t MINI_CIRCUIT_SIZE = Flavor::MINI_CIRCUIT_SIZE; + + static constexpr std::string_view NAME_STRING = "GoblinTranslator"; + static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES; + std::shared_ptr proving_key; + std::shared_ptr verification_key; + + // The crs_factory holds the path to the srs and exposes methods to extract the srs elements + std::shared_ptr> crs_factory_; + + // The commitment key is passed to the prover but also used herein to compute the verfication key commitments + std::shared_ptr commitment_key; + + bool computed_witness = false; + size_t total_num_gates = 0; // num_gates (already include zero row offset) (used to compute dyadic size) + size_t dyadic_circuit_size = 0; // final power-of-2 circuit size + size_t mini_circuit_dyadic_size = 0; // The size of the small circuit that contains non-range constraint relations + + // We only need the standard crs factory. GoblinTranslator is not supposed to be used with Grumpkin + GoblinTranslatorComposer() { crs_factory_ = barretenberg::srs::get_crs_factory(); } + + GoblinTranslatorComposer(std::shared_ptr p_key, std::shared_ptr v_key) + : proving_key(std::move(p_key)) + , verification_key(std::move(v_key)) + {} + + std::shared_ptr compute_proving_key(const CircuitBuilder& circuit_builder); + std::shared_ptr compute_verification_key(const CircuitBuilder& circuit_builder); + + void compute_circuit_size_parameters(CircuitBuilder& circuit_builder); + + void compute_witness(CircuitBuilder& circuit_builder); + + GoblinTranslatorProver create_prover(CircuitBuilder& circuit_builder); + GoblinTranslatorVerifier create_verifier(const CircuitBuilder& circuit_builder); + + std::shared_ptr compute_commitment_key(size_t circuit_size) + { + if (commitment_key) { + return commitment_key; + } + + commitment_key = std::make_shared(circuit_size, crs_factory_); + return commitment_key; + }; +}; +} // namespace proof_system::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.test.cpp new file mode 100644 index 00000000000..ed7c1274d5e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.test.cpp @@ -0,0 +1,81 @@ +#include "barretenberg/translator_vm/goblin_translator_composer.hpp" +#include "barretenberg/common/log.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp" +#include "barretenberg/relations/relation_parameters.hpp" +#include "barretenberg/sumcheck/sumcheck_round.hpp" +#include "barretenberg/translator_vm/goblin_translator_prover.hpp" + +#include + +using namespace proof_system::honk; + +namespace test_goblin_translator_composer { + +namespace { +auto& engine = numeric::random::get_debug_engine(); +} + +std::vector add_variables(auto& circuit_constructor, std::vector variables) +{ + std::vector res; + for (size_t i = 0; i < variables.size(); i++) { + res.emplace_back(circuit_constructor.add_variable(variables[i])); + } + return res; +} + +void prove_and_verify(auto& circuit_constructor, auto& composer, bool expected_result) +{ + auto prover = composer.create_prover(circuit_constructor); + auto verifier = composer.create_verifier(circuit_constructor); + auto proof = prover.construct_proof(); + bool verified = verifier.verify_proof(proof); + EXPECT_EQ(verified, expected_result); +}; + +void ensure_non_zero(auto& polynomial) +{ + bool has_non_zero_coefficient = false; + for (auto& coeff : polynomial) { + has_non_zero_coefficient |= !coeff.is_zero(); + } + ASSERT_TRUE(has_non_zero_coefficient); +} + +class GoblinTranslatorComposerTests : public ::testing::Test { + protected: + static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../srs_db/ignition"); } +}; + +/** + * @brief Test simple circuit with public inputs + * + */ +TEST_F(GoblinTranslatorComposerTests, Basic) +{ + using point = barretenberg::g1::affine_element; + using scalar = barretenberg::fr; + using Fq = barretenberg::fq; + + auto P1 = point::random_element(); + auto P2 = point::random_element(); + auto z = scalar::random_element(); + + // Add the same operations to the ECC op queue; the native computation is performed under the hood. + auto op_queue = std::make_shared(); + for (size_t i = 0; i < 500; i++) { + op_queue->add_accumulate(P1); + op_queue->mul_accumulate(P2, z); + } + Fq batching_challenge = Fq::random_element(); + Fq x = Fq::random_element(); + auto circuit_builder = proof_system::GoblinTranslatorCircuitBuilder(batching_challenge, x); + circuit_builder.feed_ecc_op_queue_into_circuit(op_queue); + EXPECT_TRUE(circuit_builder.check_circuit()); + + auto composer = GoblinTranslatorComposer(); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); +} + +} // namespace test_goblin_translator_composer diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.cpp new file mode 100644 index 00000000000..5ad81ecb1cb --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.cpp @@ -0,0 +1,385 @@ +#include "goblin_translator_prover.hpp" +#include "barretenberg/commitment_schemes/claim.hpp" +#include "barretenberg/commitment_schemes/commitment_key.hpp" +#include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" +#include "barretenberg/honk/proof_system/power_polynomial.hpp" +#include "barretenberg/proof_system/library/grand_product_library.hpp" +#include "barretenberg/sumcheck/sumcheck.hpp" + +namespace proof_system::honk { + +/** + * Create GoblinTranslatorProver from proving key, witness and manifest. + * + * @param input_key Proving key. + * @param input_manifest Input manifest + * + * @tparam settings Settings class. + * */ + +GoblinTranslatorProver::GoblinTranslatorProver(std::shared_ptr input_key, + std::shared_ptr commitment_key) + : key(input_key) + , commitment_key(commitment_key) +{ + // Copy all polynomials from the proving key + prover_polynomials.op = key->op; + prover_polynomials.x_lo_y_hi = key->x_lo_y_hi; + prover_polynomials.x_hi_z_1 = key->x_hi_z_1; + prover_polynomials.y_lo_z_2 = key->y_lo_z_2; + prover_polynomials.p_x_low_limbs = key->p_x_low_limbs; + prover_polynomials.p_x_low_limbs_range_constraint_0 = key->p_x_low_limbs_range_constraint_0; + prover_polynomials.p_x_low_limbs_range_constraint_1 = key->p_x_low_limbs_range_constraint_1; + prover_polynomials.p_x_low_limbs_range_constraint_2 = key->p_x_low_limbs_range_constraint_2; + prover_polynomials.p_x_low_limbs_range_constraint_3 = key->p_x_low_limbs_range_constraint_3; + prover_polynomials.p_x_low_limbs_range_constraint_4 = key->p_x_low_limbs_range_constraint_4; + prover_polynomials.p_x_low_limbs_range_constraint_tail = key->p_x_low_limbs_range_constraint_tail; + prover_polynomials.p_x_high_limbs = key->p_x_high_limbs; + prover_polynomials.p_x_high_limbs_range_constraint_0 = key->p_x_high_limbs_range_constraint_0; + prover_polynomials.p_x_high_limbs_range_constraint_1 = key->p_x_high_limbs_range_constraint_1; + prover_polynomials.p_x_high_limbs_range_constraint_2 = key->p_x_high_limbs_range_constraint_2; + prover_polynomials.p_x_high_limbs_range_constraint_3 = key->p_x_high_limbs_range_constraint_3; + prover_polynomials.p_x_high_limbs_range_constraint_4 = key->p_x_high_limbs_range_constraint_4; + prover_polynomials.p_x_high_limbs_range_constraint_tail = key->p_x_high_limbs_range_constraint_tail; + prover_polynomials.p_y_low_limbs = key->p_y_low_limbs; + prover_polynomials.p_y_low_limbs_range_constraint_0 = key->p_y_low_limbs_range_constraint_0; + prover_polynomials.p_y_low_limbs_range_constraint_1 = key->p_y_low_limbs_range_constraint_1; + prover_polynomials.p_y_low_limbs_range_constraint_2 = key->p_y_low_limbs_range_constraint_2; + prover_polynomials.p_y_low_limbs_range_constraint_3 = key->p_y_low_limbs_range_constraint_3; + prover_polynomials.p_y_low_limbs_range_constraint_4 = key->p_y_low_limbs_range_constraint_4; + prover_polynomials.p_y_low_limbs_range_constraint_tail = key->p_y_low_limbs_range_constraint_tail; + prover_polynomials.p_y_high_limbs = key->p_y_high_limbs; + prover_polynomials.p_y_high_limbs_range_constraint_0 = key->p_y_high_limbs_range_constraint_0; + prover_polynomials.p_y_high_limbs_range_constraint_1 = key->p_y_high_limbs_range_constraint_1; + prover_polynomials.p_y_high_limbs_range_constraint_2 = key->p_y_high_limbs_range_constraint_2; + prover_polynomials.p_y_high_limbs_range_constraint_3 = key->p_y_high_limbs_range_constraint_3; + prover_polynomials.p_y_high_limbs_range_constraint_4 = key->p_y_high_limbs_range_constraint_4; + prover_polynomials.p_y_high_limbs_range_constraint_tail = key->p_y_high_limbs_range_constraint_tail; + prover_polynomials.z_low_limbs = key->z_low_limbs; + prover_polynomials.z_low_limbs_range_constraint_0 = key->z_low_limbs_range_constraint_0; + prover_polynomials.z_low_limbs_range_constraint_1 = key->z_low_limbs_range_constraint_1; + prover_polynomials.z_low_limbs_range_constraint_2 = key->z_low_limbs_range_constraint_2; + prover_polynomials.z_low_limbs_range_constraint_3 = key->z_low_limbs_range_constraint_3; + prover_polynomials.z_low_limbs_range_constraint_4 = key->z_low_limbs_range_constraint_4; + prover_polynomials.z_low_limbs_range_constraint_tail = key->z_low_limbs_range_constraint_tail; + prover_polynomials.z_high_limbs = key->z_high_limbs; + prover_polynomials.z_high_limbs_range_constraint_0 = key->z_high_limbs_range_constraint_0; + prover_polynomials.z_high_limbs_range_constraint_1 = key->z_high_limbs_range_constraint_1; + prover_polynomials.z_high_limbs_range_constraint_2 = key->z_high_limbs_range_constraint_2; + prover_polynomials.z_high_limbs_range_constraint_3 = key->z_high_limbs_range_constraint_3; + prover_polynomials.z_high_limbs_range_constraint_4 = key->z_high_limbs_range_constraint_4; + prover_polynomials.z_high_limbs_range_constraint_tail = key->z_high_limbs_range_constraint_tail; + prover_polynomials.accumulators_binary_limbs_0 = key->accumulators_binary_limbs_0; + prover_polynomials.accumulators_binary_limbs_1 = key->accumulators_binary_limbs_1; + prover_polynomials.accumulators_binary_limbs_2 = key->accumulators_binary_limbs_2; + prover_polynomials.accumulators_binary_limbs_3 = key->accumulators_binary_limbs_3; + prover_polynomials.accumulator_low_limbs_range_constraint_0 = key->accumulator_low_limbs_range_constraint_0; + prover_polynomials.accumulator_low_limbs_range_constraint_1 = key->accumulator_low_limbs_range_constraint_1; + prover_polynomials.accumulator_low_limbs_range_constraint_2 = key->accumulator_low_limbs_range_constraint_2; + prover_polynomials.accumulator_low_limbs_range_constraint_3 = key->accumulator_low_limbs_range_constraint_3; + prover_polynomials.accumulator_low_limbs_range_constraint_4 = key->accumulator_low_limbs_range_constraint_4; + prover_polynomials.accumulator_low_limbs_range_constraint_tail = key->accumulator_low_limbs_range_constraint_tail; + prover_polynomials.accumulator_high_limbs_range_constraint_0 = key->accumulator_high_limbs_range_constraint_0; + prover_polynomials.accumulator_high_limbs_range_constraint_1 = key->accumulator_high_limbs_range_constraint_1; + prover_polynomials.accumulator_high_limbs_range_constraint_2 = key->accumulator_high_limbs_range_constraint_2; + prover_polynomials.accumulator_high_limbs_range_constraint_3 = key->accumulator_high_limbs_range_constraint_3; + prover_polynomials.accumulator_high_limbs_range_constraint_4 = key->accumulator_high_limbs_range_constraint_4; + prover_polynomials.accumulator_high_limbs_range_constraint_tail = key->accumulator_high_limbs_range_constraint_tail; + prover_polynomials.quotient_low_binary_limbs = key->quotient_low_binary_limbs; + prover_polynomials.quotient_high_binary_limbs = key->quotient_high_binary_limbs; + prover_polynomials.quotient_low_limbs_range_constraint_0 = key->quotient_low_limbs_range_constraint_0; + prover_polynomials.quotient_low_limbs_range_constraint_1 = key->quotient_low_limbs_range_constraint_1; + prover_polynomials.quotient_low_limbs_range_constraint_2 = key->quotient_low_limbs_range_constraint_2; + prover_polynomials.quotient_low_limbs_range_constraint_3 = key->quotient_low_limbs_range_constraint_3; + prover_polynomials.quotient_low_limbs_range_constraint_4 = key->quotient_low_limbs_range_constraint_4; + prover_polynomials.quotient_low_limbs_range_constraint_tail = key->quotient_low_limbs_range_constraint_tail; + prover_polynomials.quotient_high_limbs_range_constraint_0 = key->quotient_high_limbs_range_constraint_0; + prover_polynomials.quotient_high_limbs_range_constraint_1 = key->quotient_high_limbs_range_constraint_1; + prover_polynomials.quotient_high_limbs_range_constraint_2 = key->quotient_high_limbs_range_constraint_2; + prover_polynomials.quotient_high_limbs_range_constraint_3 = key->quotient_high_limbs_range_constraint_3; + prover_polynomials.quotient_high_limbs_range_constraint_4 = key->quotient_high_limbs_range_constraint_4; + prover_polynomials.quotient_high_limbs_range_constraint_tail = key->quotient_high_limbs_range_constraint_tail; + prover_polynomials.relation_wide_limbs = key->relation_wide_limbs; + prover_polynomials.relation_wide_limbs_range_constraint_0 = key->relation_wide_limbs_range_constraint_0; + prover_polynomials.relation_wide_limbs_range_constraint_1 = key->relation_wide_limbs_range_constraint_1; + prover_polynomials.relation_wide_limbs_range_constraint_2 = key->relation_wide_limbs_range_constraint_2; + prover_polynomials.relation_wide_limbs_range_constraint_3 = key->relation_wide_limbs_range_constraint_3; + prover_polynomials.concatenated_range_constraints_0 = key->concatenated_range_constraints_0; + prover_polynomials.concatenated_range_constraints_1 = key->concatenated_range_constraints_1; + prover_polynomials.concatenated_range_constraints_2 = key->concatenated_range_constraints_2; + prover_polynomials.concatenated_range_constraints_3 = key->concatenated_range_constraints_3; + prover_polynomials.ordered_range_constraints_0 = key->ordered_range_constraints_0; + prover_polynomials.ordered_range_constraints_1 = key->ordered_range_constraints_1; + prover_polynomials.ordered_range_constraints_2 = key->ordered_range_constraints_2; + prover_polynomials.ordered_range_constraints_3 = key->ordered_range_constraints_3; + prover_polynomials.ordered_range_constraints_4 = key->ordered_range_constraints_4; + prover_polynomials.x_lo_y_hi_shift = key->x_lo_y_hi.shifted(); + prover_polynomials.x_hi_z_1_shift = key->x_hi_z_1.shifted(); + prover_polynomials.y_lo_z_2_shift = key->y_lo_z_2.shifted(); + prover_polynomials.p_x_low_limbs_shift = key->p_x_low_limbs.shifted(); + prover_polynomials.p_x_low_limbs_range_constraint_0_shift = key->p_x_low_limbs_range_constraint_0.shifted(); + prover_polynomials.p_x_low_limbs_range_constraint_1_shift = key->p_x_low_limbs_range_constraint_1.shifted(); + prover_polynomials.p_x_low_limbs_range_constraint_2_shift = key->p_x_low_limbs_range_constraint_2.shifted(); + prover_polynomials.p_x_low_limbs_range_constraint_3_shift = key->p_x_low_limbs_range_constraint_3.shifted(); + prover_polynomials.p_x_low_limbs_range_constraint_4_shift = key->p_x_low_limbs_range_constraint_4.shifted(); + prover_polynomials.p_x_low_limbs_range_constraint_tail_shift = key->p_x_low_limbs_range_constraint_tail.shifted(); + prover_polynomials.p_x_high_limbs_shift = key->p_x_high_limbs.shifted(); + prover_polynomials.p_x_high_limbs_range_constraint_0_shift = key->p_x_high_limbs_range_constraint_0.shifted(); + prover_polynomials.p_x_high_limbs_range_constraint_1_shift = key->p_x_high_limbs_range_constraint_1.shifted(); + prover_polynomials.p_x_high_limbs_range_constraint_2_shift = key->p_x_high_limbs_range_constraint_2.shifted(); + prover_polynomials.p_x_high_limbs_range_constraint_3_shift = key->p_x_high_limbs_range_constraint_3.shifted(); + prover_polynomials.p_x_high_limbs_range_constraint_4_shift = key->p_x_high_limbs_range_constraint_4.shifted(); + prover_polynomials.p_x_high_limbs_range_constraint_tail_shift = key->p_x_high_limbs_range_constraint_tail.shifted(); + prover_polynomials.p_y_low_limbs_shift = key->p_y_low_limbs.shifted(); + prover_polynomials.p_y_low_limbs_range_constraint_0_shift = key->p_y_low_limbs_range_constraint_0.shifted(); + prover_polynomials.p_y_low_limbs_range_constraint_1_shift = key->p_y_low_limbs_range_constraint_1.shifted(); + prover_polynomials.p_y_low_limbs_range_constraint_2_shift = key->p_y_low_limbs_range_constraint_2.shifted(); + prover_polynomials.p_y_low_limbs_range_constraint_3_shift = key->p_y_low_limbs_range_constraint_3.shifted(); + prover_polynomials.p_y_low_limbs_range_constraint_4_shift = key->p_y_low_limbs_range_constraint_4.shifted(); + prover_polynomials.p_y_low_limbs_range_constraint_tail_shift = key->p_y_low_limbs_range_constraint_tail.shifted(); + prover_polynomials.p_y_high_limbs_shift = key->p_y_high_limbs.shifted(); + prover_polynomials.p_y_high_limbs_range_constraint_0_shift = key->p_y_high_limbs_range_constraint_0.shifted(); + prover_polynomials.p_y_high_limbs_range_constraint_1_shift = key->p_y_high_limbs_range_constraint_1.shifted(); + prover_polynomials.p_y_high_limbs_range_constraint_2_shift = key->p_y_high_limbs_range_constraint_2.shifted(); + prover_polynomials.p_y_high_limbs_range_constraint_3_shift = key->p_y_high_limbs_range_constraint_3.shifted(); + prover_polynomials.p_y_high_limbs_range_constraint_4_shift = key->p_y_high_limbs_range_constraint_4.shifted(); + prover_polynomials.p_y_high_limbs_range_constraint_tail_shift = key->p_y_high_limbs_range_constraint_tail.shifted(); + prover_polynomials.z_low_limbs_shift = key->z_low_limbs.shifted(); + prover_polynomials.z_low_limbs_range_constraint_0_shift = key->z_low_limbs_range_constraint_0.shifted(); + prover_polynomials.z_low_limbs_range_constraint_1_shift = key->z_low_limbs_range_constraint_1.shifted(); + prover_polynomials.z_low_limbs_range_constraint_2_shift = key->z_low_limbs_range_constraint_2.shifted(); + prover_polynomials.z_low_limbs_range_constraint_3_shift = key->z_low_limbs_range_constraint_3.shifted(); + prover_polynomials.z_low_limbs_range_constraint_4_shift = key->z_low_limbs_range_constraint_4.shifted(); + prover_polynomials.z_low_limbs_range_constraint_tail_shift = key->z_low_limbs_range_constraint_tail.shifted(); + prover_polynomials.z_high_limbs_shift = key->z_high_limbs.shifted(); + prover_polynomials.z_high_limbs_range_constraint_0_shift = key->z_high_limbs_range_constraint_0.shifted(); + prover_polynomials.z_high_limbs_range_constraint_1_shift = key->z_high_limbs_range_constraint_1.shifted(); + prover_polynomials.z_high_limbs_range_constraint_2_shift = key->z_high_limbs_range_constraint_2.shifted(); + prover_polynomials.z_high_limbs_range_constraint_3_shift = key->z_high_limbs_range_constraint_3.shifted(); + prover_polynomials.z_high_limbs_range_constraint_4_shift = key->z_high_limbs_range_constraint_4.shifted(); + prover_polynomials.z_high_limbs_range_constraint_tail_shift = key->z_high_limbs_range_constraint_tail.shifted(); + prover_polynomials.accumulators_binary_limbs_0_shift = key->accumulators_binary_limbs_0.shifted(); + prover_polynomials.accumulators_binary_limbs_1_shift = key->accumulators_binary_limbs_1.shifted(); + prover_polynomials.accumulators_binary_limbs_2_shift = key->accumulators_binary_limbs_2.shifted(); + prover_polynomials.accumulators_binary_limbs_3_shift = key->accumulators_binary_limbs_3.shifted(); + prover_polynomials.accumulator_low_limbs_range_constraint_0_shift = + key->accumulator_low_limbs_range_constraint_0.shifted(); + prover_polynomials.accumulator_low_limbs_range_constraint_1_shift = + key->accumulator_low_limbs_range_constraint_1.shifted(); + prover_polynomials.accumulator_low_limbs_range_constraint_2_shift = + key->accumulator_low_limbs_range_constraint_2.shifted(); + prover_polynomials.accumulator_low_limbs_range_constraint_3_shift = + key->accumulator_low_limbs_range_constraint_3.shifted(); + prover_polynomials.accumulator_low_limbs_range_constraint_4_shift = + key->accumulator_low_limbs_range_constraint_4.shifted(); + prover_polynomials.accumulator_low_limbs_range_constraint_tail_shift = + key->accumulator_low_limbs_range_constraint_tail.shifted(); + prover_polynomials.accumulator_high_limbs_range_constraint_0_shift = + key->accumulator_high_limbs_range_constraint_0.shifted(); + prover_polynomials.accumulator_high_limbs_range_constraint_1_shift = + key->accumulator_high_limbs_range_constraint_1.shifted(); + prover_polynomials.accumulator_high_limbs_range_constraint_2_shift = + key->accumulator_high_limbs_range_constraint_2.shifted(); + prover_polynomials.accumulator_high_limbs_range_constraint_3_shift = + key->accumulator_high_limbs_range_constraint_3.shifted(); + prover_polynomials.accumulator_high_limbs_range_constraint_4_shift = + key->accumulator_high_limbs_range_constraint_4.shifted(); + prover_polynomials.accumulator_high_limbs_range_constraint_tail_shift = + key->accumulator_high_limbs_range_constraint_tail.shifted(); + prover_polynomials.quotient_low_binary_limbs_shift = key->quotient_low_binary_limbs.shifted(); + prover_polynomials.quotient_high_binary_limbs_shift = key->quotient_high_binary_limbs.shifted(); + prover_polynomials.quotient_low_limbs_range_constraint_0_shift = + key->quotient_low_limbs_range_constraint_0.shifted(); + prover_polynomials.quotient_low_limbs_range_constraint_1_shift = + key->quotient_low_limbs_range_constraint_1.shifted(); + prover_polynomials.quotient_low_limbs_range_constraint_2_shift = + key->quotient_low_limbs_range_constraint_2.shifted(); + prover_polynomials.quotient_low_limbs_range_constraint_3_shift = + key->quotient_low_limbs_range_constraint_3.shifted(); + prover_polynomials.quotient_low_limbs_range_constraint_4_shift = + key->quotient_low_limbs_range_constraint_4.shifted(); + prover_polynomials.quotient_low_limbs_range_constraint_tail_shift = + key->quotient_low_limbs_range_constraint_tail.shifted(); + prover_polynomials.quotient_high_limbs_range_constraint_0_shift = + key->quotient_high_limbs_range_constraint_0.shifted(); + prover_polynomials.quotient_high_limbs_range_constraint_1_shift = + key->quotient_high_limbs_range_constraint_1.shifted(); + prover_polynomials.quotient_high_limbs_range_constraint_2_shift = + key->quotient_high_limbs_range_constraint_2.shifted(); + prover_polynomials.quotient_high_limbs_range_constraint_3_shift = + key->quotient_high_limbs_range_constraint_3.shifted(); + prover_polynomials.quotient_high_limbs_range_constraint_4_shift = + key->quotient_high_limbs_range_constraint_4.shifted(); + prover_polynomials.quotient_high_limbs_range_constraint_tail_shift = + key->quotient_high_limbs_range_constraint_tail.shifted(); + prover_polynomials.relation_wide_limbs_shift = key->relation_wide_limbs.shifted(); + prover_polynomials.relation_wide_limbs_range_constraint_0_shift = + key->relation_wide_limbs_range_constraint_0.shifted(); + prover_polynomials.relation_wide_limbs_range_constraint_1_shift = + key->relation_wide_limbs_range_constraint_1.shifted(); + prover_polynomials.relation_wide_limbs_range_constraint_2_shift = + key->relation_wide_limbs_range_constraint_2.shifted(); + prover_polynomials.relation_wide_limbs_range_constraint_3_shift = + key->relation_wide_limbs_range_constraint_3.shifted(); + prover_polynomials.ordered_range_constraints_0_shift = key->ordered_range_constraints_0.shifted(); + prover_polynomials.ordered_range_constraints_1_shift = key->ordered_range_constraints_1.shifted(); + prover_polynomials.ordered_range_constraints_2_shift = key->ordered_range_constraints_2.shifted(); + prover_polynomials.ordered_range_constraints_3_shift = key->ordered_range_constraints_3.shifted(); + prover_polynomials.ordered_range_constraints_4_shift = key->ordered_range_constraints_4.shifted(); + prover_polynomials.lagrange_first = key->lagrange_first; + prover_polynomials.lagrange_last = key->lagrange_last; + prover_polynomials.lagrange_odd_in_minicircuit = key->lagrange_odd_in_minicircuit; + prover_polynomials.lagrange_even_in_minicircuit = key->lagrange_even_in_minicircuit; + prover_polynomials.lagrange_second = key->lagrange_second; + prover_polynomials.lagrange_second_to_last_in_minicircuit = key->lagrange_second_to_last_in_minicircuit; + prover_polynomials.ordered_extra_range_constraints_numerator = key->ordered_extra_range_constraints_numerator; +} + +/** + * @brief Add circuit size and values used in the relations to the transcript + * + */ +void GoblinTranslatorProver::execute_preamble_round() +{ + const auto circuit_size = static_cast(key->circuit_size); + const auto SHIFT = uint256_t(1) << Flavor::NUM_LIMB_BITS; + const auto SHIFTx2 = uint256_t(1) << (Flavor::NUM_LIMB_BITS * 2); + const auto SHIFTx3 = uint256_t(1) << (Flavor::NUM_LIMB_BITS * 3); + const auto accumulated_result = typename Flavor::BF(uint256_t(key->accumulators_binary_limbs_0[1]) + + uint256_t(key->accumulators_binary_limbs_1[1]) * SHIFT + + uint256_t(key->accumulators_binary_limbs_2[1]) * SHIFTx2 + + uint256_t(key->accumulators_binary_limbs_3[1]) * SHIFTx3); + transcript.send_to_verifier("circuit_size", circuit_size); + transcript.send_to_verifier("evaluation_input_x", key->evaluation_input_x); + transcript.send_to_verifier("batching_challenge_v", key->batching_challenge_v); + transcript.send_to_verifier("accumulated_result", accumulated_result); +} + +/** + * @brief Compute commitments to the first three wires + * + */ +void GoblinTranslatorProver::execute_wire_and_sorted_constraints_commitments_round() +{ + // Commit to all wire polynomials + auto wire_polys = key->get_wires(); + auto labels = commitment_labels.get_wires(); + for (size_t idx = 0; idx < wire_polys.size(); ++idx) { + transcript.send_to_verifier(labels[idx], commitment_key->commit(wire_polys[idx])); + } +} + +/** + * @brief Compute permutation product polynomial and commitments + * + */ +void GoblinTranslatorProver::execute_grand_product_computation_round() +{ + // Compute and store parameters required by relations in Sumcheck + auto [gamma] = transcript.get_challenges("gamma"); + const size_t NUM_LIMB_BITS = Flavor::NUM_LIMB_BITS; + relation_parameters.beta = 0; + relation_parameters.gamma = gamma; + relation_parameters.public_input_delta = 0; + relation_parameters.lookup_grand_product_delta = 0; + auto uint_evaluation_input = uint256_t(key->evaluation_input_x); + relation_parameters.evaluation_input_x = { uint_evaluation_input.slice(0, NUM_LIMB_BITS), + uint_evaluation_input.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2), + uint_evaluation_input.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3), + uint_evaluation_input.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4), + uint_evaluation_input }; + + relation_parameters.accumulated_result = { key->accumulators_binary_limbs_0[1], + key->accumulators_binary_limbs_1[1], + key->accumulators_binary_limbs_2[1], + key->accumulators_binary_limbs_3[1] }; + + std::vector uint_batching_challenge_powers; + auto batching_challenge_v = key->batching_challenge_v; + uint_batching_challenge_powers.emplace_back(batching_challenge_v); + auto running_power = batching_challenge_v * batching_challenge_v; + uint_batching_challenge_powers.emplace_back(running_power); + running_power *= batching_challenge_v; + uint_batching_challenge_powers.emplace_back(running_power); + running_power *= batching_challenge_v; + uint_batching_challenge_powers.emplace_back(running_power); + + for (size_t i = 0; i < 4; i++) { + relation_parameters.batching_challenge_v[i] = { + uint_batching_challenge_powers[i].slice(0, NUM_LIMB_BITS), + uint_batching_challenge_powers[i].slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2), + uint_batching_challenge_powers[i].slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3), + uint_batching_challenge_powers[i].slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4), + uint_batching_challenge_powers[i] + }; + } + // Compute constraint permutation grand product + grand_product_library::compute_grand_products(key, prover_polynomials, relation_parameters); + + transcript.send_to_verifier(commitment_labels.z_perm, commitment_key->commit(key->z_perm)); +} + +/** + * @brief Run Sumcheck resulting in u = (u_1,...,u_d) challenges and all evaluations at u being calculated. + * + */ +void GoblinTranslatorProver::execute_relation_check_rounds() +{ + using Sumcheck = sumcheck::SumcheckProver; + + auto sumcheck = Sumcheck(key->circuit_size, transcript); + + auto alpha = transcript.get_challenge("alpha"); + sumcheck_output = sumcheck.prove(prover_polynomials, relation_parameters, alpha); +} + +/** + * @brief Execute the ZeroMorph protocol to prove the multilinear evaluations produced by Sumcheck + * @details See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the unrolled protocol. + * + * */ +void GoblinTranslatorProver::execute_zeromorph_rounds() +{ + using ZeroMorph = pcs::zeromorph::ZeroMorphProver_; + ZeroMorph::prove(prover_polynomials.get_unshifted(), + prover_polynomials.get_to_be_shifted(), + sumcheck_output.claimed_evaluations.get_unshifted(), + sumcheck_output.claimed_evaluations.get_shifted(), + sumcheck_output.challenge, + commitment_key, + transcript, + prover_polynomials.get_concatenated_constraints(), + sumcheck_output.claimed_evaluations.get_concatenated_constraints(), + prover_polynomials.get_concatenation_groups()); +} + +plonk::proof& GoblinTranslatorProver::export_proof() +{ + proof.proof_data = transcript.proof_data; + return proof; +} + +plonk::proof& GoblinTranslatorProver::construct_proof() +{ + // Add circuit size public input size and public inputs to transcript. + execute_preamble_round(); + + // Compute first three wire commitments + execute_wire_and_sorted_constraints_commitments_round(); + + // Fiat-Shamir: gamma + // Compute grand product(s) and commitments. + execute_grand_product_computation_round(); + + // Fiat-Shamir: alpha + // Run sumcheck subprotocol. + execute_relation_check_rounds(); + + // Fiat-Shamir: rho, y, x, z + // Execute Zeromorph multilinear PCS + execute_zeromorph_rounds(); + + return export_proof(); +} + +} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.hpp new file mode 100644 index 00000000000..47772d1ca7b --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.hpp @@ -0,0 +1,57 @@ +#pragma once +#include "barretenberg/flavor/goblin_translator.hpp" +#include "barretenberg/plonk/proof_system/types/proof.hpp" +#include "barretenberg/relations/relation_parameters.hpp" +#include "barretenberg/sumcheck/sumcheck_output.hpp" + +namespace proof_system::honk { + +// We won't compile this class with honk::flavor::Standard, but we will like want to compile it (at least for testing) +// with a flavor that uses the curve Grumpkin, or a flavor that does/does not have zk, etc. +class GoblinTranslatorProver { + + using Flavor = honk::flavor::GoblinTranslator; + using FF = typename Flavor::FF; + using Commitment = typename Flavor::Commitment; + using CommitmentKey = typename Flavor::CommitmentKey; + using ProvingKey = typename Flavor::ProvingKey; + using Polynomial = typename Flavor::Polynomial; + using ProverPolynomials = typename Flavor::ProverPolynomials; + using CommitmentLabels = typename Flavor::CommitmentLabels; + using Curve = typename Flavor::Curve; + + static size_t constexpr MINI_CIRCUIT_SIZE = Flavor::MINI_CIRCUIT_SIZE; + static size_t constexpr FULL_CIRCUIT_SIZE = Flavor::FULL_CIRCUIT_SIZE; + + public: + explicit GoblinTranslatorProver(std::shared_ptr input_key, + std::shared_ptr commitment_key); + + void execute_preamble_round(); + void execute_wire_and_sorted_constraints_commitments_round(); + void execute_grand_product_computation_round(); + void execute_relation_check_rounds(); + void execute_zeromorph_rounds(); + plonk::proof& export_proof(); + plonk::proof& construct_proof(); + + BaseTranscript transcript; + + proof_system::RelationParameters relation_parameters; + + std::shared_ptr key; + + // Container for spans of all polynomials required by the prover (i.e. all multivariates evaluated by Sumcheck). + ProverPolynomials prover_polynomials; + + CommitmentLabels commitment_labels; + + std::shared_ptr commitment_key; + + sumcheck::SumcheckOutput sumcheck_output; + + private: + plonk::proof proof; +}; + +} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_verifier.cpp new file mode 100644 index 00000000000..d280143e2f2 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_verifier.cpp @@ -0,0 +1,312 @@ +#include "./goblin_translator_verifier.hpp" +#include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" +#include "barretenberg/honk/proof_system/power_polynomial.hpp" +#include "barretenberg/sumcheck/sumcheck.hpp" +#include "barretenberg/transcript/transcript.hpp" + +using namespace barretenberg; +using namespace proof_system::honk::sumcheck; + +namespace proof_system::honk { + +GoblinTranslatorVerifier::GoblinTranslatorVerifier(std::shared_ptr verifier_key) + : key(verifier_key) +{} + +GoblinTranslatorVerifier::GoblinTranslatorVerifier(GoblinTranslatorVerifier&& other) noexcept + : key(std::move(other.key)) + , pcs_verification_key(std::move(other.pcs_verification_key)) +{} + +GoblinTranslatorVerifier& GoblinTranslatorVerifier::operator=(GoblinTranslatorVerifier&& other) noexcept +{ + key = other.key; + pcs_verification_key = (std::move(other.pcs_verification_key)); + commitments.clear(); + pcs_fr_elements.clear(); + return *this; +} + +void GoblinTranslatorVerifier::put_translation_data_in_relation_parameters(const uint256_t& evaluation_input_x, + const BF& batching_challenge_v, + const uint256_t& accumulated_result) +{ + + const auto compute_four_limbs = [](const auto& in) { + constexpr size_t NUM_LIMB_BITS = Flavor::NUM_LIMB_BITS; + return std::array{ in.slice(0, NUM_LIMB_BITS), + in.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2), + in.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3), + in.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4) }; + }; + + const auto compute_five_limbs = [](const auto& in) { + constexpr size_t NUM_LIMB_BITS = Flavor::NUM_LIMB_BITS; + return std::array{ in.slice(0, NUM_LIMB_BITS), + in.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2), + in.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3), + in.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4), + in }; + }; + + relation_parameters.evaluation_input_x = compute_five_limbs(evaluation_input_x); + + uint256_t batching_challenge_v_power{ batching_challenge_v }; + for (size_t i = 0; i < 4; i++) { + relation_parameters.batching_challenge_v[i] = compute_five_limbs(batching_challenge_v_power); + batching_challenge_v_power = BF(batching_challenge_v_power) * batching_challenge_v; + } + + relation_parameters.accumulated_result = compute_four_limbs(accumulated_result); +}; + +/** + * @brief This function verifies an GoblinTranslator Honk proof for given program settings. + */ +bool GoblinTranslatorVerifier::verify_proof(const plonk::proof& proof) +{ + using Curve = typename Flavor::Curve; + using ZeroMorph = pcs::zeromorph::ZeroMorphVerifier_; + using VerifierCommitments = typename Flavor::VerifierCommitments; + using CommitmentLabels = typename Flavor::CommitmentLabels; + + transcript = BaseTranscript{ proof.proof_data }; + + auto commitments = VerifierCommitments(key, transcript); + auto commitment_labels = CommitmentLabels(); + + // TODO(Adrian): Change the initialization of the transcript to take the VK hash? + const auto circuit_size = transcript.template receive_from_prover("circuit_size"); + evaluation_input_x = transcript.template receive_from_prover("evaluation_input_x"); + batching_challenge_v = transcript.template receive_from_prover("batching_challenge_v"); + + const BF accumulated_result = transcript.template receive_from_prover("accumulated_result"); + + put_translation_data_in_relation_parameters(evaluation_input_x, batching_challenge_v, accumulated_result); + + if (circuit_size != key->circuit_size) { + return false; + } + + // Get all the values of wires + const auto receive_commitment = [&](const std::string& label) { + return transcript.template receive_from_prover(label); + }; + + commitments.op = receive_commitment(commitment_labels.op); + commitments.x_lo_y_hi = receive_commitment(commitment_labels.x_lo_y_hi); + commitments.x_hi_z_1 = receive_commitment(commitment_labels.x_hi_z_1); + commitments.y_lo_z_2 = receive_commitment(commitment_labels.y_lo_z_2); + commitments.p_x_low_limbs = receive_commitment(commitment_labels.p_x_low_limbs); + commitments.p_x_low_limbs_range_constraint_0 = + receive_commitment(commitment_labels.p_x_low_limbs_range_constraint_0); + commitments.p_x_low_limbs_range_constraint_1 = + receive_commitment(commitment_labels.p_x_low_limbs_range_constraint_1); + commitments.p_x_low_limbs_range_constraint_2 = + receive_commitment(commitment_labels.p_x_low_limbs_range_constraint_2); + commitments.p_x_low_limbs_range_constraint_3 = + receive_commitment(commitment_labels.p_x_low_limbs_range_constraint_3); + commitments.p_x_low_limbs_range_constraint_4 = + receive_commitment(commitment_labels.p_x_low_limbs_range_constraint_4); + commitments.p_x_low_limbs_range_constraint_tail = + receive_commitment(commitment_labels.p_x_low_limbs_range_constraint_tail); + commitments.p_x_high_limbs = receive_commitment(commitment_labels.p_x_high_limbs); + commitments.p_x_high_limbs_range_constraint_0 = + receive_commitment(commitment_labels.p_x_high_limbs_range_constraint_0); + commitments.p_x_high_limbs_range_constraint_1 = + receive_commitment(commitment_labels.p_x_high_limbs_range_constraint_1); + commitments.p_x_high_limbs_range_constraint_2 = + receive_commitment(commitment_labels.p_x_high_limbs_range_constraint_2); + commitments.p_x_high_limbs_range_constraint_3 = + receive_commitment(commitment_labels.p_x_high_limbs_range_constraint_3); + commitments.p_x_high_limbs_range_constraint_4 = + receive_commitment(commitment_labels.p_x_high_limbs_range_constraint_4); + commitments.p_x_high_limbs_range_constraint_tail = + receive_commitment(commitment_labels.p_x_high_limbs_range_constraint_tail); + commitments.p_y_low_limbs = receive_commitment(commitment_labels.p_y_low_limbs); + commitments.p_y_low_limbs_range_constraint_0 = + receive_commitment(commitment_labels.p_y_low_limbs_range_constraint_0); + commitments.p_y_low_limbs_range_constraint_1 = + receive_commitment(commitment_labels.p_y_low_limbs_range_constraint_1); + commitments.p_y_low_limbs_range_constraint_2 = + receive_commitment(commitment_labels.p_y_low_limbs_range_constraint_2); + commitments.p_y_low_limbs_range_constraint_3 = + receive_commitment(commitment_labels.p_y_low_limbs_range_constraint_3); + commitments.p_y_low_limbs_range_constraint_4 = + receive_commitment(commitment_labels.p_y_low_limbs_range_constraint_4); + commitments.p_y_low_limbs_range_constraint_tail = + receive_commitment(commitment_labels.p_y_low_limbs_range_constraint_tail); + commitments.p_y_high_limbs = receive_commitment(commitment_labels.p_y_high_limbs); + commitments.p_y_high_limbs_range_constraint_0 = + receive_commitment(commitment_labels.p_y_high_limbs_range_constraint_0); + commitments.p_y_high_limbs_range_constraint_1 = + receive_commitment(commitment_labels.p_y_high_limbs_range_constraint_1); + commitments.p_y_high_limbs_range_constraint_2 = + receive_commitment(commitment_labels.p_y_high_limbs_range_constraint_2); + commitments.p_y_high_limbs_range_constraint_3 = + receive_commitment(commitment_labels.p_y_high_limbs_range_constraint_3); + commitments.p_y_high_limbs_range_constraint_4 = + receive_commitment(commitment_labels.p_y_high_limbs_range_constraint_4); + commitments.p_y_high_limbs_range_constraint_tail = + receive_commitment(commitment_labels.p_y_high_limbs_range_constraint_tail); + commitments.z_low_limbs = receive_commitment(commitment_labels.z_low_limbs); + commitments.z_low_limbs_range_constraint_0 = receive_commitment(commitment_labels.z_low_limbs_range_constraint_0); + commitments.z_low_limbs_range_constraint_1 = receive_commitment(commitment_labels.z_low_limbs_range_constraint_1); + commitments.z_low_limbs_range_constraint_2 = receive_commitment(commitment_labels.z_low_limbs_range_constraint_2); + commitments.z_low_limbs_range_constraint_3 = receive_commitment(commitment_labels.z_low_limbs_range_constraint_3); + commitments.z_low_limbs_range_constraint_4 = receive_commitment(commitment_labels.z_low_limbs_range_constraint_4); + commitments.z_low_limbs_range_constraint_tail = + receive_commitment(commitment_labels.z_low_limbs_range_constraint_tail); + commitments.z_high_limbs = receive_commitment(commitment_labels.z_high_limbs); + commitments.z_high_limbs_range_constraint_0 = receive_commitment(commitment_labels.z_high_limbs_range_constraint_0); + commitments.z_high_limbs_range_constraint_1 = receive_commitment(commitment_labels.z_high_limbs_range_constraint_1); + commitments.z_high_limbs_range_constraint_2 = receive_commitment(commitment_labels.z_high_limbs_range_constraint_2); + commitments.z_high_limbs_range_constraint_3 = receive_commitment(commitment_labels.z_high_limbs_range_constraint_3); + commitments.z_high_limbs_range_constraint_4 = receive_commitment(commitment_labels.z_high_limbs_range_constraint_4); + commitments.z_high_limbs_range_constraint_tail = + receive_commitment(commitment_labels.z_high_limbs_range_constraint_tail); + commitments.accumulators_binary_limbs_0 = receive_commitment(commitment_labels.accumulators_binary_limbs_0); + commitments.accumulators_binary_limbs_1 = receive_commitment(commitment_labels.accumulators_binary_limbs_1); + commitments.accumulators_binary_limbs_2 = receive_commitment(commitment_labels.accumulators_binary_limbs_2); + commitments.accumulators_binary_limbs_3 = receive_commitment(commitment_labels.accumulators_binary_limbs_3); + commitments.accumulator_low_limbs_range_constraint_0 = + receive_commitment(commitment_labels.accumulator_low_limbs_range_constraint_0); + commitments.accumulator_low_limbs_range_constraint_1 = + receive_commitment(commitment_labels.accumulator_low_limbs_range_constraint_1); + commitments.accumulator_low_limbs_range_constraint_2 = + receive_commitment(commitment_labels.accumulator_low_limbs_range_constraint_2); + commitments.accumulator_low_limbs_range_constraint_3 = + receive_commitment(commitment_labels.accumulator_low_limbs_range_constraint_3); + commitments.accumulator_low_limbs_range_constraint_4 = + receive_commitment(commitment_labels.accumulator_low_limbs_range_constraint_4); + commitments.accumulator_low_limbs_range_constraint_tail = + receive_commitment(commitment_labels.accumulator_low_limbs_range_constraint_tail); + commitments.accumulator_high_limbs_range_constraint_0 = + receive_commitment(commitment_labels.accumulator_high_limbs_range_constraint_0); + commitments.accumulator_high_limbs_range_constraint_1 = + receive_commitment(commitment_labels.accumulator_high_limbs_range_constraint_1); + commitments.accumulator_high_limbs_range_constraint_2 = + receive_commitment(commitment_labels.accumulator_high_limbs_range_constraint_2); + commitments.accumulator_high_limbs_range_constraint_3 = + receive_commitment(commitment_labels.accumulator_high_limbs_range_constraint_3); + commitments.accumulator_high_limbs_range_constraint_4 = + receive_commitment(commitment_labels.accumulator_high_limbs_range_constraint_4); + commitments.accumulator_high_limbs_range_constraint_tail = + receive_commitment(commitment_labels.accumulator_high_limbs_range_constraint_tail); + commitments.quotient_low_binary_limbs = receive_commitment(commitment_labels.quotient_low_binary_limbs); + commitments.quotient_high_binary_limbs = receive_commitment(commitment_labels.quotient_high_binary_limbs); + commitments.quotient_low_limbs_range_constraint_0 = + receive_commitment(commitment_labels.quotient_low_limbs_range_constraint_0); + commitments.quotient_low_limbs_range_constraint_1 = + receive_commitment(commitment_labels.quotient_low_limbs_range_constraint_1); + commitments.quotient_low_limbs_range_constraint_2 = + receive_commitment(commitment_labels.quotient_low_limbs_range_constraint_2); + commitments.quotient_low_limbs_range_constraint_3 = + receive_commitment(commitment_labels.quotient_low_limbs_range_constraint_3); + commitments.quotient_low_limbs_range_constraint_4 = + receive_commitment(commitment_labels.quotient_low_limbs_range_constraint_4); + commitments.quotient_low_limbs_range_constraint_tail = + receive_commitment(commitment_labels.quotient_low_limbs_range_constraint_tail); + commitments.quotient_high_limbs_range_constraint_0 = + receive_commitment(commitment_labels.quotient_high_limbs_range_constraint_0); + commitments.quotient_high_limbs_range_constraint_1 = + receive_commitment(commitment_labels.quotient_high_limbs_range_constraint_1); + commitments.quotient_high_limbs_range_constraint_2 = + receive_commitment(commitment_labels.quotient_high_limbs_range_constraint_2); + commitments.quotient_high_limbs_range_constraint_3 = + receive_commitment(commitment_labels.quotient_high_limbs_range_constraint_3); + commitments.quotient_high_limbs_range_constraint_4 = + receive_commitment(commitment_labels.quotient_high_limbs_range_constraint_4); + commitments.quotient_high_limbs_range_constraint_tail = + receive_commitment(commitment_labels.quotient_high_limbs_range_constraint_tail); + commitments.relation_wide_limbs = receive_commitment(commitment_labels.relation_wide_limbs); + commitments.relation_wide_limbs_range_constraint_0 = + receive_commitment(commitment_labels.relation_wide_limbs_range_constraint_0); + commitments.relation_wide_limbs_range_constraint_1 = + receive_commitment(commitment_labels.relation_wide_limbs_range_constraint_1); + commitments.relation_wide_limbs_range_constraint_2 = + receive_commitment(commitment_labels.relation_wide_limbs_range_constraint_2); + commitments.relation_wide_limbs_range_constraint_3 = + receive_commitment(commitment_labels.relation_wide_limbs_range_constraint_3); + commitments.ordered_range_constraints_0 = receive_commitment(commitment_labels.ordered_range_constraints_0); + commitments.ordered_range_constraints_1 = receive_commitment(commitment_labels.ordered_range_constraints_1); + commitments.ordered_range_constraints_2 = receive_commitment(commitment_labels.ordered_range_constraints_2); + commitments.ordered_range_constraints_3 = receive_commitment(commitment_labels.ordered_range_constraints_3); + commitments.ordered_range_constraints_4 = receive_commitment(commitment_labels.ordered_range_constraints_4); + + // Get permutation challenges + auto [gamma] = transcript.get_challenges("gamma"); + + relation_parameters.beta = 0; + relation_parameters.gamma = gamma; + relation_parameters.public_input_delta = 0; + relation_parameters.lookup_grand_product_delta = 0; + + // Get commitment to permutation and lookup grand products + commitments.z_perm = receive_commitment(commitment_labels.z_perm); + + // Execute Sumcheck Verifier + auto sumcheck = SumcheckVerifier(circuit_size); + + auto alpha = transcript.get_challenge("alpha"); + auto [multivariate_challenge, claimed_evaluations, sumcheck_verified] = + sumcheck.verify(relation_parameters, alpha, transcript); + + // If Sumcheck did not verify, return false + if (sumcheck_verified.has_value() && !sumcheck_verified.value()) { + info("sumcheck failed"); + return false; + } + + // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description ofthe + // unrolled protocol. + auto pairing_points = ZeroMorph::verify(commitments.get_unshifted(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + transcript, + commitments.get_concatenation_groups(), + claimed_evaluations.get_concatenated_constraints()); + + auto verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); + + return verified; +} + +bool GoblinTranslatorVerifier::verify_translation(const TranslationEvaluations& translation_evaluations) +{ + const auto reconstruct_from_array = [&](const auto& arr) { + const BF elt_0 = (static_cast(arr[0])); + const BF elt_1 = (static_cast(arr[1]) << 68); + const BF elt_2 = (static_cast(arr[2]) << 136); + const BF elt_3 = (static_cast(arr[3]) << 204); + const BF reconstructed = elt_0 + elt_1 + elt_2 + elt_3; + return reconstructed; + }; + + const auto& reconstruct_value_from_eccvm_evaluations = [&](const TranslationEvaluations& translation_evaluations, + auto& relation_parameters) { + const BF accumulated_result = reconstruct_from_array(relation_parameters.accumulated_result); + const BF x = reconstruct_from_array(relation_parameters.evaluation_input_x); + const BF v1 = reconstruct_from_array(relation_parameters.batching_challenge_v[0]); + const BF v2 = reconstruct_from_array(relation_parameters.batching_challenge_v[1]); + const BF v3 = reconstruct_from_array(relation_parameters.batching_challenge_v[2]); + const BF v4 = reconstruct_from_array(relation_parameters.batching_challenge_v[3]); + const BF& op = translation_evaluations.op; + const BF& Px = translation_evaluations.Px; + const BF& Py = translation_evaluations.Py; + const BF& z1 = translation_evaluations.z1; + const BF& z2 = translation_evaluations.z2; + + const BF eccvm_opening = (op + (v1 * Px) + (v2 * Py) + (v3 * z1) + (v4 * z2)); + // multiply by x here to deal with shift + return x * accumulated_result == eccvm_opening; + }; + + bool is_value_reconstructed = + reconstruct_value_from_eccvm_evaluations(translation_evaluations, relation_parameters); + return is_value_reconstructed; +} + +} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_verifier.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_verifier.hpp new file mode 100644 index 00000000000..ff49cd546ce --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_verifier.hpp @@ -0,0 +1,39 @@ +#pragma once +#include "barretenberg/flavor/goblin_translator.hpp" +#include "barretenberg/goblin/translation_evaluations.hpp" +#include "barretenberg/plonk/proof_system/types/proof.hpp" + +namespace proof_system::honk { +class GoblinTranslatorVerifier { + public: + using Flavor = honk::flavor::GoblinTranslator; + using FF = typename Flavor::FF; + using BF = typename Flavor::BF; + using Commitment = typename Flavor::Commitment; + using VerificationKey = typename Flavor::VerificationKey; + using VerifierCommitmentKey = typename Flavor::VerifierCommitmentKey; + using TranslationEvaluations = barretenberg::TranslationEvaluations; + + BF evaluation_input_x = 0; + BF batching_challenge_v = 0; + std::shared_ptr key; + std::map commitments; + std::map pcs_fr_elements; + std::shared_ptr pcs_verification_key; + BaseTranscript transcript; + RelationParameters relation_parameters; + + explicit GoblinTranslatorVerifier(std::shared_ptr verifier_key = nullptr); + GoblinTranslatorVerifier(GoblinTranslatorVerifier&& other) noexcept; + GoblinTranslatorVerifier(const GoblinTranslatorVerifier& other) = delete; + GoblinTranslatorVerifier& operator=(const GoblinTranslatorVerifier& other) = delete; + GoblinTranslatorVerifier& operator=(GoblinTranslatorVerifier&& other) noexcept; + ~GoblinTranslatorVerifier() = default; + + void put_translation_data_in_relation_parameters(const uint256_t& evaluation_input_x, + const BF& batching_challenge_v, + const uint256_t& accumulated_result); + bool verify_proof(const plonk::proof& proof); + bool verify_translation(const TranslationEvaluations& translation_evaluations); +}; +} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp index aac5c124212..063a1837730 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp @@ -483,7 +483,8 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorPermutationRelationCorrectness) // Compute the grand product polynomial grand_product_library::compute_grand_product>( circuit_size, prover_polynomials, params); - prover_polynomials.z_perm_shift = polynomial_container[Flavor::ALL_ENTITIES_IDS::Z_PERM].shifted(); + prover_polynomials.z_perm_shift = + polynomial_container[90].shifted(); // TODO(https://github.com/AztecProtocol/barretenberg/issues/784) using Relations = typename Flavor::Relations; @@ -558,17 +559,20 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorGenPermSortRelationCorrectness) polynomial_pointers[i + 1]->begin()); }); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/784) + enum ORDERED_RANGE_CONSTRAINTS : size_t { C0 = 85, C1, C2, C3, C4 }; + // Get shifted polynomials prover_polynomials.ordered_range_constraints_0_shift = - polynomial_container[Flavor::ORDERED_RANGE_CONSTRAINTS_0].shifted(); + polynomial_container[ORDERED_RANGE_CONSTRAINTS::C0].shifted(); prover_polynomials.ordered_range_constraints_1_shift = - polynomial_container[Flavor::ORDERED_RANGE_CONSTRAINTS_1].shifted(); + polynomial_container[ORDERED_RANGE_CONSTRAINTS::C1].shifted(); prover_polynomials.ordered_range_constraints_2_shift = - polynomial_container[Flavor::ORDERED_RANGE_CONSTRAINTS_2].shifted(); + polynomial_container[ORDERED_RANGE_CONSTRAINTS::C2].shifted(); prover_polynomials.ordered_range_constraints_3_shift = - polynomial_container[Flavor::ORDERED_RANGE_CONSTRAINTS_3].shifted(); + polynomial_container[ORDERED_RANGE_CONSTRAINTS::C3].shifted(); prover_polynomials.ordered_range_constraints_4_shift = - polynomial_container[Flavor::ORDERED_RANGE_CONSTRAINTS_4].shifted(); + polynomial_container[ORDERED_RANGE_CONSTRAINTS::C4].shifted(); using Relations = typename Flavor::Relations; @@ -1072,22 +1076,22 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorNonNativeRelationCorrectness) auto& engine = numeric::random::get_debug_engine(); - proof_system::ECCOpQueue op_queue; + auto op_queue = std::make_shared(); // Generate random EccOpQueue actions for (size_t i = 0; i < ((Flavor::MINI_CIRCUIT_SIZE >> 1) - 1); i++) { switch (engine.get_random_uint8() & 3) { case 0: - op_queue.empty_row(); + op_queue->empty_row(); break; case 1: - op_queue.eq(); + op_queue->eq(); break; case 2: - op_queue.add_accumulate(GroupElement::random_element(&engine)); + op_queue->add_accumulate(GroupElement::random_element(&engine)); break; case 3: - op_queue.mul_accumulate(GroupElement::random_element(&engine), FF::random_element(&engine)); + op_queue->mul_accumulate(GroupElement::random_element(&engine), FF::random_element(&engine)); break; } } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp index 3100efad8e9..3cd04b03ff1 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp @@ -56,10 +56,6 @@ template class UltraComposer_ { std::shared_ptr compute_commitment_key(size_t circuit_size) { - if (commitment_key) { - return commitment_key; - } - commitment_key = std::make_shared(circuit_size, crs_factory_); return commitment_key; }; @@ -91,9 +87,9 @@ template class UltraComposer_ { * @param size Size of commitment key required to commit to shifted op queue contribution t_i * @return MergeVerifier_ */ - MergeVerifier_ create_merge_verifier(size_t size) + MergeVerifier_ create_merge_verifier(size_t srs_size) { - auto pcs_verification_key = std::make_unique(size, crs_factory_); + auto pcs_verification_key = std::make_unique(srs_size, crs_factory_); return MergeVerifier_(std::move(pcs_verification_key)); }