Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
relation_checker.hpp
Go to the documentation of this file.
1#pragma once
2
11
12namespace bb {
13
19template <typename Flavor> class RelationChecker {
20 public:
22 std::map<size_t,
23 uint32_t>; // key is the subrelation idx, value is the row idx.
24 // for relations which `has_linearly_dependent`, those subrelations which are "not
25 // linearly independent" (i.e., are only required to vanish on the entire execution trace)
26 // are treated as follows: if they do _not_ vanish when evaluated over the entire execution
27 // trace, we set the row_idx in this data structure to 0.
29 std::map<std::string, FirstSubrelationFailures>; // key is the name of a Relation, value is of type
30 // `FirstSubrelationFailures`. Theck if there are no failures,
31 // simply check if this hashmap is empty.
35 static AllSubrelationFailures check_all([[maybe_unused]] const auto& polynomials,
36 [[maybe_unused]] const auto& params)
37 {
38 // default
40 }
41
45 template <typename Relation, bool has_linearly_dependent = false>
46 static FirstSubrelationFailures check(const auto& polynomials,
47 const auto& params,
48 [[maybe_unused]] std::string label = "Relation",
49 uint32_t start_row = 0)
50 {
51 FirstSubrelationFailures first_failure_per_subrelation;
52 // Define the appropriate accumulator type for the relation and initialize to zero
54 for (auto& element : result) {
55 element = 0;
56 }
57
58 for (uint32_t i = start_row; i < polynomials.get_polynomial_size(); i++) {
59
60 Relation::accumulate(result, polynomials.get_row(i), params, 1);
61 size_t subrelation_idx = 0;
62
63 // Iterate over all the subrelation results and report if a linearly independent one failed
64 for (auto& element : result) {
65 if constexpr (has_linearly_dependent) {
66 if (element != 0 && Relation::SUBRELATION_LINEARLY_INDEPENDENT[subrelation_idx]) {
67 // only record the first failure for this subrelation
68 if (!first_failure_per_subrelation.contains(subrelation_idx)) {
69 first_failure_per_subrelation[subrelation_idx] = i;
70 }
71 }
72 } else {
73 if (element != 0) {
74 // only record the first failure for this subrelation
75 if (!first_failure_per_subrelation.contains(subrelation_idx)) {
76 first_failure_per_subrelation[subrelation_idx] = i;
77 }
78 }
79 }
80 subrelation_idx++;
81 }
82 }
83
84 if constexpr (has_linearly_dependent) {
85 size_t subrelation_idx = 0;
86 for (auto& element : result) {
87 // Check that linearly _dependent_ subrelation result is 0 over the entire execution trace
88 if (element != 0 && !Relation::SUBRELATION_LINEARLY_INDEPENDENT[subrelation_idx]) {
89 if (!first_failure_per_subrelation.contains(subrelation_idx)) {
90 first_failure_per_subrelation[subrelation_idx] = 0;
91 }
92 }
93 subrelation_idx++;
94 }
95 }
96 return first_failure_per_subrelation;
97 };
98};
99
100// Specialization for Ultra
101template <> class RelationChecker<bb::UltraFlavor> : public RelationChecker<void> {
103
104 public:
105 static AllSubrelationFailures check_all(const auto& polynomials, const auto& params)
106 {
107 using FF = UltraFlavor::FF;
108
109 AllSubrelationFailures all_subrelation_failures;
110
111 // Linearly independent relations (must be satisfied at each row)
112 auto ultra_arithmetic_subrelation_failures =
113 Base::check<ArithmeticRelation<FF>>(polynomials, params, "UltraArithmetic");
114 if (!ultra_arithmetic_subrelation_failures.empty()) {
115 all_subrelation_failures["UltraArithmetic"] = ultra_arithmetic_subrelation_failures;
116 }
117 auto ultra_permutation_subrelation_failures =
118 Base::check<UltraPermutationRelation<FF>>(polynomials, params, "UltraPermutation");
119 if (!ultra_permutation_subrelation_failures.empty()) {
120 all_subrelation_failures["UltraPermutation"] = ultra_permutation_subrelation_failures;
121 }
122 auto ultra_delta_range_subrelation_failures =
123 Base::check<DeltaRangeConstraintRelation<FF>>(polynomials, params, "DeltaRangeConstraint");
124 if (!ultra_delta_range_subrelation_failures.empty()) {
125 all_subrelation_failures["UltraDeltaRange"] = ultra_delta_range_subrelation_failures;
126 }
127 auto ultra_elliptic_subrelation_failures = Base::check<EllipticRelation<FF>>(polynomials, params, "Elliptic");
128 if (!ultra_elliptic_subrelation_failures.empty()) {
129 all_subrelation_failures["UltraElliptic"] = ultra_elliptic_subrelation_failures;
130 }
131 auto ultra_memory_subrelation_failures = Base::check<MemoryRelation<FF>>(polynomials, params, "Memory");
132 if (!ultra_memory_subrelation_failures.empty()) {
133 all_subrelation_failures["UltraMemory"] = ultra_memory_subrelation_failures;
134 }
135 auto ultra_non_native_field_subrelation_failures =
136 Base::check<NonNativeFieldRelation<FF>>(polynomials, params, "NonNativeField");
137 if (!ultra_non_native_field_subrelation_failures.empty()) {
138 all_subrelation_failures["NonNativeField"] = ultra_non_native_field_subrelation_failures;
139 }
140 auto ultra_poseidon2_external_subrelation_failures =
141 Base::check<Poseidon2ExternalRelation<FF>>(polynomials, params, "Poseidon2External");
142 if (!ultra_poseidon2_external_subrelation_failures.empty()) {
143 all_subrelation_failures["UltraPoseidon2External"] = ultra_poseidon2_external_subrelation_failures;
144 }
145 auto ultra_poseidon2_internal_subrelation_failures =
146 Base::check<Poseidon2InternalRelation<FF>>(polynomials, params, "Poseidon2Internal");
147 if (!ultra_poseidon2_internal_subrelation_failures.empty()) {
148 all_subrelation_failures["UltraPoseidon2Internal"] = ultra_poseidon2_internal_subrelation_failures;
149 }
150
151 // Relations that have "linearly dependent" subrelations
152 auto ultra_log_derivative_subrelation_failures =
153 Base::check<LogDerivLookupRelation<FF>, true>(polynomials, params, "LogDerivLookup");
154 if (!ultra_log_derivative_subrelation_failures.empty()) {
155 all_subrelation_failures["UltraLogDerivative"] = ultra_log_derivative_subrelation_failures;
156 }
157 return all_subrelation_failures;
158 }
159};
160
161// Specialization for Mega
162template <> class RelationChecker<MegaFlavor> : public RelationChecker<void> {
164
165 public:
166 static AllSubrelationFailures check_all(const auto& polynomials, const auto& params)
167 {
168 using FF = MegaFlavor::FF;
169
170 AllSubrelationFailures all_subrelation_failures;
171
172 // Linearly independent relations shared with Ultra --- EXCEPT Poseidon2InternalRelation,
173 // which is not present in MegaFlavor (Mega covers all internal rounds via the compressed
174 // quad-internal block).
175 auto arith = Base::check<ArithmeticRelation<FF>>(polynomials, params, "UltraArithmetic");
176 if (!arith.empty()) {
177 all_subrelation_failures["UltraArithmetic"] = arith;
178 }
179 auto perm = Base::check<UltraPermutationRelation<FF>>(polynomials, params, "UltraPermutation");
180 if (!perm.empty()) {
181 all_subrelation_failures["UltraPermutation"] = perm;
182 }
183 auto delta_range = Base::check<DeltaRangeConstraintRelation<FF>>(polynomials, params, "DeltaRangeConstraint");
184 if (!delta_range.empty()) {
185 all_subrelation_failures["UltraDeltaRange"] = delta_range;
186 }
187 auto elliptic = Base::check<EllipticRelation<FF>>(polynomials, params, "Elliptic");
188 if (!elliptic.empty()) {
189 all_subrelation_failures["UltraElliptic"] = elliptic;
190 }
191 auto memory = Base::check<MemoryRelation<FF>>(polynomials, params, "Memory");
192 if (!memory.empty()) {
193 all_subrelation_failures["UltraMemory"] = memory;
194 }
195 auto nnf = Base::check<NonNativeFieldRelation<FF>>(polynomials, params, "NonNativeField");
196 if (!nnf.empty()) {
197 all_subrelation_failures["NonNativeField"] = nnf;
198 }
199 auto p2_ext = Base::check<Poseidon2ExternalRelation<FF>>(polynomials, params, "Poseidon2External");
200 if (!p2_ext.empty()) {
201 all_subrelation_failures["UltraPoseidon2External"] = p2_ext;
202 }
203 auto p2_initial_ext =
204 Base::check<Poseidon2InitialExternalRelation<FF>>(polynomials, params, "Poseidon2InitialExternal");
205 if (!p2_initial_ext.empty()) {
206 all_subrelation_failures["Poseidon2InitialExternal"] = p2_initial_ext;
207 }
208
209 // Compressed quad-internal relations (Mega-only, replacing Poseidon2InternalRelation).
210 auto p2_quad = Base::check<Poseidon2QuadInternalRelation<FF>>(polynomials, params, "Poseidon2QuadInternal");
211 if (!p2_quad.empty()) {
212 all_subrelation_failures["Poseidon2QuadInternal"] = p2_quad;
213 }
214 auto p2_quad_term = Base::check<Poseidon2QuadInternalTerminalRelation<FF>>(
215 polynomials, params, "Poseidon2QuadInternalTerminal");
216 if (!p2_quad_term.empty()) {
217 all_subrelation_failures["Poseidon2QuadInternalTerminal"] = p2_quad_term;
218 }
219 auto p2_entry =
220 Base::check<Poseidon2TransitionEntryRelation<FF>>(polynomials, params, "Poseidon2TransitionEntry");
221 if (!p2_entry.empty()) {
222 all_subrelation_failures["Poseidon2TransitionEntry"] = p2_entry;
223 }
224
225 // Linearly-dependent log-derivative lookup (shared with Ultra).
226 auto logderiv = Base::check<LogDerivLookupRelation<FF>, true>(polynomials, params, "LogDerivLookup");
227 if (!logderiv.empty()) {
228 all_subrelation_failures["UltraLogDerivative"] = logderiv;
229 }
230
231 // Mega-specific relations.
232 auto mega_ecc_op_queue_subrelation_failures =
233 Base::check<EccOpQueueRelation<FF>>(polynomials, params, "EccOpQueue");
234 if (!mega_ecc_op_queue_subrelation_failures.empty()) {
235 all_subrelation_failures["MegaEccOpQueue"] = mega_ecc_op_queue_subrelation_failures;
236 }
237
238 auto mega_databus_lookup_subrelation_failures =
239 Base::check<DatabusLookupRelation<FF>, true>(polynomials, params, "DatabusLookup");
240 if (!mega_databus_lookup_subrelation_failures.empty()) {
241 all_subrelation_failures["MegaDatabusLookup"] = mega_databus_lookup_subrelation_failures;
242 }
243
244 return all_subrelation_failures;
245 }
246};
247
248// Specialization for TranslatorFlavor: checks the four row-by-row relations that do not require
249// grand product polynomials (Permutation and DeltaRangeConstraint are excluded as they need z_perm
250// and sorted ordered_range_constraints polynomials computed during proving).
251template <> class RelationChecker<TranslatorFlavor> : public RelationChecker<void> {
253
254 public:
255 static AllSubrelationFailures check_all(const auto& polynomials, const auto& params)
256 {
257 using FF = TranslatorFlavor::FF;
258 AllSubrelationFailures all_subrelation_failures;
259
260 auto try_check = [&]<typename R>(const char* name) {
261 auto failures = Base::check<R>(polynomials, params, name);
262 if (!failures.empty()) {
263 all_subrelation_failures[name] = failures;
264 }
265 };
266
267 try_check.template operator()<TranslatorOpcodeConstraintRelation<FF>>("TranslatorOpcodeConstraint");
268 try_check.template operator()<TranslatorAccumulatorTransferRelation<FF>>("TranslatorAccumulatorTransfer");
269 try_check.template operator()<TranslatorDecompositionRelation<FF>>("TranslatorDecomposition");
270 try_check.template operator()<TranslatorNonNativeFieldRelation<FF>>("TranslatorNonNativeField");
271
272 return all_subrelation_failures;
273 }
274};
275
276} // namespace bb
Curve::ScalarField FF
static AllSubrelationFailures check_all(const auto &polynomials, const auto &params)
static AllSubrelationFailures check_all(const auto &polynomials, const auto &params)
static AllSubrelationFailures check_all(const auto &polynomials, const auto &params)
A debugging utility for checking whether a set of polynomials satisfies the relations for a given Fla...
static AllSubrelationFailures check_all(const auto &polynomials, const auto &params)
Check that the provided polynomials satisfy all relations for a given Flavor.
static FirstSubrelationFailures check(const auto &polynomials, const auto &params, std::string label="Relation", uint32_t start_row=0)
Check that a single specified relation is satisfied for a set of polynomials.
std::map< size_t, uint32_t > FirstSubrelationFailures
std::map< std::string, FirstSubrelationFailures > AllSubrelationFailures
A wrapper for Relations to expose methods used by the Sumcheck prover or verifier to add the contribu...
ArrayOfValues< FF, RelationImpl::SUBRELATION_PARTIAL_LENGTHS > SumcheckArrayOfValuesOverSubrelations
Curve::ScalarField FF
Curve::ScalarField FF
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
MemoryStore memory