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 // Start with all relations that are shared with Ultra
171 AllSubrelationFailures all_subrelation_failures = RelationChecker<UltraFlavor>::check_all(polynomials, params);
172
173 // Mega-specific relations
174 // There is one relation that does not `have_linearly_dependent`.
175 auto mega_ecc_op_queue_subrelation_failures =
176 Base::check<EccOpQueueRelation<FF>>(polynomials, params, "EccOpQueue");
177 if (!mega_ecc_op_queue_subrelation_failures.empty()) {
178 all_subrelation_failures["MegaEccOpQueue"] = mega_ecc_op_queue_subrelation_failures;
179 }
180
181 // There is one one relation that satisfies `have_linearly_dependent`
182 auto mega_databus_lookup_subrelation_failures =
183 Base::check<DatabusLookupRelation<FF>, true>(polynomials, params, "DatabusLookup");
184 if (!mega_databus_lookup_subrelation_failures.empty()) {
185 all_subrelation_failures["MegaDatabusLookup"] = mega_databus_lookup_subrelation_failures;
186 }
187
188 return all_subrelation_failures;
189 }
190};
191
192// Specialization for TranslatorFlavor: checks the four row-by-row relations that do not require
193// grand product polynomials (Permutation and DeltaRangeConstraint are excluded as they need z_perm
194// and sorted ordered_range_constraints polynomials computed during proving).
195template <> class RelationChecker<TranslatorFlavor> : public RelationChecker<void> {
197
198 public:
199 static AllSubrelationFailures check_all(const auto& polynomials, const auto& params)
200 {
201 using FF = TranslatorFlavor::FF;
202 AllSubrelationFailures all_subrelation_failures;
203
204 auto try_check = [&]<typename R>(const char* name) {
205 auto failures = Base::check<R>(polynomials, params, name);
206 if (!failures.empty()) {
207 all_subrelation_failures[name] = failures;
208 }
209 };
210
211 try_check.template operator()<TranslatorOpcodeConstraintRelation<FF>>("TranslatorOpcodeConstraint");
212 try_check.template operator()<TranslatorAccumulatorTransferRelation<FF>>("TranslatorAccumulatorTransfer");
213 try_check.template operator()<TranslatorDecompositionRelation<FF>>("TranslatorDecomposition");
214 try_check.template operator()<TranslatorNonNativeFieldRelation<FF>>("TranslatorNonNativeField");
215
216 return all_subrelation_failures;
217 }
218};
219
220} // 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