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 chonk = std::dynamic_pointer_cast<Chonk>(request.ivc_in_progress);
111 auto proof = chonk->prove();
112 auto vk_and_hash = chonk->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("ChonkComputeVk - deriving MegaVerificationKey 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 info("ChonkComputeVk - VK derived, size: ", to_buffer(*verification_key).size(), " bytes");
166
167 return { .bytes = to_buffer(*verification_key), .fields = verification_key->to_field_elements() };
168}
169
171{
172 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
174 /*witness=*/{} };
175
176 std::shared_ptr<Chonk::ProverInstance> prover_instance = get_acir_program_prover_instance(program);
177 auto computed_vk = std::make_shared<Chonk::MegaVerificationKey>(prover_instance->get_precomputed());
178
179 if (circuit.verification_key.empty()) {
180 info("FAIL: Expected precomputed vk for function ", circuit.name);
181 throw_or_abort("Missing precomputed VK");
182 }
183
184 // Deserialize directly from buffer
185 auto precomputed_vk = from_buffer<std::shared_ptr<Chonk::MegaVerificationKey>>(circuit.verification_key);
186
187 Response response;
188 response.valid = true;
189 if (*computed_vk != *precomputed_vk) {
190 response.valid = false;
191 response.actual_vk = to_buffer(computed_vk);
192 }
193 return response;
194}
195
197{
198 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
199 Response response;
200
201 const auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode));
202 acir_format::AcirProgram program{ constraint_system };
203
204 // Get IVC constraints if any
205 const auto& ivc_constraints = constraint_system.hn_recursion_constraints;
206
207 // Create metadata with appropriate IVC context
209 .ivc = ivc_constraints.empty() ? nullptr : acir_format::create_mock_chonk_from_constraints(ivc_constraints),
210 .collect_gates_per_opcode = include_gates_per_opcode
211 };
212
213 // Create and finalize circuit
214 auto builder = acir_format::create_circuit<MegaCircuitBuilder>(program, metadata);
215 builder.finalize_circuit(/*ensure_nonzero=*/true);
216
217 // Set response values
218 response.acir_opcodes = program.constraints.num_acir_opcodes;
219 response.circuit_size = static_cast<uint32_t>(builder.num_gates());
220
221 // Optionally include gates per opcode
222 if (include_gates_per_opcode) {
223 response.gates_per_opcode = std::vector<uint32_t>(program.constraints.gates_per_opcode.begin(),
224 program.constraints.gates_per_opcode.end());
225 }
226
227 // Log circuit details
228 info("ChonkStats - circuit: ",
229 circuit.name,
230 ", acir_opcodes: ",
231 response.acir_opcodes,
232 ", circuit_size: ",
233 response.circuit_size);
234
235 // Print execution trace details
236 builder.blocks.summarize();
237
238 return response;
239}
240
241} // 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.
#define info(...)
Definition log.hpp:93
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 a Chonk instance 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 verification key in multiple formats.
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={}) &&
void throw_or_abort(std::string const &err)