13#include <gtest/gtest.h>
22using Fr =
typename G1::Fr;
38 &polys.msm_size_of_msm,
50 &polys.msm_collision_x1,
51 &polys.msm_collision_x2,
52 &polys.msm_collision_x3,
53 &polys.msm_collision_x4,
63 &polys.msm_transition,
67 &polys.msm_accumulator_x,
68 &polys.msm_accumulator_y,
81 auto generators = G1::derive_generators(
"test generators", 3);
82 auto a = generators[0];
83 auto b = generators[1];
88 op_queue->mul_accumulate(
a, x);
89 op_queue->mul_accumulate(
b, y);
90 op_queue->eq_and_reset();
106 const FF beta_sqr = beta.
sqr();
107 const FF beta_cube = beta_sqr * beta;
108 auto eccvm_set_permutation_delta =
109 gamma * (gamma + beta_sqr) * (gamma + beta_sqr + beta_sqr) * (gamma + beta_sqr + beta_sqr + beta_sqr);
110 eccvm_set_permutation_delta = eccvm_set_permutation_delta.
invert();
116 .public_input_delta = 0,
117 .beta_sqr = beta_sqr,
118 .beta_cube = beta_cube,
119 .eccvm_set_permutation_delta = eccvm_set_permutation_delta,
122 const size_t num_rows = polynomials.get_polynomial_size();
123 const size_t unmasked_witness_size = num_rows - NUM_DISABLED_ROWS_IN_SUMCHECK;
124 compute_logderivative_inverse<FF, ECCVMLookupRelation<FF>>(polynomials, params, unmasked_witness_size);
125 compute_grand_product<Flavor, ECCVMSetRelation<FF>>(polynomials, params, unmasked_witness_size);
126 polynomials.z_perm_shift =
Polynomial(polynomials.z_perm.shifted());
136 const size_t num_rows = polynomials.get_polynomial_size();
137 for (
size_t i = 2; i < num_rows - 1; i++) {
138 if (polynomials.transcript_add[i] ==
FF(0) && polynomials.transcript_mul[i] ==
FF(0) &&
139 polynomials.transcript_eq[i] ==
FF(0) && polynomials.transcript_reset_accumulator[i] ==
FF(0) &&
140 polynomials.lagrange_first[i] ==
FF(0) && polynomials.lagrange_last[i] ==
FF(0)) {
165 auto polynomials = build_valid_eccvm_msm_state();
169 EXPECT_TRUE(baseline.empty()) <<
"Baseline MSM relation should pass";
172 ASSERT_EQ(polynomials.msm_add[1],
FF(1)) <<
"Row 1 should be an active MSM add row";
173 ASSERT_EQ(polynomials.msm_transition[1],
FF(1)) <<
"Row 1 should have msm_transition=1";
178 polynomials.set_shifted();
181 EXPECT_TRUE(failures.empty()) <<
"MSM relation should STILL PASS — acc is unused when msm_transition=1";
200 auto polynomials = build_valid_eccvm_msm_state();
203 EXPECT_TRUE(baseline.empty()) <<
"Baseline MSM relation should pass";
206 const size_t num_rows = polynomials.get_polynomial_size();
207 size_t active_row = 0;
208 for (
size_t i = 1; i < num_rows - 1; i++) {
209 if (polynomials.msm_add[i] ==
FF(1) && polynomials.msm_transition[i] ==
FF(0)) {
214 ASSERT_NE(active_row, 0) <<
"Should find an interior active MSM add row";
218 polynomials.set_shifted();
221 EXPECT_FALSE(failures.empty()) <<
"MSM relation should fail after active-row accumulator corruption";
226 auto polynomials = build_valid_eccvm_msm_state();
229 const size_t num_rows = polynomials.get_polynomial_size();
230 size_t no_op_row = 0;
231 for (
size_t i = 2; i < num_rows - 1; i++) {
232 if (polynomials.msm_add[i] ==
FF(0) && polynomials.msm_double[i] ==
FF(0) &&
233 polynomials.msm_skew[i] ==
FF(0) && polynomials.msm_transition[i] ==
FF(0) &&
234 polynomials.lagrange_first[i] ==
FF(0)) {
239 ASSERT_NE(no_op_row, 0) <<
"Should find a no-op row in the MSM table";
243 polynomials.set_shifted();
246 EXPECT_FALSE(failures.empty()) <<
"MSM relation should fail after no-op accumulator corruption";
249 bool found_noop_subrelation_failure = failures.contains(45) || failures.contains(46);
250 EXPECT_TRUE(found_noop_subrelation_failure)
251 <<
"Failure should be detected by subrelations 45/46 (no-op accumulator preservation)";
272 auto polynomials = build_valid_eccvm_msm_state();
277 EXPECT_TRUE(baseline.empty()) <<
"Baseline MSM relation should pass";
279 const size_t num_rows = polynomials.get_polynomial_size();
280 auto msm_polys = get_msm_polynomials(polynomials);
283 for (
auto* poly : msm_polys) {
284 for (
size_t k = num_rows - 1; k >= 2; k--) {
285 poly->at(k) = (*poly)[k - 1];
294 polynomials.msm_size_of_msm.at(1) = polynomials.msm_pc[1] - polynomials.msm_pc[2];
297 polynomials.set_shifted();
300 EXPECT_FALSE(failures.empty()) <<
"MSM relation should fail after shifting MSM table by one row";
303 for (
const auto& [subrelation_idx, row_idx] : failures) {
304 info(
"Shifted MSM table: subrelation ", subrelation_idx,
" first failed at row ", row_idx);
308 EXPECT_EQ(failures.size(), 2U) <<
"Exactly two subrelations should fail (45 and 46)";
309 EXPECT_TRUE(failures.contains(45)) <<
"Subrelation 45 (no-op acc_x preservation) should fail";
310 EXPECT_TRUE(failures.contains(46)) <<
"Subrelation 46 (no-op acc_y preservation) should fail";
315 auto full_params = compute_full_relation_params(polynomials);
318 auto transcript_failures =
320 EXPECT_TRUE(transcript_failures.empty()) <<
"ECCVMTranscriptRelation should still pass";
322 auto point_table_failures =
324 EXPECT_TRUE(point_table_failures.empty()) <<
"ECCVMPointTableRelation should still pass";
328 EXPECT_TRUE(wnaf_failures.empty()) <<
"ECCVMWnafRelation should still pass";
330 auto bools_failures =
332 EXPECT_TRUE(bools_failures.empty()) <<
"ECCVMBoolsRelation should still pass";
340 EXPECT_FALSE(set_failures.empty()) <<
"ECCVMSetRelation should also fail (MSM output tuples are shifted)";
346 polynomials, full_params,
"ECCVMLookupRelation");
347 EXPECT_TRUE(lookup_failures.empty()) <<
"ECCVMLookupRelation should still pass (inverse computed post-shift)";
359 auto polynomials = build_valid_eccvm_msm_state();
364 EXPECT_TRUE(baseline.empty()) <<
"Baseline transcript relation should pass";
366 size_t noop_row = find_transcript_noop_row(polynomials);
367 ASSERT_NE(noop_row, 0) <<
"Should find a transcript no-op row";
371 polynomials.transcript_accumulator_not_empty.at(noop_row + 1) =
FF(1);
372 polynomials.set_shifted();
376 EXPECT_FALSE(failures.empty()) <<
"Transcript relation should fail after corrupting accumulator_not_empty on "
377 "the row following a no-op";
378 EXPECT_TRUE(failures.contains(22)) <<
"Subrelation 22 (accumulator_infinity) should catch the corruption";
static void SetUpTestSuite()
A container for the prover polynomials.
typename Curve::ScalarField FF
bb::Polynomial< FF > Polynomial
Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x .....
A debugging utility for checking whether a set of polynomials satisfies the relations for a given Fla...
A wrapper for Relations to expose methods used by the Sumcheck prover or verifier to add the contribu...
typename ECCVMFlavor::ProverPolynomials ProverPolynomials
void add_hiding_op_for_test(const std::shared_ptr< ECCOpQueue > &op_queue)
Set a hiding op on the op_queue for testing.
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
Entry point for Barretenberg command-line interface.
group< fq, fr, Bn254G1Params > g1
TEST_F(IPATest, ChallengesAreZero)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Container for parameters used by the grand product (permutation, lookup) Honk relations.
constexpr field invert() const noexcept
static field random_element(numeric::RNG *engine=nullptr) noexcept
BB_INLINE constexpr field sqr() const noexcept