From 11e848d999b7fe8556bd0f4fb5ce03e4617030a4 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Tue, 8 Apr 2025 12:13:38 +0000 Subject: [PATCH 01/26] create file/folder --- .../primitives/bit_by_bit_decomposition/bit_by_bit.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.hpp diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.hpp new file mode 100644 index 000000000000..e2dc61685492 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.hpp @@ -0,0 +1,8 @@ +#pragma once +#include "../circuit_builders/circuit_builders_fwd.hpp" +#include "../witness/witness.hpp" +#include "barretenberg/transcript/origin_tag.hpp" + +using namespace bb; + +namespace bb::stdlib {} From 3d5de5a322c7c0f51b62958ed185f6fb1d95c4c0 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 9 Apr 2025 10:19:32 +0000 Subject: [PATCH 02/26] added indicator array computation method + test template --- .../cpp/src/barretenberg/constants.hpp | 2 +- .../ultra_recursive_verifier.cpp | 11 ++- .../primitives/biggroup/biggroup.test.cpp | 2 +- .../bit_by_bit_decomposition/bit_by_bit.hpp | 60 ++++++++++++++- .../bit_by_bit.test.cpp | 76 +++++++++++++++++++ 5 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp index 6d6e07e5c4d3..d1914c998650 100644 --- a/barretenberg/cpp/src/barretenberg/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -4,7 +4,7 @@ namespace bb { // The log of the max circuit size assumed in order to achieve constant sized Honk proofs // TODO(https://github.com/AztecProtocol/barretenberg/issues/1046): Remove the need for const sized proofs -static constexpr uint32_t CONST_PROOF_SIZE_LOG_N = 28; +static constexpr uint32_t CONST_PROOF_SIZE_LOG_N = 20; // The log of the max circuit size of circuits being folded. This size is assumed by the PG prover and verifier in order // to ensure a constant PG proof size and a PG recursive verifier circuit that is independent of the size of the diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index 700c0640bbca..c1b5085eff2e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -2,9 +2,9 @@ #include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_delta.hpp" +#include "barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.hpp" #include "barretenberg/stdlib/primitives/public_input_component/public_input_component.hpp" #include "barretenberg/transcript/transcript.hpp" - namespace bb::stdlib::recursion::honk { template @@ -88,6 +88,15 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ typename Curve::ScalarField recursion_separator = Curve::ScalarField::from_witness_index(builder, builder->add_variable(42)); agg_obj.aggregate(nested_agg_obj, recursion_separator); + info(builder->get_estimated_num_finalized_gates()); + auto array_of_bits = compute_padding_indicator_array(key->log_circuit_size); + size_t idx = 0; + for (auto bit : array_of_bits) { + info(idx++, " ", bit); + } + + info(array_of_bits.size()); + info(builder->get_estimated_num_finalized_gates()); // Execute Sumcheck Verifier and extract multivariate opening point u = (u_0, ..., u_{d-1}) and purported // multivariate evaluations at u diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp index 855d970fb951..da752d19ccf0 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp @@ -61,7 +61,7 @@ template class stdlib_biggroup : public testing::Test { Builder builder; affine_element input_a(element::random_element()); - element_ct a = element_ct::from_witness(&builder, input_a); + element_ct a = element_ct::from_witness(builder, input_a); a.set_origin_tag(next_submitted_value_origin_tag); // Tag is preserved after being set EXPECT_EQ(a.get_origin_tag(), next_submitted_value_origin_tag); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.hpp index e2dc61685492..dba3c25ed1b6 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.hpp @@ -3,6 +3,62 @@ #include "../witness/witness.hpp" #include "barretenberg/transcript/origin_tag.hpp" -using namespace bb; +namespace bb::stdlib { -namespace bb::stdlib {} +/** + * @brief For a small N = `domain_size` and a given witness `x`, compute an array [1 `x` times, 0 'domain_size' - + * `x` times] in-circuit. + * 1) Constrain `x` to be in the range [1,..., domain_size - 1] by asserting the product + * \f{align}{ \prod_{i=1}^{N-1} (x - i) == 0 \f}. + * 2) For \f$ i = 0, ..., N-1 \f$, evaluate \f$L_i(x)\f$. Since \f$ 0 < x < N \f$, \f$ L_i(x) = 1 \f$ if and only if + * \f$ x == FF(i)\f$. + * 3) Starting at \f$ b_{N-1} = L_{N-1}(x)\f$, compute partial sums + * \f{align}{b_i = \sum_{i}^{N-1} L_i(x) = L_i(x) + b_{i+1}\f}. + * We compute Lagrange coefficients out-of-circuit, since N is a circuit + * constant. The resulting array is being used to pad the number of Verifier rounds in Sumcheck and Shplemini to a + * fixed constant. + * Note that the number of gates required to compute [b_0,..., b_{N-1}] only depends on N. + */ +template +static std::array compute_padding_indicator_array(const Fr& x) +{ + using Data = BarycentricDataRunTime; + + std::array result{}; + Builder* builder = x.get_context(); + Fr zero{ 0 }; + zero.convert_constant_to_fixed_witness(builder); + // 1) Build prefix products: + // prefix[i] = ∏_{m=0..(i-1)} (x - big_domain[m]), with prefix[0] = 1. + std::vector prefix(domain_size + 1, Fr(1)); + for (size_t i = 0; i < domain_size; ++i) { + prefix[i + 1] = prefix[i] * (x - Data::big_domain[i]); + } + // Range constrain 0 < x < domain_size + prefix.back().assert_equal(zero); + // 2) Build suffix products: + // suffix[i] = ∏_{m=i..(domain_size-1)} (x - big_domain[m]), + // but we'll store it in reverse: + // suffix[domain_size] = 1. + std::vector suffix(domain_size + 1, Fr(1)); + for (size_t i = domain_size; i > 0; i--) { + suffix[i - 1] = suffix[i] * (x - Data::big_domain[i - 1]); + } + + // 3) Combine prefix & suffix to get L_i(x): + // L_i(x) = (1 / lagrange_denominators[i]) * prefix[i] * suffix[i+1]. + // (We skip factor (x - big_domain[i]) by splitting into prefix & suffix.) + for (size_t i = 0; i < domain_size; ++i) { + const Fr inv_denom_i = Data::lagrange_denominators[i].invert(); + result[i] = inv_denom_i * prefix[i] * suffix[i + 1]; + } + // Convert result into the array of partial sums b_i. + for (size_t idx = domain_size - 1; idx > 0; idx--) { + // Use idx - 1 in the body if you prefer + result[idx - 1] += result[idx]; + } + + return result; +} + +} // namespace bb::stdlib diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.test.cpp new file mode 100644 index 000000000000..9e8c18297e65 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.test.cpp @@ -0,0 +1,76 @@ +#include "bit_by_bit.hpp" +#include "../circuit_builders/circuit_builders_fwd.hpp" +#include "../witness/witness.hpp" +#include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/stdlib/primitives/circuit_builders/circuit_builders.hpp" +#include "barretenberg/transcript/origin_tag.hpp" +#include + +using namespace bb; +namespace { +template struct PaddingTestParams { + using Fr = Fr_; + using Builder = Builder_; +}; + +template class PaddingIndicatorArrayTest : public testing::Test { + public: + using Fr = typename Param::Fr; + using Builder = typename Param::Builder; + + static constexpr size_t domain_size = 25; + + public: + void test_value_in_range() + { + for (size_t idx = 1; idx < domain_size; idx++) { + Builder builder; + Fr x = Fr::from_witness(&builder, idx); + + auto result = compute_padding_indicator_array(x); + + EXPECT_TRUE(CircuitChecker::check(builder)); + } + } + + void test_edge_cases() + { + + // Check that log_circuit_size is constrained to be != 0 + { + Builder builder; + + Fr zero = Fr::from_witness(&builder, 0); + + auto result = compute_padding_indicator_array(x); + + EXPECT_FALSE(CircuitChecker::check(builder)); + } + + // Check that log_circuit_size can take the max possible value + { + Builder builder; + + Fr zero = Fr::from_witness(&builder, domain_size); + + auto result = compute_padding_indicator_array(x); + + EXPECT_TRUE(CircuitChecker::check(builder)); + } + } + + void test_value_not_in_range() + { + for (size_t idx = 1; idx < domain_size; idx++) { + Builder builder; + uint256_t scalar_raw = engine.get_random_uint256(); + + Fr x = Fr::from_witness(&builder, scalar_raw); + + auto result = compute_padding_indicator_array(x); + + EXPECT_FALSE(CircuitChecker::check(builder)); + } + } +}; +} // namespace From 44cb8c67800ace57394b8d69717b48144b123d7b Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 9 Apr 2025 10:59:21 +0000 Subject: [PATCH 03/26] fix build --- barretenberg/cpp/src/barretenberg/constants.hpp | 2 +- .../stdlib/primitives/biggroup/biggroup.test.cpp | 2 +- .../bit_by_bit_decomposition/bit_by_bit.test.cpp | 12 +++++++++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp index d1914c998650..6d6e07e5c4d3 100644 --- a/barretenberg/cpp/src/barretenberg/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -4,7 +4,7 @@ namespace bb { // The log of the max circuit size assumed in order to achieve constant sized Honk proofs // TODO(https://github.com/AztecProtocol/barretenberg/issues/1046): Remove the need for const sized proofs -static constexpr uint32_t CONST_PROOF_SIZE_LOG_N = 20; +static constexpr uint32_t CONST_PROOF_SIZE_LOG_N = 28; // The log of the max circuit size of circuits being folded. This size is assumed by the PG prover and verifier in order // to ensure a constant PG proof size and a PG recursive verifier circuit that is independent of the size of the diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp index da752d19ccf0..855d970fb951 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp @@ -61,7 +61,7 @@ template class stdlib_biggroup : public testing::Test { Builder builder; affine_element input_a(element::random_element()); - element_ct a = element_ct::from_witness(builder, input_a); + element_ct a = element_ct::from_witness(&builder, input_a); a.set_origin_tag(next_submitted_value_origin_tag); // Tag is preserved after being set EXPECT_EQ(a.get_origin_tag(), next_submitted_value_origin_tag); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.test.cpp index 9e8c18297e65..2da82fc8ddc9 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.test.cpp @@ -8,6 +8,8 @@ using namespace bb; namespace { +auto& engine = numeric::get_debug_randomness(); + template struct PaddingTestParams { using Fr = Fr_; using Builder = Builder_; @@ -28,6 +30,7 @@ template class PaddingIndicatorArrayTest : public testing::Test Fr x = Fr::from_witness(&builder, idx); auto result = compute_padding_indicator_array(x); + info("num gates = ", builder.get_estimated_num_finalized_gates()); EXPECT_TRUE(CircuitChecker::check(builder)); } @@ -42,7 +45,8 @@ template class PaddingIndicatorArrayTest : public testing::Test Fr zero = Fr::from_witness(&builder, 0); - auto result = compute_padding_indicator_array(x); + auto result = compute_padding_indicator_array(zero); + info("num gates = ", builder.get_estimated_num_finalized_gates()); EXPECT_FALSE(CircuitChecker::check(builder)); } @@ -51,9 +55,10 @@ template class PaddingIndicatorArrayTest : public testing::Test { Builder builder; - Fr zero = Fr::from_witness(&builder, domain_size); + Fr N = Fr::from_witness(&builder, domain_size); - auto result = compute_padding_indicator_array(x); + auto result = compute_padding_indicator_array(N); + info("num gates = ", builder.get_estimated_num_finalized_gates()); EXPECT_TRUE(CircuitChecker::check(builder)); } @@ -68,6 +73,7 @@ template class PaddingIndicatorArrayTest : public testing::Test Fr x = Fr::from_witness(&builder, scalar_raw); auto result = compute_padding_indicator_array(x); + info("num gates = ", builder.get_estimated_num_finalized_gates()); EXPECT_FALSE(CircuitChecker::check(builder)); } From 174e8814bdc2277277513ab16dafef87028cdcf7 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 9 Apr 2025 14:30:46 +0000 Subject: [PATCH 04/26] tests + rename --- .../bit_by_bit.test.cpp | 82 ----------- ...by_bit.hpp => padding_indicator_array.hpp} | 15 +- .../padding_indicator_array.test.cpp | 133 ++++++++++++++++++ 3 files changed, 142 insertions(+), 88 deletions(-) delete mode 100644 barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.test.cpp rename barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/{bit_by_bit.hpp => padding_indicator_array.hpp} (90%) create mode 100644 barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.test.cpp deleted file mode 100644 index 2da82fc8ddc9..000000000000 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.test.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "bit_by_bit.hpp" -#include "../circuit_builders/circuit_builders_fwd.hpp" -#include "../witness/witness.hpp" -#include "barretenberg/circuit_checker/circuit_checker.hpp" -#include "barretenberg/stdlib/primitives/circuit_builders/circuit_builders.hpp" -#include "barretenberg/transcript/origin_tag.hpp" -#include - -using namespace bb; -namespace { -auto& engine = numeric::get_debug_randomness(); - -template struct PaddingTestParams { - using Fr = Fr_; - using Builder = Builder_; -}; - -template class PaddingIndicatorArrayTest : public testing::Test { - public: - using Fr = typename Param::Fr; - using Builder = typename Param::Builder; - - static constexpr size_t domain_size = 25; - - public: - void test_value_in_range() - { - for (size_t idx = 1; idx < domain_size; idx++) { - Builder builder; - Fr x = Fr::from_witness(&builder, idx); - - auto result = compute_padding_indicator_array(x); - info("num gates = ", builder.get_estimated_num_finalized_gates()); - - EXPECT_TRUE(CircuitChecker::check(builder)); - } - } - - void test_edge_cases() - { - - // Check that log_circuit_size is constrained to be != 0 - { - Builder builder; - - Fr zero = Fr::from_witness(&builder, 0); - - auto result = compute_padding_indicator_array(zero); - info("num gates = ", builder.get_estimated_num_finalized_gates()); - - EXPECT_FALSE(CircuitChecker::check(builder)); - } - - // Check that log_circuit_size can take the max possible value - { - Builder builder; - - Fr N = Fr::from_witness(&builder, domain_size); - - auto result = compute_padding_indicator_array(N); - info("num gates = ", builder.get_estimated_num_finalized_gates()); - - EXPECT_TRUE(CircuitChecker::check(builder)); - } - } - - void test_value_not_in_range() - { - for (size_t idx = 1; idx < domain_size; idx++) { - Builder builder; - uint256_t scalar_raw = engine.get_random_uint256(); - - Fr x = Fr::from_witness(&builder, scalar_raw); - - auto result = compute_padding_indicator_array(x); - info("num gates = ", builder.get_estimated_num_finalized_gates()); - - EXPECT_FALSE(CircuitChecker::check(builder)); - } - } -}; -} // namespace diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.hpp similarity index 90% rename from barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.hpp rename to barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.hpp index dba3c25ed1b6..59b99de1e7bc 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.hpp @@ -20,30 +20,33 @@ namespace bb::stdlib { * Note that the number of gates required to compute [b_0,..., b_{N-1}] only depends on N. */ template -static std::array compute_padding_indicator_array(const Fr& x) +static std::array compute_padding_indicator_array(const Fr& log_n) { using Data = BarycentricDataRunTime; std::array result{}; - Builder* builder = x.get_context(); + Builder* builder = log_n.get_context(); Fr zero{ 0 }; zero.convert_constant_to_fixed_witness(builder); // 1) Build prefix products: // prefix[i] = ∏_{m=0..(i-1)} (x - big_domain[m]), with prefix[0] = 1. std::vector prefix(domain_size + 1, Fr(1)); for (size_t i = 0; i < domain_size; ++i) { - prefix[i + 1] = prefix[i] * (x - Data::big_domain[i]); + prefix[i + 1] = prefix[i] * (log_n - Data::big_domain[i]); } - // Range constrain 0 < x < domain_size - prefix.back().assert_equal(zero); + // 2) Build suffix products: // suffix[i] = ∏_{m=i..(domain_size-1)} (x - big_domain[m]), // but we'll store it in reverse: // suffix[domain_size] = 1. std::vector suffix(domain_size + 1, Fr(1)); for (size_t i = domain_size; i > 0; i--) { - suffix[i - 1] = suffix[i] * (x - Data::big_domain[i - 1]); + suffix[i - 1] = suffix[i] * (log_n - Data::big_domain[i - 1]); } + info("suffix 1 ", suffix[1]); + + // Range constrain 0 < x < domain_size + suffix[1].assert_equal(zero); // 3) Combine prefix & suffix to get L_i(x): // L_i(x) = (1 / lagrange_denominators[i]) * prefix[i] * suffix[i+1]. diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.test.cpp new file mode 100644 index 000000000000..b277bc992148 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.test.cpp @@ -0,0 +1,133 @@ +#include "../witness/witness.hpp" +#include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/common/test.hpp" +#include "barretenberg/stdlib/primitives/circuit_builders/circuit_builders.hpp" +#include "barretenberg/transcript/origin_tag.hpp" +#include "bit_by_bit.hpp" + +#include "barretenberg/stdlib/primitives/curves/bn254.hpp" +#include "barretenberg/stdlib/primitives/field/field.hpp" + +using namespace bb; +namespace { +auto& engine = numeric::get_debug_randomness(); + +template struct PaddingTestParams { + using Fr = Fr_; + using Builder = Builder_; +}; + +template class PaddingIndicatorArrayTest : public testing::Test { + public: + using Fr = typename Param::Fr; + using Builder = typename Param::Builder; + + static constexpr size_t domain_size = 25; + + public: + void test_value_in_range() + { + for (size_t idx = 1; idx < domain_size; idx++) { + Builder builder; + Fr x = Fr::from_witness(&builder, idx); + + [[maybe_unused]] auto result = compute_padding_indicator_array(x); + + info("num gates = ", builder.get_estimated_num_finalized_gates()); + + EXPECT_TRUE(CircuitChecker::check(builder)); + } + } + + void test_edge_cases() + { + + // Check that log_circuit_size is constrained to be != 0 + { + Builder builder; + + Fr zero = Fr::from_witness(&builder, 0); + + [[maybe_unused]] auto result = compute_padding_indicator_array(zero); + info("num gates = ", builder.get_estimated_num_finalized_gates()); + + EXPECT_FALSE(CircuitChecker::check(builder)); + } + + // Check that log_circuit_size can take the max possible value + { + Builder builder; + + Fr N = Fr::from_witness(&builder, domain_size - 1); + + [[maybe_unused]] auto result = compute_padding_indicator_array(N); + info("num gates = ", builder.get_estimated_num_finalized_gates()); + + EXPECT_TRUE(CircuitChecker::check(builder)); + } + } + + void test_value_not_in_range() + { + for (size_t idx = 1; idx < domain_size; idx++) { + Builder builder; + uint256_t scalar_raw = engine.get_random_uint256(); + + Fr x = Fr::from_witness(&builder, scalar_raw); + + compute_padding_indicator_array(x); + info("num gates = ", builder.get_estimated_num_finalized_gates()); + + EXPECT_FALSE(CircuitChecker::check(builder)); + } + } + void test_gate_count_independence() + { + auto get_gate_count = [](const uint256_t& scalar_raw) -> size_t { + Builder builder; + Fr x = Fr::from_witness(&builder, scalar_raw); + [[maybe_unused]] auto result = compute_padding_indicator_array(x); + + size_t gate_count = builder.get_estimated_num_finalized_gates(); + info("x = ", x.get_value(), ", gates = ", gate_count); + return gate_count; + }; + + // Valid input: x in [1, domain_size - 1] + uint256_t x_in_range = (domain_size - 1) / 2; + size_t gates_in_range = get_gate_count(x_in_range); + + // Random input + uint256_t random_scalar = engine.get_random_uint256(); + size_t gates_random = get_gate_count(random_scalar); + + EXPECT_EQ(gates_in_range, gates_random); + } +}; + +using TestTypes = testing::Types< + PaddingTestParams>>::ScalarField, + bb::MegaCircuitBuilder>, + PaddingTestParams::ScalarField, bb::UltraCircuitBuilder>, + PaddingTestParams::ScalarField, bb::CircuitSimulatorBN254>>; + +TYPED_TEST_SUITE(PaddingIndicatorArrayTest, TestTypes); + +TYPED_TEST(PaddingIndicatorArrayTest, TestValueInRange) +{ + TestFixture::test_value_in_range(); +} + +TYPED_TEST(PaddingIndicatorArrayTest, TestEdgeCases) +{ + TestFixture::test_edge_cases(); +} +TYPED_TEST(PaddingIndicatorArrayTest, TestValueNotInrange) +{ + TestFixture::test_value_not_in_range(); +} +TYPED_TEST(PaddingIndicatorArrayTest, TestGateCountIndependence) +{ + TestFixture::test_gate_count_independence(); +} +} // namespace From 3ce110da2eeb93d45e1dbf0f5f0ffd45fbbc99b4 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 9 Apr 2025 14:34:11 +0000 Subject: [PATCH 05/26] undo changes in UH recursive --- .../stdlib/honk_verifier/ultra_recursive_verifier.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index c1b5085eff2e..700c0640bbca 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -2,9 +2,9 @@ #include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_delta.hpp" -#include "barretenberg/stdlib/primitives/bit_by_bit_decomposition/bit_by_bit.hpp" #include "barretenberg/stdlib/primitives/public_input_component/public_input_component.hpp" #include "barretenberg/transcript/transcript.hpp" + namespace bb::stdlib::recursion::honk { template @@ -88,15 +88,6 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ typename Curve::ScalarField recursion_separator = Curve::ScalarField::from_witness_index(builder, builder->add_variable(42)); agg_obj.aggregate(nested_agg_obj, recursion_separator); - info(builder->get_estimated_num_finalized_gates()); - auto array_of_bits = compute_padding_indicator_array(key->log_circuit_size); - size_t idx = 0; - for (auto bit : array_of_bits) { - info(idx++, " ", bit); - } - - info(array_of_bits.size()); - info(builder->get_estimated_num_finalized_gates()); // Execute Sumcheck Verifier and extract multivariate opening point u = (u_0, ..., u_{d-1}) and purported // multivariate evaluations at u From 1b4a34d248477636640ef1ea6fc0d4b22d0b6c0e Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 9 Apr 2025 14:56:30 +0000 Subject: [PATCH 06/26] fix build --- .../bit_by_bit_decomposition/padding_indicator_array.test.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.test.cpp index b277bc992148..7de296d532f6 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.test.cpp @@ -1,9 +1,8 @@ +#include "padding_indicator_array.hpp" #include "../witness/witness.hpp" #include "barretenberg/circuit_checker/circuit_checker.hpp" #include "barretenberg/common/test.hpp" #include "barretenberg/stdlib/primitives/circuit_builders/circuit_builders.hpp" -#include "barretenberg/transcript/origin_tag.hpp" -#include "bit_by_bit.hpp" #include "barretenberg/stdlib/primitives/curves/bn254.hpp" #include "barretenberg/stdlib/primitives/field/field.hpp" From ff18da454ea8b1ee5b64a05ddda69994204a0074 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 10 Apr 2025 08:22:29 +0000 Subject: [PATCH 07/26] rename+docs --- .../padding_indicator_array.hpp | 67 ----------------- .../padding_indicator_array.hpp | 75 +++++++++++++++++++ .../padding_indicator_array.test.cpp | 3 +- 3 files changed, 77 insertions(+), 68 deletions(-) delete mode 100644 barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.hpp create mode 100644 barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp rename barretenberg/cpp/src/barretenberg/stdlib/primitives/{bit_by_bit_decomposition => padding_indicator_array}/padding_indicator_array.test.cpp (96%) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.hpp deleted file mode 100644 index 59b99de1e7bc..000000000000 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once -#include "../circuit_builders/circuit_builders_fwd.hpp" -#include "../witness/witness.hpp" -#include "barretenberg/transcript/origin_tag.hpp" - -namespace bb::stdlib { - -/** - * @brief For a small N = `domain_size` and a given witness `x`, compute an array [1 `x` times, 0 'domain_size' - - * `x` times] in-circuit. - * 1) Constrain `x` to be in the range [1,..., domain_size - 1] by asserting the product - * \f{align}{ \prod_{i=1}^{N-1} (x - i) == 0 \f}. - * 2) For \f$ i = 0, ..., N-1 \f$, evaluate \f$L_i(x)\f$. Since \f$ 0 < x < N \f$, \f$ L_i(x) = 1 \f$ if and only if - * \f$ x == FF(i)\f$. - * 3) Starting at \f$ b_{N-1} = L_{N-1}(x)\f$, compute partial sums - * \f{align}{b_i = \sum_{i}^{N-1} L_i(x) = L_i(x) + b_{i+1}\f}. - * We compute Lagrange coefficients out-of-circuit, since N is a circuit - * constant. The resulting array is being used to pad the number of Verifier rounds in Sumcheck and Shplemini to a - * fixed constant. - * Note that the number of gates required to compute [b_0,..., b_{N-1}] only depends on N. - */ -template -static std::array compute_padding_indicator_array(const Fr& log_n) -{ - using Data = BarycentricDataRunTime; - - std::array result{}; - Builder* builder = log_n.get_context(); - Fr zero{ 0 }; - zero.convert_constant_to_fixed_witness(builder); - // 1) Build prefix products: - // prefix[i] = ∏_{m=0..(i-1)} (x - big_domain[m]), with prefix[0] = 1. - std::vector prefix(domain_size + 1, Fr(1)); - for (size_t i = 0; i < domain_size; ++i) { - prefix[i + 1] = prefix[i] * (log_n - Data::big_domain[i]); - } - - // 2) Build suffix products: - // suffix[i] = ∏_{m=i..(domain_size-1)} (x - big_domain[m]), - // but we'll store it in reverse: - // suffix[domain_size] = 1. - std::vector suffix(domain_size + 1, Fr(1)); - for (size_t i = domain_size; i > 0; i--) { - suffix[i - 1] = suffix[i] * (log_n - Data::big_domain[i - 1]); - } - info("suffix 1 ", suffix[1]); - - // Range constrain 0 < x < domain_size - suffix[1].assert_equal(zero); - - // 3) Combine prefix & suffix to get L_i(x): - // L_i(x) = (1 / lagrange_denominators[i]) * prefix[i] * suffix[i+1]. - // (We skip factor (x - big_domain[i]) by splitting into prefix & suffix.) - for (size_t i = 0; i < domain_size; ++i) { - const Fr inv_denom_i = Data::lagrange_denominators[i].invert(); - result[i] = inv_denom_i * prefix[i] * suffix[i + 1]; - } - // Convert result into the array of partial sums b_i. - for (size_t idx = domain_size - 1; idx > 0; idx--) { - // Use idx - 1 in the body if you prefer - result[idx - 1] += result[idx]; - } - - return result; -} - -} // namespace bb::stdlib diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp new file mode 100644 index 000000000000..d64ec6613e08 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp @@ -0,0 +1,75 @@ +#pragma once +#include "../circuit_builders/circuit_builders_fwd.hpp" +#include "../witness/witness.hpp" + +namespace bb::stdlib { + +/** + * @brief For a small integer N = `virtual_log_n` and a given witness x = `log_n`, compute in-circuit an + * `indicator_padding_array` of size N, such that + * \f{align}{ \text{indicator_padding_array}[i] = `` i < x ". \f} + * + * 1) Constrain x to be in the range [1,..., N - 1] by asserting + * \f{align}{ \prod_{i=1}^{N-1} (x - i) == 0 \f}. + * + * 2) For \f$ i = 0, ..., N-1 \f$, evaluate \f$L_i(x)\f$. + * Since \f$ 0 < x < N \f$, \f$ L_i(x) = 1 \f$ if and only if \f$ x == FF(i)\f$. + * + * 3) Starting at \f$ b_{N-1} = L_{N-1}(x)\f$, compute the step functions + * \f{align}{ + * b_i(x) = \sum_{i}^{N-1} L_i(x) = L_i(x) + b_{i+1}(x) \f}. + * + * We compute Lagrange coefficients out-of-circuit, since N is a circuit constant. + * + * The resulting array is being used to pad the number of Verifier rounds in Sumcheck and Shplemini to a fixed constant + * and turn Recursive Verifier circuits into constant circuits. Note that the number of gates required to compute + * [b_0(x),..., b_{N-1}(x)] only depends on N. + * + */ +template +static std::array compute_padding_indicator_array(const Fr& log_n) +{ + // Create a domain of size `virtual_log_n` and compute Lagrange denominators + using Data = BarycentricDataRunTime; + + std::array result{}; + Builder* builder = log_n.get_context(); + Fr zero{ 0 }; + zero.convert_constant_to_fixed_witness(builder); + // 1) Build prefix products: + // prefix[i] = ∏_{m=0..(i-1)} (x - big_domain[m]), with prefix[0] = 1. + std::vector prefix(virtual_log_n + 1, Fr(1)); + for (size_t i = 0; i < virtual_log_n; ++i) { + prefix[i + 1] = prefix[i] * (log_n - Data::big_domain[i]); + } + + // 2) Build suffix products: + // suffix[i] = ∏_{m=i..(virtual_log_n-1)} (x - big_domain[m]), + // but we'll store it in reverse: + // suffix[virtual_log_n] = 1. + std::vector suffix(virtual_log_n + 1, Fr(1)); + for (size_t i = virtual_log_n; i > 0; i--) { + suffix[i - 1] = suffix[i] * (log_n - Data::big_domain[i - 1]); + } + + // To ensure 0 < log_n < N, note that suffix[1] = \prod_{i=1}^{N-1} (x - i), therefore we just need to ensure + // that this product is 0. + suffix[1].assert_equal(zero); + + // 3) Combine prefixes & suffixes to get L_i(x): + // L_i(x) = (1 / lagrange_denominators[i]) * prefix[i] * suffix[i+1]. + // (We skip factor (x - big_domain[i]) by splitting into prefix & suffix.) + for (size_t i = 0; i < virtual_log_n; ++i) { + const Fr inv_denom_i = Data::lagrange_denominators[i].invert(); + result[i] = inv_denom_i * prefix[i] * suffix[i + 1]; + } + // Convert result into the array of step function evaluations sums b_i. + for (size_t idx = virtual_log_n - 1; idx > 0; idx--) { + // Use idx - 1 in the body if you prefer + result[idx - 1] += result[idx]; + } + + return result; +} + +} // namespace bb::stdlib diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp similarity index 96% rename from barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.test.cpp rename to barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp index 7de296d532f6..fa87e9bff49d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bit_by_bit_decomposition/padding_indicator_array.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp @@ -30,7 +30,8 @@ template class PaddingIndicatorArrayTest : public testing::Test Builder builder; Fr x = Fr::from_witness(&builder, idx); - [[maybe_unused]] auto result = compute_padding_indicator_array(x); + auto result = compute_padding_indicator_array(x); + EXPECT_TRUE(result[idx - 1].get_value() == 1); info("num gates = ", builder.get_estimated_num_finalized_gates()); From 56b25b243056b16f5dc2fb20159c219cab2eec14 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 10 Apr 2025 08:28:27 +0000 Subject: [PATCH 08/26] stray info --- .../padding_indicator_array/padding_indicator_array.test.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp index fa87e9bff49d..5fb7362b8b3b 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp @@ -75,7 +75,7 @@ template class PaddingIndicatorArrayTest : public testing::Test Fr x = Fr::from_witness(&builder, scalar_raw); - compute_padding_indicator_array(x); + [[maybe_unused]] auto result = compute_padding_indicator_array(x); info("num gates = ", builder.get_estimated_num_finalized_gates()); EXPECT_FALSE(CircuitChecker::check(builder)); @@ -89,7 +89,6 @@ template class PaddingIndicatorArrayTest : public testing::Test [[maybe_unused]] auto result = compute_padding_indicator_array(x); size_t gate_count = builder.get_estimated_num_finalized_gates(); - info("x = ", x.get_value(), ", gates = ", gate_count); return gate_count; }; From c33a1b04eb50c12eb1f54552a9a7f4ee596575ce Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 10 Apr 2025 11:14:50 +0000 Subject: [PATCH 09/26] split shplemini into padding/non padding --- .../commitment_schemes/shplonk/shplemini.hpp | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 04179cbd1c25..4773327ecf46 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -420,6 +420,172 @@ template class ShpleminiVerifier_ { return { commitments, scalars, shplonk_evaluation_challenge }; }; + // padding enabled + template + static BatchOpeningClaim compute_batch_opening_claim( + const std::array padding_indicator_array, + ClaimBatcher& claim_batcher, + const std::vector& multivariate_challenge, + const Commitment& g1_identity, + const std::shared_ptr& transcript, + const RepeatedCommitmentsData& repeated_commitments = {}, + const bool has_zk = false, + bool* consistency_checked = nullptr, // TODO(https://github.com/AztecProtocol/barretenberg/issues/1191). + // Shplemini Refactoring: Remove bool pointer + const std::array& libra_commitments = {}, + const Fr& libra_univariate_evaluation = Fr{ 0 }) + + { + + Fr batched_evaluation = Fr{ 0 }; + + // While Shplemini is not templated on Flavor, we derive ZK flag this way + Commitment hiding_polynomial_commitment; + if (has_zk) { + hiding_polynomial_commitment = + transcript->template receive_from_prover("Gemini:masking_poly_comm"); + batched_evaluation = transcript->template receive_from_prover("Gemini:masking_poly_eval"); + } + + // Get the challenge ρ to batch commitments to multilinear polynomials and their shifts + const Fr gemini_batching_challenge = transcript->template get_challenge("rho"); + + // Process Gemini transcript data: + // - Get Gemini commitments (com(A₁), com(A₂), … , com(Aₙ₋₁)) + const std::vector fold_commitments = + GeminiVerifier::get_fold_commitments(virtual_log_n, transcript); + // - Get Gemini evaluation challenge for Aᵢ, i = 0, … , d−1 + const Fr gemini_evaluation_challenge = transcript->template get_challenge("Gemini:r"); + + // - Get evaluations (A₀(−r), A₁(−r²), ... , Aₙ₋₁(−r²⁽ⁿ⁻¹⁾)) + const std::vector gemini_fold_neg_evaluations = + GeminiVerifier::get_gemini_evaluations(virtual_log_n, transcript); + + // - Compute vector (r, r², ... , r^{2^{d-1}}), where d = log_n + const std::vector gemini_eval_challenge_powers = + gemini::powers_of_evaluation_challenge(gemini_evaluation_challenge, virtual_log_n); + + std::array libra_evaluations; + if (has_zk) { + libra_evaluations[0] = transcript->template receive_from_prover("Libra:concatenation_eval"); + libra_evaluations[1] = transcript->template receive_from_prover("Libra:shifted_grand_sum_eval"); + libra_evaluations[2] = transcript->template receive_from_prover("Libra:grand_sum_eval"); + libra_evaluations[3] = transcript->template receive_from_prover("Libra:quotient_eval"); + } + + // Process Shplonk transcript data: + // - Get Shplonk batching challenge + const Fr shplonk_batching_challenge = transcript->template get_challenge("Shplonk:nu"); + + // Compute the powers of ν that are required for batching Gemini, SmallSubgroupIPA, and committed sumcheck + // univariate opening claims. + const std::vector shplonk_batching_challenge_powers = + compute_shplonk_batching_challenge_powers(shplonk_batching_challenge, virtual_log_n, has_zk); + // - Get the quotient commitment for the Shplonk batching of Gemini opening claims + const auto Q_commitment = transcript->template receive_from_prover("Shplonk:Q"); + + // Start populating the vector (Q, f₀, ... , fₖ₋₁, g₀, ... , gₘ₋₁, com(A₁), ... , com(A_{d-1}), [1]₁) where fᵢ + // are the k commitments to unshifted polynomials and gⱼ are the m commitments to shifted polynomials + std::vector commitments{ Q_commitment }; + + // Get Shplonk opening point z + const Fr shplonk_evaluation_challenge = transcript->template get_challenge("Shplonk:z"); + + // Start computing the scalar to be multiplied by [1]₁ + Fr constant_term_accumulator = Fr(0); + + // Initialize the vector of scalars placing the scalar 1 correposnding to Q_commitment + std::vector scalars; + if constexpr (Curve::is_stdlib_type) { + auto builder = shplonk_batching_challenge.get_context(); + scalars.emplace_back(Fr(builder, 1)); + } else { + scalars.emplace_back(Fr(1)); + } + + // Compute 1/(z − r), 1/(z + r), 1/(z - r²), 1/(z + r²), … , 1/(z - r^{2^{d-1}}), 1/(z + r^{2^{d-1}}) + // These represent the denominators of the summand terms in Shplonk partially evaluated polynomial Q_z + const std::vector inverse_vanishing_evals = ShplonkVerifier::compute_inverted_gemini_denominators( + shplonk_evaluation_challenge, gemini_eval_challenge_powers); + // Compute the additional factors to be multiplied with unshifted and shifted commitments when lazily + // reconstructing the commitment of Q_z + claim_batcher.compute_scalars_for_each_batch(inverse_vanishing_evals[0], // 1/(z − r) + inverse_vanishing_evals[1], // 1/(z + r) + shplonk_batching_challenge, + gemini_evaluation_challenge); + + if (has_zk) { + commitments.emplace_back(hiding_polynomial_commitment); + scalars.emplace_back(-claim_batcher.get_unshifted_batch_scalar()); // corresponds to ρ⁰ + } + + // Place the commitments to prover polynomials in the commitments vector. Compute the evaluation of the + // batched multilinear polynomial. Populate the vector of scalars for the final batch mul + + Fr gemini_batching_challenge_power = Fr(1); + if (has_zk) { + // ρ⁰ is used to batch the hiding polynomial which has already been added to the commitments vector + gemini_batching_challenge_power *= gemini_batching_challenge; + } + + // Update the commitments and scalars vectors as well as the batched evaluation given the present batches + claim_batcher.update_batch_mul_inputs_and_batched_evaluation( + commitments, scalars, batched_evaluation, gemini_batching_challenge, gemini_batching_challenge_power); + + // Reconstruct Aᵢ(r²ⁱ) for i=0, ..., d - 1 from the batched evaluation of the multilinear polynomials and + // Aᵢ(−r²ⁱ) for i = 0, ..., d - 1. In the case of interleaving, we compute A₀(r) as A₀₊(r) + P₊(r^s). + const std::vector gemini_fold_pos_evaluations = + GeminiVerifier_::compute_fold_pos_evaluations(log_n, + batched_evaluation, + multivariate_challenge, + gemini_eval_challenge_powers, + gemini_fold_neg_evaluations); + + // Place the commitments to Gemini fold polynomials Aᵢ in the vector of batch_mul commitments, compute the + // contributions from Aᵢ(−r²ⁱ) for i=1, … , d − 1 to the constant term accumulator, add corresponding scalars + // for the batch mul + batch_gemini_claims_received_from_prover(log_n, + fold_commitments, + gemini_fold_neg_evaluations, + gemini_fold_pos_evaluations, + inverse_vanishing_evals, + shplonk_batching_challenge_powers, + commitments, + scalars, + constant_term_accumulator); + // Add contributions from A₀₊(r) and A₀₋(-r) to constant_term_accumulator: + // Add A₀₊(r)/(z−r) to the constant term accumulator + constant_term_accumulator += gemini_fold_pos_evaluations[0] * inverse_vanishing_evals[0]; + // Add A₀₋(-r)/(z+r) to the constant term accumulator + constant_term_accumulator += + gemini_fold_neg_evaluations[0] * shplonk_batching_challenge * inverse_vanishing_evals[1]; + + remove_repeated_commitments(commitments, scalars, repeated_commitments, has_zk); + + // For ZK flavors, the sumcheck output contains the evaluations of Libra univariates that submitted to the + // ShpleminiVerifier, otherwise this argument is set to be empty + if (has_zk) { + add_zk_data(virtual_log_n, + commitments, + scalars, + constant_term_accumulator, + libra_commitments, + libra_evaluations, + gemini_evaluation_challenge, + shplonk_batching_challenge_powers, + shplonk_evaluation_challenge); + + *consistency_checked = SmallSubgroupIPAVerifier::check_libra_evaluations_consistency( + libra_evaluations, gemini_evaluation_challenge, multivariate_challenge, libra_univariate_evaluation); + } + + // Finalize the batch opening claim + commitments.emplace_back(g1_identity); + scalars.emplace_back(constant_term_accumulator); + + return { commitments, scalars, shplonk_evaluation_challenge }; + }; + /** * @brief Place fold polynomial commitments to `commitments` and compute the corresponding scalar multipliers. * From f99869beb0ad0047c602ab8b85c47b71b6576bd1 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 10 Apr 2025 11:53:10 +0000 Subject: [PATCH 10/26] small fix for barycentric data to access inverted denominators --- barretenberg/cpp/src/barretenberg/polynomials/barycentric.hpp | 3 ++- .../padding_indicator_array/padding_indicator_array.hpp | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/polynomials/barycentric.hpp b/barretenberg/cpp/src/barretenberg/polynomials/barycentric.hpp index f9c25d981fd4..61a8422b5dd3 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/barycentric.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/barycentric.hpp @@ -195,7 +195,8 @@ template construct_denominator_inverses(const auto& big_domain, const auto& lagrange_denominators) { - std::array result{}; // default init to 0 since below does not init all elements + std::array result = + lagrange_denominators; // default init to 0 since below does not init all elements for (size_t k = domain_size; k < num_evals; ++k) { for (size_t j = 0; j < domain_size; ++j) { Fr inv = lagrange_denominators[j]; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp index d64ec6613e08..3fe9942e9a9b 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp @@ -60,8 +60,7 @@ static std::array compute_padding_indicator_array(const Fr& l // L_i(x) = (1 / lagrange_denominators[i]) * prefix[i] * suffix[i+1]. // (We skip factor (x - big_domain[i]) by splitting into prefix & suffix.) for (size_t i = 0; i < virtual_log_n; ++i) { - const Fr inv_denom_i = Data::lagrange_denominators[i].invert(); - result[i] = inv_denom_i * prefix[i] * suffix[i + 1]; + result[i] = Data::precomputed_denominator_inverses[i] * prefix[i] * suffix[i + 1]; } // Convert result into the array of step function evaluations sums b_i. for (size_t idx = virtual_log_n - 1; idx > 0; idx--) { From c2b45b79181961f8b9da40148c9fd99dc7e7169a Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 10 Apr 2025 12:09:18 +0000 Subject: [PATCH 11/26] fix doxygen --- .../padding_indicator_array.hpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp index 3fe9942e9a9b..a0447e412246 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp @@ -5,25 +5,26 @@ namespace bb::stdlib { /** + * @file * @brief For a small integer N = `virtual_log_n` and a given witness x = `log_n`, compute in-circuit an - * `indicator_padding_array` of size N, such that - * \f{align}{ \text{indicator_padding_array}[i] = `` i < x ". \f} + * `indicator_padding_array` of size \f$ N \f$, such that + * \f{align}{ \text{indicator_padding_array}[i] = \text{"} i < x \text{"}. \f} * - * 1) Constrain x to be in the range [1,..., N - 1] by asserting - * \f{align}{ \prod_{i=1}^{N-1} (x - i) == 0 \f}. + * 1) Constrain x to be in the range \f$ [1, \ldots, N - 1] \f$ by asserting + * \f{align}{ \prod_{i=1}^{N-1} (x - i) = 0 \f}. * - * 2) For \f$ i = 0, ..., N-1 \f$, evaluate \f$L_i(x)\f$. - * Since \f$ 0 < x < N \f$, \f$ L_i(x) = 1 \f$ if and only if \f$ x == FF(i)\f$. + * 2) For \f$ i = 0, ..., N-1 \f$, evaluate \f$ L_i(x) \f$. + * Since \f$ 0 < x < N \f$, \f$ L_i(x) = 1 \f$ if and only if \f$ x = FF(i) \f$. * * 3) Starting at \f$ b_{N-1} = L_{N-1}(x)\f$, compute the step functions * \f{align}{ * b_i(x) = \sum_{i}^{N-1} L_i(x) = L_i(x) + b_{i+1}(x) \f}. * - * We compute Lagrange coefficients out-of-circuit, since N is a circuit constant. + * We compute the Lagrange coefficients out-of-circuit, since \f$ N \f$ is a circuit constant. * * The resulting array is being used to pad the number of Verifier rounds in Sumcheck and Shplemini to a fixed constant * and turn Recursive Verifier circuits into constant circuits. Note that the number of gates required to compute - * [b_0(x),..., b_{N-1}(x)] only depends on N. + * \f$ [b_0(x), \ldots, b_{N-1}(x)] \f$ only depends on \f$ N \f$ adding ~\f$ 4\cdot N \f$ gates to the circuit. * */ template From 239190f0a94f20d4cf5ed10244ec77ae598452be Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 10 Apr 2025 13:27:57 +0000 Subject: [PATCH 12/26] fix build --- .../barretenberg/polynomials/barycentric.hpp | 19 ++++++++++++------- .../padding_indicator_array.hpp | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/polynomials/barycentric.hpp b/barretenberg/cpp/src/barretenberg/polynomials/barycentric.hpp index 61a8422b5dd3..05a254491305 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/barycentric.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/barycentric.hpp @@ -195,13 +195,18 @@ template construct_denominator_inverses(const auto& big_domain, const auto& lagrange_denominators) { - std::array result = - lagrange_denominators; // default init to 0 since below does not init all elements - for (size_t k = domain_size; k < num_evals; ++k) { - for (size_t j = 0; j < domain_size; ++j) { - Fr inv = lagrange_denominators[j]; - inv *= (big_domain[k] - big_domain[j]); - result[k * domain_size + j] = inv; + std::array result{}; // default init to 0 since below does not init all elements + if constexpr (num_evals == 1) { + result = lagrange_denominators; + } else { + // Used in Univariate's `extend_to` method to extend univariates given by > 4 evaluations ( deg>3 ) to a + // bigger evaluation domains. + for (size_t k = domain_size; k < num_evals; ++k) { + for (size_t j = 0; j < domain_size; ++j) { + Fr inv = lagrange_denominators[j]; + inv *= (big_domain[k] - big_domain[j]); + result[k * domain_size + j] = inv; + } } } return batch_invert(result); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp index a0447e412246..8357e54c7e55 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp @@ -31,7 +31,7 @@ template static std::array compute_padding_indicator_array(const Fr& log_n) { // Create a domain of size `virtual_log_n` and compute Lagrange denominators - using Data = BarycentricDataRunTime; + using Data = BarycentricDataRunTime; std::array result{}; Builder* builder = log_n.get_context(); From 8df3c2209e0040c8ef284d373fc1cadb07e17fdc Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 10 Apr 2025 15:48:17 +0000 Subject: [PATCH 13/26] integrating --- .../commitment_schemes/gemini/gemini.hpp | 46 +++++++++++++++ .../commitment_schemes/shplonk/shplemini.hpp | 57 ++++++++++++++----- .../ultra_recursive_verifier.cpp | 10 +++- 3 files changed, 97 insertions(+), 16 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index 15fa3c53c632..1646328272e7 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -595,6 +595,52 @@ template class GeminiVerifier_ { value_to_emplace = dummy_round ? zero : eval_pos_prev; }; fold_pos_evaluations.emplace_back(value_to_emplace); + info("native , l = ", l - 1, " value ", value_to_emplace); + } + + std::reverse(fold_pos_evaluations.begin(), fold_pos_evaluations.end()); + + return fold_pos_evaluations; + } + template + static std::vector compute_fold_pos_evaluations( + const std::array& padding_indicator_array, + const Fr& batched_evaluation, + std::span evaluation_point, // CONST_PROOF_SIZE + std::span challenge_powers, // r_squares CONST_PROOF_SIZE_LOG_N + std::span fold_neg_evals) + { + std::vector evals(fold_neg_evals.begin(), fold_neg_evals.end()); + + Fr eval_pos_prev = batched_evaluation; + + std::vector fold_pos_evaluations; + fold_pos_evaluations.reserve(virtual_log_n); + // Either a computed eval of A_i at r^{2^i}, or 0 + Fr value_to_emplace; + + // Solve the sequence of linear equations + for (size_t l = virtual_log_n; l != 0; --l) { + // Get r²⁽ˡ⁻¹⁾ + const Fr& challenge_power = challenge_powers[l - 1]; + // Get uₗ₋₁ + const Fr& u = evaluation_point[l - 1]; + const Fr& eval_neg = evals[l - 1]; + // Get A₍ₗ₋₁₎(−r²⁽ˡ⁻¹⁾) + // Compute the numerator + Fr eval_pos = ((challenge_power * eval_pos_prev * 2) - eval_neg * (challenge_power * (Fr(1) - u) - u)); + // Divide by the denominator + eval_pos *= (challenge_power * (Fr(1) - u) + u).invert(); + + // If current index is bigger than log_n, we propagate `batched_evaluation` to the next + // round. Otherwise, current `eval_pos` A₍ₗ₋₁₎(−r²⁽ˡ⁻¹⁾) becomes `eval_pos_prev` in the round l-2. + eval_pos_prev = + padding_indicator_array[l - 1] * eval_pos + (Fr{ 1 } - padding_indicator_array[l - 1]) * eval_pos_prev; + // If current index is bigger than log_n, we emplace 0, which is later multiplied against + // Commitment::one(). + value_to_emplace = padding_indicator_array[l - 1] * eval_pos_prev; + fold_pos_evaluations.emplace_back(value_to_emplace); + info("recursive , l = ", l - 1, " value ", value_to_emplace); } std::reverse(fold_pos_evaluations.begin(), fold_pos_evaluations.end()); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 4773327ecf46..ebee104d6b17 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -423,7 +423,7 @@ template class ShpleminiVerifier_ { // padding enabled template static BatchOpeningClaim compute_batch_opening_claim( - const std::array padding_indicator_array, + const std::array& padding_indicator_array, ClaimBatcher& claim_batcher, const std::vector& multivariate_challenge, const Commitment& g1_identity, @@ -535,7 +535,7 @@ template class ShpleminiVerifier_ { // Reconstruct Aᵢ(r²ⁱ) for i=0, ..., d - 1 from the batched evaluation of the multilinear polynomials and // Aᵢ(−r²ⁱ) for i = 0, ..., d - 1. In the case of interleaving, we compute A₀(r) as A₀₊(r) + P₊(r^s). const std::vector gemini_fold_pos_evaluations = - GeminiVerifier_::compute_fold_pos_evaluations(log_n, + GeminiVerifier_::compute_fold_pos_evaluations(padding_indicator_array, batched_evaluation, multivariate_challenge, gemini_eval_challenge_powers, @@ -544,7 +544,7 @@ template class ShpleminiVerifier_ { // Place the commitments to Gemini fold polynomials Aᵢ in the vector of batch_mul commitments, compute the // contributions from Aᵢ(−r²ⁱ) for i=1, … , d − 1 to the constant term accumulator, add corresponding scalars // for the batch mul - batch_gemini_claims_received_from_prover(log_n, + batch_gemini_claims_received_from_prover(padding_indicator_array, fold_commitments, gemini_fold_neg_evaluations, gemini_fold_pos_evaluations, @@ -658,18 +658,9 @@ template class ShpleminiVerifier_ { constant_term_accumulator += scaling_factor_neg * gemini_neg_evaluations[j] + scaling_factor_pos * gemini_pos_evaluations[j]; - if constexpr (Curve::is_stdlib_type) { - auto builder = gemini_neg_evaluations[0].get_context(); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): insecure! - stdlib::bool_t dummy_round = stdlib::witness_t(builder, j >= log_n); - Fr zero = Fr(0); - scaling_factor_neg = Fr::conditional_assign(dummy_round, zero, scaling_factor_neg); - scaling_factor_pos = Fr::conditional_assign(dummy_round, zero, scaling_factor_pos); - } else { - if (j >= log_n) { - scaling_factor_neg = 0; - scaling_factor_pos = 0; - } + if (j >= log_n) { + scaling_factor_neg = 0; + scaling_factor_pos = 0; } // Place the scaling factor to the 'scalars' vector scalars.emplace_back(-scaling_factor_neg - scaling_factor_pos); @@ -677,6 +668,42 @@ template class ShpleminiVerifier_ { commitments.emplace_back(std::move(fold_commitments[j - 1])); } } + template + static void batch_gemini_claims_received_from_prover(const std::array padding_indicator_array, + const std::vector& fold_commitments, + const std::vector& gemini_neg_evaluations, + const std::vector& gemini_pos_evaluations, + const std::vector& inverse_vanishing_evals, + const std::vector& shplonk_batching_challenge_powers, + std::vector& commitments, + std::vector& scalars, + Fr& constant_term_accumulator) + { + + // Start from 1, because the commitment to A_0 is reconstructed from the commitments to the multilinear + // polynomials. The corresponding evaluations are also handled separately. + for (size_t j = 1; j < virtual_log_n; ++j) { + // The index of 1/ (z - r^{2^{j}}) in the vector of inverted Gemini denominators + const size_t pos_index = 2 * j; + // The index of 1/ (z + r^{2^{j}}) in the vector of inverted Gemini denominators + const size_t neg_index = 2 * j + 1; + + // Compute the "positive" scaling factor (ν^{2j}) / (z - r^{2^{j}}) + Fr scaling_factor_pos = shplonk_batching_challenge_powers[pos_index] * inverse_vanishing_evals[pos_index]; + // Compute the "negative" scaling factor (ν^{2j+1}) / (z + r^{2^{j}}) + Fr scaling_factor_neg = shplonk_batching_challenge_powers[neg_index] * inverse_vanishing_evals[neg_index]; + + // Accumulate the const term contribution given by + // v^{2j} * A_j(r^{2^j}) /(z - r^{2^j}) + v^{2j+1} * A_j(-r^{2^j}) /(z+ r^{2^j}) + constant_term_accumulator += + scaling_factor_neg * gemini_neg_evaluations[j] + scaling_factor_pos * gemini_pos_evaluations[j]; + + // Place the scaling factor to the 'scalars' vector + scalars.emplace_back(-padding_indicator_array[j] * (scaling_factor_neg + scaling_factor_pos)); + // Move com(Aᵢ) to the 'commitments' vector + commitments.emplace_back(std::move(fold_commitments[j - 1])); + } + } /** * @brief Combines scalars of repeating commitments to reduce the number of scalar multiplications performed by the diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index 700c0640bbca..f9429e724830 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -2,6 +2,7 @@ #include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_delta.hpp" +#include "barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp" #include "barretenberg/stdlib/primitives/public_input_component/public_input_component.hpp" #include "barretenberg/transcript/transcript.hpp" @@ -93,6 +94,13 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ // multivariate evaluations at u // TODO(https://github.com/AztecProtocol/barretenberg/issues/1283): Suspicious get_value(). const size_t log_circuit_size = numeric::get_msb(static_cast(key->circuit_size.get_value())); + + const auto padding_indicator_array = + compute_padding_indicator_array(key->log_circuit_size); + size_t counter = 0; + for (auto indicator : padding_indicator_array) { + info(counter++, " ", indicator); + } auto sumcheck = Sumcheck(log_circuit_size, transcript); // Receive commitments to Libra masking polynomials @@ -115,7 +123,7 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ .shifted = ClaimBatch{ commitments.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_shifted() } }; const BatchOpeningClaim opening_claim = - Shplemini::compute_batch_opening_claim(key->circuit_size, + Shplemini::compute_batch_opening_claim(padding_indicator_array, claim_batcher, sumcheck_output.challenge, Commitment::one(builder), From aa4c0f970f286784e582bd18773a56f33f3909fe Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 10 Apr 2025 16:45:56 +0000 Subject: [PATCH 14/26] fix off-by-one issue --- .../padding_indicator_array.hpp | 31 ++++++++++--------- .../padding_indicator_array.test.cpp | 10 ++++-- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp index 8357e54c7e55..6e8a39938919 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp @@ -8,23 +8,24 @@ namespace bb::stdlib { * @file * @brief For a small integer N = `virtual_log_n` and a given witness x = `log_n`, compute in-circuit an * `indicator_padding_array` of size \f$ N \f$, such that - * \f{align}{ \text{indicator_padding_array}[i] = \text{"} i < x \text{"}. \f} + * \f{align}{ \text{indicator_padding_array}[i] = \text{"} i < x \text{"}. \f}. To achieve the strict ineqaulity, we + * evaluate all Lagranges at (x-1) and compute step functions. More concretely * - * 1) Constrain x to be in the range \f$ [1, \ldots, N - 1] \f$ by asserting - * \f{align}{ \prod_{i=1}^{N-1} (x - i) = 0 \f}. + * 1) Constrain x to be in the range \f$ [2, \ldots, N] \f$ by asserting + * \f{align}{ \prod_{i=1}^{N-1} (x - 1 - i) = 0 \f}. * * 2) For \f$ i = 0, ..., N-1 \f$, evaluate \f$ L_i(x) \f$. - * Since \f$ 0 < x < N \f$, \f$ L_i(x) = 1 \f$ if and only if \f$ x = FF(i) \f$. + * Since \f$ 1 < x <= N \f$, \f$ L_i(x - 1) = 1 \f$ if and only if \f$ x - 1 = i \f$. * - * 3) Starting at \f$ b_{N-1} = L_{N-1}(x)\f$, compute the step functions + * 3) Starting at \f$ b_{N-1} = L_{N-1}(x - 1)\f$, compute the step functions * \f{align}{ - * b_i(x) = \sum_{i}^{N-1} L_i(x) = L_i(x) + b_{i+1}(x) \f}. + * b_i(x - 1) = \sum_{i}^{N-1} L_i(x - 1) = L_i(x - 1) + b_{i+1}(x - 1) \f}. * * We compute the Lagrange coefficients out-of-circuit, since \f$ N \f$ is a circuit constant. * * The resulting array is being used to pad the number of Verifier rounds in Sumcheck and Shplemini to a fixed constant * and turn Recursive Verifier circuits into constant circuits. Note that the number of gates required to compute - * \f$ [b_0(x), \ldots, b_{N-1}(x)] \f$ only depends on \f$ N \f$ adding ~\f$ 4\cdot N \f$ gates to the circuit. + * \f$ [b_0(x-1), \ldots, b_{N-1}(x-1)] \f$ only depends on \f$ N \f$ adding ~\f$ 4\cdot N \f$ gates to the circuit. * */ template @@ -38,27 +39,27 @@ static std::array compute_padding_indicator_array(const Fr& l Fr zero{ 0 }; zero.convert_constant_to_fixed_witness(builder); // 1) Build prefix products: - // prefix[i] = ∏_{m=0..(i-1)} (x - big_domain[m]), with prefix[0] = 1. - std::vector prefix(virtual_log_n + 1, Fr(1)); + // prefix[i] = ∏_{m=0..(i-1)} (x - 1 - big_domain[m]), with prefix[0] = 1. + std::vector prefix(virtual_log_n + 1, Fr{ 1 }); for (size_t i = 0; i < virtual_log_n; ++i) { - prefix[i + 1] = prefix[i] * (log_n - Data::big_domain[i]); + prefix[i + 1] = prefix[i] * (log_n - Fr{ 1 } - Data::big_domain[i]); } // 2) Build suffix products: - // suffix[i] = ∏_{m=i..(virtual_log_n-1)} (x - big_domain[m]), + // suffix[i] = ∏_{m=i..(N-1)} (x - 1 - big_domain[m]), // but we'll store it in reverse: // suffix[virtual_log_n] = 1. std::vector suffix(virtual_log_n + 1, Fr(1)); for (size_t i = virtual_log_n; i > 0; i--) { - suffix[i - 1] = suffix[i] * (log_n - Data::big_domain[i - 1]); + suffix[i - 1] = suffix[i] * (log_n - Fr{ 1 } - Data::big_domain[i - 1]); } - // To ensure 0 < log_n < N, note that suffix[1] = \prod_{i=1}^{N-1} (x - i), therefore we just need to ensure + // To ensure 0 < log_n < N, note that suffix[1] = \prod_{i=1}^{N-1} (x - 1 - i), therefore we just need to ensure // that this product is 0. suffix[1].assert_equal(zero); - // 3) Combine prefixes & suffixes to get L_i(x): - // L_i(x) = (1 / lagrange_denominators[i]) * prefix[i] * suffix[i+1]. + // 3) Combine prefixes & suffixes to get L_i(x-1): + // L_i(x-1) = (1 / lagrange_denominators[i]) * prefix[i] * suffix[i+1]. // (We skip factor (x - big_domain[i]) by splitting into prefix & suffix.) for (size_t i = 0; i < virtual_log_n; ++i) { result[i] = Data::precomputed_denominator_inverses[i] * prefix[i] * suffix[i + 1]; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp index 5fb7362b8b3b..14dfbe25a5a9 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp @@ -26,7 +26,7 @@ template class PaddingIndicatorArrayTest : public testing::Test public: void test_value_in_range() { - for (size_t idx = 1; idx < domain_size; idx++) { + for (size_t idx = 2; idx <= domain_size; idx++) { Builder builder; Fr x = Fr::from_witness(&builder, idx); @@ -34,7 +34,10 @@ template class PaddingIndicatorArrayTest : public testing::Test EXPECT_TRUE(result[idx - 1].get_value() == 1); info("num gates = ", builder.get_estimated_num_finalized_gates()); - + // Check that the sum of indicators is indeed x + Fr sum_of_indicators = std::accumulate(result.begin(), result.end(), Fr{ 0 }); + EXPECT_TRUE((sum_of_indicators == x).get_value()); + // Check the correctness of the circuit EXPECT_TRUE(CircuitChecker::check(builder)); } } @@ -58,7 +61,7 @@ template class PaddingIndicatorArrayTest : public testing::Test { Builder builder; - Fr N = Fr::from_witness(&builder, domain_size - 1); + Fr N = Fr::from_witness(&builder, domain_size); [[maybe_unused]] auto result = compute_padding_indicator_array(N); info("num gates = ", builder.get_estimated_num_finalized_gates()); @@ -81,6 +84,7 @@ template class PaddingIndicatorArrayTest : public testing::Test EXPECT_FALSE(CircuitChecker::check(builder)); } } + void test_gate_count_independence() { auto get_gate_count = [](const uint256_t& scalar_raw) -> size_t { From 3613f1963f080c6db4db79e5a9d33aebf4ce0773 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 10 Apr 2025 17:10:12 +0000 Subject: [PATCH 15/26] sumcheck fine? --- .../barretenberg/polynomials/gate_separator.hpp | 8 ++++---- .../honk_verifier/ultra_recursive_verifier.cpp | 4 ++-- .../cpp/src/barretenberg/sumcheck/sumcheck.hpp | 12 +++++------- .../src/barretenberg/sumcheck/sumcheck_round.hpp | 15 ++++++++------- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp b/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp index 99ebe84864c4..e883aadd3763 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp @@ -116,12 +116,12 @@ template struct GateSeparatorPolynomial { * (1-X_i) + X_i\cdot \beta_i\right)\vert_{X_i = u_i}\f$ computed by \ref univariate_eval. * @param challenge \f$ i \f$-th verifier challenge \f$ u_{i}\f$ */ - template void partially_evaluate(const FF& challenge, const stdlib::bool_t& dummy) + template void partially_evaluate(const FF& challenge, const stdlib::field_t& indicator) { - FF current_univariate_eval = univariate_eval(challenge, dummy); + FF current_univariate_eval = univariate_eval(challenge); // If dummy round, make no update to the partial_evaluation_result - partial_evaluation_result = FF::conditional_assign( - dummy, partial_evaluation_result, partial_evaluation_result * current_univariate_eval); + partial_evaluation_result = (FF(1) - indicator) * partial_evaluation_result + + indicator * partial_evaluation_result * current_univariate_eval; current_element_idx++; periodicity *= 2; } diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index f9429e724830..3346b58ca0ac 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -108,8 +108,8 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ if constexpr (Flavor::HasZK) { libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); } - SumcheckOutput sumcheck_output = - sumcheck.verify(verification_key->relation_parameters, verification_key->alphas, gate_challenges); + SumcheckOutput sumcheck_output = sumcheck.verify( + verification_key->relation_parameters, verification_key->alphas, gate_challenges, padding_indicator_array); // For MegaZKFlavor: the sumcheck output contains claimed evaluations of the Libra polynomials if constexpr (Flavor::HasZK) { diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 38fe283f5f30..a7028aa5cb60 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -654,7 +654,8 @@ template class */ SumcheckOutput verify(const bb::RelationParameters& relation_parameters, RelationSeparator alpha, - std::vector& gate_challenges) + std::vector& gate_challenges, + const std::array& padding_indicator_array = {}) requires(!IsGrumpkinFlavor) { bool verified(true); @@ -694,17 +695,14 @@ template class multivariate_challenge.emplace_back(round_challenge); if constexpr (IsRecursiveFlavor) { - typename Flavor::CircuitBuilder* builder = round_challenge.get_context(); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): insecure dummy_round derivation! - stdlib::bool_t dummy_round = stdlib::witness_t(builder, round_idx >= multivariate_d); - bool checked = round.check_sum(round_univariate, dummy_round); + bool checked = round.check_sum(round_univariate, padding_indicator_array[round_idx]); // Only utilize the checked value if this is not a constant proof size padding round if (round_idx < multivariate_d) { verified = verified && checked; } - round.compute_next_target_sum(round_univariate, round_challenge, dummy_round); - gate_separators.partially_evaluate(round_challenge, dummy_round); + round.compute_next_target_sum(round_univariate, round_challenge, padding_indicator_array[round_idx]); + gate_separators.partially_evaluate(round_challenge, padding_indicator_array[round_idx]); } else { if (round_idx < multivariate_d) { diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index 02967e075482..2f94fa5fabc0 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -611,17 +611,18 @@ template class SumcheckVerifierRound { * */ template - bool check_sum(bb::Univariate& univariate, stdlib::bool_t dummy_round) + bool check_sum(bb::Univariate& univariate, + const stdlib::field_t& indicator) { FF total_sum = - FF::conditional_assign(dummy_round, target_total_sum, univariate.value_at(0) + univariate.value_at(1)); + (FF(1) - indicator) * target_total_sum + indicator * (univariate.value_at(0) + univariate.value_at(1)); // TODO(#673): Conditionals like this can go away once native verification is is just recursive verification // with a simulated builder. bool sumcheck_round_failed(false); // This bool is only needed for debugging - if (!dummy_round.get_value()) { - sumcheck_round_failed = (target_total_sum.get_value() != total_sum.get_value()); - } + // if (!dummy_round.get_value()) { + // sumcheck_round_failed = (target_total_sum.get_value() != total_sum.get_value()); + // } if constexpr (IsECCVMRecursiveFlavor) { // https://github.com/AztecProtocol/barretenberg/issues/998): Avoids the scenario where the assert_equal @@ -660,10 +661,10 @@ template class SumcheckVerifierRound { template void compute_next_target_sum(bb::Univariate& univariate, FF& round_challenge, - stdlib::bool_t dummy_round) + const stdlib::field_t& indicator) { // Evaluate \f$\tilde{S}^{i}(u_{i}) \f$ - target_total_sum = FF::conditional_assign(dummy_round, target_total_sum, univariate.evaluate(round_challenge)); + target_total_sum = (FF(1) - indicator) * target_total_sum + indicator * univariate.evaluate(round_challenge); } /** From e0c1aaa4a9cba6328b84fa6dbc74186fa7eeb56a Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Fri, 11 Apr 2025 14:04:31 +0000 Subject: [PATCH 16/26] dummy round removal --- .../commitment_schemes/gemini/gemini.hpp | 27 ++++++------------- .../commitment_schemes/shplonk/shplemini.hpp | 25 +++++------------ .../polynomials/gate_separator.hpp | 7 ++--- .../polynomials/row_disabling_polynomial.hpp | 16 ++++------- .../decider_recursive_verifier.cpp | 10 ++++--- .../ultra_recursive_verifier.cpp | 2 +- .../padding_indicator_array.hpp | 7 ++--- .../mega_zk_recursive_flavor.hpp | 1 - .../src/barretenberg/sumcheck/sumcheck.hpp | 13 +++++---- .../barretenberg/sumcheck/sumcheck_round.hpp | 8 +++--- 10 files changed, 42 insertions(+), 74 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index 034abf683c7e..09e78e83cfb3 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -580,35 +580,24 @@ template class GeminiVerifier_ { // Divide by the denominator eval_pos *= (challenge_power * (Fr(1) - u) + u).invert(); if constexpr (use_padding) { - if constexpr (Curve::is_stdlib_type) { - auto builder = evaluation_point[0].get_context(); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): insecure dummy_round derivation! - stdlib::bool_t dummy_round = stdlib::witness_t(builder, l > log_n); - // If current index is bigger than log_n, we propagate `batched_evaluation` to the next - // round. Otherwise, current `eval_pos` A₍ₗ₋₁₎(−r²⁽ˡ⁻¹⁾) becomes `eval_pos_prev` in the round l-2. - eval_pos_prev = Fr::conditional_assign(dummy_round, eval_pos_prev, eval_pos); - // If current index is bigger than log_n, we emplace 0, which is later multiplied against - // Commitment::one(). - value_to_emplace = Fr::conditional_assign(dummy_round, zero, eval_pos_prev); - - } else { - // Perform the same logic natively - bool dummy_round = l > log_n; - eval_pos_prev = dummy_round ? eval_pos_prev : eval_pos; - value_to_emplace = dummy_round ? zero : eval_pos_prev; - }; + // If current index is bigger than log_n, we propagate `batched_evaluation` to the next + // round. Otherwise, current `eval_pos` A₍ₗ₋₁₎(−r²⁽ˡ⁻¹⁾) becomes `eval_pos_prev` in the round l-2. + bool dummy_round = l > log_n; + eval_pos_prev = dummy_round ? eval_pos_prev : eval_pos; + value_to_emplace = dummy_round ? zero : eval_pos_prev; + } else { eval_pos_prev = eval_pos; value_to_emplace = eval_pos_prev; } fold_pos_evaluations.emplace_back(value_to_emplace); - info("native , l = ", l - 1, " value ", value_to_emplace); } std::reverse(fold_pos_evaluations.begin(), fold_pos_evaluations.end()); return fold_pos_evaluations; } + template static std::vector compute_fold_pos_evaluations( const std::array& padding_indicator_array, @@ -616,6 +605,7 @@ template class GeminiVerifier_ { std::span evaluation_point, // CONST_PROOF_SIZE std::span challenge_powers, // r_squares CONST_PROOF_SIZE_LOG_N std::span fold_neg_evals) + requires Curve::is_stdlib_type { std::vector evals(fold_neg_evals.begin(), fold_neg_evals.end()); @@ -647,7 +637,6 @@ template class GeminiVerifier_ { // Commitment::one(). value_to_emplace = padding_indicator_array[l - 1] * eval_pos_prev; fold_pos_evaluations.emplace_back(value_to_emplace); - info("recursive , l = ", l - 1, " value ", value_to_emplace); } std::reverse(fold_pos_evaluations.begin(), fold_pos_evaluations.end()); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 03b426bff12f..c7a8e892c32e 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -493,10 +493,8 @@ template class ShpleminiVerifier_ { shplonk_evaluation_challenge, gemini_eval_challenge_powers); // Compute the additional factors to be multiplied with unshifted and shifted commitments when lazily // reconstructing the commitment of Q_z - claim_batcher.compute_scalars_for_each_batch(inverse_vanishing_evals[0], // 1/(z − r) - inverse_vanishing_evals[1], // 1/(z + r) - shplonk_batching_challenge, - gemini_evaluation_challenge); + claim_batcher.compute_scalars_for_each_batch( + inverse_vanishing_evals, shplonk_batching_challenge, gemini_evaluation_challenge); if (has_zk) { commitments.emplace_back(hiding_polynomial_commitment); @@ -623,7 +621,6 @@ template class ShpleminiVerifier_ { Fr& constant_term_accumulator) { const size_t virtual_log_n = use_padding ? gemini_neg_evaluations.size() : log_n; - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1159): Decouple constants from primitives. // Start from 1, because the commitment to A_0 is reconstructed from the commitments to the multilinear // polynomials. The corresponding evaluations are also handled separately. for (size_t j = 1; j < virtual_log_n; ++j) { @@ -643,18 +640,9 @@ template class ShpleminiVerifier_ { scaling_factor_neg * gemini_neg_evaluations[j] + scaling_factor_pos * gemini_pos_evaluations[j]; if constexpr (use_padding) { - if constexpr (Curve::is_stdlib_type) { - auto builder = gemini_neg_evaluations[0].get_context(); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): insecure! - stdlib::bool_t dummy_round = stdlib::witness_t(builder, j >= log_n); - Fr zero = Fr(0); - scaling_factor_neg = Fr::conditional_assign(dummy_round, zero, scaling_factor_neg); - scaling_factor_pos = Fr::conditional_assign(dummy_round, zero, scaling_factor_pos); - } else { - if (j >= log_n) { - scaling_factor_neg = 0; - scaling_factor_pos = 0; - } + if (j >= log_n) { + scaling_factor_neg = 0; + scaling_factor_pos = 0; } } // Place the scaling factor to the 'scalars' vector @@ -664,7 +652,7 @@ template class ShpleminiVerifier_ { } } template - static void batch_gemini_claims_received_from_prover(const std::array padding_indicator_array, + static void batch_gemini_claims_received_from_prover(const std::array& padding_indicator_array, const std::vector& fold_commitments, const std::vector& gemini_neg_evaluations, const std::vector& gemini_pos_evaluations, @@ -673,6 +661,7 @@ template class ShpleminiVerifier_ { std::vector& commitments, std::vector& scalars, Fr& constant_term_accumulator) + requires Curve::is_stdlib_type { // Start from 1, because the commitment to A_0 is reconstructed from the commitments to the multilinear diff --git a/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp b/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp index e883aadd3763..0915ddc7479f 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp @@ -84,16 +84,13 @@ template struct GateSeparatorPolynomial { /** * @brief Evaluate \f$ ((1−X_{i}) + X_{i}\cdot \beta_{i})\f$ at the challenge point \f$ X_{i}=u_{i} \f$. */ - template FF univariate_eval(const FF& challenge, const Bool& dummy_round) const + FF univariate_eval(const FF& challenge, const FF& indicator) const { // For the Ultra Recursive flavor to ensure constant size proofs, we perform constant amount of hashing // producing 28 gate betas and we need to use the betas in the dummy rounds to ensure the permutation related // selectors stay the same regardless of real circuit size. FF one{ 1 }; - one.convert_constant_to_fixed_witness(challenge.get_context()); - - FF beta_val = FF::conditional_assign(dummy_round, one, betas[current_element_idx]); - return (FF(1) + (challenge * (beta_val - FF(1)))); + return (one + indicator * challenge * (betas[current_element_idx] - one)); } /** diff --git a/barretenberg/cpp/src/barretenberg/polynomials/row_disabling_polynomial.hpp b/barretenberg/cpp/src/barretenberg/polynomials/row_disabling_polynomial.hpp index 6b8c6c341353..e5ebcb4300ab 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/row_disabling_polynomial.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/row_disabling_polynomial.hpp @@ -178,21 +178,15 @@ template struct RowDisablingPolynomial { * @brief stdlib version of the above that ensures that the verifier's work does not depend on `log_circuit_size`. * */ - template - static FF evaluate_at_challenge(std::vector multivariate_challenge, - const size_t log_circuit_size, - Builder* builder) + template + static FF evaluate_at_challenge(std::span multivariate_challenge, + const std::array& padding_indicator_array) { - const size_t virtual_log_n = multivariate_challenge.size(); FF evaluation_at_multivariate_challenge{ 1 }; - const FF one = FF{ 1 }; for (size_t idx = 2; idx < virtual_log_n; idx++) { - stdlib::bool_t dummy_round = stdlib::witness_t(builder, idx >= log_circuit_size); - evaluation_at_multivariate_challenge = - FF::conditional_assign(dummy_round, - evaluation_at_multivariate_challenge * one, - evaluation_at_multivariate_challenge * multivariate_challenge[idx]); + const FF& indicator = padding_indicator_array[idx]; + evaluation_at_multivariate_challenge *= FF{ 1 } - indicator + indicator * multivariate_challenge[idx]; } return one - evaluation_at_multivariate_challenge; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp index 129a5b8635a6..554d36d6b8a2 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp @@ -1,6 +1,7 @@ #include "barretenberg/stdlib/honk_verifier/decider_recursive_verifier.hpp" #include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" +#include "barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp" #include "barretenberg/transcript/transcript.hpp" namespace bb::stdlib::recursion::honk { @@ -29,17 +30,20 @@ DeciderRecursiveVerifier_::AggregationObject DeciderRecursiveVerifier_(accumulator->verification_key->log_circuit_size.get_value()); + + const auto padding_indicator_array = + compute_padding_indicator_array(accumulator->verification_key->log_circuit_size); Sumcheck sumcheck(log_circuit_size, transcript, accumulator->target_sum); - SumcheckOutput output = - sumcheck.verify(accumulator->relation_parameters, accumulator->alphas, accumulator->gate_challenges); + SumcheckOutput output = sumcheck.verify( + accumulator->relation_parameters, accumulator->alphas, accumulator->gate_challenges, padding_indicator_array); // Execute Shplemini rounds. ClaimBatcher claim_batcher{ .unshifted = ClaimBatch{ commitments.get_unshifted(), output.claimed_evaluations.get_unshifted() }, .shifted = ClaimBatch{ commitments.get_to_be_shifted(), output.claimed_evaluations.get_shifted() } }; - const auto opening_claim = Shplemini::compute_batch_opening_claim(log_circuit_size, + const auto opening_claim = Shplemini::compute_batch_opening_claim(padding_indicator_array, claim_batcher, output.challenge, Commitment::one(builder), diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index 4aa17e354b93..e0bd3f8804a1 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -96,7 +96,7 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ const size_t log_circuit_size = numeric::get_msb(static_cast(key->circuit_size.get_value())); const auto padding_indicator_array = - compute_padding_indicator_array(key->log_circuit_size); + compute_padding_indicator_array(key->log_circuit_size); size_t counter = 0; for (auto indicator : padding_indicator_array) { info(counter++, " ", indicator); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp index 6e8a39938919..b0db00f6d601 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp @@ -28,16 +28,13 @@ namespace bb::stdlib { * \f$ [b_0(x-1), \ldots, b_{N-1}(x-1)] \f$ only depends on \f$ N \f$ adding ~\f$ 4\cdot N \f$ gates to the circuit. * */ -template +template static std::array compute_padding_indicator_array(const Fr& log_n) { // Create a domain of size `virtual_log_n` and compute Lagrange denominators using Data = BarycentricDataRunTime; std::array result{}; - Builder* builder = log_n.get_context(); - Fr zero{ 0 }; - zero.convert_constant_to_fixed_witness(builder); // 1) Build prefix products: // prefix[i] = ∏_{m=0..(i-1)} (x - 1 - big_domain[m]), with prefix[0] = 1. std::vector prefix(virtual_log_n + 1, Fr{ 1 }); @@ -56,7 +53,7 @@ static std::array compute_padding_indicator_array(const Fr& l // To ensure 0 < log_n < N, note that suffix[1] = \prod_{i=1}^{N-1} (x - 1 - i), therefore we just need to ensure // that this product is 0. - suffix[1].assert_equal(zero); + suffix[1].assert_equal(Fr{ 0 }); // 3) Combine prefixes & suffixes to get L_i(x-1): // L_i(x-1) = (1 / lagrange_denominators[i]) * prefix[i] * suffix[i+1]. diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_zk_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_zk_recursive_flavor.hpp index 9952e11bd255..50b832200b91 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_zk_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_zk_recursive_flavor.hpp @@ -34,7 +34,6 @@ template class MegaZKRecursiveFlavor_ : public MegaRecurs public: using NativeFlavor = MegaZKFlavor; - // Indicates that this flavor runs with non-ZK Sumcheck. static constexpr bool HasZK = true; // BATCHED_RELATION_PARTIAL_LENGTH = algebraic degree of sumcheck relation *after* multiplying by the `pow_zeta` diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 07cce357e34e..11532b21bf9a 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -700,10 +700,7 @@ template class // Ultra, Mega, and their derivatives constant. Note that there's no artificial padding in // Translator if constexpr (IsRecursiveFlavor && Flavor::USE_PADDING) { - typename Flavor::CircuitBuilder* builder = round_challenge.get_context(); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): insecure dummy_round derivation! - stdlib::bool_t dummy_round = stdlib::witness_t(builder, round_idx >= multivariate_d); - bool checked = round.check_sum(round_univariate, dummy_round); + bool checked = round.check_sum(round_univariate, padding_indicator_array[round_idx]); // Only utilize the checked value if this is not a constant proof size padding round if (round_idx < multivariate_d) { verified = verified && checked; @@ -738,13 +735,15 @@ template class // For ZK Flavors: the evaluation of the Row Disabling Polynomial at the sumcheck challenge if constexpr (Flavor::HasZK) { libra_evaluation = transcript->template receive_from_prover("Libra:claimed_evaluation"); - if constexpr (!IsRecursiveFlavor) { + if constexpr (IsRecursiveFlavor && Flavor::USE_PADDING) { + correcting_factor = + RowDisablingPolynomial::evaluate_at_challenge(multivariate_challenge, padding_indicator_array); + } else if constexpr (Flavor::USE_PADDING) { correcting_factor = RowDisablingPolynomial::evaluate_at_challenge(multivariate_challenge, multivariate_d); } else { - typename Flavor::CircuitBuilder* builder = libra_evaluation.get_context(); correcting_factor = - RowDisablingPolynomial::evaluate_at_challenge(multivariate_challenge, multivariate_d, builder); + RowDisablingPolynomial::evaluate_at_challenge(multivariate_challenge, multivariate_d); } full_honk_purported_value = diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index 31e34af7d242..e6ae53d431ee 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -596,7 +596,7 @@ template class SumcheckVerifierRound { // TODO(#673): Conditionals like this can go away once native verification is is just recursive verification // with a simulated builder. bool sumcheck_round_failed(false); - // This method is used by TranslatorRecursiveFlavor where dummy_round flags are not needed. + // This method is also used by TranslatorRecursiveFlavor where dummy_round flags are not needed. if constexpr (IsRecursiveFlavor) { sumcheck_round_failed = target_total_sum.get_value() != total_sum.get_value(); target_total_sum.assert_equal(total_sum); @@ -626,9 +626,9 @@ template class SumcheckVerifierRound { // with a simulated builder. bool sumcheck_round_failed(false); // This bool is only needed for debugging - // if (!dummy_round.get_value()) { - // sumcheck_round_failed = (target_total_sum.get_value() != total_sum.get_value()); - // } + if (indicator.get_value() == FF{ 1 }.get_value()) { + sumcheck_round_failed = (target_total_sum.get_value() != total_sum.get_value()); + } target_total_sum.assert_equal(total_sum); From 75877c229c99772b3e4f31b52ebcaf3884bfccc2 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Mon, 21 Apr 2025 11:15:30 +0000 Subject: [PATCH 17/26] better separation of padding and non-padding + simplifications --- .../commitment_schemes/gemini/gemini.hpp | 25 ++++++------------- .../commitment_schemes/ipa/ipa.test.cpp | 4 +-- .../commitment_schemes/kzg/kzg.test.cpp | 3 +-- .../commitment_schemes/shplonk/shplemini.hpp | 23 ++++++----------- .../shplonk/shplemini.test.cpp | 21 +++++++--------- .../shplemini.test.cpp | 3 +-- .../src/barretenberg/eccvm/eccvm_verifier.cpp | 2 +- .../polynomials/gate_separator.hpp | 2 +- .../polynomials/row_disabling_polynomial.hpp | 2 +- .../eccvm_recursive_verifier.cpp | 2 +- .../decider_recursive_verifier.cpp | 2 +- .../ultra_recursive_verifier.cpp | 7 ++---- .../padding_indicator_array.test.cpp | 10 ++++---- .../translator_recursive_verifier.cpp | 2 +- .../src/barretenberg/sumcheck/sumcheck.hpp | 3 --- .../barretenberg/sumcheck/sumcheck_round.hpp | 7 ++---- .../translator_vm/translator_verifier.cpp | 2 +- .../ultra_honk/decider_verifier.cpp | 2 +- .../recursion/recursive_verifier.cpp | 2 +- .../vm2/constraining/verifier.cpp | 2 +- 20 files changed, 46 insertions(+), 80 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index 09e78e83cfb3..538ef8215b5d 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -360,8 +360,6 @@ template class GeminiVerifier_ { { const size_t log_n = multilinear_challenge.size(); const bool has_interleaved = claim_batcher.interleaved.has_value(); - // GeminiVerifier is only used in tests, so no padding required. - static constexpr bool use_padding = false; const Fr rho = transcript->template get_challenge("rho"); @@ -446,7 +444,7 @@ template class GeminiVerifier_ { } // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., m-1 - std::vector gemini_fold_pos_evaluations = compute_fold_pos_evaluations( + std::vector gemini_fold_pos_evaluations = compute_fold_pos_evaluations( log_n, batched_evaluation, multilinear_challenge, r_squares, evaluations, p_neg); // Extract the evaluation A₀(r) = A₀₊(r) + P₊(r^s) auto full_a_0_pos = gemini_fold_pos_evaluations[0]; @@ -540,7 +538,6 @@ template class GeminiVerifier_ { * @param fold_neg_evals Evaluations \f$ A_{i-1}(-r^{2^{i-1}}) \f$. * @return Evaluation \f$ A_0(r) \f$. */ - template static std::vector compute_fold_pos_evaluations( const size_t log_n, const Fr& batched_evaluation, @@ -553,7 +550,6 @@ template class GeminiVerifier_ { Fr eval_pos_prev = batched_evaluation; // Virtual size allows padding in Shplemini. - const size_t virtual_log_n = use_padding ? evaluation_point.size() : log_n; Fr zero{ 0 }; if constexpr (Curve::is_stdlib_type) { @@ -561,14 +557,14 @@ template class GeminiVerifier_ { } std::vector fold_pos_evaluations; - fold_pos_evaluations.reserve(virtual_log_n); + fold_pos_evaluations.reserve(log_n); // Either a computed eval of A_i at r^{2^i}, or 0 Fr value_to_emplace; // Add the contribution of P-((-r)ˢ) to get A_0(-r), which is 0 if there are no interleaved polynomials evals[0] += p_neg; // Solve the sequence of linear equations - for (size_t l = virtual_log_n; l != 0; --l) { + for (size_t l = log_n; l != 0; --l) { // Get r²⁽ˡ⁻¹⁾ const Fr& challenge_power = challenge_powers[l - 1]; // Get uₗ₋₁ @@ -579,17 +575,10 @@ template class GeminiVerifier_ { Fr eval_pos = ((challenge_power * eval_pos_prev * 2) - eval_neg * (challenge_power * (Fr(1) - u) - u)); // Divide by the denominator eval_pos *= (challenge_power * (Fr(1) - u) + u).invert(); - if constexpr (use_padding) { - // If current index is bigger than log_n, we propagate `batched_evaluation` to the next - // round. Otherwise, current `eval_pos` A₍ₗ₋₁₎(−r²⁽ˡ⁻¹⁾) becomes `eval_pos_prev` in the round l-2. - bool dummy_round = l > log_n; - eval_pos_prev = dummy_round ? eval_pos_prev : eval_pos; - value_to_emplace = dummy_round ? zero : eval_pos_prev; - - } else { - eval_pos_prev = eval_pos; - value_to_emplace = eval_pos_prev; - } + + eval_pos_prev = eval_pos; + value_to_emplace = eval_pos_prev; + fold_pos_evaluations.emplace_back(value_to_emplace); } diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp index 8835ba455577..2d018891d3ce 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp @@ -11,8 +11,6 @@ using Curve = curve::Grumpkin; class IPATest : public CommitmentTest { public: - static constexpr bool USE_PADDING = false; - using Fr = typename Curve::ScalarField; using GroupElement = typename Curve::Element; using CK = CommitmentKey; @@ -25,7 +23,7 @@ class IPATest : public CommitmentTest { using ShplonkVerifier = ShplonkVerifier_; using GeminiProver = GeminiProver_; using GeminiVerifier = GeminiVerifier_; - using ShpleminiVerifier = ShpleminiVerifier_; + using ShpleminiVerifier = ShpleminiVerifier_; using ClaimBatcher = ClaimBatcher_; using ClaimBatch = ClaimBatcher::Batch; diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index 24fd04890fa0..d28351c65262 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -10,7 +10,6 @@ using Curve = curve::BN254; class KZGTest : public CommitmentTest { public: - static constexpr bool USE_PADDING = true; using Fr = typename Curve::ScalarField; using Commitment = typename Curve::AffineElement; using PCS = KZG; @@ -19,7 +18,7 @@ class KZGTest : public CommitmentTest { using ShplonkVerifier = ShplonkVerifier_; using GeminiProver = GeminiProver_; using GeminiVerifier = GeminiVerifier_; - using ShpleminiVerifier = ShpleminiVerifier_; + using ShpleminiVerifier = ShpleminiVerifier_; static constexpr size_t n = 16; static constexpr size_t log_n = 4; diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index c7a8e892c32e..fdb1bb6aedeb 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -180,7 +180,7 @@ template class ShpleminiProver_ { * */ -template class ShpleminiVerifier_ { +template class ShpleminiVerifier_ { using Fr = typename Curve::ScalarField; using GroupElement = typename Curve::Element; using Commitment = typename Curve::AffineElement; @@ -337,12 +337,12 @@ template class ShpleminiVerifier_ { // Reconstruct Aᵢ(r²ⁱ) for i=0, ..., d - 1 from the batched evaluation of the multilinear polynomials and // Aᵢ(−r²ⁱ) for i = 0, ..., d - 1. In the case of interleaving, we compute A₀(r) as A₀₊(r) + P₊(r^s). const std::vector gemini_fold_pos_evaluations = - GeminiVerifier_::template compute_fold_pos_evaluations(log_n, - batched_evaluation, - multivariate_challenge, - gemini_eval_challenge_powers, - gemini_fold_neg_evaluations, - p_neg); + GeminiVerifier_::compute_fold_pos_evaluations(log_n, + batched_evaluation, + multivariate_challenge, + gemini_eval_challenge_powers, + gemini_fold_neg_evaluations, + p_neg); // Place the commitments to Gemini fold polynomials Aᵢ in the vector of batch_mul commitments, compute the // contributions from Aᵢ(−r²ⁱ) for i=1, … , d − 1 to the constant term accumulator, add corresponding scalars @@ -620,10 +620,9 @@ template class ShpleminiVerifier_ { std::vector& scalars, Fr& constant_term_accumulator) { - const size_t virtual_log_n = use_padding ? gemini_neg_evaluations.size() : log_n; // Start from 1, because the commitment to A_0 is reconstructed from the commitments to the multilinear // polynomials. The corresponding evaluations are also handled separately. - for (size_t j = 1; j < virtual_log_n; ++j) { + for (size_t j = 1; j < log_n; ++j) { // The index of 1/ (z - r^{2^{j}}) in the vector of inverted Gemini denominators const size_t pos_index = 2 * j; // The index of 1/ (z + r^{2^{j}}) in the vector of inverted Gemini denominators @@ -639,12 +638,6 @@ template class ShpleminiVerifier_ { constant_term_accumulator += scaling_factor_neg * gemini_neg_evaluations[j] + scaling_factor_pos * gemini_pos_evaluations[j]; - if constexpr (use_padding) { - if (j >= log_n) { - scaling_factor_neg = 0; - scaling_factor_pos = 0; - } - } // Place the scaling factor to the 'scalars' vector scalars.emplace_back(-scaling_factor_neg - scaling_factor_pos); // Move com(Aᵢ) to the 'commitments' vector diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp index 678fd48a9ae4..5c7a62497800 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp @@ -152,8 +152,7 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) { using Curve = TypeParam::Curve; using GeminiProver = GeminiProver_; - static constexpr bool USE_PADDING = true; - using ShpleminiVerifier = ShpleminiVerifier_; + using ShpleminiVerifier = ShpleminiVerifier_; using ShplonkVerifier = ShplonkVerifier_; using Fr = typename Curve::ScalarField; using GroupElement = typename Curve::Element; @@ -237,12 +236,12 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) Fr expected_constant_term_accumulator{ 0 }; std::vector gemini_fold_pos_evaluations = - GeminiVerifier_::template compute_fold_pos_evaluations(this->log_n, - expected_constant_term_accumulator, - mle_opening_point, - r_squares, - prover_evaluations, - expected_constant_term_accumulator); + GeminiVerifier_::compute_fold_pos_evaluations(this->log_n, + expected_constant_term_accumulator, + mle_opening_point, + r_squares, + prover_evaluations, + expected_constant_term_accumulator); std::vector commitments; std::vector scalars; @@ -272,8 +271,7 @@ TYPED_TEST(ShpleminiTest, ShpleminiZKNoSumcheckOpenings) using ZKData = ZKSumcheckData; using Curve = TypeParam::Curve; using ShpleminiProver = ShpleminiProver_; - static constexpr bool USE_PADDING = true; - using ShpleminiVerifier = ShpleminiVerifier_; + using ShpleminiVerifier = ShpleminiVerifier_; using Fr = typename Curve::ScalarField; using Commitment = typename Curve::AffineElement; using CK = typename TypeParam::CommitmentKey; @@ -391,8 +389,7 @@ TYPED_TEST(ShpleminiTest, ShpleminiZKWithSumcheckOpenings) using CK = typename TypeParam::CommitmentKey; using ShpleminiProver = ShpleminiProver_; - static constexpr bool USE_PADDING = true; - using ShpleminiVerifier = ShpleminiVerifier_; + using ShpleminiVerifier = ShpleminiVerifier_; std::shared_ptr ck = create_commitment_key(4096); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp index c0c53cc49b8c..ed144ebb7ecb 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp @@ -35,8 +35,7 @@ TEST(ShpleminiRecursionTest, ProveAndVerifySingle) using NativePCS = std::conditional_t, KZG, IPA>; using CommitmentKey = typename NativePCS::CK; using ShpleminiProver = ShpleminiProver_; - static constexpr bool USE_PADDING = true; - using ShpleminiVerifier = ShpleminiVerifier_; + using ShpleminiVerifier = ShpleminiVerifier_; using Fr = typename Curve::ScalarField; using NativeFr = typename Curve::NativeCurve::ScalarField; using Transcript = bb::BaseTranscript>; diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index fcd750f84583..868a48823faf 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -12,7 +12,7 @@ namespace bb { bool ECCVMVerifier::verify_proof(const ECCVMProof& proof) { using Curve = typename Flavor::Curve; - using Shplemini = ShpleminiVerifier_; + using Shplemini = ShpleminiVerifier_; using Shplonk = ShplonkVerifier_; using OpeningClaim = OpeningClaim; using ClaimBatcher = ClaimBatcher_; diff --git a/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp b/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp index 0915ddc7479f..fa61b88d531a 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp @@ -113,7 +113,7 @@ template struct GateSeparatorPolynomial { * (1-X_i) + X_i\cdot \beta_i\right)\vert_{X_i = u_i}\f$ computed by \ref univariate_eval. * @param challenge \f$ i \f$-th verifier challenge \f$ u_{i}\f$ */ - template void partially_evaluate(const FF& challenge, const stdlib::field_t& indicator) + void partially_evaluate(const FF& challenge, const FF& indicator) { FF current_univariate_eval = univariate_eval(challenge); // If dummy round, make no update to the partial_evaluation_result diff --git a/barretenberg/cpp/src/barretenberg/polynomials/row_disabling_polynomial.hpp b/barretenberg/cpp/src/barretenberg/polynomials/row_disabling_polynomial.hpp index e5ebcb4300ab..f5fe7ead851f 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/row_disabling_polynomial.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/row_disabling_polynomial.hpp @@ -189,7 +189,7 @@ template struct RowDisablingPolynomial { evaluation_at_multivariate_challenge *= FF{ 1 } - indicator + indicator * multivariate_challenge[idx]; } - return one - evaluation_at_multivariate_challenge; + return FF{ 1 } - evaluation_at_multivariate_challenge; } }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp index ca66fa211567..8e784fbf8e4b 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp @@ -23,7 +23,7 @@ std::pair, std::shared_ptr::verify_proof(const ECCVMProof& proof) { using Curve = typename Flavor::Curve; - using Shplemini = ShpleminiVerifier_; + using Shplemini = ShpleminiVerifier_; using Shplonk = ShplonkVerifier_; using OpeningClaim = OpeningClaim; using ClaimBatcher = ClaimBatcher_; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp index 554d36d6b8a2..55572e14a453 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp @@ -17,7 +17,7 @@ DeciderRecursiveVerifier_::AggregationObject DeciderRecursiveVerifier_; using PCS = typename Flavor::PCS; using Curve = typename Flavor::Curve; - using Shplemini = ::bb::ShpleminiVerifier_; + using Shplemini = ::bb::ShpleminiVerifier_; using VerifierCommitments = typename Flavor::VerifierCommitments; using Transcript = typename Flavor::Transcript; using ClaimBatcher = ClaimBatcher_; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index 49651d1a0a28..954cfca5b577 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -44,7 +44,7 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ using Sumcheck = ::bb::SumcheckVerifier; using PCS = typename Flavor::PCS; using Curve = typename Flavor::Curve; - using Shplemini = ::bb::ShpleminiVerifier_; + using Shplemini = ::bb::ShpleminiVerifier_; using VerifierCommitments = typename Flavor::VerifierCommitments; using Transcript = typename Flavor::Transcript; using ClaimBatcher = ClaimBatcher_; @@ -97,10 +97,7 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ const auto padding_indicator_array = compute_padding_indicator_array(key->log_circuit_size); - size_t counter = 0; - for (auto indicator : padding_indicator_array) { - info(counter++, " ", indicator); - } + auto sumcheck = Sumcheck(log_circuit_size, transcript); // Receive commitments to Libra masking polynomials diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp index 14dfbe25a5a9..4723a432870f 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp @@ -30,7 +30,7 @@ template class PaddingIndicatorArrayTest : public testing::Test Builder builder; Fr x = Fr::from_witness(&builder, idx); - auto result = compute_padding_indicator_array(x); + auto result = compute_padding_indicator_array(x); EXPECT_TRUE(result[idx - 1].get_value() == 1); info("num gates = ", builder.get_estimated_num_finalized_gates()); @@ -51,7 +51,7 @@ template class PaddingIndicatorArrayTest : public testing::Test Fr zero = Fr::from_witness(&builder, 0); - [[maybe_unused]] auto result = compute_padding_indicator_array(zero); + [[maybe_unused]] auto result = compute_padding_indicator_array(zero); info("num gates = ", builder.get_estimated_num_finalized_gates()); EXPECT_FALSE(CircuitChecker::check(builder)); @@ -63,7 +63,7 @@ template class PaddingIndicatorArrayTest : public testing::Test Fr N = Fr::from_witness(&builder, domain_size); - [[maybe_unused]] auto result = compute_padding_indicator_array(N); + [[maybe_unused]] auto result = compute_padding_indicator_array(N); info("num gates = ", builder.get_estimated_num_finalized_gates()); EXPECT_TRUE(CircuitChecker::check(builder)); @@ -78,7 +78,7 @@ template class PaddingIndicatorArrayTest : public testing::Test Fr x = Fr::from_witness(&builder, scalar_raw); - [[maybe_unused]] auto result = compute_padding_indicator_array(x); + [[maybe_unused]] auto result = compute_padding_indicator_array(x); info("num gates = ", builder.get_estimated_num_finalized_gates()); EXPECT_FALSE(CircuitChecker::check(builder)); @@ -90,7 +90,7 @@ template class PaddingIndicatorArrayTest : public testing::Test auto get_gate_count = [](const uint256_t& scalar_raw) -> size_t { Builder builder; Fr x = Fr::from_witness(&builder, scalar_raw); - [[maybe_unused]] auto result = compute_padding_indicator_array(x); + [[maybe_unused]] auto result = compute_padding_indicator_array(x); size_t gate_count = builder.get_estimated_num_finalized_gates(); return gate_count; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp index 8c80ff3a9beb..6e2ae9dc8246 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp @@ -63,7 +63,7 @@ TranslatorRecursiveVerifier_::AggregationObject TranslatorRecursiveVerif using Sumcheck = ::bb::SumcheckVerifier; using PCS = typename Flavor::PCS; using Curve = typename Flavor::Curve; - using Shplemini = ::bb::ShpleminiVerifier_; + using Shplemini = ::bb::ShpleminiVerifier_; using VerifierCommitments = typename Flavor::VerifierCommitments; using CommitmentLabels = typename Flavor::CommitmentLabels; using ClaimBatcher = ClaimBatcher_; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 11532b21bf9a..70af8987103c 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -738,9 +738,6 @@ template class if constexpr (IsRecursiveFlavor && Flavor::USE_PADDING) { correcting_factor = RowDisablingPolynomial::evaluate_at_challenge(multivariate_challenge, padding_indicator_array); - } else if constexpr (Flavor::USE_PADDING) { - correcting_factor = - RowDisablingPolynomial::evaluate_at_challenge(multivariate_challenge, multivariate_d); } else { correcting_factor = RowDisablingPolynomial::evaluate_at_challenge(multivariate_challenge, multivariate_d); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index e6ae53d431ee..9b0e52d4d70b 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -616,9 +616,7 @@ template class SumcheckVerifierRound { * @param univariate Round univariate \f$\tilde{S}^{i}\f$ represented by its evaluations over \f$0,\ldots,D\f$. * */ - template - bool check_sum(bb::Univariate& univariate, - const stdlib::field_t& indicator) + bool check_sum(bb::Univariate& univariate, const FF& indicator) { FF total_sum = (FF(1) - indicator) * target_total_sum + indicator * (univariate.value_at(0) + univariate.value_at(1)); @@ -657,10 +655,9 @@ template class SumcheckVerifierRound { * @param round_challenge \f$ u_i\f$ * */ - template void compute_next_target_sum(bb::Univariate& univariate, FF& round_challenge, - const stdlib::field_t& indicator) + const FF& indicator) { // Evaluate \f$\tilde{S}^{i}(u_{i}) \f$ target_total_sum = (FF(1) - indicator) * target_total_sum + indicator * univariate.evaluate(round_challenge); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index 49ae849e98a8..596abf991546 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -57,7 +57,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof, { using Curve = Flavor::Curve; using PCS = Flavor::PCS; - using Shplemini = ShpleminiVerifier_; + using Shplemini = ShpleminiVerifier_; using ClaimBatcher = ClaimBatcher_; using ClaimBatch = ClaimBatcher::Batch; using InterleavedBatch = ClaimBatcher::InterleavedBatch; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp index a7a1fef12bb2..2feb4e0bd214 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp @@ -36,7 +36,7 @@ template bool DeciderVerifier_::verify() { using PCS = typename Flavor::PCS; using Curve = typename Flavor::Curve; - using Shplemini = ShpleminiVerifier_; + using Shplemini = ShpleminiVerifier_; using VerifierCommitments = typename Flavor::VerifierCommitments; using ClaimBatcher = ClaimBatcher_; using ClaimBatch = ClaimBatcher::Batch; diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp index 117c2a74fba7..6c5505168eaa 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp @@ -79,7 +79,7 @@ AvmRecursiveVerifier_::AggregationObject AvmRecursiveVerifier_:: using VerifierCommitments = typename Flavor::VerifierCommitments; using RelationParams = RelationParameters; using Transcript = typename Flavor::Transcript; - using Shplemini = ShpleminiVerifier_; + using Shplemini = ShpleminiVerifier_; using ClaimBatcher = ClaimBatcher_; using ClaimBatch = ClaimBatcher::Batch; diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.cpp index 36aeb1335a59..c8df4cdc8662 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.cpp @@ -44,7 +44,7 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vector; + using Shplemini = ShpleminiVerifier_; using ClaimBatcher = ClaimBatcher_; using ClaimBatch = ClaimBatcher::Batch; using VerifierCommitmentKey = typename Flavor::VerifierCommitmentKey; From ce290bc97a18f168ba3de27291b8c23e7ef76a85 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Mon, 21 Apr 2025 15:22:36 +0000 Subject: [PATCH 18/26] docs + simplify sumcheck logic --- .../commitment_schemes/gemini/gemini.hpp | 29 ++++++++-- .../commitment_schemes/shplonk/shplemini.hpp | 56 ++++++++++++++----- .../src/barretenberg/sumcheck/sumcheck.hpp | 16 +++--- .../barretenberg/sumcheck/sumcheck_round.hpp | 1 - 4 files changed, 76 insertions(+), 26 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index 538ef8215b5d..c524da9b00a9 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -536,7 +536,7 @@ template class GeminiVerifier_ { * @param evaluation_point Evaluation point \f$ (u_0, \ldots, u_{d-1}) \f$ padded to CONST_PROOF_SIZE_LOG_N. * @param challenge_powers Powers of \f$ r \f$, \f$ r^2 \), ..., \( r^{2^{d-1}} \f$. * @param fold_neg_evals Evaluations \f$ A_{i-1}(-r^{2^{i-1}}) \f$. - * @return Evaluation \f$ A_0(r) \f$. + * @return \f$ A_0(r), A_1(r^2), \ldots, A_{d-1}(r^{2^{d-1}})\f$. */ static std::vector compute_fold_pos_evaluations( const size_t log_n, @@ -586,7 +586,29 @@ template class GeminiVerifier_ { return fold_pos_evaluations; } - + /** + * @brief A method to compute \f$ A_0(r), A_1(r^2), \ldots, A_{d-1}(r^{2^{d-1}})\f$ padded to `virtual_log_n` >= d. + * Required in the stdlib context by the Flavors with USE_PADDING = true. + * + * @details The main difference from the non-padding method is that instead of using `log_n`, this method uses + * `padding_indicator_array` of field elements computed in-circuit. + * Since i-th entry of this array is FF{1} if i < log_n and 0 otherwise, we use these entries to either assign + * `eval_pos_prev` the value `eval_pos` computed in the current iteration of the loop, or to propagate the batched + * evaluation of the multilinear polynomials to the next iteration. This ensures the correctnes of the computation + * of the required positive evaluations. + * + * To ensure that dummy evaluations cannot be used to tamper with the final batch_mul result, we multiply dummy + * positive evaluations by the entries of `padding_indicator_array`. + * + * @tparam virtual_log_n The fixed log circuit size determined by Flavor. + * @param padding_indicator_array An array with first log_n entries equal to 1, and the remaining entries are 0. + * @param batched_evaluation The evaluation of the batched polynomial at \f$ (u_0, \ldots, u_{d-1})\f$. + * @param evaluation_point Evaluation point \f$ (u_0, \ldots, u_{d-1}) \f$ padded to `virtual_log_n` size. + * @param challenge_powers Powers of \f$ r^{2^i}\f$ for \f$ i = 0, \ldots, \text{virtual_log_n} - 1 \f$. + * @param fold_neg_evals Evaluations \f$ A_{i-1}(-r^{2^{i-1}}) \f$ for \f$i = 0, \ldots,\text{virtual_log_n} - 1 + * \f$. + * @return \f A_{i}}(r^{2^{i}})\f$ \f$ i = 0, \ldots, \text{virtual_log_n} - 1 \f$. + */ template static std::vector compute_fold_pos_evaluations( const std::array& padding_indicator_array, @@ -624,8 +646,7 @@ template class GeminiVerifier_ { padding_indicator_array[l - 1] * eval_pos + (Fr{ 1 } - padding_indicator_array[l - 1]) * eval_pos_prev; // If current index is bigger than log_n, we emplace 0, which is later multiplied against // Commitment::one(). - value_to_emplace = padding_indicator_array[l - 1] * eval_pos_prev; - fold_pos_evaluations.emplace_back(value_to_emplace); + fold_pos_evaluations.emplace_back(padding_indicator_array[l - 1] * eval_pos_prev); } std::reverse(fold_pos_evaluations.begin(), fold_pos_evaluations.end()); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index fdb1bb6aedeb..739b55acbf0e 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -190,6 +190,11 @@ template class ShpleminiVerifier_ { using ClaimBatcher = ClaimBatcher_; public: + /** + * @brief Non-padding version of \ref compute_batch_opening_claim. Used by all native verifiers and by recursive + * Translator and ECCVM verifiers. + * + */ template static BatchOpeningClaim compute_batch_opening_claim( const size_t log_n, @@ -404,7 +409,12 @@ template class ShpleminiVerifier_ { return { commitments, scalars, shplonk_evaluation_challenge }; }; - // padding enabled + /** + * @brief Padding version of \ref compute_batch_opening_claim. Used by recursive verifiers for the + * Flavors with USE_PADDING = true. Since ECCVM and Translator do not require padding, this method does not support + * interleaving or committed sumcheck logic. + * + */ template static BatchOpeningClaim compute_batch_opening_claim( const std::array& padding_indicator_array, @@ -418,6 +428,7 @@ template class ShpleminiVerifier_ { // Shplemini Refactoring: Remove bool pointer const std::array& libra_commitments = {}, const Fr& libra_univariate_evaluation = Fr{ 0 }) + requires Curve::is_stdlib_type { @@ -480,12 +491,8 @@ template class ShpleminiVerifier_ { // Initialize the vector of scalars placing the scalar 1 correposnding to Q_commitment std::vector scalars; - if constexpr (Curve::is_stdlib_type) { - auto builder = shplonk_batching_challenge.get_context(); - scalars.emplace_back(Fr(builder, 1)); - } else { - scalars.emplace_back(Fr(1)); - } + auto builder = shplonk_batching_challenge.get_context(); + scalars.emplace_back(Fr(builder, 1)); // Compute 1/(z − r), 1/(z + r), 1/(z - r²), 1/(z + r²), … , 1/(z - r^{2^{d-1}}), 1/(z + r^{2^{d-1}}) // These represent the denominators of the summand terms in Shplonk partially evaluated polynomial Q_z @@ -535,12 +542,6 @@ template class ShpleminiVerifier_ { commitments, scalars, constant_term_accumulator); - // Add contributions from A₀₊(r) and A₀₋(-r) to constant_term_accumulator: - // Add A₀₊(r)/(z−r) to the constant term accumulator - constant_term_accumulator += gemini_fold_pos_evaluations[0] * inverse_vanishing_evals[0]; - // Add A₀₋(-r)/(z+r) to the constant term accumulator - constant_term_accumulator += - gemini_fold_neg_evaluations[0] * shplonk_batching_challenge * inverse_vanishing_evals[1]; remove_repeated_commitments(commitments, scalars, repeated_commitments, has_zk); @@ -644,6 +645,29 @@ template class ShpleminiVerifier_ { commitments.emplace_back(std::move(fold_commitments[j - 1])); } } + + /** + * @brief A method to compute the scalars to be multiplied against \f$ [A_i]\f$ for \f$ i = 1, \ldots, + * \text{virtual_log_n} \f$ and to update the Shplonk constant term accumulator. Required in the stdlib context by + * the Flavors with USE_PADDING = true. + * + * @details The main difference from the non-padding method is that instead of using `log_n`, this method uses + * `padding_indicator_array` of field elements computed in-circuit. + * Since i-th entry of this array is FF{1} if i < log_n and 0 otherwise, we ensure that dummy evaluations cannot be + * used to tamper with the final batch_mul result, by multiplying dummy positive evaluations by the entries of + * `padding_indicator_array`. + * + * @tparam virtual_log_n + * @param padding_indicator_array + * @param fold_commitments + * @param gemini_neg_evaluations + * @param gemini_pos_evaluations + * @param inverse_vanishing_evals + * @param shplonk_batching_challenge_powers + * @param commitments + * @param scalars + * @param constant_term_accumulator + */ template static void batch_gemini_claims_received_from_prover(const std::array& padding_indicator_array, const std::vector& fold_commitments, @@ -656,6 +680,12 @@ template class ShpleminiVerifier_ { Fr& constant_term_accumulator) requires Curve::is_stdlib_type { + // Add contributions from A₀₊(r) and A₀₋(-r) to constant_term_accumulator: + // Add A₀₊(r)/(z−r) to the constant term accumulator + constant_term_accumulator += gemini_pos_evaluations[0] * inverse_vanishing_evals[0]; + // Add A₀₋(-r)/(z+r) to the constant term accumulator + constant_term_accumulator += + gemini_neg_evaluations[0] * shplonk_batching_challenge_powers[1] * inverse_vanishing_evals[1]; // Start from 1, because the commitment to A_0 is reconstructed from the commitments to the multilinear // polynomials. The corresponding evaluations are also handled separately. diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 70af8987103c..651741403011 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -699,24 +699,24 @@ template class // The recursive logic differs from the native one because of a hack making Sumcheck circuits in // Ultra, Mega, and their derivatives constant. Note that there's no artificial padding in // Translator + bool checked(true); if constexpr (IsRecursiveFlavor && Flavor::USE_PADDING) { - bool checked = round.check_sum(round_univariate, padding_indicator_array[round_idx]); - // Only utilize the checked value if this is not a constant proof size padding round - if (round_idx < multivariate_d) { - verified = verified && checked; - } - + checked = round.check_sum(round_univariate, padding_indicator_array[round_idx]); round.compute_next_target_sum(round_univariate, round_challenge, padding_indicator_array[round_idx]); gate_separators.partially_evaluate(round_challenge, padding_indicator_array[round_idx]); } else { + // This condition is needed to prevent updating the target total sum in dummy rounds when USE_PADDING = + // true. It is always satisfied when Sumcheck is instantiated with ECCVM or Translator + // Recursive Flavors. if (round_idx < multivariate_d) { - bool checked = round.check_sum(round_univariate); - verified = verified && checked; + checked = round.check_sum(round_univariate); round.compute_next_target_sum(round_univariate, round_challenge); gate_separators.partially_evaluate(round_challenge); } } + + verified = verified && checked; } // Extract claimed evaluations of Libra univariates and compute their sum multiplied by the Libra challenge // Final round diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index 9b0e52d4d70b..cf96ecf7fbef 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -596,7 +596,6 @@ template class SumcheckVerifierRound { // TODO(#673): Conditionals like this can go away once native verification is is just recursive verification // with a simulated builder. bool sumcheck_round_failed(false); - // This method is also used by TranslatorRecursiveFlavor where dummy_round flags are not needed. if constexpr (IsRecursiveFlavor) { sumcheck_round_failed = target_total_sum.get_value() != total_sum.get_value(); target_total_sum.assert_equal(total_sum); From f11dd3d04597351c6a66f76e30742a9b36c7e7be Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Tue, 22 Apr 2025 09:27:54 +0000 Subject: [PATCH 19/26] fixing tests --- .../commitment_schemes_recursion/shplemini.test.cpp | 5 ++++- .../honk_verifier/ultra_recursive_verifier.cpp | 2 +- .../honk_verifier/ultra_recursive_verifier.test.cpp | 2 +- .../padding_indicator_array.hpp | 12 ++++++------ .../constraining/recursion/recursive_verifier.cpp | 9 ++++++--- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp index ed144ebb7ecb..b44799b22f38 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp @@ -9,6 +9,7 @@ #include "barretenberg/srs/global_crs.hpp" #include "barretenberg/stdlib/primitives/curves/bn254.hpp" #include "barretenberg/stdlib/primitives/curves/grumpkin.hpp" +#include "barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp" #include "barretenberg/stdlib/transcript/transcript.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" #include @@ -48,6 +49,8 @@ TEST(ShpleminiRecursionTest, ProveAndVerifySingle) using diff_t = std::vector::difference_type; size_t N = 1 << log_circuit_size; + const auto padding_indicator_array = + stdlib::compute_padding_indicator_array(Fr(log_circuit_size)); constexpr size_t NUM_POLYS = 5; constexpr size_t NUM_SHIFTED = 2; constexpr size_t NUM_RIGHT_SHIFTED_BY_K = 1; @@ -122,7 +125,7 @@ TEST(ShpleminiRecursionTest, ProveAndVerifySingle) .k_shift_magnitude = MockClaimGen::k_magnitude }; - const auto opening_claim = ShpleminiVerifier::compute_batch_opening_claim(log_circuit_size, + const auto opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array, claim_batcher, u_challenge_in_circuit, Commitment::one(&builder), diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index 954cfca5b577..78e9006f7511 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -96,7 +96,7 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ const size_t log_circuit_size = numeric::get_msb(static_cast(key->circuit_size.get_value())); const auto padding_indicator_array = - compute_padding_indicator_array(key->log_circuit_size); + compute_padding_indicator_array(FF::from_witness(builder, log_circuit_size)); auto sumcheck = Sumcheck(log_circuit_size, transcript); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp index ddbb367bcf6a..39926b8f32d1 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp @@ -176,7 +176,7 @@ template class RecursiveVerifierTest : public testing }; auto [blocks_10, verification_key_10] = get_blocks(10); - auto [blocks_11, verification_key_11] = get_blocks(11); + auto [blocks_11, verification_key_11] = get_blocks(14); compare_ultra_blocks_and_verification_keys({ blocks_10, blocks_11 }, { verification_key_10, verification_key_11 }); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp index b0db00f6d601..5f5eab02e8d2 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp @@ -11,8 +11,8 @@ namespace bb::stdlib { * \f{align}{ \text{indicator_padding_array}[i] = \text{"} i < x \text{"}. \f}. To achieve the strict ineqaulity, we * evaluate all Lagranges at (x-1) and compute step functions. More concretely * - * 1) Constrain x to be in the range \f$ [2, \ldots, N] \f$ by asserting - * \f{align}{ \prod_{i=1}^{N-1} (x - 1 - i) = 0 \f}. + * 1) Constrain x to be in the range \f$ [1, \ldots, N] \f$ by asserting + * \f{align}{ \prod_{i=0}^{N-1} (x - 1 - i) = 0 \f}. * * 2) For \f$ i = 0, ..., N-1 \f$, evaluate \f$ L_i(x) \f$. * Since \f$ 1 < x <= N \f$, \f$ L_i(x - 1) = 1 \f$ if and only if \f$ x - 1 = i \f$. @@ -37,9 +37,9 @@ static std::array compute_padding_indicator_array(const Fr& l std::array result{}; // 1) Build prefix products: // prefix[i] = ∏_{m=0..(i-1)} (x - 1 - big_domain[m]), with prefix[0] = 1. - std::vector prefix(virtual_log_n + 1, Fr{ 1 }); - for (size_t i = 0; i < virtual_log_n; ++i) { - prefix[i + 1] = prefix[i] * (log_n - Fr{ 1 } - Data::big_domain[i]); + std::vector prefix(virtual_log_n, Fr{ 1 }); + for (size_t i = 1; i < virtual_log_n; ++i) { + prefix[i] = prefix[i - 1] * (log_n - Fr{ 1 } - Data::big_domain[i - 1]); } // 2) Build suffix products: @@ -53,7 +53,7 @@ static std::array compute_padding_indicator_array(const Fr& l // To ensure 0 < log_n < N, note that suffix[1] = \prod_{i=1}^{N-1} (x - 1 - i), therefore we just need to ensure // that this product is 0. - suffix[1].assert_equal(Fr{ 0 }); + suffix[0].assert_equal(Fr{ 0 }); // 3) Combine prefixes & suffixes to get L_i(x-1): // L_i(x-1) = (1 / lagrange_denominators[i]) * prefix[i] * suffix[i+1]. diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp index 6c5505168eaa..45f83aa3901d 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp @@ -9,6 +9,7 @@ #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/polynomials/shared_shifted_virtual_zeroes_array.hpp" #include "barretenberg/stdlib/primitives/field/field.hpp" +#include "barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp" #include "barretenberg/transcript/transcript.hpp" #include "barretenberg/vm2/common/aztec_constants.hpp" @@ -109,6 +110,8 @@ AvmRecursiveVerifier_::AggregationObject AvmRecursiveVerifier_:: // unconstrained const size_t log_circuit_size = numeric::get_msb(static_cast(circuit_size.get_value())); + const auto padding_indicator_array = + stdlib::compute_padding_indicator_array(FF(log_circuit_size)); auto sumcheck = SumcheckVerifier(log_circuit_size, transcript); FF alpha = transcript->template get_challenge("Sumcheck:alpha"); @@ -120,8 +123,8 @@ AvmRecursiveVerifier_::AggregationObject AvmRecursiveVerifier_:: // No need to constrain that sumcheck_verified is true as this is guaranteed by the implementation of // when called over a "circuit field" types. - SumcheckOutput output = sumcheck.verify(relation_parameters, alpha, gate_challenges); - + SumcheckOutput output = + sumcheck.verify(relation_parameters, alpha, gate_challenges, padding_indicator_array); vinfo("verified sumcheck: ", (output.verified)); // Public columns evaluation checks @@ -140,7 +143,7 @@ AvmRecursiveVerifier_::AggregationObject AvmRecursiveVerifier_:: .shifted = ClaimBatch{ commitments.get_to_be_shifted(), output.claimed_evaluations.get_shifted() } }; const BatchOpeningClaim opening_claim = Shplemini::compute_batch_opening_claim( - log_circuit_size, claim_batcher, output.challenge, Commitment::one(&builder), transcript); + padding_indicator_array, claim_batcher, output.challenge, Commitment::one(&builder), transcript); auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); From ff200992dc1a82b615727b4f89e8365326c5ce1b Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Tue, 22 Apr 2025 11:30:49 +0000 Subject: [PATCH 20/26] clean up sumcheck verifier constructors --- .../commitment_schemes/gemini/gemini.hpp | 1 - .../cpp/src/barretenberg/eccvm/eccvm.test.cpp | 2 +- .../src/barretenberg/eccvm/eccvm_verifier.cpp | 2 +- .../eccvm_recursive_verifier.cpp | 2 +- .../decider_recursive_verifier.cpp | 5 +--- .../ultra_recursive_verifier.cpp | 2 +- .../translator_recursive_verifier.cpp | 2 +- .../src/barretenberg/sumcheck/sumcheck.hpp | 23 ++++++++++++------- .../recursion/recursive_verifier.cpp | 2 +- 9 files changed, 22 insertions(+), 19 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index c524da9b00a9..062b3406a9fa 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -549,7 +549,6 @@ template class GeminiVerifier_ { std::vector evals(fold_neg_evals.begin(), fold_neg_evals.end()); Fr eval_pos_prev = batched_evaluation; - // Virtual size allows padding in Shplemini. Fr zero{ 0 }; if constexpr (Curve::is_stdlib_type) { diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm.test.cpp index 3e5e21eea64c..5d7c6ae75103 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm.test.cpp @@ -149,7 +149,7 @@ TEST_F(ECCVMTests, CommittedSumcheck) std::shared_ptr verifier_transcript = std::make_shared(prover_transcript->proof_data); // Execute Sumcheck Verifier - SumcheckVerifier sumcheck_verifier(CONST_ECCVM_LOG_N, verifier_transcript); + SumcheckVerifier sumcheck_verifier(verifier_transcript); SumcheckOutput verifier_output = sumcheck_verifier.verify(relation_parameters, alpha, gate_challenges); // Evaluate prover's round univariates at corresponding challenges and compare them with the claimed evaluations diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index 868a48823faf..ff1b39c5d9aa 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -49,7 +49,7 @@ bool ECCVMVerifier::verify_proof(const ECCVMProof& proof) commitments.z_perm = transcript->template receive_from_prover(commitment_labels.z_perm); // Execute Sumcheck Verifier - SumcheckVerifier sumcheck(CONST_ECCVM_LOG_N, transcript); + SumcheckVerifier sumcheck(transcript); FF alpha = transcript->template get_challenge("Sumcheck:alpha"); std::vector gate_challenges(CONST_ECCVM_LOG_N); for (size_t idx = 0; idx < gate_challenges.size(); idx++) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp index 8e784fbf8e4b..91b2cb49e8aa 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp @@ -65,7 +65,7 @@ ECCVMRecursiveVerifier_::verify_proof(const ECCVMProof& proof) commitments.z_perm = transcript->template receive_from_prover(commitment_labels.z_perm); // Execute Sumcheck Verifier - Sumcheck sumcheck(CONST_PROOF_SIZE_LOG_N, transcript); + Sumcheck sumcheck(transcript); const FF alpha = transcript->template get_challenge("Sumcheck:alpha"); std::vector gate_challenges(CONST_ECCVM_LOG_N); for (size_t idx = 0; idx < gate_challenges.size(); idx++) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp index 55572e14a453..33dfce5ac69d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp @@ -28,12 +28,9 @@ DeciderRecursiveVerifier_::AggregationObject DeciderRecursiveVerifier_verification_key, accumulator->witness_commitments }; - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1283): fix log_circuit_size usage in stdlib cases. - const size_t log_circuit_size = static_cast(accumulator->verification_key->log_circuit_size.get_value()); - const auto padding_indicator_array = compute_padding_indicator_array(accumulator->verification_key->log_circuit_size); - Sumcheck sumcheck(log_circuit_size, transcript, accumulator->target_sum); + Sumcheck sumcheck(transcript, accumulator->target_sum); SumcheckOutput output = sumcheck.verify( accumulator->relation_parameters, accumulator->alphas, accumulator->gate_challenges, padding_indicator_array); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index 78e9006f7511..51bbba0f5d81 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -98,7 +98,7 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ const auto padding_indicator_array = compute_padding_indicator_array(FF::from_witness(builder, log_circuit_size)); - auto sumcheck = Sumcheck(log_circuit_size, transcript); + auto sumcheck = Sumcheck(transcript); // Receive commitments to Libra masking polynomials std::array libra_commitments = {}; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp index 6e2ae9dc8246..a939e4b2d8e4 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp @@ -97,7 +97,7 @@ TranslatorRecursiveVerifier_::AggregationObject TranslatorRecursiveVerif commitments.z_perm = transcript->template receive_from_prover(commitment_labels.z_perm); // Execute Sumcheck Verifier - Sumcheck sumcheck(TranslatorFlavor::CONST_TRANSLATOR_LOG_N, transcript); + Sumcheck sumcheck(transcript); FF alpha = transcript->template get_challenge("Sumcheck:alpha"); std::vector gate_challenges(TranslatorFlavor::CONST_TRANSLATOR_LOG_N); for (size_t idx = 0; idx < gate_challenges.size(); idx++) { diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 651741403011..210d64e35ee9 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -625,7 +625,7 @@ template class * @brief Number of variables in Prover Polynomials. * */ - const size_t multivariate_d; + size_t multivariate_d; std::shared_ptr transcript; SumcheckVerifierRound round; @@ -638,11 +638,24 @@ template class std::vector round_univariate_commitments = {}; std::vector> round_univariate_evaluations = {}; - // Verifier instantiates sumcheck with circuit size, optionally a different target sum than 0 can be specified. + // Native Ultra, Mega, and AVM Verifiers instantiate sumcheck with circuit size, optionally a different target sum + // than 0 can be specified. explicit SumcheckVerifier(size_t multivariate_d, std::shared_ptr transcript, FF target_sum = 0) : multivariate_d(multivariate_d) , transcript(transcript) , round(target_sum){}; + + // Recursive Verifiers without padding use the fixed log of the circuit size to determine the number of sumcheck + // rounds. Recursive Verifiers **with padding** are not permitted to use multivariate_d. + explicit SumcheckVerifier(std::shared_ptr transcript, FF target_sum = 0) + : transcript(transcript) + , round(target_sum) + { + if constexpr (!Flavor::USE_PADDING) { + // If the circuit sizes are genuinely fixed, use the log of the const fixed size. + this->multivariate_d = virtual_log_n; + } + }; /** * @brief Extract round univariate, check sum, generate challenge, compute next target sum..., repeat until * final round, then use purported evaluations to generate purported full Honk relation value and check against @@ -669,12 +682,6 @@ template class // All but final round. // target_total_sum is initialized to zero then mutated in place. - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1144): Add proper constraints for taking the log of - // a field_t link multivariate_d. - if (multivariate_d == 0) { - throw_or_abort("Number of variables in multivariate is 0."); - } - bb::Univariate round_univariate; if constexpr (Flavor::HasZK) { diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp index 45f83aa3901d..d9f53cc3becd 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp @@ -112,7 +112,7 @@ AvmRecursiveVerifier_::AggregationObject AvmRecursiveVerifier_:: const size_t log_circuit_size = numeric::get_msb(static_cast(circuit_size.get_value())); const auto padding_indicator_array = stdlib::compute_padding_indicator_array(FF(log_circuit_size)); - auto sumcheck = SumcheckVerifier(log_circuit_size, transcript); + auto sumcheck = SumcheckVerifier(transcript); FF alpha = transcript->template get_challenge("Sumcheck:alpha"); From da0569146666dfd5d154956820d742ffec5ed216 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Tue, 22 Apr 2025 13:13:17 +0000 Subject: [PATCH 21/26] add constraints --- .../decider_recursive_verifier.cpp | 3 ++ .../ultra_recursive_verifier.cpp | 6 +-- .../padding_indicator_array.hpp | 23 ++++++++++ .../padding_indicator_array.test.cpp | 45 ++++++++++++++++--- 4 files changed, 69 insertions(+), 8 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp index 33dfce5ac69d..c5a599ca5dd7 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp @@ -30,6 +30,9 @@ DeciderRecursiveVerifier_::AggregationObject DeciderRecursiveVerifier_(accumulator->verification_key->log_circuit_size); + + constrain_log_circuit_size(padding_indicator_array, accumulator->verification_key->circuit_size); + Sumcheck sumcheck(transcript, accumulator->target_sum); SumcheckOutput output = sumcheck.verify( diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index 51bbba0f5d81..f12fce7ad8de 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -92,11 +92,11 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ // Execute Sumcheck Verifier and extract multivariate opening point u = (u_0, ..., u_{d-1}) and purported // multivariate evaluations at u - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1283): Suspicious get_value(). - const size_t log_circuit_size = numeric::get_msb(static_cast(key->circuit_size.get_value())); const auto padding_indicator_array = - compute_padding_indicator_array(FF::from_witness(builder, log_circuit_size)); + compute_padding_indicator_array(key->log_circuit_size); + + constrain_log_circuit_size(padding_indicator_array, key->circuit_size); auto sumcheck = Sumcheck(transcript); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp index 5f5eab02e8d2..46c9e726d3ee 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp @@ -70,4 +70,27 @@ static std::array compute_padding_indicator_array(const Fr& l return result; } +/** + * @brief Given a witness `n` and a padding indicator array computed from `log_n`, check in-circuit that the latter is + * indded the logarithm of `n`. + * + * @details It is crucial that `log_n` is constrained to be in range [1, virtual_log_n], as it forces the first `log_n` + * entries of `padding_indicator_array` to be equal to 1 and the rest of the entries to be equal to 0. This implies that + * `n` can be reconstructed by incrementing each entry in the array and taking their product. + * + * @tparam Fr + * @tparam virtual_log_n + * @param padding_indicator_array + * @param n expected = 2^(log_n) + */ +template +static void constrain_log_circuit_size(const std::array& padding_indicator_array, const Fr& n) +{ + Fr accumulated_circuit_size{ 1 }; + for (auto& indicator : padding_indicator_array) { + accumulated_circuit_size *= indicator + Fr{ 1 }; + }; + + n.assert_equal(accumulated_circuit_size); +} } // namespace bb::stdlib diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp index 4723a432870f..974b43fb265d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp @@ -23,10 +23,9 @@ template class PaddingIndicatorArrayTest : public testing::Test static constexpr size_t domain_size = 25; - public: void test_value_in_range() { - for (size_t idx = 2; idx <= domain_size; idx++) { + for (size_t idx = 1; idx <= domain_size; idx++) { Builder builder; Fr x = Fr::from_witness(&builder, idx); @@ -37,6 +36,10 @@ template class PaddingIndicatorArrayTest : public testing::Test // Check that the sum of indicators is indeed x Fr sum_of_indicators = std::accumulate(result.begin(), result.end(), Fr{ 0 }); EXPECT_TRUE((sum_of_indicators == x).get_value()); + // Create a witness = 2^idx + Fr exponent = Fr::from_witness(&builder, 1 << idx); + // Using the indicator values, compute 2^idx in-circuit. + stdlib::constrain_log_circuit_size(result, exponent); // Check the correctness of the circuit EXPECT_TRUE(CircuitChecker::check(builder)); } @@ -87,25 +90,53 @@ template class PaddingIndicatorArrayTest : public testing::Test void test_gate_count_independence() { - auto get_gate_count = [](const uint256_t& scalar_raw) -> size_t { + auto get_gate_count = [](const uint32_t& scalar_raw) -> size_t { Builder builder; Fr x = Fr::from_witness(&builder, scalar_raw); [[maybe_unused]] auto result = compute_padding_indicator_array(x); size_t gate_count = builder.get_estimated_num_finalized_gates(); + // Create a witness = 2^(idx) + Fr exponent = Fr::from_witness(&builder, 1UL << scalar_raw); + // Using the indicator values, compute 2^idx in-circuit. + stdlib::constrain_log_circuit_size(result, exponent); return gate_count; }; // Valid input: x in [1, domain_size - 1] - uint256_t x_in_range = (domain_size - 1) / 2; + uint32_t x_in_range = (domain_size - 1) / 2; size_t gates_in_range = get_gate_count(x_in_range); // Random input - uint256_t random_scalar = engine.get_random_uint256(); + uint32_t random_scalar = engine.get_random_uint32(); size_t gates_random = get_gate_count(random_scalar); EXPECT_EQ(gates_in_range, gates_random); } + + void test_log_constraint_failure() + { + for (size_t idx = 1; idx <= domain_size; idx++) { + Builder builder; + Fr x = Fr::from_witness(&builder, idx); + + auto result = compute_padding_indicator_array(x); + EXPECT_TRUE(result[idx - 1].get_value() == 1); + + info("num gates = ", builder.get_estimated_num_finalized_gates()); + // Check that the sum of indicators is indeed x + Fr sum_of_indicators = std::accumulate(result.begin(), result.end(), Fr{ 0 }); + EXPECT_TRUE((sum_of_indicators == x).get_value()); + // Check the correctness of the circuit + EXPECT_TRUE(CircuitChecker::check(builder)); + // Create a witness = 2^idx + Fr exponent = Fr::from_witness(&builder, (1 << idx) + 1); + // Using the indicator values, compute tampered "2^idx" in-circuit. + stdlib::constrain_log_circuit_size(result, exponent); + // Circuit check must fail as 2^(log_n) != n + EXPECT_FALSE(CircuitChecker::check(builder)); + } + } }; using TestTypes = testing::Types< @@ -133,4 +164,8 @@ TYPED_TEST(PaddingIndicatorArrayTest, TestGateCountIndependence) { TestFixture::test_gate_count_independence(); } +TYPED_TEST(PaddingIndicatorArrayTest, TestLogConstraintFailure) +{ + TestFixture::test_log_constraint_failure(); +} } // namespace From bacaae40831e5a53094f6828901a4b877649c19a Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Tue, 22 Apr 2025 14:58:04 +0000 Subject: [PATCH 22/26] fix AcirHonkRecursionConstraint tests --- .../stdlib_circuit_builders/ultra_recursive_flavor.hpp | 2 ++ .../stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp index ae3e9fb54447..13589fc7c96e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp @@ -149,6 +149,8 @@ template class UltraRecursiveFlavor_ { size_t num_frs_read = 0; this->circuit_size = deserialize_from_frs(builder, elements, num_frs_read); + this->log_circuit_size = + FF::from_witness(&builder, numeric::get_msb(static_cast(this->circuit_size.get_value()))); this->num_public_inputs = deserialize_from_frs(builder, elements, num_frs_read); this->pub_inputs_offset = deserialize_from_frs(builder, elements, num_frs_read); this->contains_pairing_point_accumulator = diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp index 59abc28f4e6f..add5f4acadf8 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp @@ -94,6 +94,8 @@ template class UltraRollupRecursiveFlavor_ : public Ultra size_t num_frs_read = 0; this->circuit_size = deserialize_from_frs(builder, elements, num_frs_read); + this->log_circuit_size = + FF::from_witness(&builder, numeric::get_msb(static_cast(this->circuit_size.get_value()))); this->num_public_inputs = deserialize_from_frs(builder, elements, num_frs_read); this->pub_inputs_offset = deserialize_from_frs(builder, elements, num_frs_read); this->contains_pairing_point_accumulator = From b26a7e3ac1fcf78d73de0117e55a1d68bc6a63bb Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 23 Apr 2025 08:37:50 +0000 Subject: [PATCH 23/26] template padding indicator array on curve to support native --- .../shplemini.test.cpp | 2 +- .../decider_recursive_verifier.cpp | 2 +- .../ultra_recursive_verifier.cpp | 2 +- .../padding_indicator_array.hpp | 10 ++++--- .../padding_indicator_array.test.cpp | 26 +++++++++---------- .../recursion/recursive_verifier.cpp | 2 +- 6 files changed, 24 insertions(+), 20 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp index b44799b22f38..9cc4b59bbb1e 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp @@ -50,7 +50,7 @@ TEST(ShpleminiRecursionTest, ProveAndVerifySingle) size_t N = 1 << log_circuit_size; const auto padding_indicator_array = - stdlib::compute_padding_indicator_array(Fr(log_circuit_size)); + stdlib::compute_padding_indicator_array(Fr(log_circuit_size)); constexpr size_t NUM_POLYS = 5; constexpr size_t NUM_SHIFTED = 2; constexpr size_t NUM_RIGHT_SHIFTED_BY_K = 1; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp index c5a599ca5dd7..3d6c10acfc3d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp @@ -29,7 +29,7 @@ DeciderRecursiveVerifier_::AggregationObject DeciderRecursiveVerifier_verification_key, accumulator->witness_commitments }; const auto padding_indicator_array = - compute_padding_indicator_array(accumulator->verification_key->log_circuit_size); + compute_padding_indicator_array(accumulator->verification_key->log_circuit_size); constrain_log_circuit_size(padding_indicator_array, accumulator->verification_key->circuit_size); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index 4aeb4fad4cbe..e2311165dfe7 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -93,7 +93,7 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ // multivariate evaluations at u const auto padding_indicator_array = - compute_padding_indicator_array(key->log_circuit_size); + compute_padding_indicator_array(key->log_circuit_size); constrain_log_circuit_size(padding_indicator_array, key->circuit_size); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp index 46c9e726d3ee..895b749bc77d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp @@ -28,9 +28,11 @@ namespace bb::stdlib { * \f$ [b_0(x-1), \ldots, b_{N-1}(x-1)] \f$ only depends on \f$ N \f$ adding ~\f$ 4\cdot N \f$ gates to the circuit. * */ -template -static std::array compute_padding_indicator_array(const Fr& log_n) +template +static std::array compute_padding_indicator_array( + const typename Curve::ScalarField& log_n) { + using Fr = typename Curve::ScalarField; // Create a domain of size `virtual_log_n` and compute Lagrange denominators using Data = BarycentricDataRunTime; @@ -53,7 +55,9 @@ static std::array compute_padding_indicator_array(const Fr& l // To ensure 0 < log_n < N, note that suffix[1] = \prod_{i=1}^{N-1} (x - 1 - i), therefore we just need to ensure // that this product is 0. - suffix[0].assert_equal(Fr{ 0 }); + if constexpr (Curve::is_stdlib_type) { + suffix[0].assert_equal(Fr{ 0 }); + } // 3) Combine prefixes & suffixes to get L_i(x-1): // L_i(x-1) = (1 / lagrange_denominators[i]) * prefix[i] * suffix[i+1]. diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp index 974b43fb265d..59bb436b6a03 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp @@ -11,14 +11,15 @@ using namespace bb; namespace { auto& engine = numeric::get_debug_randomness(); -template struct PaddingTestParams { - using Fr = Fr_; +template struct PaddingTestParams { + using Curve = Curve_; using Builder = Builder_; }; template class PaddingIndicatorArrayTest : public testing::Test { public: - using Fr = typename Param::Fr; + using Curve = typename Param::Curve; + using Fr = typename Curve::ScalarField; using Builder = typename Param::Builder; static constexpr size_t domain_size = 25; @@ -29,7 +30,7 @@ template class PaddingIndicatorArrayTest : public testing::Test Builder builder; Fr x = Fr::from_witness(&builder, idx); - auto result = compute_padding_indicator_array(x); + auto result = compute_padding_indicator_array(x); EXPECT_TRUE(result[idx - 1].get_value() == 1); info("num gates = ", builder.get_estimated_num_finalized_gates()); @@ -54,7 +55,7 @@ template class PaddingIndicatorArrayTest : public testing::Test Fr zero = Fr::from_witness(&builder, 0); - [[maybe_unused]] auto result = compute_padding_indicator_array(zero); + [[maybe_unused]] auto result = compute_padding_indicator_array(zero); info("num gates = ", builder.get_estimated_num_finalized_gates()); EXPECT_FALSE(CircuitChecker::check(builder)); @@ -66,7 +67,7 @@ template class PaddingIndicatorArrayTest : public testing::Test Fr N = Fr::from_witness(&builder, domain_size); - [[maybe_unused]] auto result = compute_padding_indicator_array(N); + [[maybe_unused]] auto result = compute_padding_indicator_array(N); info("num gates = ", builder.get_estimated_num_finalized_gates()); EXPECT_TRUE(CircuitChecker::check(builder)); @@ -81,7 +82,7 @@ template class PaddingIndicatorArrayTest : public testing::Test Fr x = Fr::from_witness(&builder, scalar_raw); - [[maybe_unused]] auto result = compute_padding_indicator_array(x); + [[maybe_unused]] auto result = compute_padding_indicator_array(x); info("num gates = ", builder.get_estimated_num_finalized_gates()); EXPECT_FALSE(CircuitChecker::check(builder)); @@ -93,7 +94,7 @@ template class PaddingIndicatorArrayTest : public testing::Test auto get_gate_count = [](const uint32_t& scalar_raw) -> size_t { Builder builder; Fr x = Fr::from_witness(&builder, scalar_raw); - [[maybe_unused]] auto result = compute_padding_indicator_array(x); + [[maybe_unused]] auto result = compute_padding_indicator_array(x); size_t gate_count = builder.get_estimated_num_finalized_gates(); // Create a witness = 2^(idx) @@ -120,7 +121,7 @@ template class PaddingIndicatorArrayTest : public testing::Test Builder builder; Fr x = Fr::from_witness(&builder, idx); - auto result = compute_padding_indicator_array(x); + auto result = compute_padding_indicator_array(x); EXPECT_TRUE(result[idx - 1].get_value() == 1); info("num gates = ", builder.get_estimated_num_finalized_gates()); @@ -140,10 +141,9 @@ template class PaddingIndicatorArrayTest : public testing::Test }; using TestTypes = testing::Types< - PaddingTestParams>>::ScalarField, - bb::MegaCircuitBuilder>, - PaddingTestParams::ScalarField, bb::UltraCircuitBuilder>, - PaddingTestParams::ScalarField, bb::CircuitSimulatorBN254>>; + PaddingTestParams>>, bb::MegaCircuitBuilder>, + PaddingTestParams, bb::UltraCircuitBuilder>, + PaddingTestParams, bb::CircuitSimulatorBN254>>; TYPED_TEST_SUITE(PaddingIndicatorArrayTest, TestTypes); diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp index d9f53cc3becd..a5e93db191ea 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.cpp @@ -111,7 +111,7 @@ AvmRecursiveVerifier_::AggregationObject AvmRecursiveVerifier_:: // unconstrained const size_t log_circuit_size = numeric::get_msb(static_cast(circuit_size.get_value())); const auto padding_indicator_array = - stdlib::compute_padding_indicator_array(FF(log_circuit_size)); + stdlib::compute_padding_indicator_array(FF(log_circuit_size)); auto sumcheck = SumcheckVerifier(transcript); FF alpha = transcript->template get_challenge("Sumcheck:alpha"); From 5f317e1644d3f9f94846ea504692cb1be14544a6 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 23 Apr 2025 12:30:45 +0000 Subject: [PATCH 24/26] replace log_n with padding array everywhere, remove redundant code --- .../commitment_schemes/gemini/gemini.hpp | 77 ++---- .../commitment_schemes/ipa/ipa.test.cpp | 15 +- .../commitment_schemes/kzg/kzg.test.cpp | 20 +- .../commitment_schemes/shplonk/shplemini.hpp | 245 +----------------- .../shplonk/shplemini.test.cpp | 10 +- .../shplemini.test.cpp | 2 +- .../src/barretenberg/eccvm/eccvm_verifier.cpp | 6 +- .../polynomials/gate_separator.hpp | 12 - .../eccvm_recursive_verifier.cpp | 9 +- .../translator_recursive_verifier.cpp | 10 +- .../src/barretenberg/sumcheck/sumcheck.hpp | 32 +-- .../barretenberg/sumcheck/sumcheck_round.hpp | 53 +--- .../translator_vm/translator_verifier.cpp | 7 +- .../ultra_honk/decider_verifier.cpp | 16 +- .../vm2/constraining/verifier.cpp | 11 +- 15 files changed, 123 insertions(+), 402 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index 062b3406a9fa..703c2537b3aa 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -531,20 +531,20 @@ template class GeminiVerifier_ { * In the case of interleaving, the first "negative" evaluation has to be corrected by the contribution from \f$ * P_{-}(-r^s)\f$, where \f$ s \f$ is the size of the group to be interleaved. * - * @param log_n The log of the size of the polynomial being opened. + * @param padding_indicator_array An array with first log_n entries equal to 1, and the remaining entries are 0. * @param batched_evaluation The evaluation of the batched polynomial at \f$ (u_0, \ldots, u_{d-1})\f$. * @param evaluation_point Evaluation point \f$ (u_0, \ldots, u_{d-1}) \f$ padded to CONST_PROOF_SIZE_LOG_N. * @param challenge_powers Powers of \f$ r \f$, \f$ r^2 \), ..., \( r^{2^{d-1}} \f$. * @param fold_neg_evals Evaluations \f$ A_{i-1}(-r^{2^{i-1}}) \f$. * @return \f$ A_0(r), A_1(r^2), \ldots, A_{d-1}(r^{2^{d-1}})\f$. */ - static std::vector compute_fold_pos_evaluations( - const size_t log_n, - const Fr& batched_evaluation, - std::span evaluation_point, // CONST_PROOF_SIZE - std::span challenge_powers, // r_squares CONST_PROOF_SIZE_LOG_N - std::span fold_neg_evals, - Fr p_neg = Fr(0)) + template + static std::vector compute_fold_pos_evaluations(const std::array& padding_indicator_array, + const Fr& batched_evaluation, + std::span evaluation_point, // size = virtual_log_n + std::span challenge_powers, // size = virtual_log_n + std::span fold_neg_evals, // size = virtual_log_n + Fr p_neg = Fr(0)) { std::vector evals(fold_neg_evals.begin(), fold_neg_evals.end()); @@ -556,14 +556,12 @@ template class GeminiVerifier_ { } std::vector fold_pos_evaluations; - fold_pos_evaluations.reserve(log_n); - // Either a computed eval of A_i at r^{2^i}, or 0 - Fr value_to_emplace; + fold_pos_evaluations.reserve(virtual_log_n); // Add the contribution of P-((-r)ˢ) to get A_0(-r), which is 0 if there are no interleaved polynomials evals[0] += p_neg; // Solve the sequence of linear equations - for (size_t l = log_n; l != 0; --l) { + for (size_t l = virtual_log_n; l != 0; --l) { // Get r²⁽ˡ⁻¹⁾ const Fr& challenge_power = challenge_powers[l - 1]; // Get uₗ₋₁ @@ -575,10 +573,13 @@ template class GeminiVerifier_ { // Divide by the denominator eval_pos *= (challenge_power * (Fr(1) - u) + u).invert(); - eval_pos_prev = eval_pos; - value_to_emplace = eval_pos_prev; - - fold_pos_evaluations.emplace_back(value_to_emplace); + // If current index is bigger than log_n, we propagate `batched_evaluation` to the next + // round. Otherwise, current `eval_pos` A₍ₗ₋₁₎(−r²⁽ˡ⁻¹⁾) becomes `eval_pos_prev` in the round l-2. + eval_pos_prev = + padding_indicator_array[l - 1] * eval_pos + (Fr{ 1 } - padding_indicator_array[l - 1]) * eval_pos_prev; + // If current index is bigger than log_n, we emplace 0, which is later multiplied against + // Commitment::one(). + fold_pos_evaluations.emplace_back(padding_indicator_array[l - 1] * eval_pos_prev); } std::reverse(fold_pos_evaluations.begin(), fold_pos_evaluations.end()); @@ -608,50 +609,6 @@ template class GeminiVerifier_ { * \f$. * @return \f A_{i}}(r^{2^{i}})\f$ \f$ i = 0, \ldots, \text{virtual_log_n} - 1 \f$. */ - template - static std::vector compute_fold_pos_evaluations( - const std::array& padding_indicator_array, - const Fr& batched_evaluation, - std::span evaluation_point, // CONST_PROOF_SIZE - std::span challenge_powers, // r_squares CONST_PROOF_SIZE_LOG_N - std::span fold_neg_evals) - requires Curve::is_stdlib_type - { - std::vector evals(fold_neg_evals.begin(), fold_neg_evals.end()); - - Fr eval_pos_prev = batched_evaluation; - - std::vector fold_pos_evaluations; - fold_pos_evaluations.reserve(virtual_log_n); - // Either a computed eval of A_i at r^{2^i}, or 0 - Fr value_to_emplace; - - // Solve the sequence of linear equations - for (size_t l = virtual_log_n; l != 0; --l) { - // Get r²⁽ˡ⁻¹⁾ - const Fr& challenge_power = challenge_powers[l - 1]; - // Get uₗ₋₁ - const Fr& u = evaluation_point[l - 1]; - const Fr& eval_neg = evals[l - 1]; - // Get A₍ₗ₋₁₎(−r²⁽ˡ⁻¹⁾) - // Compute the numerator - Fr eval_pos = ((challenge_power * eval_pos_prev * 2) - eval_neg * (challenge_power * (Fr(1) - u) - u)); - // Divide by the denominator - eval_pos *= (challenge_power * (Fr(1) - u) + u).invert(); - - // If current index is bigger than log_n, we propagate `batched_evaluation` to the next - // round. Otherwise, current `eval_pos` A₍ₗ₋₁₎(−r²⁽ˡ⁻¹⁾) becomes `eval_pos_prev` in the round l-2. - eval_pos_prev = - padding_indicator_array[l - 1] * eval_pos + (Fr{ 1 } - padding_indicator_array[l - 1]) * eval_pos_prev; - // If current index is bigger than log_n, we emplace 0, which is later multiplied against - // Commitment::one(). - fold_pos_evaluations.emplace_back(padding_indicator_array[l - 1] * eval_pos_prev); - } - - std::reverse(fold_pos_evaluations.begin(), fold_pos_evaluations.end()); - - return fold_pos_evaluations; - } }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp index 2d018891d3ce..7163760c2d61 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp @@ -303,8 +303,14 @@ TEST_F(IPATest, ShpleminiIPAWithShift) auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); - const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim( - small_log_n, mock_claims.claim_batcher, mle_opening_point, vk->get_g1_identity(), verifier_transcript); + std::array padding_indicator_array; + std::ranges::fill(padding_indicator_array, Fr{ 1 }); + + const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array, + mock_claims.claim_batcher, + mle_opening_point, + vk->get_g1_identity(), + verifier_transcript); auto result = PCS::reduce_verify_batch_opening_claim(batch_opening_claim, vk, verifier_transcript); // auto result = PCS::reduce_verify(vk, shplonk_verifier_claim, verifier_transcript); @@ -355,7 +361,10 @@ TEST_F(IPATest, ShpleminiIPAShiftsRemoval) // vectors corresponding to the "shifted" commitment auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); - const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(small_log_n, + std::array padding_indicator_array; + std::ranges::fill(padding_indicator_array, Fr{ 1 }); + + const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array, mock_claims.claim_batcher, mle_opening_point, vk->get_g1_identity(), diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index d28351c65262..a0feffba486b 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -190,8 +190,14 @@ TEST_F(KZGTest, ShpleminiKzgWithShift) // Gemini verifier output: // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1 - const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim( - log_n, mock_claims.claim_batcher, mle_opening_point, vk->get_g1_identity(), verifier_transcript); + std::array padding_indicator_array; + std::ranges::fill(padding_indicator_array, Fr{ 1 }); + + const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array, + mock_claims.claim_batcher, + mle_opening_point, + vk->get_g1_identity(), + verifier_transcript); const auto pairing_points = PCS::reduce_verify_batch_opening_claim(batch_opening_claim, verifier_transcript); // Final pairing check: e([Q] - [Q_z] + z[W], [1]_2) = e([W], [x]_2) @@ -238,7 +244,10 @@ TEST_F(KZGTest, ShpleminiKzgWithShiftAndInterleaving) // Gemini verifier output: // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1 - const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(log_n, + std::array padding_indicator_array; + std::ranges::fill(padding_indicator_array, Fr{ 1 }); + + const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array, mock_claims.claim_batcher, mle_opening_point, vk->get_g1_identity(), @@ -305,7 +314,10 @@ TEST_F(KZGTest, ShpleminiKzgShiftsRemoval) // Gemini verifier output: // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1 - const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(log_n, + std::array padding_indicator_array; + std::ranges::fill(padding_indicator_array, Fr{ 1 }); + + const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array, mock_claims.claim_batcher, mle_opening_point, vk->get_g1_identity(), diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 739b55acbf0e..2c0bcd3c8e67 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -195,9 +195,9 @@ template class ShpleminiVerifier_ { * Translator and ECCVM verifiers. * */ - template + template static BatchOpeningClaim compute_batch_opening_claim( - const size_t log_n, + const std::array& padding_indicator_array, ClaimBatcher& claim_batcher, const std::vector& multivariate_challenge, const Commitment& g1_identity, @@ -214,9 +214,6 @@ template class ShpleminiVerifier_ { { const bool committed_sumcheck = !sumcheck_round_evaluations.empty(); - // When padding is enabled, the size of the multilinear challenge may be bigger than the log of `circuit_size`. - const size_t virtual_log_n = multivariate_challenge.size(); - Fr batched_evaluation = Fr{ 0 }; // While Shplemini is not templated on Flavor, we derive ZK flag this way @@ -284,12 +281,8 @@ template class ShpleminiVerifier_ { // Initialize the vector of scalars placing the scalar 1 correposnding to Q_commitment std::vector scalars; - if constexpr (Curve::is_stdlib_type) { - auto builder = shplonk_batching_challenge.get_context(); - scalars.emplace_back(Fr(builder, 1)); - } else { - scalars.emplace_back(Fr(1)); - } + + scalars.emplace_back(Fr(1)); // Compute 1/(z − r), 1/(z + r), 1/(z - r²), 1/(z + r²), … , 1/(z - r^{2^{d-1}}), 1/(z + r^{2^{d-1}}) // These represent the denominators of the summand terms in Shplonk partially evaluated polynomial Q_z @@ -323,7 +316,7 @@ template class ShpleminiVerifier_ { if (claim_batcher.interleaved) { // Currently, the prover places the Interleaving claims before the Gemini dummy claims. // TODO(https://github.com/AztecProtocol/barretenberg/issues/1293): Decouple Gemini from Interleaving. - const size_t interleaved_pos_index = 2 * log_n; + const size_t interleaved_pos_index = 2 * virtual_log_n; const size_t interleaved_neg_index = interleaved_pos_index + 1; shplonk_batching_pos = shplonk_batching_challenge_powers[interleaved_pos_index]; shplonk_batching_neg = shplonk_batching_challenge_powers[interleaved_neg_index]; @@ -342,7 +335,7 @@ template class ShpleminiVerifier_ { // Reconstruct Aᵢ(r²ⁱ) for i=0, ..., d - 1 from the batched evaluation of the multilinear polynomials and // Aᵢ(−r²ⁱ) for i = 0, ..., d - 1. In the case of interleaving, we compute A₀(r) as A₀₊(r) + P₊(r^s). const std::vector gemini_fold_pos_evaluations = - GeminiVerifier_::compute_fold_pos_evaluations(log_n, + GeminiVerifier_::compute_fold_pos_evaluations(padding_indicator_array, batched_evaluation, multivariate_challenge, gemini_eval_challenge_powers, @@ -352,7 +345,7 @@ template class ShpleminiVerifier_ { // Place the commitments to Gemini fold polynomials Aᵢ in the vector of batch_mul commitments, compute the // contributions from Aᵢ(−r²ⁱ) for i=1, … , d − 1 to the constant term accumulator, add corresponding scalars // for the batch mul - batch_gemini_claims_received_from_prover(log_n, + batch_gemini_claims_received_from_prover(padding_indicator_array, fold_commitments, gemini_fold_neg_evaluations, gemini_fold_pos_evaluations, @@ -409,166 +402,6 @@ template class ShpleminiVerifier_ { return { commitments, scalars, shplonk_evaluation_challenge }; }; - /** - * @brief Padding version of \ref compute_batch_opening_claim. Used by recursive verifiers for the - * Flavors with USE_PADDING = true. Since ECCVM and Translator do not require padding, this method does not support - * interleaving or committed sumcheck logic. - * - */ - template - static BatchOpeningClaim compute_batch_opening_claim( - const std::array& padding_indicator_array, - ClaimBatcher& claim_batcher, - const std::vector& multivariate_challenge, - const Commitment& g1_identity, - const std::shared_ptr& transcript, - const RepeatedCommitmentsData& repeated_commitments = {}, - const bool has_zk = false, - bool* consistency_checked = nullptr, // TODO(https://github.com/AztecProtocol/barretenberg/issues/1191). - // Shplemini Refactoring: Remove bool pointer - const std::array& libra_commitments = {}, - const Fr& libra_univariate_evaluation = Fr{ 0 }) - requires Curve::is_stdlib_type - - { - - Fr batched_evaluation = Fr{ 0 }; - - // While Shplemini is not templated on Flavor, we derive ZK flag this way - Commitment hiding_polynomial_commitment; - if (has_zk) { - hiding_polynomial_commitment = - transcript->template receive_from_prover("Gemini:masking_poly_comm"); - batched_evaluation = transcript->template receive_from_prover("Gemini:masking_poly_eval"); - } - - // Get the challenge ρ to batch commitments to multilinear polynomials and their shifts - const Fr gemini_batching_challenge = transcript->template get_challenge("rho"); - - // Process Gemini transcript data: - // - Get Gemini commitments (com(A₁), com(A₂), … , com(Aₙ₋₁)) - const std::vector fold_commitments = - GeminiVerifier::get_fold_commitments(virtual_log_n, transcript); - // - Get Gemini evaluation challenge for Aᵢ, i = 0, … , d−1 - const Fr gemini_evaluation_challenge = transcript->template get_challenge("Gemini:r"); - - // - Get evaluations (A₀(−r), A₁(−r²), ... , Aₙ₋₁(−r²⁽ⁿ⁻¹⁾)) - const std::vector gemini_fold_neg_evaluations = - GeminiVerifier::get_gemini_evaluations(virtual_log_n, transcript); - - // - Compute vector (r, r², ... , r^{2^{d-1}}), where d = log_n - const std::vector gemini_eval_challenge_powers = - gemini::powers_of_evaluation_challenge(gemini_evaluation_challenge, virtual_log_n); - - std::array libra_evaluations; - if (has_zk) { - libra_evaluations[0] = transcript->template receive_from_prover("Libra:concatenation_eval"); - libra_evaluations[1] = transcript->template receive_from_prover("Libra:shifted_grand_sum_eval"); - libra_evaluations[2] = transcript->template receive_from_prover("Libra:grand_sum_eval"); - libra_evaluations[3] = transcript->template receive_from_prover("Libra:quotient_eval"); - } - - // Process Shplonk transcript data: - // - Get Shplonk batching challenge - const Fr shplonk_batching_challenge = transcript->template get_challenge("Shplonk:nu"); - - // Compute the powers of ν that are required for batching Gemini, SmallSubgroupIPA, and committed sumcheck - // univariate opening claims. - const std::vector shplonk_batching_challenge_powers = - compute_shplonk_batching_challenge_powers(shplonk_batching_challenge, virtual_log_n, has_zk); - // - Get the quotient commitment for the Shplonk batching of Gemini opening claims - const auto Q_commitment = transcript->template receive_from_prover("Shplonk:Q"); - - // Start populating the vector (Q, f₀, ... , fₖ₋₁, g₀, ... , gₘ₋₁, com(A₁), ... , com(A_{d-1}), [1]₁) where fᵢ - // are the k commitments to unshifted polynomials and gⱼ are the m commitments to shifted polynomials - std::vector commitments{ Q_commitment }; - - // Get Shplonk opening point z - const Fr shplonk_evaluation_challenge = transcript->template get_challenge("Shplonk:z"); - - // Start computing the scalar to be multiplied by [1]₁ - Fr constant_term_accumulator = Fr(0); - - // Initialize the vector of scalars placing the scalar 1 correposnding to Q_commitment - std::vector scalars; - auto builder = shplonk_batching_challenge.get_context(); - scalars.emplace_back(Fr(builder, 1)); - - // Compute 1/(z − r), 1/(z + r), 1/(z - r²), 1/(z + r²), … , 1/(z - r^{2^{d-1}}), 1/(z + r^{2^{d-1}}) - // These represent the denominators of the summand terms in Shplonk partially evaluated polynomial Q_z - const std::vector inverse_vanishing_evals = ShplonkVerifier::compute_inverted_gemini_denominators( - shplonk_evaluation_challenge, gemini_eval_challenge_powers); - // Compute the additional factors to be multiplied with unshifted and shifted commitments when lazily - // reconstructing the commitment of Q_z - claim_batcher.compute_scalars_for_each_batch( - inverse_vanishing_evals, shplonk_batching_challenge, gemini_evaluation_challenge); - - if (has_zk) { - commitments.emplace_back(hiding_polynomial_commitment); - scalars.emplace_back(-claim_batcher.get_unshifted_batch_scalar()); // corresponds to ρ⁰ - } - - // Place the commitments to prover polynomials in the commitments vector. Compute the evaluation of the - // batched multilinear polynomial. Populate the vector of scalars for the final batch mul - - Fr gemini_batching_challenge_power = Fr(1); - if (has_zk) { - // ρ⁰ is used to batch the hiding polynomial which has already been added to the commitments vector - gemini_batching_challenge_power *= gemini_batching_challenge; - } - - // Update the commitments and scalars vectors as well as the batched evaluation given the present batches - claim_batcher.update_batch_mul_inputs_and_batched_evaluation( - commitments, scalars, batched_evaluation, gemini_batching_challenge, gemini_batching_challenge_power); - - // Reconstruct Aᵢ(r²ⁱ) for i=0, ..., d - 1 from the batched evaluation of the multilinear polynomials and - // Aᵢ(−r²ⁱ) for i = 0, ..., d - 1. In the case of interleaving, we compute A₀(r) as A₀₊(r) + P₊(r^s). - const std::vector gemini_fold_pos_evaluations = - GeminiVerifier_::compute_fold_pos_evaluations(padding_indicator_array, - batched_evaluation, - multivariate_challenge, - gemini_eval_challenge_powers, - gemini_fold_neg_evaluations); - - // Place the commitments to Gemini fold polynomials Aᵢ in the vector of batch_mul commitments, compute the - // contributions from Aᵢ(−r²ⁱ) for i=1, … , d − 1 to the constant term accumulator, add corresponding scalars - // for the batch mul - batch_gemini_claims_received_from_prover(padding_indicator_array, - fold_commitments, - gemini_fold_neg_evaluations, - gemini_fold_pos_evaluations, - inverse_vanishing_evals, - shplonk_batching_challenge_powers, - commitments, - scalars, - constant_term_accumulator); - - remove_repeated_commitments(commitments, scalars, repeated_commitments, has_zk); - - // For ZK flavors, the sumcheck output contains the evaluations of Libra univariates that submitted to the - // ShpleminiVerifier, otherwise this argument is set to be empty - if (has_zk) { - add_zk_data(virtual_log_n, - commitments, - scalars, - constant_term_accumulator, - libra_commitments, - libra_evaluations, - gemini_evaluation_challenge, - shplonk_batching_challenge_powers, - shplonk_evaluation_challenge); - - *consistency_checked = SmallSubgroupIPAVerifier::check_libra_evaluations_consistency( - libra_evaluations, gemini_evaluation_challenge, multivariate_challenge, libra_univariate_evaluation); - } - - // Finalize the batch opening claim - commitments.emplace_back(g1_identity); - scalars.emplace_back(constant_term_accumulator); - - return { commitments, scalars, shplonk_evaluation_challenge }; - }; - /** * @brief Place fold polynomial commitments to `commitments` and compute the corresponding scalar multipliers. * @@ -611,63 +444,6 @@ template class ShpleminiVerifier_ { * @param scalars Output vector where the computed scalars will be stored. * @param constant_term_accumulator The accumulator for the summands of the Shplonk constant term. */ - static void batch_gemini_claims_received_from_prover(const size_t log_n, - const std::vector& fold_commitments, - const std::vector& gemini_neg_evaluations, - const std::vector& gemini_pos_evaluations, - const std::vector& inverse_vanishing_evals, - const std::vector& shplonk_batching_challenge_powers, - std::vector& commitments, - std::vector& scalars, - Fr& constant_term_accumulator) - { - // Start from 1, because the commitment to A_0 is reconstructed from the commitments to the multilinear - // polynomials. The corresponding evaluations are also handled separately. - for (size_t j = 1; j < log_n; ++j) { - // The index of 1/ (z - r^{2^{j}}) in the vector of inverted Gemini denominators - const size_t pos_index = 2 * j; - // The index of 1/ (z + r^{2^{j}}) in the vector of inverted Gemini denominators - const size_t neg_index = 2 * j + 1; - - // Compute the "positive" scaling factor (ν^{2j}) / (z - r^{2^{j}}) - Fr scaling_factor_pos = shplonk_batching_challenge_powers[pos_index] * inverse_vanishing_evals[pos_index]; - // Compute the "negative" scaling factor (ν^{2j+1}) / (z + r^{2^{j}}) - Fr scaling_factor_neg = shplonk_batching_challenge_powers[neg_index] * inverse_vanishing_evals[neg_index]; - - // Accumulate the const term contribution given by - // v^{2j} * A_j(r^{2^j}) /(z - r^{2^j}) + v^{2j+1} * A_j(-r^{2^j}) /(z+ r^{2^j}) - constant_term_accumulator += - scaling_factor_neg * gemini_neg_evaluations[j] + scaling_factor_pos * gemini_pos_evaluations[j]; - - // Place the scaling factor to the 'scalars' vector - scalars.emplace_back(-scaling_factor_neg - scaling_factor_pos); - // Move com(Aᵢ) to the 'commitments' vector - commitments.emplace_back(std::move(fold_commitments[j - 1])); - } - } - - /** - * @brief A method to compute the scalars to be multiplied against \f$ [A_i]\f$ for \f$ i = 1, \ldots, - * \text{virtual_log_n} \f$ and to update the Shplonk constant term accumulator. Required in the stdlib context by - * the Flavors with USE_PADDING = true. - * - * @details The main difference from the non-padding method is that instead of using `log_n`, this method uses - * `padding_indicator_array` of field elements computed in-circuit. - * Since i-th entry of this array is FF{1} if i < log_n and 0 otherwise, we ensure that dummy evaluations cannot be - * used to tamper with the final batch_mul result, by multiplying dummy positive evaluations by the entries of - * `padding_indicator_array`. - * - * @tparam virtual_log_n - * @param padding_indicator_array - * @param fold_commitments - * @param gemini_neg_evaluations - * @param gemini_pos_evaluations - * @param inverse_vanishing_evals - * @param shplonk_batching_challenge_powers - * @param commitments - * @param scalars - * @param constant_term_accumulator - */ template static void batch_gemini_claims_received_from_prover(const std::array& padding_indicator_array, const std::vector& fold_commitments, @@ -678,14 +454,7 @@ template class ShpleminiVerifier_ { std::vector& commitments, std::vector& scalars, Fr& constant_term_accumulator) - requires Curve::is_stdlib_type { - // Add contributions from A₀₊(r) and A₀₋(-r) to constant_term_accumulator: - // Add A₀₊(r)/(z−r) to the constant term accumulator - constant_term_accumulator += gemini_pos_evaluations[0] * inverse_vanishing_evals[0]; - // Add A₀₋(-r)/(z+r) to the constant term accumulator - constant_term_accumulator += - gemini_neg_evaluations[0] * shplonk_batching_challenge_powers[1] * inverse_vanishing_evals[1]; // Start from 1, because the commitment to A_0 is reconstructed from the commitments to the multilinear // polynomials. The corresponding evaluations are also handled separately. diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp index 5c7a62497800..758b8ef1f023 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp @@ -352,7 +352,10 @@ TYPED_TEST(ShpleminiTest, ShpleminiZKNoSumcheckOpenings) bool consistency_checked = true; // Run Shplemini - const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(this->log_n, + std::arraylog_n> padding_indicator_array; + std::ranges::fill(padding_indicator_array, Fr{ 1 }); + + const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array, mock_claims.claim_batcher, const_size_mle_opening_point, this->vk()->get_g1_identity(), @@ -458,7 +461,10 @@ TYPED_TEST(ShpleminiTest, ShpleminiZKWithSumcheckOpenings) bool consistency_checked = true; // Run Shplemini - const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(this->log_n, + std::arraylog_n> padding_indicator_array; + std::ranges::fill(padding_indicator_array, Fr{ 1 }); + + const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array, mock_claims.claim_batcher, challenge, this->vk()->get_g1_identity(), diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp index 9cc4b59bbb1e..b4720082a5bc 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp @@ -50,7 +50,7 @@ TEST(ShpleminiRecursionTest, ProveAndVerifySingle) size_t N = 1 << log_circuit_size; const auto padding_indicator_array = - stdlib::compute_padding_indicator_array(Fr(log_circuit_size)); + stdlib::compute_padding_indicator_array(log_circuit_size); constexpr size_t NUM_POLYS = 5; constexpr size_t NUM_SHIFTED = 2; constexpr size_t NUM_RIGHT_SHIFTED_BY_K = 1; diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index ff1b39c5d9aa..cdbb78c36b56 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -78,8 +78,12 @@ bool ECCVMVerifier::verify_proof(const ECCVMProof& proof) .unshifted = ClaimBatch{ commitments.get_unshifted(), sumcheck_output.claimed_evaluations.get_unshifted() }, .shifted = ClaimBatch{ commitments.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_shifted() } }; + + std::array padding_indicator_array; + std::ranges::fill(padding_indicator_array, FF{ 1 }); + BatchOpeningClaim sumcheck_batch_opening_claims = - Shplemini::compute_batch_opening_claim(CONST_ECCVM_LOG_N, + Shplemini::compute_batch_opening_claim(padding_indicator_array, claim_batcher, sumcheck_output.challenge, key->pcs_verification_key->get_g1_identity(), diff --git a/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp b/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp index fa61b88d531a..eaa04f75960c 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp @@ -81,18 +81,6 @@ template struct GateSeparatorPolynomial { */ FF univariate_eval(FF challenge) const { return (FF(1) + (challenge * (betas[current_element_idx] - FF(1)))); }; - /** - * @brief Evaluate \f$ ((1−X_{i}) + X_{i}\cdot \beta_{i})\f$ at the challenge point \f$ X_{i}=u_{i} \f$. - */ - FF univariate_eval(const FF& challenge, const FF& indicator) const - { - // For the Ultra Recursive flavor to ensure constant size proofs, we perform constant amount of hashing - // producing 28 gate betas and we need to use the betas in the dummy rounds to ensure the permutation related - // selectors stay the same regardless of real circuit size. - FF one{ 1 }; - return (one + indicator * challenge * (betas[current_element_idx] - one)); - } - /** * @brief Partially evaluate the \f$pow_{\beta} \f$-polynomial at the new challenge and update \f$ c_i \f$ * @details Update the constant \f$c_{i} \to c_{i+1} \f$ multiplying it by \f$pow_{\beta}\f$'s factor \f$\left( diff --git a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp index 91b2cb49e8aa..f799b69ee05a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp @@ -89,8 +89,15 @@ ECCVMRecursiveVerifier_::verify_proof(const ECCVMProof& proof) .unshifted = ClaimBatch{ commitments.get_unshifted(), sumcheck_output.claimed_evaluations.get_unshifted() }, .shifted = ClaimBatch{ commitments.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_shifted() } }; + + FF one{ 1 }; + one.convert_constant_to_fixed_witness(builder); + + std::array padding_indicator_array; + std::ranges::fill(padding_indicator_array, one); + BatchOpeningClaim sumcheck_batch_opening_claims = - Shplemini::compute_batch_opening_claim(CONST_ECCVM_LOG_N, + Shplemini::compute_batch_opening_claim(padding_indicator_array, claim_batcher, sumcheck_output.challenge, key->pcs_verification_key->get_g1_identity(), diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp index a939e4b2d8e4..795199f90d04 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp @@ -107,7 +107,13 @@ TranslatorRecursiveVerifier_::AggregationObject TranslatorRecursiveVerif std::array libra_commitments = {}; libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); - auto sumcheck_output = sumcheck.verify(relation_parameters, alpha, gate_challenges); + FF one{ 1 }; + one.convert_constant_to_fixed_witness(builder); + + std::array padding_indicator_array; + std::ranges::fill(padding_indicator_array, one); + + auto sumcheck_output = sumcheck.verify(relation_parameters, alpha, gate_challenges, padding_indicator_array); libra_commitments[1] = transcript->template receive_from_prover("Libra:grand_sum_commitment"); libra_commitments[2] = transcript->template receive_from_prover("Libra:quotient_commitment"); @@ -122,7 +128,7 @@ TranslatorRecursiveVerifier_::AggregationObject TranslatorRecursiveVerif .evaluations = sumcheck_output.claimed_evaluations.get_interleaved() } }; const BatchOpeningClaim opening_claim = - Shplemini::compute_batch_opening_claim(TranslatorFlavor::CONST_TRANSLATOR_LOG_N, + Shplemini::compute_batch_opening_claim(padding_indicator_array, claim_batcher, sumcheck_output.challenge, Commitment::one(builder), diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 210d64e35ee9..cc64578d1cde 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -703,25 +703,9 @@ template class FF round_challenge = transcript->template get_challenge("Sumcheck:u_" + std::to_string(round_idx)); multivariate_challenge.emplace_back(round_challenge); - // The recursive logic differs from the native one because of a hack making Sumcheck circuits in - // Ultra, Mega, and their derivatives constant. Note that there's no artificial padding in - // Translator - bool checked(true); - if constexpr (IsRecursiveFlavor && Flavor::USE_PADDING) { - checked = round.check_sum(round_univariate, padding_indicator_array[round_idx]); - round.compute_next_target_sum(round_univariate, round_challenge, padding_indicator_array[round_idx]); - gate_separators.partially_evaluate(round_challenge, padding_indicator_array[round_idx]); - - } else { - // This condition is needed to prevent updating the target total sum in dummy rounds when USE_PADDING = - // true. It is always satisfied when Sumcheck is instantiated with ECCVM or Translator - // Recursive Flavors. - if (round_idx < multivariate_d) { - checked = round.check_sum(round_univariate); - round.compute_next_target_sum(round_univariate, round_challenge); - gate_separators.partially_evaluate(round_challenge); - } - } + const bool checked = round.check_sum(round_univariate, padding_indicator_array[round_idx]); + round.compute_next_target_sum(round_univariate, round_challenge, padding_indicator_array[round_idx]); + gate_separators.partially_evaluate(round_challenge, padding_indicator_array[round_idx]); verified = verified && checked; } @@ -742,13 +726,9 @@ template class // For ZK Flavors: the evaluation of the Row Disabling Polynomial at the sumcheck challenge if constexpr (Flavor::HasZK) { libra_evaluation = transcript->template receive_from_prover("Libra:claimed_evaluation"); - if constexpr (IsRecursiveFlavor && Flavor::USE_PADDING) { - correcting_factor = - RowDisablingPolynomial::evaluate_at_challenge(multivariate_challenge, padding_indicator_array); - } else { - correcting_factor = - RowDisablingPolynomial::evaluate_at_challenge(multivariate_challenge, multivariate_d); - } + + correcting_factor = + RowDisablingPolynomial::evaluate_at_challenge(multivariate_challenge, padding_indicator_array); full_honk_purported_value = full_honk_purported_value * correcting_factor + libra_evaluation * libra_challenge; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index cf96ecf7fbef..b842836d6e00 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -582,30 +582,6 @@ template class SumcheckVerifierRound { { Utils::zero_elements(relation_evaluations); }; - /** - * @brief Check that the round target sum is correct - * @details The verifier receives the claimed evaluations of the round univariate \f$ \tilde{S}^i \f$ at \f$X_i = - * 0,\ldots, D \f$ and checks \f$\sigma_i = \tilde{S}^{i-1}(u_{i-1}) \stackrel{?}{=} \tilde{S}^i(0) + \tilde{S}^i(1) - * \f$ - * @param univariate Round univariate \f$\tilde{S}^{i}\f$ represented by its evaluations over \f$0,\ldots,D\f$. - * - */ - bool check_sum(SumcheckRoundUnivariate& univariate) - { - FF total_sum = univariate.value_at(0) + univariate.value_at(1); - // TODO(#673): Conditionals like this can go away once native verification is is just recursive verification - // with a simulated builder. - bool sumcheck_round_failed(false); - if constexpr (IsRecursiveFlavor) { - sumcheck_round_failed = target_total_sum.get_value() != total_sum.get_value(); - target_total_sum.assert_equal(total_sum); - } else { - sumcheck_round_failed = (target_total_sum != total_sum); - } - - round_failed = round_failed || sumcheck_round_failed; - return !sumcheck_round_failed; - }; /** * @brief Check that the round target sum is correct @@ -619,33 +595,22 @@ template class SumcheckVerifierRound { { FF total_sum = (FF(1) - indicator) * target_total_sum + indicator * (univariate.value_at(0) + univariate.value_at(1)); - // TODO(#673): Conditionals like this can go away once native verification is is just recursive verification - // with a simulated builder. bool sumcheck_round_failed(false); - // This bool is only needed for debugging - if (indicator.get_value() == FF{ 1 }.get_value()) { - sumcheck_round_failed = (target_total_sum.get_value() != total_sum.get_value()); - } + if constexpr (IsRecursiveFlavor) { + // This bool is only needed for debugging + if (indicator.get_value() == FF{ 1 }.get_value()) { + sumcheck_round_failed = (target_total_sum.get_value() != total_sum.get_value()); + } - target_total_sum.assert_equal(total_sum); + target_total_sum.assert_equal(total_sum); + } else { + sumcheck_round_failed = (target_total_sum != total_sum); + } round_failed = round_failed || sumcheck_round_failed; return !sumcheck_round_failed; }; - /** - * @brief After checking that the univariate is good for this round, compute the next target sum given by the - * evaluation \f$\tilde{S}^i(u_i)\f$. - * - * @param univariate \f$ \tilde{S}^i(X) \f$, given by its evaluations over \f$ \{0,1,2,\ldots, D\}\f$. - * @param round_challenge \f$ u_i\f$ - */ - void compute_next_target_sum(SumcheckRoundUnivariate& univariate, FF& round_challenge) - { - // Evaluate \f$\tilde{S}^{i}(u_{i}) \f$ - target_total_sum = univariate.evaluate(round_challenge); - } - /** * @brief After checking that the univariate is good for this round, compute the next target sum given by the * evaluation \f$ \tilde{S}^i(u_i) \f$. diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index 596abf991546..71fed6f2860d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -102,7 +102,10 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof, std::array libra_commitments = {}; libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); - auto sumcheck_output = sumcheck.verify(relation_parameters, alpha, gate_challenges); + std::array padding_indicator_array; + std::ranges::fill(padding_indicator_array, FF{ 1 }); + + auto sumcheck_output = sumcheck.verify(relation_parameters, alpha, gate_challenges, padding_indicator_array); // If Sumcheck did not verify, return false if (!sumcheck_output.verified) { @@ -122,7 +125,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof, .evaluations = sumcheck_output.claimed_evaluations.get_interleaved() } }; const BatchOpeningClaim opening_claim = - Shplemini::compute_batch_opening_claim(TranslatorFlavor::CONST_TRANSLATOR_LOG_N, + Shplemini::compute_batch_opening_claim(padding_indicator_array, claim_batcher, sumcheck_output.challenge, Commitment::one(), diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp index 2feb4e0bd214..879bc46e04eb 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp @@ -1,6 +1,7 @@ #include "decider_verifier.hpp" #include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" +#include "barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" #include "barretenberg/transcript/transcript.hpp" #include "barretenberg/ultra_honk/decider_verification_key.hpp" @@ -45,14 +46,21 @@ template bool DeciderVerifier_::verify() VerifierCommitments commitments{ accumulator->verification_key, accumulator->witness_commitments }; const size_t log_circuit_size = static_cast(accumulator->verification_key->log_circuit_size); - SumcheckVerifier sumcheck(log_circuit_size, transcript, accumulator->target_sum); + + std::array padding_indicator_array; + + for (size_t idx = 0; idx < CONST_PROOF_SIZE_LOG_N; idx++) { + padding_indicator_array[idx] = (idx < log_circuit_size) ? FF{ 1 } : FF{ 0 }; + } + + SumcheckVerifier sumcheck(transcript, accumulator->target_sum); // For MegaZKFlavor: receive commitments to Libra masking polynomials std::array libra_commitments = {}; if constexpr (Flavor::HasZK) { libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); } - SumcheckOutput sumcheck_output = - sumcheck.verify(accumulator->relation_parameters, accumulator->alphas, accumulator->gate_challenges); + SumcheckOutput sumcheck_output = sumcheck.verify( + accumulator->relation_parameters, accumulator->alphas, accumulator->gate_challenges, padding_indicator_array); // For MegaZKFlavor: the sumcheck output contains claimed evaluations of the Libra polynomials if constexpr (Flavor::HasZK) { @@ -71,7 +79,7 @@ template bool DeciderVerifier_::verify() .shifted = ClaimBatch{ commitments.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_shifted() } }; const BatchOpeningClaim opening_claim = - Shplemini::compute_batch_opening_claim(log_circuit_size, + Shplemini::compute_batch_opening_claim(padding_indicator_array, claim_batcher, sumcheck_output.challenge, Commitment::one(), diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.cpp index c8df4cdc8662..473a998f5a1c 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.cpp @@ -77,6 +77,12 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vector padding_indicator_array; + + for (size_t idx = 0; idx < CONST_PROOF_SIZE_LOG_N; idx++) { + padding_indicator_array[idx] = (idx < log_circuit_size) ? FF{ 1 } : FF{ 0 }; + } auto sumcheck = SumcheckVerifier(log_circuit_size, transcript); FF alpha = transcript->template get_challenge("Sumcheck:alpha"); @@ -86,7 +92,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } - SumcheckOutput output = sumcheck.verify(relation_parameters, alpha, gate_challenges); + SumcheckOutput output = + sumcheck.verify(relation_parameters, alpha, gate_challenges, padding_indicator_array); // If Sumcheck did not verify, return false if (!output.verified) { @@ -109,7 +116,7 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vector opening_claim = Shplemini::compute_batch_opening_claim( - log_circuit_size, claim_batcher, output.challenge, Commitment::one(), transcript); + padding_indicator_array, claim_batcher, output.challenge, Commitment::one(), transcript); const auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); VerifierCommitmentKey pcs_vkey{}; From 6fa8d9c6ce49ab6a6421ebcc22d6347354348b79 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 23 Apr 2025 16:52:53 +0000 Subject: [PATCH 25/26] more clean-up --- .../commitment_schemes/gemini/gemini.hpp | 41 +++++++------------ .../commitment_schemes/shplonk/shplemini.hpp | 29 +++++++------ .../shplonk/shplemini.test.cpp | 24 +++++------ .../polynomials/gate_separator.hpp | 2 + .../polynomials/row_disabling_polynomial.hpp | 5 ++- .../ultra_recursive_verifier.cpp | 2 + .../ultra_recursive_verifier.test.cpp | 6 +-- .../ultra_recursive_flavor.hpp | 3 ++ .../ultra_rollup_recursive_flavor.hpp | 3 ++ .../src/barretenberg/sumcheck/sumcheck.hpp | 24 +---------- .../barretenberg/sumcheck/sumcheck.test.cpp | 19 ++++++--- .../translator_vm/translator_verifier.cpp | 2 +- .../barretenberg/ultra_honk/sumcheck.test.cpp | 10 +++-- .../vm2/constraining/verifier.cpp | 2 +- 14 files changed, 81 insertions(+), 91 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index 703c2537b3aa..2d532853f3c1 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -442,10 +442,11 @@ template class GeminiVerifier_ { p_pos = transcript->template receive_from_prover("Gemini:P_0_pos"); p_neg = transcript->template receive_from_prover("Gemini:P_0_neg"); } + std::vector padding_indicator_array(log_n, Fr{ 1 }); // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., m-1 std::vector gemini_fold_pos_evaluations = compute_fold_pos_evaluations( - log_n, batched_evaluation, multilinear_challenge, r_squares, evaluations, p_neg); + padding_indicator_array, batched_evaluation, multilinear_challenge, r_squares, evaluations, p_neg); // Extract the evaluation A₀(r) = A₀₊(r) + P₊(r^s) auto full_a_0_pos = gemini_fold_pos_evaluations[0]; std::vector> fold_polynomial_opening_claims; @@ -531,21 +532,30 @@ template class GeminiVerifier_ { * In the case of interleaving, the first "negative" evaluation has to be corrected by the contribution from \f$ * P_{-}(-r^s)\f$, where \f$ s \f$ is the size of the group to be interleaved. * + * This method uses `padding_indicator_array`, whose i-th entry is FF{1} if i < log_n and 0 otherwise. + * We use these entries to either assign `eval_pos_prev` the value `eval_pos` computed in the current iteration of + * the loop, or to propagate the batched evaluation of the multilinear polynomials to the next iteration. This + * ensures the correctnes of the computation of the required positive evaluations. + * + * To ensure that dummy evaluations cannot be used to tamper with the final batch_mul result, we multiply dummy + * positive evaluations by the entries of `padding_indicator_array`. + * * @param padding_indicator_array An array with first log_n entries equal to 1, and the remaining entries are 0. * @param batched_evaluation The evaluation of the batched polynomial at \f$ (u_0, \ldots, u_{d-1})\f$. * @param evaluation_point Evaluation point \f$ (u_0, \ldots, u_{d-1}) \f$ padded to CONST_PROOF_SIZE_LOG_N. * @param challenge_powers Powers of \f$ r \f$, \f$ r^2 \), ..., \( r^{2^{d-1}} \f$. * @param fold_neg_evals Evaluations \f$ A_{i-1}(-r^{2^{i-1}}) \f$. - * @return \f$ A_0(r), A_1(r^2), \ldots, A_{d-1}(r^{2^{d-1}})\f$. + * @return \f A_{i}}(r^{2^{i}})\f$ \f$ i = 0, \ldots, \text{virtual_log_n} - 1 \f$. */ - template - static std::vector compute_fold_pos_evaluations(const std::array& padding_indicator_array, + static std::vector compute_fold_pos_evaluations(std::span padding_indicator_array, const Fr& batched_evaluation, std::span evaluation_point, // size = virtual_log_n std::span challenge_powers, // size = virtual_log_n std::span fold_neg_evals, // size = virtual_log_n Fr p_neg = Fr(0)) { + const size_t virtual_log_n = evaluation_point.size(); + std::vector evals(fold_neg_evals.begin(), fold_neg_evals.end()); Fr eval_pos_prev = batched_evaluation; @@ -586,29 +596,6 @@ template class GeminiVerifier_ { return fold_pos_evaluations; } - /** - * @brief A method to compute \f$ A_0(r), A_1(r^2), \ldots, A_{d-1}(r^{2^{d-1}})\f$ padded to `virtual_log_n` >= d. - * Required in the stdlib context by the Flavors with USE_PADDING = true. - * - * @details The main difference from the non-padding method is that instead of using `log_n`, this method uses - * `padding_indicator_array` of field elements computed in-circuit. - * Since i-th entry of this array is FF{1} if i < log_n and 0 otherwise, we use these entries to either assign - * `eval_pos_prev` the value `eval_pos` computed in the current iteration of the loop, or to propagate the batched - * evaluation of the multilinear polynomials to the next iteration. This ensures the correctnes of the computation - * of the required positive evaluations. - * - * To ensure that dummy evaluations cannot be used to tamper with the final batch_mul result, we multiply dummy - * positive evaluations by the entries of `padding_indicator_array`. - * - * @tparam virtual_log_n The fixed log circuit size determined by Flavor. - * @param padding_indicator_array An array with first log_n entries equal to 1, and the remaining entries are 0. - * @param batched_evaluation The evaluation of the batched polynomial at \f$ (u_0, \ldots, u_{d-1})\f$. - * @param evaluation_point Evaluation point \f$ (u_0, \ldots, u_{d-1}) \f$ padded to `virtual_log_n` size. - * @param challenge_powers Powers of \f$ r^{2^i}\f$ for \f$ i = 0, \ldots, \text{virtual_log_n} - 1 \f$. - * @param fold_neg_evals Evaluations \f$ A_{i-1}(-r^{2^{i-1}}) \f$ for \f$i = 0, \ldots,\text{virtual_log_n} - 1 - * \f$. - * @return \f A_{i}}(r^{2^{i}})\f$ \f$ i = 0, \ldots, \text{virtual_log_n} - 1 \f$. - */ }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 2c0bcd3c8e67..6c334210844a 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -195,9 +195,9 @@ template class ShpleminiVerifier_ { * Translator and ECCVM verifiers. * */ - template + template static BatchOpeningClaim compute_batch_opening_claim( - const std::array& padding_indicator_array, + std::span padding_indicator_array, ClaimBatcher& claim_batcher, const std::vector& multivariate_challenge, const Commitment& g1_identity, @@ -212,6 +212,8 @@ template class ShpleminiVerifier_ { const std::vector>& sumcheck_round_evaluations = {}) { + const size_t virtual_log_n = multivariate_challenge.size(); + const bool committed_sumcheck = !sumcheck_round_evaluations.empty(); Fr batched_evaluation = Fr{ 0 }; @@ -421,9 +423,11 @@ template class ShpleminiVerifier_ { * \frac{\nu^2}{z - r^2} + \frac{\nu^3}{z + r^2}, * \frac{\nu^4}{z - r^4} + \frac{\nu^5}{z + r^4}, * \ldots, - * \frac{\nu^{2 \cdot d} } {z - r^{2^{d-1}}} + \frac{\nu^{2 \cdot d + 1}}{z + r^{2^{d-1}}}. \f} - * The commitments \f$ [A_1]_1, \ldots, [A_{d-1}]_1 \f$ are multiplied by these scalars in the final `batch_mul` - * perfomed by KZG or IPA. + * \frac{\nu^{2 \cdot d} } {z - r^{2^{d-1}}} + \frac{\nu^{2 \cdot d + 1}}{z + r^{2^{d-1}}} \f} + * and multiplies them against the entries of `padding_indicator_array`. The commitments \f$ [A_1]_1, \ldots, + * [A_{d-1}]_1 \f$ are multiplied by these scalars in the final `batch_mul` perfomed by KZG or IPA. Since + * `padding_indicator_array[i]` = 1 for i < log_n, and 0 otherwise, it ensures that the contributions from "dummy" + * rounds do not affect the final `batch mul`. * * 3. Accumulates the summands of the constant term: * \f{align}{ @@ -431,7 +435,7 @@ template class ShpleminiVerifier_ { * A_i\left(-r^{2^i}\right)}{z+ r^{2^i}} \f} for \f$ i = 1, \ldots, d-1 \f$ and adds them to the * 'constant_term_accumulator'. * - * @param log_n The logarithm of the circuit size, determining the depth of the Gemini protocol. + * @param padding_indicator_array An array with first log_n entries equal to 1, and the remaining entries are 0. * @param fold_commitments A vector containing the commitments to the Gemini fold polynomials \f$ A_i \f$. * @param gemini_neg_evaluations The evaluations of Gemini fold polynomials \f$ A_i \f$ at \f$ -r^{2^i} \f$ for \f$ * i = 0, \ldots, d - 1 \f$. @@ -444,18 +448,17 @@ template class ShpleminiVerifier_ { * @param scalars Output vector where the computed scalars will be stored. * @param constant_term_accumulator The accumulator for the summands of the Shplonk constant term. */ - template - static void batch_gemini_claims_received_from_prover(const std::array& padding_indicator_array, + static void batch_gemini_claims_received_from_prover(std::span padding_indicator_array, const std::vector& fold_commitments, - const std::vector& gemini_neg_evaluations, - const std::vector& gemini_pos_evaluations, - const std::vector& inverse_vanishing_evals, - const std::vector& shplonk_batching_challenge_powers, + std::span gemini_neg_evaluations, + std::span gemini_pos_evaluations, + std::span inverse_vanishing_evals, + std::span shplonk_batching_challenge_powers, std::vector& commitments, std::vector& scalars, Fr& constant_term_accumulator) { - + const size_t virtual_log_n = gemini_neg_evaluations.size(); // Start from 1, because the commitment to A_0 is reconstructed from the commitments to the multilinear // polynomials. The corresponding evaluations are also handled separately. for (size_t j = 1; j < virtual_log_n; ++j) { diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp index 758b8ef1f023..8af96e53efc3 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp @@ -234,9 +234,10 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) ShplonkVerifier::compute_inverted_gemini_denominators(shplonk_eval_challenge, r_squares); Fr expected_constant_term_accumulator{ 0 }; + std::vector padding_indicator_array(this->log_n, Fr{ 1 }); std::vector gemini_fold_pos_evaluations = - GeminiVerifier_::compute_fold_pos_evaluations(this->log_n, + GeminiVerifier_::compute_fold_pos_evaluations(padding_indicator_array, expected_constant_term_accumulator, mle_opening_point, r_squares, @@ -245,7 +246,7 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) std::vector commitments; std::vector scalars; - ShpleminiVerifier::batch_gemini_claims_received_from_prover(this->log_n, + ShpleminiVerifier::batch_gemini_claims_received_from_prover(padding_indicator_array, prover_commitments, prover_evaluations, gemini_fold_pos_evaluations, @@ -287,10 +288,7 @@ TYPED_TEST(ShpleminiTest, ShpleminiZKNoSumcheckOpenings) ZKData zk_sumcheck_data(this->log_n, prover_transcript, ck); // Generate multivariate challenge of size CONST_PROOF_SIZE_LOG_N - std::vector const_size_mle_opening_point = this->random_evaluation_point(CONST_PROOF_SIZE_LOG_N); - // Truncate the multivariate challenge to evaluate prover polynomials (As in Sumcheck) - const std::vector mle_opening_point(const_size_mle_opening_point.begin(), - const_size_mle_opening_point.begin() + this->log_n); + std::vector mle_opening_point = this->random_evaluation_point(this->log_n); // Generate random prover polynomials, compute their evaluations and commitments MockClaimGenerator mock_claims(this->n, @@ -302,19 +300,19 @@ TYPED_TEST(ShpleminiTest, ShpleminiZKNoSumcheckOpenings) // Compute the sum of the Libra constant term and Libra univariates evaluated at Sumcheck challenges const Fr claimed_inner_product = SmallSubgroupIPAProver::compute_claimed_inner_product( - zk_sumcheck_data, const_size_mle_opening_point, this->log_n); + zk_sumcheck_data, mle_opening_point, this->log_n); prover_transcript->template send_to_verifier("Libra:claimed_evaluation", claimed_inner_product); // Instantiate SmallSubgroupIPAProver, this prover sends commitments to Big Sum and Quotient polynomials SmallSubgroupIPAProver small_subgroup_ipa_prover( - zk_sumcheck_data, const_size_mle_opening_point, claimed_inner_product, prover_transcript, ck); + zk_sumcheck_data, mle_opening_point, claimed_inner_product, prover_transcript, ck); small_subgroup_ipa_prover.prove(); // Reduce to KZG or IPA based on the curve used in the test Flavor const auto opening_claim = ShpleminiProver::prove(this->n, mock_claims.polynomial_batcher, - const_size_mle_opening_point, + mle_opening_point, ck, prover_transcript, small_subgroup_ipa_prover.get_witness_polynomials()); @@ -352,12 +350,11 @@ TYPED_TEST(ShpleminiTest, ShpleminiZKNoSumcheckOpenings) bool consistency_checked = true; // Run Shplemini - std::arraylog_n> padding_indicator_array; - std::ranges::fill(padding_indicator_array, Fr{ 1 }); + std::vector padding_indicator_array(this->log_n, Fr{ 1 }); const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array, mock_claims.claim_batcher, - const_size_mle_opening_point, + mle_opening_point, this->vk()->get_g1_identity(), verifier_transcript, {}, @@ -461,8 +458,7 @@ TYPED_TEST(ShpleminiTest, ShpleminiZKWithSumcheckOpenings) bool consistency_checked = true; // Run Shplemini - std::arraylog_n> padding_indicator_array; - std::ranges::fill(padding_indicator_array, Fr{ 1 }); + std::vector padding_indicator_array(this->log_n, Fr{ 1 }); const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array, mock_claims.claim_batcher, diff --git a/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp b/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp index eaa04f75960c..e7250d728bfc 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/gate_separator.hpp @@ -100,6 +100,8 @@ template struct GateSeparatorPolynomial { * @details Update the constant \f$c_{i} \to c_{i+1} \f$ multiplying it by \f$pow_{\beta}\f$'s factor \f$\left( * (1-X_i) + X_i\cdot \beta_i\right)\vert_{X_i = u_i}\f$ computed by \ref univariate_eval. * @param challenge \f$ i \f$-th verifier challenge \f$ u_{i}\f$ + * @param indicator An entry of `padding_indicator_array`, which is equal to 1 when round_idx < log_circuit_size + * and is 0 otherwise. */ void partially_evaluate(const FF& challenge, const FF& indicator) { diff --git a/barretenberg/cpp/src/barretenberg/polynomials/row_disabling_polynomial.hpp b/barretenberg/cpp/src/barretenberg/polynomials/row_disabling_polynomial.hpp index f5fe7ead851f..a5cdfc96a09e 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/row_disabling_polynomial.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/row_disabling_polynomial.hpp @@ -174,9 +174,12 @@ template struct RowDisablingPolynomial { return FF{ 1 } - evaluation_at_multivariate_challenge; } + /** - * @brief stdlib version of the above that ensures that the verifier's work does not depend on `log_circuit_size`. + * @brief A variant of the above that uses `padding_indicator_array`. * + * @param multivariate_challenge Sumcheck evaluation challenge + * @param padding_indicator_array An array with first log_n entries equal to 1, and the remaining entries are 0. */ template static FF evaluate_at_challenge(std::span multivariate_challenge, diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index e2311165dfe7..40a858153010 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -68,6 +68,8 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ honk_proof = proof; } transcript = std::make_shared(honk_proof); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1364): Improve VKs. Clarify the usage of + // RecursiveDeciderVK here. Seems unnecessary. auto verification_key = std::make_shared(builder, key); OinkVerifier oink_verifier{ builder, verification_key, transcript }; oink_verifier.verify(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp index 39926b8f32d1..ac3224571dee 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp @@ -176,10 +176,10 @@ template class RecursiveVerifierTest : public testing }; auto [blocks_10, verification_key_10] = get_blocks(10); - auto [blocks_11, verification_key_11] = get_blocks(14); + auto [blocks_14, verification_key_14] = get_blocks(14); - compare_ultra_blocks_and_verification_keys({ blocks_10, blocks_11 }, - { verification_key_10, verification_key_11 }); + compare_ultra_blocks_and_verification_keys({ blocks_10, blocks_14 }, + { verification_key_10, verification_key_14 }); } /** diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp index 13589fc7c96e..55cb18cd6f30 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp @@ -149,6 +149,9 @@ template class UltraRecursiveFlavor_ { size_t num_frs_read = 0; this->circuit_size = deserialize_from_frs(builder, elements, num_frs_read); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1364): Improve VKs. log_circuit_size must be a + // witness to make the Recursive Verifier circuit constant. Seems that other members also need to be turned + // into witnesses. this->log_circuit_size = FF::from_witness(&builder, numeric::get_msb(static_cast(this->circuit_size.get_value()))); this->num_public_inputs = deserialize_from_frs(builder, elements, num_frs_read); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp index bb4721807124..03d32f1f98e0 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp @@ -92,6 +92,9 @@ template class UltraRollupRecursiveFlavor_ : public Ultra size_t num_frs_read = 0; this->circuit_size = deserialize_from_frs(builder, elements, num_frs_read); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1364): Improve VKs. log_circuit_size must be a + // witness to make the Recursive Verifier circuit constant. Seems that other members also need to be turned + // into witnesses. this->log_circuit_size = FF::from_witness(&builder, numeric::get_msb(static_cast(this->circuit_size.get_value()))); this->num_public_inputs = deserialize_from_frs(builder, elements, num_frs_read); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index cc64578d1cde..8fae786cff11 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -621,11 +621,6 @@ template class * */ static constexpr size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; - /** - * @brief Number of variables in Prover Polynomials. - * - */ - size_t multivariate_d; std::shared_ptr transcript; SumcheckVerifierRound round; @@ -638,24 +633,9 @@ template class std::vector round_univariate_commitments = {}; std::vector> round_univariate_evaluations = {}; - // Native Ultra, Mega, and AVM Verifiers instantiate sumcheck with circuit size, optionally a different target sum - // than 0 can be specified. - explicit SumcheckVerifier(size_t multivariate_d, std::shared_ptr transcript, FF target_sum = 0) - : multivariate_d(multivariate_d) - , transcript(transcript) - , round(target_sum){}; - - // Recursive Verifiers without padding use the fixed log of the circuit size to determine the number of sumcheck - // rounds. Recursive Verifiers **with padding** are not permitted to use multivariate_d. explicit SumcheckVerifier(std::shared_ptr transcript, FF target_sum = 0) : transcript(transcript) - , round(target_sum) - { - if constexpr (!Flavor::USE_PADDING) { - // If the circuit sizes are genuinely fixed, use the log of the const fixed size. - this->multivariate_d = virtual_log_n; - } - }; + , round(target_sum){}; /** * @brief Extract round univariate, check sum, generate challenge, compute next target sum..., repeat until * final round, then use purported evaluations to generate purported full Honk relation value and check against @@ -673,7 +653,7 @@ template class { bool verified(true); - // Pad gate challenges for Protogalaxy DeciderVerifier + // Pad gate challenges for Protogalaxy DeciderVerifier and AVM if constexpr (Flavor::USE_PADDING) { round.pad_gate_challenges(gate_challenges); } diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp index af37c8af678a..f6778d376088 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp @@ -242,7 +242,7 @@ template class SumcheckTests : public ::testing::Test { .public_input_delta = FF::one(), }; auto prover_transcript = Flavor::Transcript::prover_init_empty(); - auto sumcheck_prover = SumcheckProver(multivariate_n, prover_transcript); + auto sumcheck_prover = SumcheckProver(multivariate_n, prover_transcript); RelationSeparator prover_alpha; for (size_t idx = 0; idx < prover_alpha.size(); idx++) { @@ -264,7 +264,7 @@ template class SumcheckTests : public ::testing::Test { auto verifier_transcript = Flavor::Transcript::verifier_init_empty(prover_transcript); - auto sumcheck_verifier = SumcheckVerifier(multivariate_d, verifier_transcript); + auto sumcheck_verifier = SumcheckVerifier(verifier_transcript); RelationSeparator verifier_alpha; for (size_t idx = 0; idx < verifier_alpha.size(); idx++) { verifier_alpha[idx] = @@ -275,7 +275,10 @@ template class SumcheckTests : public ::testing::Test { verifier_gate_challenges[idx] = verifier_transcript->template get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } - auto verifier_output = sumcheck_verifier.verify(relation_parameters, verifier_alpha, verifier_gate_challenges); + std::array padding_indicator_array; + std::ranges::fill(padding_indicator_array, FF{ 1 }); + auto verifier_output = sumcheck_verifier.verify( + relation_parameters, verifier_alpha, verifier_gate_challenges, padding_indicator_array); auto verified = verifier_output.verified; @@ -331,7 +334,7 @@ template class SumcheckTests : public ::testing::Test { .public_input_delta = FF::one(), }; auto prover_transcript = Flavor::Transcript::prover_init_empty(); - auto sumcheck_prover = SumcheckProver(multivariate_n, prover_transcript); + auto sumcheck_prover = SumcheckProver(multivariate_n, prover_transcript); RelationSeparator prover_alpha; for (size_t idx = 0; idx < prover_alpha.size(); idx++) { @@ -354,7 +357,7 @@ template class SumcheckTests : public ::testing::Test { auto verifier_transcript = Flavor::Transcript::verifier_init_empty(prover_transcript); - auto sumcheck_verifier = SumcheckVerifier(multivariate_d, verifier_transcript); + auto sumcheck_verifier = SumcheckVerifier(verifier_transcript); RelationSeparator verifier_alpha; for (size_t idx = 0; idx < verifier_alpha.size(); idx++) { verifier_alpha[idx] = @@ -365,7 +368,11 @@ template class SumcheckTests : public ::testing::Test { verifier_gate_challenges[idx] = verifier_transcript->template get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } - auto verifier_output = sumcheck_verifier.verify(relation_parameters, verifier_alpha, verifier_gate_challenges); + + std::array padding_indicator_array; + std::ranges::fill(padding_indicator_array, FF{ 1 }); + auto verifier_output = sumcheck_verifier.verify( + relation_parameters, verifier_alpha, verifier_gate_challenges, padding_indicator_array); auto verified = verifier_output.verified; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index 71fed6f2860d..9ff0d9145c89 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -91,7 +91,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof, commitments.z_perm = transcript->template receive_from_prover(commitment_labels.z_perm); // Execute Sumcheck Verifier - Sumcheck sumcheck(TranslatorFlavor::CONST_TRANSLATOR_LOG_N, transcript); + Sumcheck sumcheck(transcript); FF alpha = transcript->template get_challenge("Sumcheck:alpha"); std::vector gate_challenges(Flavor::CONST_TRANSLATOR_LOG_N); for (size_t idx = 0; idx < gate_challenges.size(); idx++) { diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp index 69bd748e319c..56d13d46c0a8 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp @@ -175,7 +175,7 @@ TEST_F(SumcheckTestsRealCircuit, Ultra) auto verifier_transcript = Transcript::verifier_init_empty(prover_transcript); - auto sumcheck_verifier = SumcheckVerifier(log_circuit_size, verifier_transcript); + auto sumcheck_verifier = SumcheckVerifier(verifier_transcript); RelationSeparator verifier_alphas; for (size_t idx = 0; idx < verifier_alphas.size(); idx++) { verifier_alphas[idx] = verifier_transcript->template get_challenge("Sumcheck:alpha_" + std::to_string(idx)); @@ -186,8 +186,12 @@ TEST_F(SumcheckTestsRealCircuit, Ultra) verifier_gate_challenges[idx] = verifier_transcript->template get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } - auto verifier_output = - sumcheck_verifier.verify(decider_pk->relation_parameters, verifier_alphas, verifier_gate_challenges); + std::array padding_indicator_array; + for (size_t idx = 0; idx < padding_indicator_array.size(); idx++) { + padding_indicator_array[idx] = (idx < log_circuit_size) ? FF{ 1 } : FF{ 0 }; + } + auto verifier_output = sumcheck_verifier.verify( + decider_pk->relation_parameters, verifier_alphas, verifier_gate_challenges, padding_indicator_array); auto verified = verifier_output.verified; diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.cpp index 473a998f5a1c..48abf292b09b 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.cpp @@ -83,7 +83,7 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vector(log_circuit_size, transcript); + auto sumcheck = SumcheckVerifier(transcript); FF alpha = transcript->template get_challenge("Sumcheck:alpha"); From cc0edd7a96f6fdb48e295bc46c6db2050ad1b831 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Wed, 23 Apr 2025 20:30:04 +0000 Subject: [PATCH 26/26] minor cleanup --- .../padding_indicator_array.test.cpp | 8 ++++---- barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp index 4dded7b768ff..ab36549b5598 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.test.cpp @@ -55,7 +55,7 @@ template class PaddingIndicatorArrayTest : public testing::Test Fr zero = Fr::from_witness(&builder, 0); - [[maybe_unused]] auto result = compute_padding_indicator_array(zero); + compute_padding_indicator_array(zero); info("num gates = ", builder.get_estimated_num_finalized_gates()); EXPECT_FALSE(CircuitChecker::check(builder)); @@ -67,7 +67,7 @@ template class PaddingIndicatorArrayTest : public testing::Test Fr N = Fr::from_witness(&builder, domain_size); - [[maybe_unused]] auto result = compute_padding_indicator_array(N); + compute_padding_indicator_array(N); info("num gates = ", builder.get_estimated_num_finalized_gates()); EXPECT_TRUE(CircuitChecker::check(builder)); @@ -82,7 +82,7 @@ template class PaddingIndicatorArrayTest : public testing::Test Fr x = Fr::from_witness(&builder, scalar_raw); - [[maybe_unused]] auto result = compute_padding_indicator_array(x); + compute_padding_indicator_array(x); info("num gates = ", builder.get_estimated_num_finalized_gates()); EXPECT_FALSE(CircuitChecker::check(builder)); @@ -94,7 +94,7 @@ template class PaddingIndicatorArrayTest : public testing::Test auto get_gate_count = [](const uint32_t& scalar_raw) -> size_t { Builder builder; Fr x = Fr::from_witness(&builder, scalar_raw); - [[maybe_unused]] auto result = compute_padding_indicator_array(x); + auto result = compute_padding_indicator_array(x); size_t gate_count = builder.get_estimated_num_finalized_gates(); // Create a witness = 2^(idx) diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index b89ef44826b4..d8b976588836 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -654,7 +654,7 @@ template class SumcheckOutput verify(const bb::RelationParameters& relation_parameters, RelationSeparator alpha, std::vector& gate_challenges, - const std::array& padding_indicator_array = {}) + const std::array& padding_indicator_array) requires(!IsGrumpkinFlavor) { bool verified(true);