Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
translator_circuit_builder.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#pragma once
14
15namespace bb {
70
71 // The scalar field of BN254
72 using Fr = bb::fr;
73 // The base (coordinate) field of BN254
74 using Fq = bb::fq;
75
76 public:
77 static constexpr size_t NUM_WIRES = 81;
78 static constexpr size_t NUM_SELECTORS = 0;
79
84 void create_add_gate(const add_triple_<Fr>&) override {};
85 void create_mul_gate(const mul_triple_<Fr>&) override {};
86 void create_bool_gate(const uint32_t) override {};
87 void create_poly_gate(const poly_triple_<Fr>&) override {};
88 [[nodiscard]] size_t get_num_constant_gates() const override { return 0; };
89
93 enum WireIds : size_t {
94 OP, // The first 4 wires contain the standard values from the EccQueue wire
98 P_X_LOW_LIMBS, // P.xₗₒ split into 2 68 bit limbs
99 P_X_HIGH_LIMBS, // P.xₕᵢ split into a 68 and a 50 bit limb
100 P_Y_LOW_LIMBS, // P.yₗₒ split into 2 68 bit limbs
101 P_Y_HIGH_LIMBS, // P.yₕᵢ split into a 68 and a 50 bit limb
102 Z_LOW_LIMBS, // Low limbs of z_1 and z_2 (68 bits each)
103 Z_HIGH_LIMBS, // High Limbs of z_1 and z_2 (60 bits each)
104 ACCUMULATORS_BINARY_LIMBS_0, // Contain 68-bit limbs of current and previous accumulator (previous at higher
105 // indices because of the nuances of KZG commitment).
108 ACCUMULATORS_BINARY_LIMBS_3, // Highest limb is 50 bits (254 mod 68) P_X_LOW_LIMBS_RANGE_CONSTRAINT_0, // Low
109 // limbs split further into smaller chunks for range constraints
110 QUOTIENT_LOW_BINARY_LIMBS, // Quotient limbs
112 RELATION_WIDE_LIMBS, // Limbs for checking the correctness of mod 2²⁷² relations.
113 P_X_LOW_LIMBS_RANGE_CONSTRAINT_0, // Low limbs split further into smaller chunks for range constraints
119 P_X_HIGH_LIMBS_RANGE_CONSTRAINT_0, // High limbs split into chunks for range constraints
125 P_Y_LOW_LIMBS_RANGE_CONSTRAINT_0, // Low limbs split into chunks for range constraints
131 P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_0, // High limbs split into chunks for range constraints
137 Z_LOW_LIMBS_RANGE_CONSTRAINT_0, // Range constraints for low limbs of z_1 and z_2
143 Z_HIGH_LIMBS_RANGE_CONSTRAINT_0, // Range constraints for high limbs of z_1 and z_2
149
150 ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_0, // Range constraints for the current accumulator limbs (no need to
151 // redo previous accumulator)
163
164 QUOTIENT_LOW_LIMBS_RANGE_CONSTRAIN_0, // Range constraints for quotient
180
182
183 };
184
185 // Basic goblin translator has the minimum minicircuit size of 2048, so optimize for that case
186 // For context, minicircuit is the part of the final polynomials fed into the proving system, where we have all the
187 // arithmetic logic. However, the full circuit is several times larger (we use a trick to bring down the degree of
188 // the permutation argument)
189 static constexpr size_t DEFAULT_TRANSLATOR_VM_LENGTH = 2048;
190
191 // Maximum size of a single limb is 68 bits
192 static constexpr size_t NUM_LIMB_BITS = 68;
193
194 // For soundness we need to constrain the highest limb so that the whole value is at most 50 bits
195 static constexpr size_t NUM_LAST_LIMB_BITS = Fq::modulus.get_msb() + 1 - 3 * NUM_LIMB_BITS;
196
197 // 128-bit z_1 and z_2 are split into 2 limbs each
198 static constexpr size_t NUM_Z_LIMBS = 2;
199
200 // Number of bits in the quotient representation
201 static constexpr size_t NUM_QUOTIENT_BITS = 256;
202
203 // Number of bits in the quotient highest limb
204 static constexpr size_t NUM_LAST_QUOTIENT_LIMB_BITS = 256 - 3 * NUM_LIMB_BITS;
205
206 // Number of bits in Z scalars
207 static constexpr size_t NUM_Z_BITS = 128;
208 // The circuit builder has a default range constraint mechanism that is used throughout. It range cosntrains the
209 // values to < 2¹⁴
210 static constexpr size_t MICRO_LIMB_BITS = 14;
211
212 // Maximum size of a micro limb used for range constraints
213 static constexpr auto MAX_MICRO_LIMB_SIZE = (uint256_t(1) << MICRO_LIMB_BITS) - 1;
214
215 // To range constrain a limb to 68 bits we need 6 limbs: 5 for 14-bit windowed chunks and 1 to range constrain the
216 // highest to a more restrictive range (0 <= a < 2¹⁴ && 0 <= 4*a < 2¹⁴ ) ~ ( 0 <= a < 2¹² )
217 static constexpr size_t NUM_MICRO_LIMBS = 6;
218
219 // Number of limbs used to decompose a 254-bit value for modular arithmetic. This will represent an Fq value as 4 Fr
220 // limbs to be representable inside a circuit defined overF r.
221 static constexpr size_t NUM_BINARY_LIMBS = 4;
222
223 // Number of limbs used for computation of a result modulo 2²⁷²
224 static constexpr size_t NUM_RELATION_WIDE_LIMBS = 2;
225
226 // Range constraint of relation limbs
227 static constexpr size_t RELATION_WIDE_LIMB_BITS = 84;
228
229 // Maximum size of each relation limb (in accordance with range constraints)
231
232 // Shift of a single micro (range constraint) limb
233 static constexpr auto MICRO_SHIFT = uint256_t(1) << MICRO_LIMB_BITS;
234
235 // Maximum size of 2 lower limbs concatenated
236 static constexpr auto MAX_LOW_WIDE_LIMB_SIZE = (uint256_t(1) << (NUM_LIMB_BITS * 2)) - 1;
237
238 // Maximum size of 2 higher limbs concatenated
239 static constexpr auto MAX_HIGH_WIDE_LIMB_SIZE = (uint256_t(1) << (NUM_LIMB_BITS + NUM_LAST_LIMB_BITS)) - 1;
240
241 // Index at which the accumulation result is stored in the circuit, preceeded by one no-op that ensures translator
242 // polynomials are shiftable and three random ops that contribute to ensuring the Translator proof does not leak
243 // information about the op queue content linked to the circuits being proven
244 static constexpr size_t RESULT_ROW = 8;
245 static constexpr size_t NUM_NO_OPS_START = 1;
246
247 // Number of random ops at the beginning of Translator trace
248 static constexpr size_t NUM_RANDOM_OPS_START = 3;
249 static_assert(NUM_RANDOM_OPS_START == 3);
250
251 // Number of random ops at the end of Translator trace
252 static constexpr size_t NUM_RANDOM_OPS_END = 2;
253 static_assert(NUM_RANDOM_OPS_END == 2);
254
255 // How much you'd need to multiply a value by to perform a shift to a higher binary limb
256 static constexpr auto SHIFT_1 = uint256_t(1) << NUM_LIMB_BITS;
257
258 // Shift by 2 binary limbs
259 static constexpr auto SHIFT_2 = uint256_t(1) << (NUM_LIMB_BITS << 1);
260
261 // Precomputed inverse to easily divide by the shift by 2 limbs
262 static constexpr auto SHIFT_2_INVERSE = Fr(SHIFT_2).invert();
263
264 // Shift by 3 binary limbs
265 static constexpr auto SHIFT_3 = uint256_t(1) << (NUM_LIMB_BITS * 3);
266
267 // The modulus of the target emulated field as a 512-bit integer
269
270 // The binary modulus used in the CRT computation
271 static constexpr uint512_t BINARY_BASIS_MODULUS = uint512_t(1) << (NUM_LIMB_BITS << 2);
272
273 // Negated modulus of the target emulated field in the binary modulus
275
276 // Negated modulus of the target emulated field in the binary modulus split into 4 binary limbs + the final limb is
277 // the negated modulus of the target emulated field in the scalar field
285
315
316 static constexpr std::string_view NAME_STRING = "TranslatorCircuitBuilder";
317
318 // The challenge that is used for batching together evaluations of several polynomials
320
321 // The input we evaluate polynomials on
323
324 bool avm_mode = false;
325
327
336 TranslatorCircuitBuilder(Fq batching_challenge_v_, Fq evaluation_input_x_, bool avm_mode_ = false)
338 , batching_challenge_v(batching_challenge_v_)
339 , evaluation_input_x(evaluation_input_x_)
340 , avm_mode(avm_mode_)
341 {
343 };
344
355 TranslatorCircuitBuilder(Fq batching_challenge_v_,
356 Fq evaluation_input_x_,
358 bool avm_mode = false)
359 : TranslatorCircuitBuilder(batching_challenge_v_, evaluation_input_x_, avm_mode)
360
361 {
362 BB_BENCH_NAME("TranslatorCircuitBuilder::constructor");
364 }
365
372 {
374 return *this;
375 };
376 ~TranslatorCircuitBuilder() override = default;
377
385 {
386 uint256_t base_uint = base;
388 Fr(base_uint.slice(0, NUM_LIMB_BITS)),
389 Fr(base_uint.slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS)),
390 Fr(base_uint.slice(2 * NUM_LIMB_BITS, 3 * NUM_LIMB_BITS)),
391 Fr(base_uint.slice(3 * NUM_LIMB_BITS, 4 * NUM_LIMB_BITS)),
392 });
393 }
394
395 static void assert_well_formed_ultra_op(const UltraOp& ultra_op);
396
405 static void assert_well_formed_accumulation_input(const AccumulationInput& acc_step);
406
415 void create_accumulation_gate(const AccumulationInput& acc_step);
416
417 void populate_wires_from_ultra_op(const UltraOp& ultra_op);
418
419 void insert_pair_into_wire(WireIds wire_index, Fr first, Fr second)
420 {
421 auto& current_wire = wires[wire_index];
422 current_wire.push_back(add_variable(first));
423 current_wire.push_back(add_variable(second));
424 }
425
432
433 static AccumulationInput generate_witness_values(const UltraOp& ultra_op,
434 const Fq& previous_accumulator,
436 const Fq& evaluation_input_x);
437};
438
439} // namespace bb
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:218
virtual uint32_t add_variable(const FF &in)
CircuitBuilderBase & operator=(const CircuitBuilderBase &other)=default
TranslatorCircuitBuilder creates a circuit that evaluates the correctness of the evaluation of EccOpQ...
size_t get_num_constant_gates() const override
TranslatorCircuitBuilder(Fq batching_challenge_v_, Fq evaluation_input_x_, std::shared_ptr< ECCOpQueue > op_queue, bool avm_mode=false)
Construct a new Translator Circuit Builder object and feed op_queue inside.
static constexpr std::array< Fr, 5 > NEGATIVE_MODULUS_LIMBS
static AccumulationInput generate_witness_values(const UltraOp &ultra_op, const Fq &previous_accumulator, const Fq &batching_challenge_v, const Fq &evaluation_input_x)
Given the transcript values from the EccOpQueue, the values of the previous accumulator,...
TranslatorCircuitBuilder(Fq batching_challenge_v_, Fq evaluation_input_x_, bool avm_mode_=false)
Construct a new Translator Circuit Builder object.
TranslatorCircuitBuilder(TranslatorCircuitBuilder &&other) noexcept
void feed_ecc_op_queue_into_circuit(const std::shared_ptr< ECCOpQueue > &ecc_op_queue)
Generate all the gates required to prove the correctness of batched evalution of column polynomials r...
static void assert_well_formed_ultra_op(const UltraOp &ultra_op)
void create_accumulation_gate(const AccumulationInput &acc_step)
Create a single accumulation gate.
static std::array< Fr, NUM_BINARY_LIMBS > split_fq_into_limbs(const Fq &base)
A small function to transform a native element Fq into its bigfield representation in Fr scalars.
static constexpr size_t RELATION_WIDE_LIMB_BITS
static constexpr uint512_t BINARY_BASIS_MODULUS
static constexpr size_t NUM_LAST_QUOTIENT_LIMB_BITS
static constexpr size_t DEFAULT_TRANSLATOR_VM_LENGTH
~TranslatorCircuitBuilder() override=default
static constexpr std::string_view NAME_STRING
static constexpr uint256_t MAX_RELATION_WIDE_LIMB_SIZE
static constexpr uint512_t NEGATIVE_PRIME_MODULUS
TranslatorCircuitBuilder & operator=(TranslatorCircuitBuilder &&other) noexcept
std::array< SlabVector< uint32_t >, NUM_WIRES > wires
void populate_wires_from_ultra_op(const UltraOp &ultra_op)
void create_add_gate(const add_triple_< Fr > &) override
void create_mul_gate(const mul_triple_< Fr > &) override
static void assert_well_formed_accumulation_input(const AccumulationInput &acc_step)
Ensures the accumulation input is well-formed and can be used to create a gate.
TranslatorCircuitBuilder & operator=(const TranslatorCircuitBuilder &other)=delete
static constexpr size_t NUM_RELATION_WIDE_LIMBS
TranslatorCircuitBuilder(const TranslatorCircuitBuilder &other)=delete
void create_poly_gate(const poly_triple_< Fr > &) override
WireIds
There are so many wires that naming them has no sense, it is easier to access them with enums.
void create_bool_gate(const uint32_t) override
void insert_pair_into_wire(WireIds wire_index, Fr first, Fr second)
constexpr uint256_t slice(uint64_t start, uint64_t end) const
constexpr uint64_t get_msb() const
constexpr uintx slice(const uint64_t start, const uint64_t end) const
Definition uintx.hpp:82
uintx< uint256_t > uint512_t
Definition uintx.hpp:307
Entry point for Barretenberg command-line interface.
field< Bn254FqParams > fq
Definition fq.hpp:169
field< Bn254FrParams > fr
Definition fr.hpp:174
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
The accumulation input structure contains all the necessary values to initalize an accumulation gate ...
std::array< std::array< Fr, NUM_MICRO_LIMBS >, NUM_Z_LIMBS > z_1_microlimbs
std::array< std::array< Fr, NUM_MICRO_LIMBS >, NUM_BINARY_LIMBS > P_y_microlimbs
std::array< std::array< Fr, NUM_MICRO_LIMBS >, NUM_BINARY_LIMBS > current_accumulator_microlimbs
std::array< std::array< Fr, NUM_MICRO_LIMBS >, 2 > relation_wide_microlimbs
std::array< std::array< Fr, NUM_MICRO_LIMBS >, NUM_BINARY_LIMBS > P_x_microlimbs
std::array< std::array< Fr, NUM_MICRO_LIMBS >, NUM_BINARY_LIMBS > quotient_microlimbs
std::array< std::array< Fr, NUM_MICRO_LIMBS >, NUM_Z_LIMBS > z_2_microlimbs
std::array< Fr, NUM_RELATION_WIDE_LIMBS > relation_wide_limbs
static constexpr uint256_t modulus
constexpr field invert() const noexcept
static constexpr field zero()