Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
mock_circuit_producer.hpp
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
7#pragma once
8
14
15using namespace bb;
16
17namespace {
18
25class MockDatabusProducer {
26 private:
27 using ClientCircuit = ClientIVC::ClientCircuit;
28 using Flavor = MegaFlavor;
29 using FF = Flavor::FF;
30 using BusDataArray = std::vector<FF>;
31
32 static constexpr size_t BUS_ARRAY_SIZE = 3; // arbitrary length of mock bus inputs
33 BusDataArray app_return_data;
34 BusDataArray kernel_return_data;
35
36 FF dummy_return_val = 1; // use simple return val for easier test debugging
37
38 BusDataArray generate_random_bus_array()
39 {
40 BusDataArray result;
41 for (size_t i = 0; i < BUS_ARRAY_SIZE; ++i) {
42 result.emplace_back(dummy_return_val);
43 }
44 dummy_return_val += 1;
45 return result;
46 }
47
48 public:
52 void populate_app_databus(ClientCircuit& circuit)
53 {
54 app_return_data = generate_random_bus_array();
55 for (auto& val : app_return_data) {
56 circuit.add_public_return_data(circuit.add_variable(val));
57 }
58 };
59
64 void populate_kernel_databus(ClientCircuit& circuit)
65 {
66 // Populate calldata from previous kernel return data (if it exists)
67 for (auto& val : kernel_return_data) {
68 circuit.add_public_calldata(circuit.add_variable(val));
69 }
70 // Populate secondary_calldata from app return data (if it exists), then clear the app return data
71 for (auto& val : app_return_data) {
72 circuit.add_public_secondary_calldata(circuit.add_variable(val));
73 }
74 app_return_data.clear();
75
76 // Mock the return data for the present kernel circuit
77 kernel_return_data = generate_random_bus_array();
78 for (auto& val : kernel_return_data) {
79 circuit.add_public_return_data(circuit.add_variable(val));
80 }
81 };
82
87 void tamper_with_app_return_data() { app_return_data.emplace_back(17); }
88};
89
94struct TestSettings {
95 // number of public inputs to manually add to circuits, by default this would be 0 because we use the
96 // MockDatabusProducer to test public inputs handling
97 size_t num_public_inputs = 0;
98 // by default we will create more complex apps and kernel with various types of gates but in case we want to
99 // specifically test overflow behaviour or unstructured circuits we can manually construct simple circuits with a
100 // specified number of gates
101 size_t log2_num_gates = 0;
102};
103
112class PrivateFunctionExecutionMockCircuitProducer {
113 using ClientCircuit = ClientIVC::ClientCircuit;
114 using Flavor = MegaFlavor;
116
117 size_t circuit_counter = 0;
118 std::vector<bool> is_kernel_flags;
119
120 MockDatabusProducer mock_databus;
121 bool large_first_app = true;
122 constexpr static size_t NUM_TRAILING_KERNELS = 3; // reset, tail, hiding
123
124 public:
125 size_t total_num_circuits = 0;
126
127 PrivateFunctionExecutionMockCircuitProducer(size_t num_app_circuits, bool large_first_app = true)
128 : large_first_app(large_first_app)
129 , total_num_circuits(num_app_circuits * 2 +
130 NUM_TRAILING_KERNELS) /*One kernel per app, plus a fixed number of final kernels*/
131 {
132 // Set flags indicating which circuits are kernels vs apps
133 is_kernel_flags.resize(total_num_circuits, true);
134 for (size_t i = 0; i < num_app_circuits; ++i) {
135 is_kernel_flags[2 * i] = false; // every other circuit is an app
136 }
137 }
138
143 static std::shared_ptr<VerificationKey> get_verification_key(ClientCircuit& builder_in,
144 TraceSettings& trace_settings)
145 {
146 // This is a workaround to ensure that the circuit is finalized before we create the verification key
147 // In practice, this should not be needed as the circuit will be finalized when it is accumulated into the IVC
148 // but this is a workaround for the test setup.
150
151 // Deepcopy the opqueue to avoid modifying the original one when finalising the circuit
155 std::shared_ptr<VerificationKey> vk = std::make_shared<VerificationKey>(proving_key->get_precomputed());
156 return vk;
157 }
158
165 ClientCircuit create_next_circuit(ClientIVC& ivc, size_t log2_num_gates = 0, size_t num_public_inputs = 0)
166 {
167 const bool is_kernel = is_kernel_flags[circuit_counter];
168
169 circuit_counter++;
170
171 ClientCircuit circuit{ ivc.goblin.op_queue };
172 // if the number of gates is specified we just add a number of arithmetic gates
173 if (log2_num_gates != 0) {
174 MockCircuits::construct_arithmetic_circuit(circuit, log2_num_gates, /* include_public_inputs= */ false);
175 // Add some public inputs
176 for (size_t i = 0; i < num_public_inputs; ++i) {
177 circuit.add_public_variable(13634816 + i); // arbitrary number
178 }
179 } else {
180 // If the number of gates is not specified we create a structured mock circuit
181 if (is_kernel) {
182 GoblinMockCircuits::construct_mock_folding_kernel(circuit); // construct mock base logic
183 mock_databus.populate_kernel_databus(circuit); // populate databus inputs/outputs
184 } else {
185 bool use_large_circuit = large_first_app && (circuit_counter == 1); // first circuit is size 2^19
186 GoblinMockCircuits::construct_mock_app_circuit(circuit, use_large_circuit); // construct mock app
187 mock_databus.populate_app_databus(circuit); // populate databus outputs
188 }
189 }
190
191 if (is_kernel) {
193 } else {
195 }
196 return circuit;
197 }
198
203 TestSettings settings = {})
204 {
205 auto circuit = create_next_circuit(ivc, settings.log2_num_gates, settings.num_public_inputs);
206 return { circuit, get_verification_key(circuit, ivc.trace_settings) };
207 }
208
209 void construct_and_accumulate_next_circuit(ClientIVC& ivc, TestSettings settings = {})
210 {
211 auto [circuit, vk] = create_next_circuit_and_vk(ivc, settings);
212 ivc.accumulate(circuit, vk);
213 }
214
218 void tamper_with_databus() { mock_databus.tamper_with_app_return_data(); }
219};
220
221} // namespace
The IVC scheme used by the aztec client for private function execution.
TraceSettings trace_settings
void accumulate(ClientCircuit &circuit, const std::shared_ptr< MegaVerificationKey > &precomputed_vk)
Perform prover work for accumulation (e.g. PG folding, merge proving)
void complete_kernel_circuit_logic(ClientCircuit &circuit)
Append logic to complete a kernel circuit.
MegaCircuitBuilder ClientCircuit
The verification key is responsible for storing the commitments to the precomputed (non-witnessk) pol...
std::shared_ptr< OpQueue > op_queue
Definition goblin.hpp:48
static void construct_mock_app_circuit(MegaBuilder &builder, bool large=false)
Populate a builder with some arbitrary but nontrivial constraints.
static void construct_mock_folding_kernel(MegaBuilder &builder)
Construct a mock kernel circuit.
std::shared_ptr< ECCOpQueue > op_queue
Curve::ScalarField FF
static void construct_arithmetic_circuit(Builder &builder, const size_t target_log2_dyadic_size=4, bool include_public_inputs=true)
Populate a builder with a specified number of arithmetic gates; includes a PI.
AluTraceBuilder builder
Definition alu.test.cpp:123
UltraKeccakFlavor::VerificationKey VerificationKey
Entry point for Barretenberg command-line interface.
::testing::Types< BN254Settings, GrumpkinSettings > TestSettings
typename Flavor::FF FF
VerifierCommitmentKey< Curve > vk
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static void add_default_to_public_inputs(Builder &builder)
Adds default public inputs to the builder.