3#include "barretenberg/common/map.hpp"
4#include "barretenberg/common/mem.hpp"
5#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp"
6#include "barretenberg/polynomials/iterate_over_domain.hpp"
7#include "barretenberg/polynomials/polynomial_arithmetic.hpp"
8#include "barretenberg/transcript/transcript.hpp"
13template <const
size_t num_roots_cut_out_of_vanishing_polynomial>
14ProverPlookupWidget<num_roots_cut_out_of_vanishing_polynomial>::ProverPlookupWidget(proving_key* input_key)
15 : ProverRandomWidget(input_key)
18template <const
size_t num_roots_cut_out_of_vanishing_polynomial>
19ProverPlookupWidget<num_roots_cut_out_of_vanishing_polynomial>::ProverPlookupWidget(
const ProverPlookupWidget& other)
20 : ProverRandomWidget(other)
23template <const
size_t num_roots_cut_out_of_vanishing_polynomial>
24ProverPlookupWidget<num_roots_cut_out_of_vanishing_polynomial>::ProverPlookupWidget(ProverPlookupWidget&& other)
25 : ProverRandomWidget(other)
28template <const
size_t num_roots_cut_out_of_vanishing_polynomial>
29ProverPlookupWidget<num_roots_cut_out_of_vanishing_polynomial>& ProverPlookupWidget<
30 num_roots_cut_out_of_vanishing_polynomial>::operator=(
const ProverPlookupWidget& other)
32 ProverRandomWidget::operator=(other);
36template <const
size_t num_roots_cut_out_of_vanishing_polynomial>
37ProverPlookupWidget<num_roots_cut_out_of_vanishing_polynomial>& ProverPlookupWidget<
38 num_roots_cut_out_of_vanishing_polynomial>::operator=(ProverPlookupWidget&& other)
40 ProverRandomWidget::operator=(other);
53template <const
size_t num_roots_cut_out_of_vanishing_polynomial>
57 auto s_accum(key->polynomial_store.get(
"s_1_lagrange"));
58 auto const& s_2 = key->polynomial_store.get(
"s_2_lagrange");
59 auto const& s_3 = key->polynomial_store.get(
"s_3_lagrange");
60 auto const& s_4 = key->polynomial_store.get(
"s_4_lagrange");
63 const auto eta = fr::serialize_from_buffer(transcript.
get_challenge(
"eta", 0).begin());
67 ITERATE_OVER_DOMAIN_START(key->small_domain);
75 ITERATE_OVER_DOMAIN_END;
90 const size_t s_randomness = 3;
91 ASSERT(s_randomness < num_roots_cut_out_of_vanishing_polynomial);
92 for (
size_t k = 0; k < s_randomness; ++k) {
93 s_accum[((key->circuit_size - num_roots_cut_out_of_vanishing_polynomial) + 1 + k)] = fr::random_element();
97 polynomial s_lagrange(s_accum, key->small_domain.size);
98 key->polynomial_store.put(
"s_lagrange", std::move(s_lagrange));
101 s_accum.ifft(key->small_domain);
102 key->polynomial_store.put(
"s", std::move(s_accum));
122template <const
size_t num_roots_cut_out_of_vanishing_polynomial>
126 const size_t n = key->circuit_size;
137 std::shared_ptr<void> accumulators_ptrs[4];
140 accumulators[0] = &z_lookup[1];
141 for (
size_t k = 1; k < 4; ++k) {
143 accumulators[k] = (
fr*)accumulators_ptrs[k].get();
146 auto s_lagrange = key->polynomial_store.get(
"s_lagrange");
147 auto column_1_step_size = key->polynomial_store.get(
"q_2_lagrange");
148 auto column_2_step_size = key->polynomial_store.get(
"q_m_lagrange");
149 auto column_3_step_size = key->polynomial_store.get(
"q_c_lagrange");
151 fr eta = fr::serialize_from_buffer(transcript.
get_challenge(
"eta").begin());
152 fr eta_sqr = eta.
sqr();
153 fr eta_cube = eta_sqr * eta;
155 fr beta = fr::serialize_from_buffer(transcript.
get_challenge(
"beta").begin());
156 fr gamma = fr::serialize_from_buffer(transcript.
get_challenge(
"beta", 1).begin());
159 std::array<std::shared_ptr<fr[]>, 4> lagrange_base_tables_ptr{
160 key->polynomial_store.get(
"table_value_1_lagrange").data(),
161 key->polynomial_store.get(
"table_value_2_lagrange").data(),
162 key->polynomial_store.get(
"table_value_3_lagrange").data(),
163 key->polynomial_store.get(
"table_value_4_lagrange").data(),
165 auto lagrange_base_tables = map(lagrange_base_tables_ptr, [](
auto& e) {
return e.get(); });
167 auto lookup_selector = key->polynomial_store.get(
"table_type_lagrange");
168 auto lookup_index_selector = key->polynomial_store.get(
"q_3_lagrange");
170 std::array<std::shared_ptr<fr[]>, 3> lagrange_base_wires_ptr{
171 key->polynomial_store.get(
"w_1_lagrange").data(),
172 key->polynomial_store.get(
"w_2_lagrange").data(),
173 key->polynomial_store.get(
"w_3_lagrange").data(),
175 auto lagrange_base_wires = map(lagrange_base_wires_ptr, [](
auto& e) {
return e.get(); });
177 const fr beta_constant = beta +
fr(1);
178 const fr gamma_beta_constant = gamma * beta_constant;
201 parallel_for(key->small_domain.num_threads, [&](
size_t j) {
204 size_t start = j * key->small_domain.thread_size;
205 size_t end = (j + 1) * key->small_domain.thread_size;
208 const size_t block_mask = key->small_domain.size - 1;
211 fr next_table = lagrange_base_tables[0][start] + lagrange_base_tables[1][start] * eta +
212 lagrange_base_tables[2][start] * eta_sqr + lagrange_base_tables[3][start] * eta_cube;
213 for (size_t i = start; i < end; ++i) {
215 T0 = lookup_index_selector[i];
217 T0 += lagrange_base_wires[2][(i + 1) & block_mask] * column_3_step_size[i];
218 T0 += lagrange_base_wires[2][i];
220 T0 += lagrange_base_wires[1][(i + 1) & block_mask] * column_2_step_size[i];
221 T0 += lagrange_base_wires[1][i];
223 T0 += lagrange_base_wires[0][(i + 1) & block_mask] * column_1_step_size[i];
224 T0 += lagrange_base_wires[0][i];
225 T0 *= lookup_selector[i];
228 accumulators[0][i] = T0;
229 accumulators[0][i] += gamma;
232 T0 = lagrange_base_tables[3][(i + 1) & block_mask];
234 T0 += lagrange_base_tables[2][(i + 1) & block_mask];
236 T0 += lagrange_base_tables[1][(i + 1) & block_mask];
238 T0 += lagrange_base_tables[0][(i + 1) & block_mask];
241 accumulators[1][i] = T0 * beta + next_table;
243 accumulators[1][i] += gamma_beta_constant;
246 accumulators[2][i] = beta_constant;
249 accumulators[3][i] = s_lagrange[size_t(i + 1) & (size_t)block_mask];
250 accumulators[3][i] *= beta;
251 accumulators[3][i] += s_lagrange[(size_t)i];
252 accumulators[3][i] += gamma_beta_constant;
265 parallel_for(4, [&](
size_t i) {
266 fr* coeffs = &accumulators[i][0];
267 for (
size_t j = 0; j < key->small_domain.size - 1; ++j) {
268 coeffs[j + 1] *= coeffs[j];
291 parallel_for(key->small_domain.num_threads, [&](
size_t j) {
292 const size_t start = j * key->small_domain.thread_size;
295 const size_t end = (j == key->small_domain.num_threads - 1) ? (j + 1) * key->small_domain.thread_size - 1
296 : (j + 1) * key->small_domain.thread_size;
299 fr inversion_accumulator = fr::one();
300 for (size_t i = start; i < end; ++i) {
301 accumulators[0][i] *= accumulators[2][i];
302 accumulators[0][i] *= accumulators[1][i];
303 accumulators[0][i] *= inversion_accumulator;
304 inversion_accumulator *= accumulators[3][i];
306 inversion_accumulator = inversion_accumulator.invert();
309 for (
size_t i = end - 1; i != start - 1; --i) {
313 accumulators[0][i] *= inversion_accumulator;
314 inversion_accumulator *= accumulators[3][i];
317 z_lookup[0] = fr::one();
323 const size_t z_randomness = 3;
324 ASSERT(z_randomness < num_roots_cut_out_of_vanishing_polynomial);
325 for (
size_t k = 0; k < z_randomness; ++k) {
327 z_lookup[((n - num_roots_cut_out_of_vanishing_polynomial) + 1 + k)] = fr::random_element();
331 z_lookup.ifft(key->small_domain);
332 key->polynomial_store.put(
"z_lookup", std::move(z_lookup));
343template <const
size_t num_roots_cut_out_of_vanishing_polynomial>
347 if (round_number == 2) {
348 compute_sorted_list_polynomial(transcript);
349 const polynomial& s = key->polynomial_store.get(
"s");
353 .work_type = work_queue::WorkType::SCALAR_MULTIPLICATION,
354 .mul_scalars = s.data(),
356 .constant = key->circuit_size,
362 .work_type = work_queue::WorkType::FFT,
363 .mul_scalars =
nullptr,
371 if (round_number == 3) {
372 compute_grand_product_polynomial(transcript);
373 const polynomial& z = key->polynomial_store.get(
"z_lookup");
377 .work_type = work_queue::WorkType::SCALAR_MULTIPLICATION,
378 .mul_scalars = z.data(),
380 .constant = key->circuit_size,
386 .work_type = work_queue::WorkType::FFT,
387 .mul_scalars =
nullptr,
419template <const
size_t num_roots_cut_out_of_vanishing_polynomial>
423 auto z_lookup_fft = key->polynomial_store.get(
"z_lookup_fft");
425 fr eta = fr::serialize_from_buffer(transcript.
get_challenge(
"eta").begin());
426 fr alpha = fr::serialize_from_buffer(transcript.
get_challenge(
"alpha").begin());
427 fr beta = fr::serialize_from_buffer(transcript.
get_challenge(
"beta").begin());
428 fr gamma = fr::serialize_from_buffer(transcript.
get_challenge(
"beta", 1).begin());
430 std::array<std::shared_ptr<fr[]>, 3> wire_ffts_ptr{
431 key->polynomial_store.get(
"w_1_fft").data(),
432 key->polynomial_store.get(
"w_2_fft").data(),
433 key->polynomial_store.get(
"w_3_fft").data(),
435 auto wire_ffts = map(wire_ffts_ptr, [](
auto& e) {
return e.get(); });
437 auto s_fft = key->polynomial_store.get(
"s_fft");
439 std::array<std::shared_ptr<fr[]>, 4> table_ffts_ptr{
440 key->polynomial_store.get(
"table_value_1_fft").data(),
441 key->polynomial_store.get(
"table_value_2_fft").data(),
442 key->polynomial_store.get(
"table_value_3_fft").data(),
443 key->polynomial_store.get(
"table_value_4_fft").data(),
445 auto table_ffts = map(table_ffts_ptr, [](
auto& e) {
return e.get(); });
447 auto column_1_step_size = key->polynomial_store.get(
"q_2_fft");
448 auto column_2_step_size = key->polynomial_store.get(
"q_m_fft");
449 auto column_3_step_size = key->polynomial_store.get(
"q_c_fft");
451 auto lookup_fft = key->polynomial_store.get(
"table_type_fft");
452 auto lookup_index_fft = key->polynomial_store.get(
"q_3_fft");
454 const fr gamma_beta_constant = gamma * (
fr(1) + beta);
461 auto l_1 = key->polynomial_store.get(
"lagrange_1_fft");
463 const fr delta_factor = gamma_beta_constant.pow(key->small_domain.size - num_roots_cut_out_of_vanishing_polynomial);
464 const fr alpha_sqr = alpha.
sqr();
466 const fr beta_constant = beta +
fr(1);
468 const size_t block_mask = key->large_domain.size - 1;
471 parallel_for(key->large_domain.num_threads, [&](
size_t j) {
472 const size_t start = j * key->large_domain.thread_size;
473 const size_t end = (j + 1) * key->large_domain.thread_size;
481 std::array<fr, 4> next_ts;
482 for (size_t i = 0; i < 4; ++i) {
483 next_ts[i] = table_ffts[3][(start + i) & block_mask];
485 next_ts[i] += table_ffts[2][(start + i) & block_mask];
487 next_ts[i] += table_ffts[1][(start + i) & block_mask];
489 next_ts[i] += table_ffts[0][(start + i) & block_mask];
491 for (
size_t i = start; i < end; ++i) {
493 T0 = lookup_index_fft[i];
495 T0 += wire_ffts[2][(i + 4) & block_mask] * column_3_step_size[i];
496 T0 += wire_ffts[2][i];
498 T0 += wire_ffts[1][(i + 4) & block_mask] * column_2_step_size[i];
499 T0 += wire_ffts[1][i];
501 T0 += wire_ffts[0][(i + 4) & block_mask] * column_1_step_size[i];
502 T0 += wire_ffts[0][i];
506 numerator *= lookup_fft[i];
510 T0 = table_ffts[3][(i + 4) & block_mask];
512 T0 += table_ffts[2][(i + 4) & block_mask];
514 T0 += table_ffts[1][(i + 4) & block_mask];
516 T0 += table_ffts[0][(i + 4) & block_mask];
521 T1 += next_ts[i & 0x03UL];
522 T1 += gamma_beta_constant;
525 next_ts[i & 0x03UL] = T0;
529 numerator *= beta_constant;
532 denominator = s_fft[(i + 4) & block_mask];
534 denominator += s_fft[i];
535 denominator += gamma_beta_constant;
540 T1 = l_1[(i + 4 + 4 * num_roots_cut_out_of_vanishing_polynomial) & block_mask] * alpha_sqr;
545 numerator *= z_lookup_fft[i];
550 denominator *= z_lookup_fft[(i + 4) & block_mask];
551 denominator += T1 * delta_factor;
556 T0 = numerator - denominator;
558 key->quotient_polynomial_parts[i >> key->small_domain.log2_size][i & (key->circuit_size - 1)] +=
562 return alpha_base * alpha.sqr() * alpha;
567template <
typename Field,
typename Group,
typename Transcript, const
size_t num_roots_cut_out_of_vanishing_polynomial>
568VerifierPlookupWidget<Field, Group, Transcript, num_roots_cut_out_of_vanishing_polynomial>::VerifierPlookupWidget()
588template <
typename Field,
typename Group,
typename Transcript, const
size_t num_roots_cut_out_of_vanishing_polynomial>
591 const Field& alpha_base,
592 const Transcript& transcript,
593 Field& quotient_numerator_eval)
596 std::array<Field, 3> wire_evaluations{
597 transcript.get_field_element(
"w_1"),
598 transcript.get_field_element(
"w_2"),
599 transcript.get_field_element(
"w_3"),
601 std::array<Field, 3> shifted_wire_evaluations{
602 transcript.get_field_element(
"w_1_omega"),
603 transcript.get_field_element(
"w_2_omega"),
604 transcript.get_field_element(
"w_3_omega"),
607 std::array<Field, 4> table_evaluations{
608 transcript.get_field_element(
"table_value_1"),
609 transcript.get_field_element(
"table_value_2"),
610 transcript.get_field_element(
"table_value_3"),
611 transcript.get_field_element(
"table_value_4"),
614 std::array<Field, 4> shifted_table_evaluations{
615 transcript.get_field_element(
"table_value_1_omega"),
616 transcript.get_field_element(
"table_value_2_omega"),
617 transcript.get_field_element(
"table_value_3_omega"),
618 transcript.get_field_element(
"table_value_4_omega"),
621 Field column_1_step_size = transcript.get_field_element(
"q_2");
622 Field column_2_step_size = transcript.get_field_element(
"q_m");
623 Field column_3_step_size = transcript.get_field_element(
"q_c");
624 Field table_type_eval = transcript.get_field_element(
"table_type");
625 Field table_index_eval = transcript.get_field_element(
"q_3");
627 Field s_eval = transcript.get_field_element(
"s");
628 Field shifted_s_eval = transcript.get_field_element(
"s_omega");
630 Field z_eval = transcript.get_field_element(
"z_lookup");
631 Field shifted_z_eval = transcript.get_field_element(
"z_lookup_omega");
633 Field z = transcript.get_challenge_field_element(
"z");
634 Field alpha = transcript.get_challenge_field_element(
"alpha", 0);
635 Field beta = transcript.get_challenge_field_element(
"beta", 0);
636 Field gamma = transcript.get_challenge_field_element(
"beta", 1);
637 Field eta = transcript.get_challenge_field_element(
"eta", 0);
638 Field l_numerator = key->z_pow_n - Field(1);
640 l_numerator *= key->domain.domain_inverse;
641 Field l_1 = l_numerator / (z - Field(1));
645 Field l_end_root = (num_roots_cut_out_of_vanishing_polynomial & 1) ? key->domain.root.sqr() : key->domain.root;
646 for (
size_t i = 0; i < num_roots_cut_out_of_vanishing_polynomial / 2; ++i) {
647 l_end_root *= key->domain.root.sqr();
649 Field l_end = l_numerator / ((z * l_end_root) - Field(1));
652 const Field gamma_beta_constant = gamma * (one + beta);
655 const Field delta_factor = gamma_beta_constant.pow(key->domain.domain - num_roots_cut_out_of_vanishing_polynomial);
657 const Field alpha_sqr = alpha.sqr();
659 const Field beta_constant = beta + one;
667 Field f_eval = table_index_eval;
669 f_eval += shifted_wire_evaluations[2] * column_3_step_size;
670 f_eval += wire_evaluations[2];
672 f_eval += shifted_wire_evaluations[1] * column_2_step_size;
673 f_eval += wire_evaluations[1];
675 f_eval += shifted_wire_evaluations[0] * column_1_step_size;
676 f_eval += wire_evaluations[0];
679 Field table_eval = table_evaluations[3];
681 table_eval += table_evaluations[2];
683 table_eval += table_evaluations[1];
685 table_eval += table_evaluations[0];
688 numerator = f_eval * table_type_eval;
692 T0 = shifted_table_evaluations[3];
694 T0 += shifted_table_evaluations[2];
696 T0 += shifted_table_evaluations[1];
698 T0 += shifted_table_evaluations[0];
704 T1 += gamma_beta_constant;
708 numerator *= beta_constant;
711 denominator = shifted_s_eval;
713 denominator += s_eval;
714 denominator += gamma_beta_constant;
718 T1 = l_end * alpha_sqr;
728 denominator *= shifted_z_eval;
729 denominator += T1 * delta_factor;
733 T0 = numerator - denominator;
734 quotient_numerator_eval += T0 * alpha_base;
735 return alpha_base * alpha.sqr() * alpha;
738template <
typename Field,
typename Group,
typename Transcript, const
size_t num_roots_cut_out_of_vanishing_polynomial>
741 const Field& alpha_base,
742 const Transcript& transcript,
743 std::map<std::string, Field>&)
745 Field alpha = transcript.get_challenge_field_element(
"alpha");
746 return alpha_base * alpha.sqr() * alpha;
Definition: affine_element.hpp:11
Definition: work_queue.hpp:11
Definition: transcript_wrappers.hpp:13
std::array< uint8_t, PRNG_OUTPUT_SIZE > get_challenge(const std::string &challenge_name, const size_t idx=0) const
Definition: transcript.cpp:308
std::shared_ptr< void > get_mem_slab(size_t size)
Definition: slab_allocator.cpp:214
Definition: widget.bench.cpp:13
BBERG_INLINE constexpr field sqr() const noexcept
Definition: field_impl.hpp:61