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: Planned, auditors: [], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
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
80 [[nodiscard]] size_t get_num_constant_gates() const override { return 0; };
81
85 enum WireIds : uint8_t {
86 OP, // The first 4 wires contain the standard values from the EccQueue wire
90 P_X_LOW_LIMBS, // P.xₗₒ split into 2 68 bit limbs
91 P_X_HIGH_LIMBS, // P.xₕᵢ split into a 68 and a 50 bit limb
92 P_Y_LOW_LIMBS, // P.yₗₒ split into 2 68 bit limbs
93 P_Y_HIGH_LIMBS, // P.yₕᵢ split into a 68 and a 50 bit limb
94 Z_LOW_LIMBS, // Low limbs of z_1 and z_2 (68 bits each)
95 Z_HIGH_LIMBS, // High Limbs of z_1 and z_2 (60 bits each)
96 ACCUMULATORS_BINARY_LIMBS_0, // Contain 68-bit limbs of current and previous accumulator (previous at higher
97 // indices because of the nuances of KZG commitment).
100 ACCUMULATORS_BINARY_LIMBS_3, // Highest limb is 50 bits (254 mod 68) P_X_LOW_LIMBS_RANGE_CONSTRAINT_0, // Low
101 // limbs split further into smaller chunks for range constraints
102 QUOTIENT_LOW_BINARY_LIMBS, // Quotient limbs
104 RELATION_WIDE_LIMBS, // Limbs for checking the correctness of mod 2²⁷² relations.
105 P_X_LOW_LIMBS_RANGE_CONSTRAINT_0, // Low limbs split further into smaller chunks for range constraints
111 P_X_HIGH_LIMBS_RANGE_CONSTRAINT_0, // High limbs split into chunks for range constraints
117 P_Y_LOW_LIMBS_RANGE_CONSTRAINT_0, // Low limbs split into chunks for range constraints
123 P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_0, // High limbs split into chunks for range constraints
129 Z_LOW_LIMBS_RANGE_CONSTRAINT_0, // Range constraints for low limbs of z_1 and z_2
135 Z_HIGH_LIMBS_RANGE_CONSTRAINT_0, // Range constraints for high limbs of z_1 and z_2
141
142 ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_0, // Range constraints for the current accumulator limbs (no need to
143 // redo previous accumulator)
155
156 QUOTIENT_LOW_LIMBS_RANGE_CONSTRAIN_0, // Range constraints for quotient
172
174
175 };
176
177 // Basic goblin translator has the minimum minicircuit size of 2048, so optimize for that case
178 // For context, minicircuit is the part of the final polynomials fed into the proving system, where we have all the
179 // arithmetic logic. However, the full circuit is several times larger (we use a trick to bring down the degree of
180 // the permutation argument)
181 static constexpr size_t DEFAULT_TRANSLATOR_VM_LENGTH = 2048;
182
183 // Maximum size of a single limb is 68 bits
184 static constexpr size_t NUM_LIMB_BITS = 68;
185
186 // For soundness we need to constrain the highest limb so that the whole value is at most 50 bits
187 static constexpr size_t NUM_LAST_LIMB_BITS = Fq::modulus.get_msb() + 1 - (3 * NUM_LIMB_BITS);
188
189 // 128-bit z_1 and z_2 are split into 2 limbs each
190 static constexpr size_t NUM_Z_LIMBS = 2;
191
192 // Number of bits in the quotient representation
193 static constexpr size_t NUM_QUOTIENT_BITS = 256;
194
195 // Number of bits in the quotient highest limb
196 static constexpr size_t NUM_LAST_QUOTIENT_LIMB_BITS = 256 - (3 * NUM_LIMB_BITS);
197
198 // Number of bits in Z scalars
199 static constexpr size_t NUM_Z_BITS = 128;
200 // The circuit builder has a default range constraint mechanism that is used throughout. It range cosntrains the
201 // values to < 2¹⁴
202 static constexpr size_t MICRO_LIMB_BITS = 14;
203
204 // Maximum size of a micro limb used for range constraints
205 static constexpr auto MAX_MICRO_LIMB_SIZE = (uint256_t(1) << MICRO_LIMB_BITS) - 1;
206
207 // To range constrain a limb to 68 bits we need 6 limbs: 5 for 14-bit windowed chunks and 1 to range constrain the
208 // highest to a more restrictive range (0 <= a < 2¹⁴ && 0 <= 4*a < 2¹⁴ ) ~ ( 0 <= a < 2¹² )
209 static constexpr size_t NUM_MICRO_LIMBS = 6;
210
211 // Number of limbs used to decompose a 254-bit value for modular arithmetic. This will represent an Fq value as 4 Fr
212 // limbs to be representable inside a circuit defined overF r.
213 static constexpr size_t NUM_BINARY_LIMBS = 4;
214
215 // Number of limbs used for computation of a result modulo 2²⁷²
216 static constexpr size_t NUM_RELATION_WIDE_LIMBS = 2;
217
218 // Range constraint of relation limbs
219 static constexpr size_t RELATION_WIDE_LIMB_BITS = 84;
220
221 // Maximum size of each relation limb (in accordance with range constraints)
223
224 // Shift of a single micro (range constraint) limb
225 static constexpr auto MICRO_SHIFT = uint256_t(1) << MICRO_LIMB_BITS;
226
227 // Maximum size of 2 lower limbs concatenated
228 static constexpr auto MAX_LOW_WIDE_LIMB_SIZE = (uint256_t(1) << (NUM_LIMB_BITS * 2)) - 1;
229
230 // Maximum size of 2 higher limbs concatenated
231 static constexpr auto MAX_HIGH_WIDE_LIMB_SIZE = (uint256_t(1) << (NUM_LIMB_BITS + NUM_LAST_LIMB_BITS)) - 1;
232
233 // Maximum size of z limbs
234 static constexpr auto MAX_Z_LIMB_SIZE = (uint256_t(1) << NUM_Z_BITS) - 1;
235
236 // Index at which the accumulation result is stored in the circuit, preceeded by one no-op that ensures translator
237 // polynomials are shiftable and three random ops that contribute to ensuring the Translator proof does not leak
238 // information about the op queue content linked to the circuits being proven
239 static constexpr size_t RESULT_ROW = 8;
240 static constexpr size_t NUM_NO_OPS_START = 1;
241
242 // Number of random ops at the beginning of Translator trace
243 static constexpr size_t NUM_RANDOM_OPS_START = 3;
244 static_assert(NUM_RANDOM_OPS_START == 3);
245
246 // Number of random ops at the end of Translator trace
247 static constexpr size_t NUM_RANDOM_OPS_END = 2;
248 static_assert(NUM_RANDOM_OPS_END == 2);
249
250 // How much you'd need to multiply a value by to perform a shift to a higher binary limb
251 static constexpr auto SHIFT_1 = uint256_t(1) << NUM_LIMB_BITS;
252
253 // Shift by 2 binary limbs
254 static constexpr auto SHIFT_2 = uint256_t(1) << (NUM_LIMB_BITS << 1);
255
256 // Precomputed inverse to easily divide by the shift by 2 limbs
257 static constexpr auto SHIFT_2_INVERSE = Fr(SHIFT_2).invert();
258
259 // Shift by 3 binary limbs
260 static constexpr auto SHIFT_3 = uint256_t(1) << (NUM_LIMB_BITS * 3);
261
262 // The modulus of the target emulated field as a 512-bit integer
264
265 // The binary modulus used in the CRT computation (2²⁷²)
266 static constexpr uint512_t BINARY_BASIS_MODULUS = uint512_t(1) << (NUM_LIMB_BITS << 2);
267
268 // Negated modulus of the target emulated field in the binary modulus (2²⁷² - q)
270
271 // Negated modulus of the target emulated field in the binary modulus split into 4 binary limbs + the final limb is
272 // the negated modulus of the target emulated field in the scalar field
280
310
311 static constexpr std::string_view NAME_STRING = "TranslatorCircuitBuilder";
312
313 // The challenge that is used for batching together evaluations of several polynomials
315
316 // The input we evaluate polynomials on
318
319 bool avm_mode = false;
320
322
331 TranslatorCircuitBuilder(Fq batching_challenge_v_, Fq evaluation_input_x_, bool avm_mode_ = false)
332 : batching_challenge_v(batching_challenge_v_)
333 , evaluation_input_x(evaluation_input_x_)
334 , avm_mode(avm_mode_)
335 {
337 };
338
349 TranslatorCircuitBuilder(Fq batching_challenge_v_,
350 Fq evaluation_input_x_,
352 bool avm_mode = false)
353 : TranslatorCircuitBuilder(batching_challenge_v_, evaluation_input_x_, avm_mode)
354
355 {
356 BB_BENCH_NAME("TranslatorCircuitBuilder::constructor");
358 }
359
366 {
368 return *this;
369 };
370 ~TranslatorCircuitBuilder() override = default;
371
380 {
381 uint256_t base_uint = base;
383 Fr(base_uint.slice(0, NUM_LIMB_BITS)),
384 Fr(base_uint.slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS)),
385 Fr(base_uint.slice(2 * NUM_LIMB_BITS, 3 * NUM_LIMB_BITS)),
386 Fr(base_uint.slice(3 * NUM_LIMB_BITS, 4 * NUM_LIMB_BITS)),
387 });
388 }
389
398 static void assert_well_formed_ultra_op(const UltraOp& ultra_op);
399
409 static void assert_well_formed_accumulation_input(const AccumulationInput& acc_step);
410
419 void create_accumulation_gate(const AccumulationInput& acc_step);
420
421 void populate_wires_from_ultra_op(const UltraOp& ultra_op);
422
423 void insert_pair_into_wire(WireIds wire_index, Fr first, Fr second)
424 {
425 auto& current_wire = wires[wire_index];
426 current_wire.push_back(add_variable(first));
427 current_wire.push_back(add_variable(second));
428 }
429
436
437 static AccumulationInput generate_witness_values(const UltraOp& ultra_op,
438 const Fq& previous_accumulator,
440 const Fq& evaluation_input_x);
441};
442
443} // namespace bb
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:225
virtual uint32_t add_variable(const FF &in)
Add a variable to variables.
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)
Ensures the ultra op is well-formed and can be used to create a gate.
WireIds
There are so many wires that naming them has no sense, it is easier to access them with enums.
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
void populate_wires_from_ultra_op(const UltraOp &ultra_op)
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.
std::array< std::vector< uint32_t >, NUM_WIRES > wires
TranslatorCircuitBuilder & operator=(const TranslatorCircuitBuilder &other)=delete
static constexpr size_t NUM_RELATION_WIDE_LIMBS
TranslatorCircuitBuilder(const TranslatorCircuitBuilder &other)=delete
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:81
uintx< uint256_t > uint512_t
Definition uintx.hpp:306
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
field< Bn254FqParams > fq
Definition fq.hpp:153
field< Bn254FrParams > fr
Definition fr.hpp:155
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_RELATION_WIDE_LIMBS > relation_wide_microlimbs
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 >, 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()