Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
bbapi_chonk.cpp
Go to the documentation of this file.
13
14namespace bb::bbapi {
15
17{
18 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
19
20 request.ivc_in_progress = std::make_shared<Chonk>(num_circuits);
21
22 request.ivc_stack_depth = 0;
23 return Response{};
24}
25
27{
28 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
29 if (!request.ivc_in_progress) {
30 throw_or_abort("Chonk not started. Call ChonkStart first.");
31 }
32
33 request.loaded_circuit_name = circuit.name;
34 request.loaded_circuit_constraints = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode));
35 request.loaded_circuit_vk = circuit.verification_key;
36
37 info("ChonkLoad - loaded circuit '", request.loaded_circuit_name, "'");
38
39 return Response{};
40}
41
43{
44 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
45 if (!request.ivc_in_progress) {
46 throw_or_abort("Chonk not started. Call ChonkStart first.");
47 }
48
49 if (!request.loaded_circuit_constraints.has_value()) {
50 throw_or_abort("No circuit loaded. Call ChonkLoad first.");
51 }
52
54 acir_format::AcirProgram program{ std::move(request.loaded_circuit_constraints.value()), std::move(witness_data) };
55
56 const acir_format::ProgramMetadata metadata{ .ivc = request.ivc_in_progress };
57 auto circuit = acir_format::create_circuit<IVCBase::ClientCircuit>(program, metadata);
58
60
61 if (request.vk_policy == VkPolicy::RECOMPUTE) {
62 precomputed_vk = nullptr;
63 } else if (request.vk_policy == VkPolicy::DEFAULT || request.vk_policy == VkPolicy::CHECK) {
64 if (!request.loaded_circuit_vk.empty()) {
65 precomputed_vk = from_buffer<std::shared_ptr<Chonk::MegaVerificationKey>>(request.loaded_circuit_vk);
66
67 if (request.vk_policy == VkPolicy::CHECK) {
68 auto prover_instance = std::make_shared<Chonk::ProverInstance>(circuit);
69 auto computed_vk = std::make_shared<Chonk::MegaVerificationKey>(prover_instance->get_precomputed());
70
71 // Dereference to compare VK contents
72 if (*precomputed_vk != *computed_vk) {
73 throw_or_abort("VK check failed for circuit '" + request.loaded_circuit_name +
74 "': provided VK does not match computed VK");
75 }
76 }
77 }
78 } else {
79 throw_or_abort("Invalid VK policy. Valid options: default, check, recompute");
80 }
81
82 info("ChonkAccumulate - accumulating circuit '", request.loaded_circuit_name, "'");
83 request.ivc_in_progress->accumulate(circuit, precomputed_vk);
84 request.ivc_stack_depth++;
85
86 request.loaded_circuit_constraints.reset();
87 request.loaded_circuit_vk.clear();
88
89 return Response{};
90}
91
93{
94 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
95 if (!request.ivc_in_progress) {
96 throw_or_abort("Chonk not started. Call ChonkStart first.");
97 }
98
99 if (request.ivc_stack_depth == 0) {
100 throw_or_abort("No circuits accumulated. Call ChonkAccumulate first.");
101 }
102
103 info("ChonkProve - generating proof for ", request.ivc_stack_depth, " accumulated circuits");
104
105 // Call prove and verify using the appropriate IVC type
106 Response response;
107 bool verification_passed = false;
108
109 info("ChonkProve - using Chonk");
110 auto sumcheck_ivc = std::dynamic_pointer_cast<Chonk>(request.ivc_in_progress);
111 auto proof = sumcheck_ivc->prove();
112 auto vk_and_hash = sumcheck_ivc->get_hiding_kernel_vk_and_hash();
113
114 // We verify this proof. Another bb call to verify has some overhead of loading VK/proof/SRS,
115 // and it is mysterious if this transaction fails later in the lifecycle.
116 info("ChonkProve - verifying the generated proof as a sanity check");
117 ChonkNativeVerifier verifier(vk_and_hash);
118 verification_passed = verifier.verify(proof);
119
120 if (!verification_passed) {
121 throw_or_abort("Failed to verify the generated proof!");
122 }
123
124 response.proof = ChonkProof{ std::move(proof.mega_proof), std::move(proof.goblin_proof) };
125
126 request.ivc_in_progress.reset();
127 request.ivc_stack_depth = 0;
128
129 return response;
130}
131
133{
134 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
135 // Deserialize the hiding kernel verification key directly from buffer
136 auto hiding_kernel_vk = std::make_shared<Chonk::MegaVerificationKey>(from_buffer<Chonk::MegaVerificationKey>(vk));
137
138 // Verify the proof using ChonkNativeVerifier
139 auto vk_and_hash = std::make_shared<ChonkNativeVerifier::VKAndHash>(hiding_kernel_vk);
140 ChonkNativeVerifier verifier(vk_and_hash);
141 const bool verified = verifier.verify(proof);
142
143 return { .valid = verified };
144}
145
146static std::shared_ptr<Chonk::ProverInstance> get_acir_program_prover_instance(acir_format::AcirProgram& program)
147{
148 Chonk::ClientCircuit builder = acir_format::create_circuit<Chonk::ClientCircuit>(program);
149
150 // Construct the verification key via the prover-constructed proving key with the proper trace settings
152}
153
155{
156 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
157 info("ChonkComputeStandaloneVk - deriving VK for circuit '", circuit.name, "'");
158
159 auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode));
160
161 acir_format::AcirProgram program{ constraint_system, /*witness=*/{} };
162 std::shared_ptr<Chonk::ProverInstance> prover_instance = get_acir_program_prover_instance(program);
163 auto verification_key = std::make_shared<Chonk::MegaVerificationKey>(prover_instance->get_precomputed());
164
165 return { .bytes = to_buffer(*verification_key), .fields = verification_key->to_field_elements() };
166}
167
169{
170 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
171 info("ChonkComputeIvcVk - deriving IVC VK for circuit '", circuit.name, "'");
172
173 auto standalone_vk_response = bbapi::ChonkComputeStandaloneVk{
174 .circuit{ .name = "standalone_circuit", .bytecode = std::move(circuit.bytecode) }
175 }.execute();
176
177 // The hiding kernel VK is just the MegaZK verification key
178 auto hiding_kernel_vk = from_buffer<Chonk::MegaVerificationKey>(standalone_vk_response.bytes);
179 Response response;
180 response.bytes = to_buffer(hiding_kernel_vk);
181
182 info("ChonkComputeIvcVk - hiding kernel VK derived, size: ", response.bytes.size(), " bytes");
183
184 return response;
185}
186
188{
189 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
191 /*witness=*/{} };
192
193 std::shared_ptr<Chonk::ProverInstance> prover_instance = get_acir_program_prover_instance(program);
194 auto computed_vk = std::make_shared<Chonk::MegaVerificationKey>(prover_instance->get_precomputed());
195
196 if (circuit.verification_key.empty()) {
197 info("FAIL: Expected precomputed vk for function ", circuit.name);
198 throw_or_abort("Missing precomputed VK");
199 }
200
201 // Deserialize directly from buffer
202 auto precomputed_vk = from_buffer<std::shared_ptr<Chonk::MegaVerificationKey>>(circuit.verification_key);
203
204 Response response;
205 response.valid = true;
206 if (*computed_vk != *precomputed_vk) {
207 response.valid = false;
208 response.actual_vk = to_buffer(computed_vk);
209 }
210 return response;
211}
212
214{
215 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
216 Response response;
217
218 const auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode));
219 acir_format::AcirProgram program{ constraint_system };
220
221 // Get IVC constraints if any
222 const auto& ivc_constraints = constraint_system.hn_recursion_constraints;
223
224 // Create metadata with appropriate IVC context
226 .ivc = ivc_constraints.empty() ? nullptr : acir_format::create_mock_chonk_from_constraints(ivc_constraints),
227 .collect_gates_per_opcode = include_gates_per_opcode
228 };
229
230 // Create and finalize circuit
231 auto builder = acir_format::create_circuit<MegaCircuitBuilder>(program, metadata);
232 builder.finalize_circuit(/*ensure_nonzero=*/true);
233
234 // Set response values
235 response.acir_opcodes = program.constraints.num_acir_opcodes;
236 response.circuit_size = static_cast<uint32_t>(builder.num_gates());
237
238 // Optionally include gates per opcode
239 if (include_gates_per_opcode) {
240 response.gates_per_opcode = std::vector<uint32_t>(program.constraints.gates_per_opcode.begin(),
241 program.constraints.gates_per_opcode.end());
242 }
243
244 // Log circuit details
245 info("ChonkStats - circuit: ",
246 circuit.name,
247 ", acir_opcodes: ",
248 response.acir_opcodes,
249 ", circuit_size: ",
250 response.circuit_size);
251
252 // Print execution trace details
253 builder.blocks.summarize();
254
255 return response;
256}
257
258} // namespace bb::bbapi
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:219
Chonk-specific command definitions for the Barretenberg RPC API.
Verifier for Chonk IVC proofs (both native and recursive).
Output verify(const Proof &proof)
Verify a Chonk proof.
void info(Args... args)
Definition log.hpp:89
#define BB_UNUSED
AluTraceBuilder builder
Definition alu.test.cpp:124
WitnessVector witness_buf_to_witness_vector(std::vector< uint8_t > &&buf)
Convert a buffer representing a witness vector into Barretenberg's internal WitnessVector format.
std::shared_ptr< Chonk > create_mock_chonk_from_constraints(const std::vector< RecursionConstraint > &constraints)
Create an IVC object with mocked state corresponding to a set of IVC recursion constraints.
std::vector< bb::fr > WitnessVector
AcirFormat circuit_buf_to_acir_format(std::vector< uint8_t > &&buf)
Convert a buffer representing a circuit into Barretenberg's internal AcirFormat representation.
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)
Struct containing both the constraints to be added to the circuit and the witness vector.
Metadata required to create a circuit.
std::shared_ptr< bb::IVCBase > ivc
Empty response indicating successful circuit accumulation.
Response execute(BBApiRequest &request) &&
Contains the validation result.
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.
ChonkProof 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)
uint32_t acir_opcodes
Number of ACIR opcodes.
std::vector< uint32_t > gates_per_opcode
Optional: gate counts per opcode.
Response execute(BBApiRequest &request) &&
Contains the verification result.
Response execute(const BBApiRequest &request={}) &&
std::string name
Human-readable name for the circuit.
void throw_or_abort(std::string const &err)