Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
acir_format.cpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Complete, auditors: [Federico], commit: 2094fd1467dd9a94803b2c5007cf60ac357aa7d2 }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#include "acir_format.hpp"
8
25
26#include <cstddef>
27#include <cstdint>
28#include <memory>
29
30namespace acir_format {
31
32using namespace bb;
33
34template <typename Builder>
35void build_constraints(Builder& builder, AcirFormat& constraints, const ProgramMetadata& metadata)
36{
37 bool collect_gates_per_opcode = metadata.collect_gates_per_opcode;
38
39 if (collect_gates_per_opcode) {
40 constraints.gates_per_opcode.resize(constraints.num_acir_opcodes, 0);
41 }
42
43 GateCounter gate_counter{ &builder, collect_gates_per_opcode };
44
45 // Add standard width-4 Ultra arithmetic gates
46 for (auto [constraint, opcode_idx] :
49 gate_counter.track_diff(constraints.gates_per_opcode, opcode_idx);
50 }
51
52 // When an expression doesn't fit into a single width-4 gate, we split it across multiple gates and we leverage
53 // w4_shift to use the least possible number of intermediate witnesses. See the documentation of
54 // split_into_mul_quad_gates for more information.
55 for (auto [big_constraint, opcode_idx] :
57 create_big_quad_constraint(builder, big_constraint);
58 gate_counter.track_diff(constraints.gates_per_opcode, opcode_idx);
59 }
60
61 // Add logic constraint
62 for (const auto& [constraint, opcode_idx] :
65 builder, constraint.a, constraint.b, constraint.result, constraint.num_bits, constraint.is_xor_gate);
66 gate_counter.track_diff(constraints.gates_per_opcode, opcode_idx);
67 }
68
69 // Add range constraint
70 for (const auto& [constraint, opcode_idx] :
72 builder.create_dyadic_range_constraint(
73 constraint.witness,
74 constraint.num_bits,
75 std::format("acir_format::build_constraints: range constraint at opcode index {} failed", opcode_idx));
76 gate_counter.track_diff(constraints.gates_per_opcode, opcode_idx);
77 }
78
79 // Add aes128 constraints
80 for (const auto& [constraint, opcode_idx] :
83 gate_counter.track_diff(constraints.gates_per_opcode, opcode_idx);
84 }
85
86 // Add sha256 constraints
87 for (const auto& [constraint, opcode_idx] :
90 gate_counter.track_diff(constraints.gates_per_opcode, opcode_idx);
91 }
92
93 // Add ECDSA k1 constraints
94 for (const auto& [constraint, opcode_idx] :
96 create_ecdsa_verify_constraints<stdlib::secp256k1<Builder>>(builder, constraint);
97 gate_counter.track_diff(constraints.gates_per_opcode, opcode_idx);
98 }
99
100 // Add ECDSA r1 constraints
101 for (const auto& [constraint, opcode_idx] :
103 create_ecdsa_verify_constraints<stdlib::secp256r1<Builder>>(builder, constraint);
104 gate_counter.track_diff(constraints.gates_per_opcode, opcode_idx);
105 }
106
107 // Add blake2s constraints
108 for (const auto& [constraint, opcode_idx] :
111 gate_counter.track_diff(constraints.gates_per_opcode, opcode_idx);
112 }
113
114 // Add blake3 constraints
115 for (const auto& [constraint, opcode_idx] :
118 gate_counter.track_diff(constraints.gates_per_opcode, opcode_idx);
119 }
120
121 // Add keccak permutations
122 for (const auto& [constraint, opcode_idx] :
125 gate_counter.track_diff(constraints.gates_per_opcode, opcode_idx);
126 }
127
128 // Add poseidon2 constraints
129 for (const auto& [constraint, opcode_idx] :
132 gate_counter.track_diff(constraints.gates_per_opcode, opcode_idx);
133 }
134
135 // Add multi scalar mul constraints
136 for (const auto& [constraint, opcode_idx] :
140 gate_counter.track_diff(constraints.gates_per_opcode, opcode_idx);
141 }
142
143 // Add ec add constraints
144 for (const auto& [constraint, opcode_idx] :
147 gate_counter.track_diff(constraints.gates_per_opcode, opcode_idx);
148 }
149
150 // Add block constraints
151 for (const auto& [constraint, opcode_indices] :
154 if (collect_gates_per_opcode) {
155 // Each block constraint may correspond to multiple opcodes, so we record the average number of gates added
156 // by the entire constraint as the number of gates for each opcode.
157 size_t avg_gates_per_opcode = gate_counter.compute_diff() / opcode_indices.size();
158 for (size_t opcode_index : opcode_indices) {
159 constraints.gates_per_opcode[opcode_index] = avg_gates_per_opcode;
160 }
161 }
162 }
163
164 // RecursionConstraints
165 const bool is_hn_recursion_constraints = !constraints.hn_recursion_constraints.empty();
166 HonkRecursionConstraintsOutput<Builder> output = create_recursion_constraints<Builder>(
167 builder,
168 gate_counter,
169 constraints.gates_per_opcode,
170 metadata.ivc,
171 /*honk_recursion_data=*/
172 { constraints.honk_recursion_constraints, constraints.original_opcode_indices.honk_recursion_constraints },
173 /*avm_recursion_data=*/
174 { constraints.avm_recursion_constraints, constraints.original_opcode_indices.avm_recursion_constraints },
175 /*hn_recursion_data=*/
176 { constraints.hn_recursion_constraints, constraints.original_opcode_indices.hn_recursion_constraints },
177 /*chonk_recursion_data=*/
178 { constraints.chonk_recursion_constraints, constraints.original_opcode_indices.chonk_recursion_constraints });
179
180 // Process the result of adding recursion constraints and propagate the public inputs as needed
181 output.finalize(builder, is_hn_recursion_constraints, metadata.has_ipa_claim);
182}
183
190template <> UltraCircuitBuilder create_circuit(AcirProgram& program, const ProgramMetadata& metadata)
191{
192 BB_BENCH();
193 AcirFormat& constraints = program.constraints;
194 WitnessVector& witness = program.witness;
195 const bool is_write_vk_mode = witness.empty();
196
197 if (!is_write_vk_mode) {
198 BB_ASSERT_EQ(witness.size(),
199 constraints.max_witness_index + 1,
200 "ACIR witness size (" << witness.size() << ") does not match max witness index + 1 ("
201 << (constraints.max_witness_index + 1) << ").");
202 } else {
203 witness.resize(constraints.max_witness_index + 1, 0);
204 }
205
206 UltraCircuitBuilder builder{ witness, constraints.public_inputs, is_write_vk_mode };
207
208 // Populate constraints in the builder
209 build_constraints(builder, constraints, metadata);
210
211 vinfo("Created circuit");
212
213 return builder;
214};
215
222template <> MegaCircuitBuilder create_circuit(AcirProgram& program, const ProgramMetadata& metadata)
223{
224 BB_BENCH();
225 AcirFormat& constraints = program.constraints;
226 WitnessVector& witness = program.witness;
227 const bool is_write_vk_mode = witness.empty();
228
229 if (!is_write_vk_mode) {
230 BB_ASSERT_EQ(witness.size(),
231 constraints.max_witness_index + 1,
232 "ACIR witness size (" << witness.size() << ") does not match max witness index + 1 ("
233 << (constraints.max_witness_index + 1) << ").");
234 } else {
235 witness.resize(constraints.max_witness_index + 1, 0);
236 }
237
238 auto op_queue = (metadata.ivc == nullptr) ? std::make_shared<ECCOpQueue>() : metadata.ivc->get_goblin().op_queue;
239
240 // Construct a builder using the witness and public input data from acir and with the goblin-owned op_queue
241 MegaCircuitBuilder builder{ op_queue, witness, constraints.public_inputs, is_write_vk_mode };
242
243 // Populate constraints in the builder
244 build_constraints(builder, constraints, metadata);
245
246 vinfo("Created circuit");
247
248 return builder;
249};
250
253
254} // namespace acir_format
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:93
#define BB_BENCH()
Definition bb_bench.hpp:223
Shared type definitions for the Barretenberg RPC API.
Utility class for tracking the gate count of acir constraints.
#define vinfo(...)
Definition log.hpp:94
AluTraceBuilder builder
Definition alu.test.cpp:124
Base class templates for structures that contain data parameterized by the fundamental polynomials of...
void create_big_quad_constraint(Builder &builder, BigQuadConstraint &big_constraint)
template void build_constraints< MegaCircuitBuilder >(MegaCircuitBuilder &, AcirFormat &, const ProgramMetadata &)
template void build_constraints< UltraCircuitBuilder >(UltraCircuitBuilder &, AcirFormat &, const ProgramMetadata &)
void create_blake3_constraints(Builder &builder, const Blake3Constraint &constraint)
std::vector< bb::fr > WitnessVector
void create_keccak_permutations_constraints(Builder &builder, const Keccakf1600 &constraint)
void create_ec_add_constraint(Builder &builder, const EcAdd &input)
Create constraints for addition of two points on the Grumpkin curve.
void build_constraints(Builder &builder, AcirFormat &constraints, const ProgramMetadata &metadata)
Add to the builder the constraints contained in an AcirFormat instance.
void create_blake2s_constraints(Builder &builder, const Blake2sConstraint &constraint)
void create_block_constraints(UltraCircuitBuilder &builder, const BlockConstraint &constraint)
Create block constraints; Specialization for Ultra arithmetization.
UltraCircuitBuilder create_circuit(AcirProgram &program, const ProgramMetadata &metadata)
Specialization for creating an Ultra circuit from an acir program.
void create_sha256_compression_constraints(Builder &builder, const Sha256Compression &constraint)
void create_aes128_constraints(Builder &builder, const AES128Constraint &constraint)
void create_multi_scalar_mul_constraint(Builder &builder, const MultiScalarMul &constraint_input)
Create constraints for multi-scalar multiplication on the Grumpkin curve.
void create_poseidon2_permutations_constraints(Builder &builder, const Poseidon2Constraint &constraint)
void create_quad_constraint(Builder &builder, QuadConstraint &mul_quad)
Create a simple width-4 Ultra arithmetic gate constraint representing the equation.
void create_logic_gate(Builder &builder, const WitnessOrConstant< bb::fr > a, const WitnessOrConstant< bb::fr > b, const uint32_t result, const size_t num_bits, const bool is_xor_gate)
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Barretenberg's representation of ACIR constraints.
std::vector< MultiScalarMul > multi_scalar_mul_constraints
std::vector< Blake2sConstraint > blake2s_constraints
std::vector< Sha256Compression > sha256_compression
std::vector< Poseidon2Constraint > poseidon2_constraints
std::vector< LogicConstraint > logic_constraints
std::vector< EcAdd > ec_add_constraints
std::vector< QuadConstraint > quad_constraints
std::vector< Keccakf1600 > keccak_permutations
std::vector< Blake3Constraint > blake3_constraints
std::vector< EcdsaConstraint > ecdsa_r1_constraints
std::vector< RangeConstraint > range_constraints
std::vector< BigQuadConstraint > big_quad_constraints
std::vector< AES128Constraint > aes128_constraints
AcirFormatOriginalOpcodeIndices original_opcode_indices
std::vector< BlockConstraint > block_constraints
std::vector< EcdsaConstraint > ecdsa_k1_constraints
std::vector< RecursionConstraint > hn_recursion_constraints
std::vector< uint32_t > public_inputs
std::vector< size_t > gates_per_opcode
std::vector< std::vector< size_t > > block_constraints
Struct containing both the constraints to be added to the circuit and the witness vector.
Container for the output of multiple recursive verifications.
void finalize(Builder &builder, bool is_hn_recursion_constraints=false, bool has_ipa_claim=false)
Finalize the output by accumulating IPA claims/proofs, performing full IPA verification,...
Metadata required to create a circuit.
std::shared_ptr< bb::IVCBase > ivc