Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
bbapi_client_ivc.cpp
Go to the documentation of this file.
13
14namespace bb::bbapi {
15
17{
18 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
19 if (USE_SUMCHECK_IVC) {
20 request.ivc_in_progress = std::make_shared<SumcheckClientIVC>(num_circuits);
21 } else {
22 request.ivc_in_progress = std::make_shared<ClientIVC>(num_circuits, request.trace_settings);
23 }
24 request.ivc_stack_depth = 0;
25 return Response{};
26}
27
29{
30 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
31 if (!request.ivc_in_progress) {
32 throw_or_abort("ClientIVC not started. Call ClientIvcStart first.");
33 }
34
35 request.loaded_circuit_name = circuit.name;
36 request.loaded_circuit_constraints = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode));
37 request.loaded_circuit_vk = circuit.verification_key;
38
39 info("ClientIvcLoad - loaded circuit '", request.loaded_circuit_name, "'");
40
41 return Response{};
42}
43
45{
46 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
47 if (!request.ivc_in_progress) {
48 throw_or_abort("ClientIVC not started. Call ClientIvcStart first.");
49 }
50
51 if (!request.loaded_circuit_constraints.has_value()) {
52 throw_or_abort("No circuit loaded. Call ClientIvcLoad first.");
53 }
54
56 acir_format::AcirProgram program{ std::move(request.loaded_circuit_constraints.value()), std::move(witness_data) };
57
58 const acir_format::ProgramMetadata metadata{ .ivc = request.ivc_in_progress };
59 auto circuit = acir_format::create_circuit<IVCBase::ClientCircuit>(program, metadata);
60
62 if (!request.loaded_circuit_vk.empty()) {
63 // Deserialize directly from buffer
64 precomputed_vk = from_buffer<std::shared_ptr<ClientIVC::MegaVerificationKey>>(request.loaded_circuit_vk);
65 }
66
67 info("ClientIvcAccumulate - accumulating circuit '", request.loaded_circuit_name, "'");
68 request.ivc_in_progress->accumulate(circuit, precomputed_vk);
69 request.ivc_stack_depth++;
70
71 request.loaded_circuit_constraints.reset();
72 request.loaded_circuit_vk.clear();
73
74 return Response{};
75}
76
78{
79 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
80 if (!request.ivc_in_progress) {
81 throw_or_abort("ClientIVC not started. Call ClientIvcStart first.");
82 }
83
84 if (request.ivc_stack_depth == 0) {
85 throw_or_abort("No circuits accumulated. Call ClientIvcAccumulate first.");
86 }
87
88 info("ClientIvcProve - generating proof for ", request.ivc_stack_depth, " accumulated circuits");
89
90 // Call prove and verify using the appropriate IVC type
91 Response response;
92 bool verification_passed = false;
93
94 if (auto sumcheck_ivc = std::dynamic_pointer_cast<SumcheckClientIVC>(request.ivc_in_progress)) {
95 info("ClientIvcProve - using SumcheckClientIVC");
96 auto proof = sumcheck_ivc->prove();
97 auto vk = sumcheck_ivc->get_vk();
98
99 // We verify this proof. Another bb call to verify has some overhead of loading VK/proof/SRS,
100 // and it is mysterious if this transaction fails later in the lifecycle.
101 info("ClientIvcProve - verifying the generated proof as a sanity check");
102 verification_passed = SumcheckClientIVC::verify(proof, vk);
103
104 if (!verification_passed) {
105 throw_or_abort("Failed to verify the generated proof!");
106 }
107
108 response.proof = ClientIVC::Proof{ .mega_proof = std::move(proof.mega_proof),
109 .goblin_proof = std::move(proof.goblin_proof) };
110 } else if (auto client_ivc = std::dynamic_pointer_cast<ClientIVC>(request.ivc_in_progress)) {
111 info("ClientIvcProve - using ClientIVC");
112 auto proof = client_ivc->prove();
113 auto vk = client_ivc->get_vk();
114
115 // We verify this proof. Another bb call to verify has some overhead of loading VK/proof/SRS,
116 // and it is mysterious if this transaction fails later in the lifecycle.
117 info("ClientIvcProve - verifying the generated proof as a sanity check");
118 verification_passed = ClientIVC::verify(proof, vk);
119
120 if (!verification_passed) {
121 throw_or_abort("Failed to verify the generated proof!");
122 }
123
124 response.proof = std::move(proof);
125 } else {
126 throw_or_abort("Unknown IVC type");
127 }
128
129 request.ivc_in_progress.reset();
130 request.ivc_stack_depth = 0;
131
132 return response;
133}
134
136{
137 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
138 // Deserialize the verification key directly from buffer
139 ClientIVC::VerificationKey verification_key = from_buffer<ClientIVC::VerificationKey>(vk);
140
141 // Verify the proof using ClientIVC's static verify method
142 const bool verified = ClientIVC::verify(proof, verification_key);
143
144 return { .valid = verified };
145}
146
147static std::shared_ptr<ClientIVC::ProverInstance> get_acir_program_prover_instance(const BBApiRequest& request,
149{
150 ClientIVC::ClientCircuit builder = acir_format::create_circuit<ClientIVC::ClientCircuit>(program);
151
152 // Construct the verification key via the prover-constructed proving key with the proper trace settings
154}
155
157{
158 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
159 info("ClientIvcComputeStandaloneVk - deriving VK for circuit '", circuit.name, "'");
160
161 auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode));
162
163 acir_format::AcirProgram program{ constraint_system, /*witness=*/{} };
164 std::shared_ptr<ClientIVC::ProverInstance> prover_instance = get_acir_program_prover_instance(request, program);
165 auto verification_key = std::make_shared<ClientIVC::MegaVerificationKey>(prover_instance->get_precomputed());
166
167 return { .bytes = to_buffer(*verification_key), .fields = verification_key->to_field_elements() };
168}
169
171{
172 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
173 info("ClientIvcComputeIvcVk - deriving IVC VK for circuit '", circuit.name, "'");
174
175 auto standalone_vk_response = bbapi::ClientIvcComputeStandaloneVk{
176 .circuit{ .name = "standalone_circuit", .bytecode = std::move(circuit.bytecode) }
177 }.execute({ .trace_settings = {} });
178
179 auto mega_vk = from_buffer<ClientIVC::MegaVerificationKey>(standalone_vk_response.bytes);
185 Response response;
186 response.bytes = to_buffer(civc_vk);
187
188 info("ClientIvcComputeIvcVk - IVC VK derived, size: ", response.bytes.size(), " bytes");
189
190 return response;
191}
192
194{
195 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
197 /*witness=*/{} };
198
199 std::shared_ptr<ClientIVC::ProverInstance> prover_instance = get_acir_program_prover_instance(request, program);
200 auto computed_vk = std::make_shared<ClientIVC::MegaVerificationKey>(prover_instance->get_precomputed());
201
202 if (circuit.verification_key.empty()) {
203 info("FAIL: Expected precomputed vk for function ", circuit.name);
204 throw_or_abort("Missing precomputed VK");
205 }
206
207 // Deserialize directly from buffer
208 auto precomputed_vk = from_buffer<std::shared_ptr<ClientIVC::MegaVerificationKey>>(circuit.verification_key);
209
210 Response response;
211 response.valid = true;
212 if (*computed_vk != *precomputed_vk) {
213 response.valid = false;
214 response.actual_vk = to_buffer(computed_vk);
215 }
216 return response;
217}
218
220{
221 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
222 Response response;
223
224 const auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode));
225 acir_format::AcirProgram program{ constraint_system };
226
227 // Get IVC constraints if any
228 const auto& ivc_constraints = constraint_system.pg_recursion_constraints;
229
230 // Create metadata with appropriate IVC context
232 .ivc = ivc_constraints.empty() ? nullptr
233 : create_mock_ivc_from_constraints(ivc_constraints, request.trace_settings),
234 .collect_gates_per_opcode = include_gates_per_opcode
235 };
236
237 // Create and finalize circuit
238 auto builder = acir_format::create_circuit<MegaCircuitBuilder>(program, metadata);
239 builder.finalize_circuit(/*ensure_nonzero=*/true);
240
241 // Set response values
242 response.acir_opcodes = program.constraints.num_acir_opcodes;
243 response.circuit_size = static_cast<uint32_t>(builder.num_gates);
244
245 // Optionally include gates per opcode
246 if (include_gates_per_opcode) {
247 response.gates_per_opcode = std::vector<uint32_t>(program.constraints.gates_per_opcode.begin(),
248 program.constraints.gates_per_opcode.end());
249 }
250
251 // Log circuit details
252 info("ClientIvcStats - circuit: ",
253 circuit.name,
254 ", acir_opcodes: ",
255 response.acir_opcodes,
256 ", circuit_size: ",
257 response.circuit_size);
258
259 // Print structured execution trace details
260 builder.blocks.set_fixed_block_sizes(request.trace_settings);
261 builder.blocks.summarize();
262
263 return response;
264}
265
266} // namespace bb::bbapi
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:218
ClientIVC-specific command definitions for the Barretenberg RPC API.
static bool verify(const Proof &proof, const VerificationKey &vk)
static bool verify(const Proof &proof, const VerificationKey &vk)
void info(Args... args)
Definition log.hpp:74
#define BB_UNUSED
AluTraceBuilder builder
Definition alu.test.cpp:123
WitnessVector witness_buf_to_witness_data(std::vector< uint8_t > &&buf)
Converts from the ACIR-native WitnessStack format to Barretenberg's internal WitnessVector format.
AcirFormat circuit_buf_to_acir_format(std::vector< uint8_t > &&buf)
bb::SlabVector< bb::fr > WitnessVector
bool USE_SUMCHECK_IVC
Global flag to control whether to use SumcheckClientIVC instead of ClientIVC.
VerifierCommitmentKey< Curve > vk
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::vector< uint8_t > to_buffer(T const &value)
std::shared_ptr< bb::IVCBase > ivc
A full proof for the IVC scheme containing a Mega proof showing correctness of the hiding circuit (wh...
std::shared_ptr< MegaVerificationKey > mega
std::string name
Human-readable name for the circuit.
Empty response indicating successful circuit accumulation.
Response execute(BBApiRequest &request) &&
bool valid
True if the precomputed VK matches the circuit.
Response execute(const BBApiRequest &request={}) &&
Contains the computed IVC verification key.
std::vector< uint8_t > bytes
Serialized IVC verification key in binary format.
Response execute(const BBApiRequest &request={}) &&
Contains the computed verification key in multiple formats.
Compute standalone verification key for a circuit.
Response execute(const BBApiRequest &request={}) &&
Empty response indicating successful circuit loading.
Response execute(BBApiRequest &request) &&
Contains the generated IVC proof.
ClientIVC::Proof proof
Complete IVC proof for all accumulated circuits.
Response execute(BBApiRequest &request) &&
Empty response indicating successful initialization.
Response execute(BBApiRequest &request) &&
Contains gate count information.
uint32_t circuit_size
Circuit size (total number of gates)
std::vector< uint32_t > gates_per_opcode
Optional: gate counts per opcode.
uint32_t acir_opcodes
Number of ACIR opcodes.
Response execute(BBApiRequest &request) &&
Contains the verification result.
Response execute(const BBApiRequest &request={}) &&
void throw_or_abort(std::string const &err)