Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
pg_recursion_constraint.cpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
18#include "proof_surgeon.hpp"
20
21namespace acir_format {
22
23using namespace bb;
24
41 const TraceSettings& trace_settings)
42{
43 auto ivc = std::make_shared<ClientIVC>(constraints.size(), trace_settings);
44
45 uint32_t oink_type = static_cast<uint32_t>(PROOF_TYPE::OINK);
46 uint32_t pg_type = static_cast<uint32_t>(PROOF_TYPE::PG);
47 uint32_t pg_final_type = static_cast<uint32_t>(PROOF_TYPE::PG_FINAL);
48 uint32_t pg_tail_type = static_cast<uint32_t>(PROOF_TYPE::PG_TAIL);
49
50 // There is a fixed set of valid combinations of IVC recursion constraints for Aztec kernel circuits:
51
52 // Case: INIT kernel; single Oink recursive verification of an app
53 if (constraints.size() == 1 && constraints[0].proof_type == oink_type) {
54 mock_ivc_accumulation(ivc, ClientIVC::QUEUE_TYPE::OINK, /*is_kernel=*/false);
55 return ivc;
56 }
57
58 // Case: RESET kernel; single PG recursive verification of a kernel
59 if (constraints.size() == 1 && constraints[0].proof_type == pg_type) {
60 ivc->recursive_verifier_native_accum = create_mock_verifier_instance<ClientIVC::Flavor>();
61 mock_ivc_accumulation(ivc, ClientIVC::QUEUE_TYPE::PG, /*is_kernel=*/true);
62 return ivc;
63 }
64
65 // Case: TAIL kernel; single PG recursive verification of a kernel
66 if (constraints.size() == 1 && constraints[0].proof_type == pg_tail_type) {
67 ivc->recursive_verifier_native_accum = create_mock_verifier_instance<ClientIVC::Flavor>();
68 mock_ivc_accumulation(ivc, ClientIVC::QUEUE_TYPE::PG_TAIL, /*is_kernel=*/true);
69 return ivc;
70 }
71
72 // Case: INNER kernel; two PG recursive verifications, kernel and app in that order
73 if (constraints.size() == 2) {
74 BB_ASSERT_EQ(constraints[0].proof_type, pg_type);
75 BB_ASSERT_EQ(constraints[1].proof_type, pg_type);
76 ivc->recursive_verifier_native_accum = create_mock_verifier_instance<ClientIVC::Flavor>();
77 mock_ivc_accumulation(ivc, ClientIVC::QUEUE_TYPE::PG, /*is_kernel=*/true);
78 mock_ivc_accumulation(ivc, ClientIVC::QUEUE_TYPE::PG, /*is_kernel=*/false);
79 return ivc;
80 }
81
82 // Case: HIDING kernel; single PG_FINAL recursive verification of a kernel
83 if (constraints.size() == 1 && constraints[0].proof_type == pg_final_type) {
84 ivc->recursive_verifier_native_accum = create_mock_verifier_instance<ClientIVC::Flavor>();
85 mock_ivc_accumulation(ivc, ClientIVC::QUEUE_TYPE::PG_FINAL, /*is_kernel=*/true);
86 return ivc;
87 }
88
89 throw_or_abort("Invalid set of IVC recursion constraints!");
90 return ivc;
91}
92
94 const std::vector<RecursionConstraint>& constraints)
95{
96 auto ivc = std::make_shared<SumcheckClientIVC>(constraints.size());
97
98 uint32_t oink_type = static_cast<uint32_t>(PROOF_TYPE::OINK);
99 uint32_t pg_type = static_cast<uint32_t>(PROOF_TYPE::PG);
100 uint32_t pg_final_type = static_cast<uint32_t>(PROOF_TYPE::PG_FINAL);
101 uint32_t pg_tail_type = static_cast<uint32_t>(PROOF_TYPE::PG_TAIL);
102
103 // There is a fixed set of valid combinations of IVC recursion constraints for Aztec kernel circuits:
104
105 // Case: INIT kernel; single Oink recursive verification of an app
106 if (constraints.size() == 1 && constraints[0].proof_type == oink_type) {
107 mock_sumcheck_ivc_accumulation(ivc, SumcheckClientIVC::QUEUE_TYPE::OINK, /*is_kernel=*/false);
108 return ivc;
109 }
110
111 // Case: RESET kernel; single PG recursive verification of a kernel
112 if (constraints.size() == 1 && constraints[0].proof_type == pg_type) {
113 mock_sumcheck_ivc_accumulation(ivc, SumcheckClientIVC::QUEUE_TYPE::PG, /*is_kernel=*/true);
114 return ivc;
115 }
116
117 // Case: TAIL kernel; single PG recursive verification of a kernel
118 if (constraints.size() == 1 && constraints[0].proof_type == pg_tail_type) {
119 mock_sumcheck_ivc_accumulation(ivc, SumcheckClientIVC::QUEUE_TYPE::PG_TAIL, /*is_kernel=*/true);
120 return ivc;
121 }
122
123 // Case: INNER kernel; two PG recursive verifications, kernel and app in that order
124 if (constraints.size() == 2) {
125 BB_ASSERT_EQ(constraints[0].proof_type, pg_type);
126 BB_ASSERT_EQ(constraints[1].proof_type, pg_type);
127 mock_sumcheck_ivc_accumulation(ivc, SumcheckClientIVC::QUEUE_TYPE::PG, /*is_kernel=*/true);
128 mock_sumcheck_ivc_accumulation(ivc, SumcheckClientIVC::QUEUE_TYPE::PG, /*is_kernel=*/false);
129 return ivc;
130 }
131
132 // Case: HIDING kernel; single PG_FINAL recursive verification of a kernel
133 if (constraints.size() == 1 && constraints[0].proof_type == pg_final_type) {
134 mock_sumcheck_ivc_accumulation(ivc, SumcheckClientIVC::QUEUE_TYPE::PG_FINAL, /*is_kernel=*/true);
135 return ivc;
136 }
137
138 throw_or_abort("Invalid set of IVC recursion constraints!");
139 return ivc;
140}
141
148 const TraceSettings& trace_settings,
149 const bool is_kernel)
150{
151 using FF = ClientIVC::FF;
152 using MegaVerificationKey = ClientIVC::MegaVerificationKey;
154
155 // Use the trace settings to determine the correct dyadic size and the public inputs offset
157 blocks.set_fixed_block_sizes(trace_settings);
158 blocks.compute_offsets(/*is_structured=*/true);
159 size_t dyadic_size = blocks.get_structured_dyadic_size();
160 size_t pub_inputs_offset = blocks.pub_inputs.trace_offset();
161
162 // Construct a mock Oink or PG proof and a mock MegaHonk verification key
163 std::vector<FF> proof;
165
166 if (is_kernel) {
168 switch (verification_type) {
169 case ClientIVC::QUEUE_TYPE::OINK:
170 proof = create_mock_oink_proof<Flavor, KernelIO>();
171 break;
172 case ClientIVC::QUEUE_TYPE::PG:
173 case ClientIVC::QUEUE_TYPE::PG_FINAL:
174 case ClientIVC::QUEUE_TYPE::PG_TAIL:
175 proof = create_mock_pg_proof<Flavor, KernelIO>();
176 break;
177 default:
178 throw_or_abort("Invalid verification type! Only OINK, PG and PG_FINAL are supported");
179 }
180 verification_key = create_mock_honk_vk<Flavor, KernelIO>(dyadic_size, pub_inputs_offset);
181 } else {
183 switch (verification_type) {
184 case ClientIVC::QUEUE_TYPE::OINK:
185 proof = create_mock_oink_proof<Flavor, AppIO>();
186 break;
187 case ClientIVC::QUEUE_TYPE::PG:
188 proof = create_mock_pg_proof<Flavor, AppIO>();
189 break;
190 default:
191 throw_or_abort("Invalid verification type! Only OINK, PG and PG_FINAL are supported");
192 }
193 verification_key = create_mock_honk_vk<Flavor, AppIO>(dyadic_size, pub_inputs_offset);
194 }
195
196 return ClientIVC::VerifierInputs{ proof, verification_key, verification_type, is_kernel };
197}
198
205 const SumcheckClientIVC::QUEUE_TYPE verification_type, const bool is_kernel)
206{
207 using IvcType = SumcheckClientIVC;
208 using FF = IvcType::FF;
209 using MegaVerificationKey = IvcType::MegaVerificationKey;
210 using Flavor = IvcType::Flavor;
211
212 size_t dyadic_size = 1 << Flavor::VIRTUAL_LOG_N; // maybe doesnt need to be correct
213 size_t pub_inputs_offset = Flavor::has_zero_row ? 1 : 0; // always 1
214
215 // Construct a mock Oink or PG proof and a mock MegaHonk verification key
216 std::vector<FF> proof;
218
219 if (is_kernel) {
221 BB_ASSERT_EQ(verification_type == SumcheckClientIVC::QUEUE_TYPE::PG ||
222 verification_type == SumcheckClientIVC::QUEUE_TYPE::PG_TAIL ||
223 verification_type == SumcheckClientIVC::QUEUE_TYPE::PG_FINAL,
224 true);
225
226 // kernel circuits are always folded, thus the proof always includes the nova fold proof
227 bool include_fold = true;
228 proof = create_mock_hyper_nova_proof<Flavor, KernelIO>(include_fold);
229
230 verification_key = create_mock_honk_vk<Flavor, KernelIO>(dyadic_size, pub_inputs_offset);
231 } else {
233 BB_ASSERT_EQ(verification_type == SumcheckClientIVC::QUEUE_TYPE::OINK ||
234 verification_type == SumcheckClientIVC::QUEUE_TYPE::PG,
235 true);
236
237 // The first app is not folded thus the proof does not include the nova fold proof
238 bool include_fold = !(verification_type == SumcheckClientIVC::QUEUE_TYPE::OINK);
239 proof = create_mock_hyper_nova_proof<Flavor, AppIO>(include_fold);
240
241 verification_key = create_mock_honk_vk<Flavor, AppIO>(dyadic_size, pub_inputs_offset);
242 }
243
244 return SumcheckClientIVC::VerifierInputs{ proof, verification_key, verification_type, is_kernel };
245}
246
255{
257 acir_format::create_mock_verification_queue_entry(type, ivc->trace_settings, is_kernel);
258 ivc->verification_queue.emplace_back(entry);
259 ivc->goblin.merge_verification_queue.emplace_back(acir_format::create_mock_merge_proof());
260 // If the type is PG_FINAL, we also need to populate the ivc instance with a mock decider proof
261 if (type == ClientIVC::QUEUE_TYPE::PG_FINAL) {
262 ivc->decider_proof = acir_format::create_mock_decider_proof<ClientIVC::Flavor>();
263 }
264 ivc->num_circuits_accumulated++;
265}
266
278 const bool is_kernel)
279{
281 using Commitment = SumcheckClientIVC::Commitment;
282
283 // Initialize verifier accumulator with proper structure
284 ivc->recursive_verifier_native_accum.challenge =
286 ivc->recursive_verifier_native_accum.batched_evaluations = { FF::zero(), FF::zero() };
287 ivc->recursive_verifier_native_accum.batched_commitments = { Commitment::one(), Commitment::one() };
288
290 ivc->verification_queue.emplace_back(entry);
291 ivc->goblin.merge_verification_queue.emplace_back(acir_format::create_mock_merge_proof());
292 if (type == SumcheckClientIVC::QUEUE_TYPE::PG_FINAL) {
293 ivc->pcs_proof = acir_format::create_mock_pcs_proof<SumcheckClientIVC::Flavor>();
294 }
295 ivc->num_circuits_accumulated++;
296}
297
306 const std::shared_ptr<MegaFlavor::VerificationKey>& mock_verification_key,
307 std::vector<uint32_t>& key_witness_indices)
308{
309 using FF = ClientIVC::FF;
310
311 // Convert the VerificationKey to fields
312 std::vector<FF> mock_vk_fields = mock_verification_key->to_field_elements();
313 BB_ASSERT_EQ(mock_vk_fields.size(), key_witness_indices.size());
314
315 // Add the fields to the witness and set the key witness indices accordingly
316 for (auto [witness_idx, value] : zip_view(key_witness_indices, mock_vk_fields)) {
317 builder.set_variable(witness_idx, value);
318 }
319}
320
321} // namespace acir_format
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:88
MegaFlavor Flavor
Flavor::FF FF
Flavor::VerificationKey MegaVerificationKey
void compute_offsets(bool is_structured)
void set_fixed_block_sizes(const TraceSettings &settings)
static constexpr size_t VIRTUAL_LOG_N
static constexpr bool has_zero_row
The IVC scheme used by the aztec client for private function execution.
Flavor::Commitment Commitment
Manages the data that is propagated on the public inputs of an application/function circuit.
Manages the data that is propagated on the public inputs of a kernel circuit.
AluTraceBuilder builder
Definition alu.test.cpp:123
Base class templates for structures that contain data parameterized by the fundamental polynomials of...
void mock_ivc_accumulation(const std::shared_ptr< ClientIVC > &ivc, ClientIVC::QUEUE_TYPE type, const bool is_kernel)
Populate an IVC instance with data that mimics the state after a single IVC accumulation (Oink or PG)
SumcheckClientIVC::VerifierInputs create_mock_verification_queue_entry_nova(const SumcheckClientIVC::QUEUE_TYPE verification_type, const bool is_kernel)
Create a mock verification queue entry with proof and VK that have the correct structure but are not ...
Goblin::MergeProof create_mock_merge_proof()
Create a mock merge proof which has the correct structure but is not necessarily valid.
void mock_sumcheck_ivc_accumulation(const std::shared_ptr< SumcheckClientIVC > &ivc, SumcheckClientIVC::QUEUE_TYPE type, const bool is_kernel)
Populate an IVC instance with data that mimics the state after a single IVC accumulation.
std::shared_ptr< SumcheckClientIVC > create_mock_sumcheck_ivc_from_constraints(const std::vector< RecursionConstraint > &constraints)
std::shared_ptr< ClientIVC > create_mock_ivc_from_constraints(const std::vector< RecursionConstraint > &constraints, const TraceSettings &trace_settings)
Create an IVC object with mocked state corresponding to a set of IVC recursion constraints.
void populate_dummy_vk_in_constraint(MegaCircuitBuilder &builder, const std::shared_ptr< MegaFlavor::VerificationKey > &mock_verification_key, std::vector< uint32_t > &key_witness_indices)
Populate VK witness fields from a recursion constraint from a provided VerificationKey.
ClientIVC::VerifierInputs create_mock_verification_queue_entry(const ClientIVC::QUEUE_TYPE verification_type, const TraceSettings &trace_settings, const bool is_kernel)
Create a mock verification queue entry with proof and VK that have the correct structure but are not ...
DefaultIO< MegaCircuitBuilder > AppIO
The data that is propagated on the public inputs of an application/function circuit.
Entry point for Barretenberg command-line interface.
typename Flavor::FF FF
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
MegaTracePublicInputBlock pub_inputs
static constexpr field zero()
void throw_or_abort(std::string const &err)