Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
ecc_lookup_relation.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Complete, auditors: [Raju], commit: 2a49eb6 }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
8#include <array>
9#include <tuple>
10
14
15namespace bb {
16
17template <typename FF_> class ECCVMLookupRelationImpl {
18 public:
19 using FF = FF_;
20 static constexpr size_t NUM_LOOKUP_TERMS = 4;
21 static constexpr size_t NUM_TABLE_TERMS = 2;
22 // 1 + polynomial degree of this relation
23 static constexpr size_t LENGTH = NUM_LOOKUP_TERMS + NUM_TABLE_TERMS + 3; // 9
24
25 // Named subrelation indices — matches SUBRELATION_PARTIAL_LENGTHS ordering.
31
32 static constexpr std::array<size_t, 2> SUBRELATION_PARTIAL_LENGTHS{
33 LENGTH, // grand product construction sub-relation
34 LENGTH // left-shiftable polynomial sub-relation
35 };
36 static_assert(NUM_SUBRELATIONS == SUBRELATION_PARTIAL_LENGTHS.size());
37
38 static constexpr std::array<bool, 2> SUBRELATION_LINEARLY_INDEPENDENT = { true, false };
39
40 template <typename AllValues> static bool operation_exists_at_row(const AllValues& row)
41
42 {
43 return (row.msm_add == 1) || (row.msm_skew == 1) || (row.precompute_select == 1);
44 }
45
53 template <typename AllEntities> static auto& get_inverse_polynomial(AllEntities& in) { return in.lookup_inverses; }
54
55 template <typename Accumulator, typename AllEntities>
56 static Accumulator compute_inverse_exists(const AllEntities& in)
57 {
58 using View = typename Accumulator::View;
59
60 const auto row_has_write = View(in.precompute_select);
61 const auto row_has_read = View(in.msm_add) + View(in.msm_skew);
62 return row_has_write + row_has_read - (row_has_write * row_has_read);
63 }
64
65 template <typename Accumulator, size_t index, typename AllEntities>
66 static Accumulator lookup_read_counts(const AllEntities& in)
67 {
68 using View = typename Accumulator::View;
69
70 if constexpr (index == 0) {
71 return Accumulator(View(in.lookup_read_counts_0));
72 }
73 if constexpr (index == 1) {
74 return Accumulator(View(in.lookup_read_counts_1));
75 }
76 return Accumulator(1);
77 }
78
79 template <typename Accumulator, size_t lookup_index, typename AllEntities>
80 static Accumulator get_lookup_term_predicate(const AllEntities& in)
81
82 {
83 using View = typename Accumulator::View;
84
85 if constexpr (lookup_index == 0) {
86 return Accumulator(View(in.msm_add1));
87 }
88 if constexpr (lookup_index == 1) {
89 return Accumulator(View(in.msm_add2));
90 }
91 if constexpr (lookup_index == 2) {
92 return Accumulator(View(in.msm_add3));
93 }
94 if constexpr (lookup_index == 3) {
95 return Accumulator(View(in.msm_add4));
96 }
97 return Accumulator(1);
98 }
99
100 template <typename Accumulator, size_t table_index, typename AllEntities>
101 static Accumulator get_table_term_predicate(const AllEntities& in)
102 {
103 using View = typename Accumulator::View;
104 // anytime `precompute_select` is on, we "turn on" the table predicate. This concretely means that the sP, where
105 // s is a WNAF slice and P is the point being processed, are "written" to the lookup table, i.e., may be
106 // read/looked up later. `table_index == 0` corresponds to positive WNAF entries, `table_index == 1` corresponds
107 // to negative WNAF entries.
108 if constexpr (table_index == 0 || table_index == 1) {
109 return Accumulator(View(in.precompute_select));
110 }
111 return Accumulator(1);
112 }
117 template <typename Accumulator, size_t table_index, typename AllEntities, typename Parameters>
118 static Accumulator compute_table_term(const AllEntities& in, const Parameters& params)
119 {
120 using View = typename Accumulator::View;
121
122 static_assert(table_index < NUM_TABLE_TERMS);
123 // table_index == 0 means our wNAF digit is positive (i.e., ∈{1, 3..., 15}).
124 // table_index == 1 means our wNAF digit is negative (i.e., ∈{-15, -13..., -1})
125
126 // round starts at 0 and increments to 7
127 // point starts at 15[P] and decrements to [P]
128 // a slice value of 0 maps to -15[P]
129
130 // we have computed `(15 - 2 * round)[P] =: (precompute_tx, precompute_ty)`.
131 // `round`∈{0, 1..., 7}
132 // if table_index == 0, we want to write (pc, 15 - 2 * round, precompute_tx, precompute_ty)
133 // if table_index == 1, we want to write (pc, round, precompute_tx, -precompute_ty)
134 // to sum up, both:
135 // (pc, round, precompute_tx, -precompute_ty) _and_
136 // (pc, 15 - 2 * round, precompute_tx, precompute_ty)
137 // will be written to the lookup table.
138 //
139 // therefore, if `pc` corresponds to the elliptic curve point [P], we will write:
140 // | pc | 0 | -15[P].x | -15[P].y |
141 // | pc | 1 | -13[P].x | -13[P].y |
142 // | pc | 2 | -11[P].x | -11[P].y |
143 // | pc | 3 | -9[P].x | -9[P].y |
144 // | pc | 4 | -7[P].x | -7[P].y |
145 // | pc | 5 | -5[P].x | -5[P].y |
146 // | pc | 6 | -3[P].x | -3[P].y |
147 // | pc | 7 | -1[P].x | -1[P].y |
148 // | pc | 8 | [P].x | [P].y |
149 // | pc | 9 | 3[P].x | 3[P].y |
150 // | pc | 10 | 5[P].x | 5[P].y |
151 // | pc | 11 | 7[P].x | 7[P].y |
152 // | pc | 12 | 9[P].x | 9[P].y |
153 // | pc | 13 | 11[P].x | 11[P].y |
154 // | pc | 14 | 13[P].x | 13[P].y |
155 // | pc | 15 | 15[P].x | 15[P].y |
156
157 const auto& precompute_pc = View(in.precompute_pc);
158 const auto& tx = View(in.precompute_tx);
159 const auto& ty = View(in.precompute_ty);
160 const auto& precompute_round = View(in.precompute_round);
161 const auto& gamma = params.gamma;
162 const auto& beta = params.beta;
163 const auto& beta_sqr = params.beta_sqr;
164 const auto& beta_cube = params.beta_cube;
165
166 if constexpr (table_index == 0) {
167 const auto positive_slice_value = -(precompute_round) + 15;
168 const auto positive_term =
169 precompute_pc + gamma + positive_slice_value * beta + tx * beta_sqr + ty * beta_cube;
170 return positive_term; // degree 1
171 }
172 if constexpr (table_index == 1) {
173 const auto negative_term = precompute_pc + gamma + precompute_round * beta + tx * beta_sqr - ty * beta_cube;
174 return negative_term; // degree 1
175 }
176 return Accumulator(1);
177 }
178
179 template <typename Accumulator, size_t lookup_index, typename AllEntities, typename Parameters>
180 static Accumulator compute_lookup_term(const AllEntities& in, const Parameters& params)
181 {
182 using View = typename Accumulator::View;
183
184 // read term: (pc, compressed_slice, (2 * compressed_slice - 15)[P])
185 // (the latter term is of course represented via an x and y coordinate.)
186 static_assert(lookup_index < NUM_LOOKUP_TERMS);
187 const auto& gamma = params.gamma;
188 const auto& beta = params.beta;
189 const auto& beta_sqr = params.beta_sqr;
190 const auto& beta_cube = params.beta_cube;
191 const auto& msm_pc = View(in.msm_pc);
192 const auto& msm_count = View(in.msm_count);
193 const auto& msm_slice1 = View(in.msm_slice1);
194 const auto& msm_slice2 = View(in.msm_slice2);
195 const auto& msm_slice3 = View(in.msm_slice3);
196 const auto& msm_slice4 = View(in.msm_slice4);
197 const auto& msm_x1 = View(in.msm_x1);
198 const auto& msm_x2 = View(in.msm_x2);
199 const auto& msm_x3 = View(in.msm_x3);
200 const auto& msm_x4 = View(in.msm_x4);
201 const auto& msm_y1 = View(in.msm_y1);
202 const auto& msm_y2 = View(in.msm_y2);
203 const auto& msm_y3 = View(in.msm_y3);
204 const auto& msm_y4 = View(in.msm_y4);
205
206 // Recall that `pc` stands for point-counter. We recall how to compute the current pc.
207 //
208 // row pc = value of pc after msm
209 // msm_count = number of (128-bit) multiplications processed so far in current MSM round (NOT INCLUDING current
210 // row) current_pc = msm_pc - msm_count next_pc = current_pc - {0, 1, 2, 3}, depending on how many adds are
211 // performed in the current row.
212 const auto current_pc = msm_pc - msm_count;
213
214 if constexpr (lookup_index == 0) {
215 const auto lookup_term1 = (current_pc) + gamma + msm_slice1 * beta + msm_x1 * beta_sqr + msm_y1 * beta_cube;
216 return lookup_term1; // degree 1
217 }
218 if constexpr (lookup_index == 1) {
219 const auto lookup_term2 =
220 (current_pc - 1) + gamma + msm_slice2 * beta + msm_x2 * beta_sqr + msm_y2 * beta_cube;
221 return lookup_term2; // degree 1
222 }
223 if constexpr (lookup_index == 2) {
224 const auto lookup_term3 =
225 (current_pc - 2) + gamma + msm_slice3 * beta + msm_x3 * beta_sqr + msm_y3 * beta_cube;
226 return lookup_term3; // degree 1
227 }
228 if constexpr (lookup_index == 3) {
229 const auto lookup_term4 =
230 (current_pc - 3) + gamma + msm_slice4 * beta + msm_x4 * beta_sqr + msm_y4 * beta_cube;
231 return lookup_term4; // degree 1
232 }
233 return Accumulator(1);
234 }
235
249 template <typename ContainerOverSubrelations, typename AllEntities, typename Parameters>
250 static void accumulate(ContainerOverSubrelations& accumulator,
251 const AllEntities& in,
252 const Parameters& params,
253 const FF& scaling_factor);
254};
255
257
258} // namespace bb
static Accumulator compute_inverse_exists(const AllEntities &in)
static Accumulator get_table_term_predicate(const AllEntities &in)
static constexpr size_t NUM_LOOKUP_TERMS
static constexpr size_t NUM_TABLE_TERMS
static auto & get_inverse_polynomial(AllEntities &in)
Get the inverse lookup polynomial.
static Accumulator compute_table_term(const AllEntities &in, const Parameters &params)
Returns the fingerprint of (precompute_pc, compressed_slice, (2 * compressed_slice - 15)[P]),...
static constexpr size_t LENGTH
static constexpr std::array< size_t, 2 > SUBRELATION_PARTIAL_LENGTHS
static Accumulator compute_lookup_term(const AllEntities &in, const Parameters &params)
static Accumulator get_lookup_term_predicate(const AllEntities &in)
static constexpr std::array< bool, 2 > SUBRELATION_LINEARLY_INDEPENDENT
static bool operation_exists_at_row(const AllValues &row)
static Accumulator lookup_read_counts(const AllEntities &in)
static void accumulate(ContainerOverSubrelations &accumulator, const AllEntities &in, const Parameters &params, const FF &scaling_factor)
Expression for ECCVM lookup tables.
A wrapper for Relations to expose methods used by the Sumcheck prover or verifier to add the contribu...
Entry point for Barretenberg command-line interface.
Definition api.hpp:5