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 validate_vk_size<Chonk::MegaVerificationKey>(request.loaded_circuit_vk);
66 precomputed_vk = from_buffer<std::shared_ptr<Chonk::MegaVerificationKey>>(request.loaded_circuit_vk);
67
68 if (request.vk_policy == VkPolicy::CHECK) {
69 auto prover_instance = std::make_shared<Chonk::ProverInstance>(circuit);
70 auto computed_vk = std::make_shared<Chonk::MegaVerificationKey>(prover_instance->get_precomputed());
71
72 // Dereference to compare VK contents
73 if (*precomputed_vk != *computed_vk) {
74 throw_or_abort("VK check failed for circuit '" + request.loaded_circuit_name +
75 "': provided VK does not match computed VK");
76 }
77 }
78 }
79 } else {
80 throw_or_abort("Invalid VK policy. Valid options: default, check, recompute");
81 }
82
83 info("ChonkAccumulate - accumulating circuit '", request.loaded_circuit_name, "'");
84 request.ivc_in_progress->accumulate(circuit, precomputed_vk);
85 request.ivc_stack_depth++;
86
87 request.loaded_circuit_constraints.reset();
88 request.loaded_circuit_vk.clear();
89
90 return Response{};
91}
92
94{
95 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
96 if (!request.ivc_in_progress) {
97 throw_or_abort("Chonk not started. Call ChonkStart first.");
98 }
99
100 if (request.ivc_stack_depth == 0) {
101 throw_or_abort("No circuits accumulated. Call ChonkAccumulate first.");
102 }
103
104 info("ChonkProve - generating proof for ", request.ivc_stack_depth, " accumulated circuits");
105
106 // Call prove and verify using the appropriate IVC type
107 Response response;
108 bool verification_passed = false;
109
110 info("ChonkProve - using Chonk");
111 auto chonk = std::dynamic_pointer_cast<Chonk>(request.ivc_in_progress);
112 auto proof = chonk->prove();
113 auto vk_and_hash = chonk->get_hiding_kernel_vk_and_hash();
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("ChonkProve - verifying the generated proof as a sanity check");
118 ChonkNativeVerifier verifier(vk_and_hash);
119 verification_passed = verifier.verify(proof);
120
121 if (!verification_passed) {
122 throw_or_abort("Failed to verify the generated proof!");
123 }
124
125 response.proof = ChonkProof{ std::move(proof.mega_proof), std::move(proof.goblin_proof) };
126
127 request.ivc_in_progress.reset();
128 request.ivc_stack_depth = 0;
129
130 return response;
131}
132
134{
135 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
136
138 validate_vk_size<VerificationKey>(vk);
139
140 // Deserialize the hiding kernel verification key directly from buffer
141 auto hiding_kernel_vk = std::make_shared<VerificationKey>(from_buffer<VerificationKey>(vk));
142
143 // Validate proof size using VK's num_public_inputs before expensive verification
144 const size_t expected_proof_size =
145 static_cast<size_t>(hiding_kernel_vk->num_public_inputs) + ChonkProof::PROOF_LENGTH_WITHOUT_PUB_INPUTS;
146 if (proof.size() != expected_proof_size) {
147 throw_or_abort("proof has wrong size: expected " + std::to_string(expected_proof_size) + ", got " +
148 std::to_string(proof.size()));
149 }
150
151 // Verify the proof using ChonkNativeVerifier
152 auto vk_and_hash = std::make_shared<ChonkNativeVerifier::VKAndHash>(hiding_kernel_vk);
153 ChonkNativeVerifier verifier(vk_and_hash);
154 const bool verified = verifier.verify(proof);
155
156 return { .valid = verified };
157}
158
159static std::shared_ptr<Chonk::ProverInstance> get_acir_program_prover_instance(acir_format::AcirProgram& program)
160{
161 Chonk::ClientCircuit builder = acir_format::create_circuit<Chonk::ClientCircuit>(program);
162
163 // Construct the verification key via the prover-constructed proving key with the proper trace settings
165}
166
168{
169 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
170 info("ChonkComputeVk - deriving MegaVerificationKey for circuit '", circuit.name, "'");
171
172 auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode));
173
174 acir_format::AcirProgram program{ constraint_system, /*witness=*/{} };
175 std::shared_ptr<Chonk::ProverInstance> prover_instance = get_acir_program_prover_instance(program);
176 auto verification_key = std::make_shared<Chonk::MegaVerificationKey>(prover_instance->get_precomputed());
177
178 info("ChonkComputeVk - VK derived, size: ", to_buffer(*verification_key).size(), " bytes");
179
180 return { .bytes = to_buffer(*verification_key), .fields = verification_key->to_field_elements() };
181}
182
184{
185 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
187 /*witness=*/{} };
188
189 std::shared_ptr<Chonk::ProverInstance> prover_instance = get_acir_program_prover_instance(program);
190 auto computed_vk = std::make_shared<Chonk::MegaVerificationKey>(prover_instance->get_precomputed());
191
192 if (circuit.verification_key.empty()) {
193 info("FAIL: Expected precomputed vk for function ", circuit.name);
194 throw_or_abort("Missing precomputed VK");
195 }
196
197 validate_vk_size<Chonk::MegaVerificationKey>(circuit.verification_key);
198
199 // Deserialize directly from buffer
200 auto precomputed_vk = from_buffer<std::shared_ptr<Chonk::MegaVerificationKey>>(circuit.verification_key);
201
202 Response response;
203 response.valid = true;
204 if (*computed_vk != *precomputed_vk) {
205 response.valid = false;
206 response.actual_vk = to_buffer(computed_vk);
207 }
208 return response;
209}
210
212{
213 BB_BENCH_NAME(MSGPACK_SCHEMA_NAME);
214 Response response;
215
216 const auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(circuit.bytecode));
217 acir_format::AcirProgram program{ constraint_system, {} };
218
219 // Get IVC constraints if any
220 const auto& ivc_constraints = constraint_system.hn_recursion_constraints;
221
222 // Create metadata with appropriate IVC context
224 .ivc = ivc_constraints.empty() ? nullptr : acir_format::create_mock_chonk_from_constraints(ivc_constraints),
225 .collect_gates_per_opcode = include_gates_per_opcode
226 };
227
228 // Create and finalize circuit
229 auto builder = acir_format::create_circuit<MegaCircuitBuilder>(program, metadata);
230 builder.finalize_circuit(/*ensure_nonzero=*/true);
231
232 // Set response values
233 response.acir_opcodes = program.constraints.num_acir_opcodes;
234 response.circuit_size = static_cast<uint32_t>(builder.num_gates());
235
236 // Optionally include gates per opcode
237 if (include_gates_per_opcode) {
238 response.gates_per_opcode = std::vector<uint32_t>(program.constraints.gates_per_opcode.begin(),
239 program.constraints.gates_per_opcode.end());
240 }
241
242 // Log circuit details
243 info("ChonkStats - circuit: ",
244 circuit.name,
245 ", acir_opcodes: ",
246 response.acir_opcodes,
247 ", circuit_size: ",
248 response.circuit_size);
249
250 // Print execution trace details
251 builder.blocks.summarize();
252
253 return response;
254}
255
256} // namespace bb::bbapi
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:225
Chonk-specific command definitions for the Barretenberg RPC API.
Flavor::VerificationKey MegaVerificationKey
Definition chonk.hpp:43
Verifier for Chonk IVC proofs (both native and recursive).
Output verify(const Proof &proof)
Verify a Chonk proof.
Base Native verification key class.
Definition flavor.hpp:135
#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::string to_string(bb::avm2::ValueTag tag)
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
static constexpr size_t PROOF_LENGTH_WITHOUT_PUB_INPUTS
The size of a Chonk proof without backend-added public inputs.
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)