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
13
14namespace bb {
15
21template <typename Flavor> class RelationChecker {
22 public:
24 std::map<size_t,
25 uint32_t>; // key is the subrelation idx, value is the row idx.
26 // for relations which `has_linearly_dependent`, those subrelations which are "not
27 // linearly independent" (i.e., are only required to vanish on the entire execution trace)
28 // are treated as follows: if they do _not_ vanish when evaluated over the entire execution
29 // trace, we set the row_idx in this data structure to 0.
31 std::map<std::string, FirstSubrelationFailures>; // key is the name of a Relation, value is of type
32 // `FirstSubrelationFailures`. Theck if there are no failures,
33 // simply check if this hashmap is empty.
37 static AllSubrelationFailures check_all([[maybe_unused]] const auto& polynomials,
38 [[maybe_unused]] const auto& params)
39 {
40 // default
42 }
43
47 template <typename Relation, bool has_linearly_dependent = false>
48 static FirstSubrelationFailures check(const auto& polynomials,
49 const auto& params,
50 [[maybe_unused]] std::string label = "Relation",
51 uint32_t start_row = 0)
52 {
53 FirstSubrelationFailures first_failure_per_subrelation;
54 // Define the appropriate accumulator type for the relation and initialize to zero
56 for (auto& element : result) {
57 element = 0;
58 }
59
60 // `IS_OFFSET_ONLY` relations (e.g. `MegaEccOpBoundaryRelation`) are only meant to vanish on
61 // the disabled-rows prefix; Sumcheck multiplies them by a row-disabling polynomial. Bound
62 // the row scan accordingly so we don't report design-time failures past the prefix.
63 uint32_t end_row = static_cast<uint32_t>(polynomials.get_polynomial_size());
64 if constexpr (requires { Relation::IS_OFFSET_ONLY; }) {
65 if constexpr (Relation::IS_OFFSET_ONLY) {
66 end_row = NUM_DISABLED_ROWS_IN_SUMCHECK;
67 }
68 }
69 for (uint32_t i = start_row; i < end_row; i++) {
70
71 Relation::accumulate(result, polynomials.get_row(i), params, 1);
72 size_t subrelation_idx = 0;
73
74 // Iterate over all the subrelation results and report if a linearly independent one failed
75 for (auto& element : result) {
76 if constexpr (has_linearly_dependent) {
77 if (element != 0 && Relation::SUBRELATION_LINEARLY_INDEPENDENT[subrelation_idx]) {
78 // only record the first failure for this subrelation
79 if (!first_failure_per_subrelation.contains(subrelation_idx)) {
80 first_failure_per_subrelation[subrelation_idx] = i;
81 }
82 }
83 } else {
84 if (element != 0) {
85 // only record the first failure for this subrelation
86 if (!first_failure_per_subrelation.contains(subrelation_idx)) {
87 first_failure_per_subrelation[subrelation_idx] = i;
88 }
89 }
90 }
91 subrelation_idx++;
92 }
93 }
94
95 if constexpr (has_linearly_dependent) {
96 size_t subrelation_idx = 0;
97 for (auto& element : result) {
98 // Check that linearly _dependent_ subrelation result is 0 over the entire execution trace
99 if (element != 0 && !Relation::SUBRELATION_LINEARLY_INDEPENDENT[subrelation_idx]) {
100 if (!first_failure_per_subrelation.contains(subrelation_idx)) {
101 first_failure_per_subrelation[subrelation_idx] = 0;
102 }
103 }
104 subrelation_idx++;
105 }
106 }
107 return first_failure_per_subrelation;
108 };
109};
110
111// Specialization for Ultra
112template <> class RelationChecker<bb::UltraFlavor> : public RelationChecker<void> {
114
115 public:
116 static AllSubrelationFailures check_all(const auto& polynomials, const auto& params)
117 {
118 using FF = UltraFlavor::FF;
119
120 AllSubrelationFailures all_subrelation_failures;
121
122 // Linearly independent relations (must be satisfied at each row)
123 auto ultra_arithmetic_subrelation_failures =
124 Base::check<ArithmeticRelation<FF>>(polynomials, params, "UltraArithmetic");
125 if (!ultra_arithmetic_subrelation_failures.empty()) {
126 all_subrelation_failures["UltraArithmetic"] = ultra_arithmetic_subrelation_failures;
127 }
128 auto ultra_permutation_subrelation_failures =
129 Base::check<UltraPermutationRelation<FF>>(polynomials, params, "UltraPermutation");
130 if (!ultra_permutation_subrelation_failures.empty()) {
131 all_subrelation_failures["UltraPermutation"] = ultra_permutation_subrelation_failures;
132 }
133 auto ultra_delta_range_subrelation_failures =
134 Base::check<DeltaRangeConstraintRelation<FF>>(polynomials, params, "DeltaRangeConstraint");
135 if (!ultra_delta_range_subrelation_failures.empty()) {
136 all_subrelation_failures["UltraDeltaRange"] = ultra_delta_range_subrelation_failures;
137 }
138 auto ultra_elliptic_subrelation_failures = Base::check<EllipticRelation<FF>>(polynomials, params, "Elliptic");
139 if (!ultra_elliptic_subrelation_failures.empty()) {
140 all_subrelation_failures["UltraElliptic"] = ultra_elliptic_subrelation_failures;
141 }
142 auto ultra_non_native_field_subrelation_failures =
143 Base::check<NonNativeFieldRelation<FF>>(polynomials, params, "NonNativeField");
144 if (!ultra_non_native_field_subrelation_failures.empty()) {
145 all_subrelation_failures["NonNativeField"] = ultra_non_native_field_subrelation_failures;
146 }
147 auto ultra_poseidon2_external_subrelation_failures =
148 Base::check<Poseidon2ExternalRelation<FF>>(polynomials, params, "Poseidon2External");
149 if (!ultra_poseidon2_external_subrelation_failures.empty()) {
150 all_subrelation_failures["UltraPoseidon2External"] = ultra_poseidon2_external_subrelation_failures;
151 }
152 auto ultra_poseidon2_internal_subrelation_failures =
153 Base::check<Poseidon2InternalRelation<FF>>(polynomials, params, "Poseidon2Internal");
154 if (!ultra_poseidon2_internal_subrelation_failures.empty()) {
155 all_subrelation_failures["UltraPoseidon2Internal"] = ultra_poseidon2_internal_subrelation_failures;
156 }
157
158 // Relations that have "linearly dependent" subrelations
159 auto ultra_log_derivative_subrelation_failures =
160 Base::check<LogDerivLookupRelation<FF>, true>(polynomials, params, "LogDerivLookup");
161 if (!ultra_log_derivative_subrelation_failures.empty()) {
162 all_subrelation_failures["UltraLogDerivative"] = ultra_log_derivative_subrelation_failures;
163 }
164 // Memory's ROM-LogUp sum subrelation is linearly dependent; it must be summed over the trace
165 // rather than checked per-row.
166 auto ultra_memory_subrelation_failures = Base::check<MemoryRelation<FF>, true>(polynomials, params, "Memory");
167 if (!ultra_memory_subrelation_failures.empty()) {
168 all_subrelation_failures["UltraMemory"] = ultra_memory_subrelation_failures;
169 }
170 return all_subrelation_failures;
171 }
172};
173
174// Specialization for Mega: iterate the flavor's own Relations_ tuple. Cannot share with
175// UltraFlavor's check_all because Mega uses the new (split) Poseidon2 relation set while Ultra
176// still uses the legacy Poseidon2External/Internal pair.
177template <> class RelationChecker<MegaFlavor> : public RelationChecker<void> {
179
180 public:
181 static AllSubrelationFailures check_all(const auto& polynomials, const auto& params)
182 {
183 using FF = MegaFlavor::FF;
184 AllSubrelationFailures all_subrelation_failures;
185 using Relations = MegaFlavor::Relations_<FF>;
186 bb::constexpr_for<0, std::tuple_size_v<Relations>, 1>([&]<size_t i>() {
188 const std::string label = "MegaRelation_" + std::to_string(i);
189 if constexpr (requires { Relation::SUBRELATION_LINEARLY_INDEPENDENT; }) {
190 auto failures = Base::check<Relation, /*has_linearly_dependent=*/true>(polynomials, params, label);
191 if (!failures.empty()) {
192 all_subrelation_failures[label] = failures;
193 }
194 } else {
195 auto failures = Base::check<Relation>(polynomials, params, label);
196 if (!failures.empty()) {
197 all_subrelation_failures[label] = failures;
198 }
199 }
200 });
201 return all_subrelation_failures;
202 }
203};
204
205// Specialization for MegaZKFlavor: iterate the flavor's own Relations_ tuple, treating any
206// relation that exposes `SUBRELATION_LINEARLY_INDEPENDENT` as having linearly-dependent subrelations.
207template <> class RelationChecker<MegaZKFlavor> : public RelationChecker<void> {
209
210 public:
211 static AllSubrelationFailures check_all(const auto& polynomials, const auto& params)
212 {
213 using FF = MegaZKFlavor::FF;
214 AllSubrelationFailures all_subrelation_failures;
215 using Relations = MegaZKFlavor::Relations_<FF>;
216 bb::constexpr_for<0, std::tuple_size_v<Relations>, 1>([&]<size_t i>() {
218 const std::string label = "MegaZKRelation_" + std::to_string(i);
219 if constexpr (requires { Relation::SUBRELATION_LINEARLY_INDEPENDENT; }) {
220 auto failures = Base::check<Relation, /*has_linearly_dependent=*/true>(polynomials, params, label);
221 if (!failures.empty()) {
222 all_subrelation_failures[label] = failures;
223 }
224 } else {
225 auto failures = Base::check<Relation>(polynomials, params, label);
226 if (!failures.empty()) {
227 all_subrelation_failures[label] = failures;
228 }
229 }
230 });
231 return all_subrelation_failures;
232 }
233};
234
235// Specialization for TranslatorFlavor: checks the four row-by-row relations that do not require
236// grand product polynomials (Permutation and DeltaRangeConstraint are excluded as they need z_perm
237// and sorted ordered_range_constraints polynomials computed during proving).
238template <> class RelationChecker<TranslatorFlavor> : public RelationChecker<void> {
240
241 public:
242 static AllSubrelationFailures check_all(const auto& polynomials, const auto& params)
243 {
244 using FF = TranslatorFlavor::FF;
245 AllSubrelationFailures all_subrelation_failures;
246
247 auto try_check = [&]<typename R>(const char* name) {
248 auto failures = Base::check<R>(polynomials, params, name);
249 if (!failures.empty()) {
250 all_subrelation_failures[name] = failures;
251 }
252 };
253
254 try_check.template operator()<TranslatorOpcodeConstraintRelation<FF>>("TranslatorOpcodeConstraint");
255 try_check.template operator()<TranslatorAccumulatorTransferRelation<FF>>("TranslatorAccumulatorTransfer");
256 try_check.template operator()<TranslatorDecompositionRelation<FF>>("TranslatorDecomposition");
257 try_check.template operator()<TranslatorNonNativeFieldRelation<FF>>("TranslatorNonNativeField");
258
259 return all_subrelation_failures;
260 }
261};
262
263} // namespace bb
std::tuple< bb::UltraPermutationRelation< FF >, bb::LogDerivLookupRelation< FF >, bb::ArithmeticRelation< FF >, bb::BilinearOrBatchedEqCheckRelation< FF >, bb::DeltaRangeConstraintRelation< FF >, bb::EllipticRelation< FF >, bb::MemoryRelation< FF >, bb::NonNativeFieldRelation< FF >, bb::EccOpQueueRelation< FF >, bb::SingleBusLookupRelation< FF, EntityId::kernel_calldata, EntityId::kernel_calldata_read_counts, EntityId::kernel_calldata_inverses, EntityId::kernel_calldata_indicator, EntityId::q_l >, bb::SingleBusLookupRelation< FF, EntityId::first_app_calldata, EntityId::first_app_calldata_read_counts, EntityId::first_app_calldata_inverses, EntityId::first_app_calldata_indicator, EntityId::q_r >, bb::SingleBusLookupRelation< FF, EntityId::second_app_calldata, EntityId::second_app_calldata_read_counts, EntityId::second_app_calldata_inverses, EntityId::second_app_calldata_indicator, EntityId::q_o >, bb::SingleBusLookupRelation< FF, EntityId::third_app_calldata, EntityId::third_app_calldata_read_counts, EntityId::third_app_calldata_inverses, EntityId::third_app_calldata_indicator, EntityId::q_4 >, bb::SingleBusLookupRelation< FF, EntityId::fourth_app_calldata, EntityId::fourth_app_calldata_read_counts, EntityId::fourth_app_calldata_inverses, EntityId::fourth_app_calldata_indicator, EntityId::q_5 >, bb::SingleBusLookupRelation< FF, EntityId::fifth_app_calldata, EntityId::fifth_app_calldata_read_counts, EntityId::fifth_app_calldata_inverses, EntityId::fifth_app_calldata_indicator, EntityId::q_c >, bb::SingleBusLookupRelation< FF, EntityId::return_data, EntityId::return_data_read_counts, EntityId::return_data_inverses, EntityId::return_data_indicator, EntityId::q_m >, bb::Poseidon2ExternalRelation< FF >, bb::Poseidon2InitialExternalRelation< FF >, bb::Poseidon2QuadInternalRelation< FF >, bb::Poseidon2QuadInternalTerminalRelation< FF >, bb::Poseidon2TransitionEntryRelation< FF > > Relations_
Curve::ScalarField FF
std::tuple< bb::ArithmeticRelation< FF >, bb::BilinearOrBatchedEqCheckRelation< FF >, bb::UltraPermutationRelation< FF >, bb::DeltaRangeConstraintRelation< FF >, bb::EccOpQueueRelation< FF >, bb::MegaEccOpBoundaryRelation< FF >, bb::SingleBusLookupRelation< FF, EntityId::kernel_calldata, EntityId::kernel_calldata_read_counts, EntityId::kernel_calldata_inverses, EntityId::kernel_calldata_indicator, EntityId::q_l >, bb::Poseidon2ExternalRelation< FF >, bb::Poseidon2InitialExternalRelation< FF >, bb::Poseidon2QuadInternalRelation< FF >, bb::Poseidon2QuadInternalTerminalRelation< FF >, bb::Poseidon2TransitionEntryRelation< FF > > Relations_
Hiding-kernel-only Mega variant: runs with ZK Sumcheck and a reduced relation set.
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)
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
std::string label
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
std::string name
VectorField result