20#include <unordered_set>
28 std::array<uint32_t, 4>
a;
29 std::array<uint32_t, 4>
b;
30 std::array<uint32_t, 4>
q;
31 std::array<uint32_t, 4>
r;
37 std::array<uint32_t, 4>
a;
38 std::array<uint32_t, 4>
b;
41template <
typename ExecutionTrace_>
45 using FF =
typename ExecutionTrace::FF;
48 static constexpr size_t NUM_WIRES = ExecutionTrace::NUM_WIRES;
52 static constexpr std::string_view
NAME_STRING =
"UltraCircuitBuilder";
106 std::array<uint32_t, 4>
a;
107 std::array<uint32_t, 4>
b;
115 for (
size_t i = 0; i < 4; ++i) {
116 valid = valid && (
a[i] == other.
a[i]);
117 valid = valid && (
b[i] == other.
b[i]);
138 for (
const auto& item : vec) {
139 auto [existing_element, not_in_set] = seen.insert(item);
142 uniqueVec.push_back(item);
145 circuit_builder->
assert_equal(item.lo_0, (*existing_element).lo_0);
146 circuit_builder->
assert_equal(item.hi_0, (*existing_element).hi_0);
147 circuit_builder->
assert_equal(item.hi_1, (*existing_element).hi_1);
171 size_t combined_hash = 0;
178 auto hash_combiner = [](
size_t lhs,
size_t rhs) {
179 return lhs ^ (rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2));
182 for (
const auto& elem : obj.
a) {
185 for (
const auto& elem : obj.
b) {
189 return combined_hash;
237 this->
tau.insert({ DUMMY_TAG, DUMMY_TAG });
254 auto& witness_values,
257 bool recursive =
false)
260 for (
size_t idx = 0; idx < varnum; ++idx) {
263 auto value = idx < witness_values.size() ? witness_values[idx] : 0;
273 this->
tau.insert({ DUMMY_TAG, DUMMY_TAG });
333 for (
auto& block :
blocks.get()) {
334 const auto& block_selectors = block.get_selectors();
335 size_t nominal_size = block_selectors[0].size();
336 for (
size_t idx = 1; idx < block_selectors.size(); ++idx) {
337 ASSERT_DEBUG(block_selectors[idx].size() == nominal_size);
361 void fix_witness(
const uint32_t witness_index,
const FF& witness_value);
364 const uint64_t target_range,
365 std::string
const msg =
"create_new_range_constraint");
420 size_t& count,
size_t& rangecount,
size_t& romcount,
size_t& ramcount,
size_t& nnfcount)
const
437 std::vector<size_t> ram_timestamps;
438 std::vector<size_t> ram_range_sizes;
439 std::vector<size_t> ram_range_exists;
455 ram_timestamps.push_back(max_timestamp);
460 const size_t ram_range_check_list_size = max_timestamp + padding;
462 size_t ram_range_check_gate_count = (ram_range_check_list_size /
NUM_WIRES);
463 ram_range_check_gate_count += 1;
465 ram_range_sizes.push_back(ram_range_check_gate_count);
466 ram_range_exists.push_back(
false);
469 auto list_size = list.second.variable_indices.size();
471 if (list.second.variable_indices.size() ==
NUM_WIRES) {
474 list_size += padding;
476 for (
size_t i = 0; i < ram_timestamps.size(); ++i) {
477 if (list.second.target_range == ram_timestamps[i]) {
478 ram_range_exists[i] =
true;
485 for (
size_t i = 0; i < ram_range_sizes.size(); ++i) {
486 if (!ram_range_exists[i]) {
487 rangecount += ram_range_sizes[i];
493 std::sort(nnf_copy.begin(), nnf_copy.end());
495 auto last = std::unique(nnf_copy.begin(), nnf_copy.end());
496 const size_t num_nnf_ops =
static_cast<size_t>(
std::distance(nnf_copy.begin(), last));
528 if (circuit_finalized) {
532 size_t rangecount = 0;
537 return count + romcount + ramcount + rangecount + nnfcount;
550 builder.add_gates_to_ensure_all_polys_are_non_zero();
551 size_t num_gates_post =
builder.get_estimated_num_finalized_gates();
553 return num_gates_post - num_gates_prior;
562 size_t tables_size = 0;
564 tables_size += table.size();
575 size_t lookups_size = 0;
577 lookups_size += table.lookup_gates.size();
624 size_t rangecount = 0;
630 size_t total = count + romcount + ramcount + rangecount;
631 std::cout <<
"gates = " << total <<
" (arith " << count <<
", rom " << romcount <<
", ram " << ramcount
632 <<
", range " << rangecount <<
", non native field gates " << nnfcount
649 bool (*generator)(std::vector<FF>&, std::vector<FF>&, std::vector<FF>&),
658 const uint32_t key_a_index,
665 const uint32_t variable_index,
666 const uint64_t num_bits,
668 std::string
const& msg =
"decompose_into_default_range");
670 const uint32_t variable_index,
671 const size_t num_bits,
672 std::string
const& msg =
"decompose_into_default_range_better_for_oddlimbnum");
683 auto& block,
const uint32_t& idx_1,
const uint32_t& idx_2,
const uint32_t& idx_3,
const uint32_t& idx_4)
685 block.populate_wires(idx_1, idx_2, idx_3, idx_4);
686 block.q_m().emplace_back(0);
687 block.q_1().emplace_back(0);
688 block.q_2().emplace_back(0);
689 block.q_3().emplace_back(0);
690 block.q_c().emplace_back(0);
691 block.q_arith().emplace_back(0);
692 block.q_4().emplace_back(0);
693 block.q_delta_range().emplace_back(0);
694 block.q_elliptic().emplace_back(0);
695 block.q_lookup_type().emplace_back(0);
696 block.q_memory().emplace_back(0);
697 block.q_nnf().emplace_back(0);
698 block.q_poseidon2_external().emplace_back(0);
699 block.q_poseidon2_internal().emplace_back(0);
702 block.pad_additional();
710 void assign_tag(
const uint32_t variable_index,
const uint32_t tag)
722 uint32_t
create_tag(
const uint32_t tag_index,
const uint32_t tau_index)
724 this->
tau.insert({ tag_index, tau_index });
749 const uint32_t hi_idx,
776 void set_ROM_element(
const size_t rom_id,
const size_t index_value,
const uint32_t value_witness);
778 const size_t index_value,
779 const std::array<uint32_t, 2>& value_witnesses);
781 uint32_t
read_ROM_array(
const size_t rom_id,
const uint32_t index_witness);
782 std::array<uint32_t, 2>
read_ROM_array_pair(
const size_t rom_id,
const uint32_t index_witness);
785 void init_RAM_element(
const size_t ram_id,
const size_t index_value,
const uint32_t value_witness);
787 uint32_t
read_RAM_array(
const size_t ram_id,
const uint32_t index_witness);
788 void write_RAM_array(
const size_t ram_id,
const uint32_t index_witness,
const uint32_t value_witness);
#define BB_ASSERT_EQ(actual, expected,...)
#define BB_ASSERT_LTE(left, right,...)
#define ASSERT(expression,...)
#define ASSERT_DEBUG(expression,...)
virtual uint32_t add_variable(const FF &in)
void failure(std::string msg)
void initialize_public_inputs(const std::vector< uint32_t > &public_inputs)
Directly initialize the public inputs vector.
CircuitBuilderBase & operator=(const CircuitBuilderBase &other)=default
bool operator==(const CircuitBuilderBase &other) const =default
const std::vector< uint32_t > & public_inputs() const
bool is_recursive_circuit
size_t num_public_inputs() const
std::vector< uint32_t > real_variable_tags
virtual void assert_equal(uint32_t a_idx, uint32_t b_idx, std::string const &msg="assert_equal")
FF get_variable(const uint32_t index) const
Get the value of the variable v_{index}.
std::map< uint32_t, uint32_t > tau
std::vector< uint32_t > real_variable_index
ROM/RAM logic handler for UltraCircuitBuilder.
std::vector< RomTranscript > rom_arrays
Each entry in ram_arrays represents an independent ROM table. RomTranscript tracks the current table ...
std::vector< RamTranscript > ram_arrays
Each entry in ram_arrays represents an independent RAM table. RamTranscript tracks the current table ...
void create_add_gate(const add_triple_< FF > &in) override
Create an addition gate, where in.a * in.a_scaling + in.b * in.b_scaling + in.c * in....
void fix_witness(const uint32_t witness_index, const FF &witness_value)
Add a gate equating a particular witness to a constant, fixing its value.
void init_RAM_element(const size_t ram_id, const size_t index_value, const uint32_t value_witness)
Initialize a RAM cell to equal value_witness
size_t get_num_finalized_gates() const override
Get the number of gates in a finalized circuit.
std::map< FF, uint32_t > constant_variable_indices
void create_ecc_dbl_gate(const ecc_dbl_gate_< FF > &in)
Create an elliptic curve doubling gate.
std::map< uint64_t, RangeList > range_lists
void add_gates_to_ensure_all_polys_are_non_zero()
Ensure all polynomials have at least one non-zero coefficient to avoid commiting to the zero-polynomi...
void print_num_estimated_finalized_gates() const override
Print the number and composition of gates in the circuit.
plookup::MultiTable & get_multitable(const plookup::MultiTableId id)
void process_range_list(RangeList &list)
size_t get_lookups_size() const
Get total number of lookups used in circuit.
void create_poseidon2_internal_gate(const poseidon2_internal_gate_< FF > &in)
Poseidon2 internal round gate, activates the q_poseidon2_internal selector and relation.
size_t create_RAM_array(const size_t array_size)
Create a new updatable memory region.
static constexpr size_t DEFAULT_NON_NATIVE_FIELD_LIMB_BITS
bool operator==(const UltraCircuitBuilder_ &other) const
static constexpr uint32_t UNINITIALIZED_MEMORY_RECORD
RomRamLogic_< ExecutionTrace > RomRamLogic
static constexpr size_t GATES_PER_NON_NATIVE_FIELD_MULTIPLICATION_ARITHMETIC
void create_big_mul_gate(const mul_quad_< FF > &in)
Create a basic multiplication gate q_m * a * b + q_1 * a + q_2 * b + q_3 * c + q_4 * d + q_c = 0 (q_a...
UltraCircuitBuilder_ & operator=(const UltraCircuitBuilder_ &other)=default
void create_big_mul_add_gate(const mul_quad_< FF > &in, const bool use_next_gate_w_4=false)
Create a big multiplication-addition gate, where in.a * in.b * in.mul_scaling + in....
void process_range_lists()
static constexpr size_t NUMBER_OF_ARITHMETIC_GATES_PER_RAM_ARRAY
void range_constrain_two_limbs(const uint32_t lo_idx, const uint32_t hi_idx, const size_t lo_limb_bits=DEFAULT_NON_NATIVE_FIELD_LIMB_BITS, const size_t hi_limb_bits=DEFAULT_NON_NATIVE_FIELD_LIMB_BITS)
static constexpr size_t NUM_WIRES
std::vector< uint32_t > decompose_into_default_range(const uint32_t variable_index, const uint64_t num_bits, const uint64_t target_range_bitnum=DEFAULT_PLOOKUP_RANGE_BITNUM, std::string const &msg="decompose_into_default_range")
std::vector< cached_partial_non_native_field_multiplication > cached_partial_non_native_field_multiplications
msgpack::sbuffer export_circuit() override
void create_sort_constraint_with_edges(const std::vector< uint32_t > &variable_index, const FF &, const FF &)
std::vector< plookup::BasicTable > lookup_tables
std::tuple< scaled_witness, scaled_witness, FF > add_simple
uint32_t read_RAM_array(const size_t ram_id, const uint32_t index_witness)
void create_big_add_gate(const add_quad_< FF > &in, const bool use_next_gate_w_4=false)
Create a big addition gate, where in.a * in.a_scaling + in.b * in.b_scaling + in.c * in....
void initialize_precomputed_table(const plookup::BasicTableId id, bool(*generator)(std::vector< FF > &, std::vector< FF > &, std::vector< FF > &), std::array< FF, 2 >(*get_values_from_key)(const std::array< uint64_t, 2 >))
size_t get_num_gates_added_to_ensure_nonzero_polynomials()
Dynamically compute the number of gates added by the "add_gates_to_ensure_all_polys_are_non_zero" met...
RomRamLogic rom_ram_logic
size_t get_estimated_total_circuit_size() const
Get the estimated size of the circuit if it was finalized now.
typename ExecutionTrace::FF FF
UltraCircuitBuilder_ & operator=(UltraCircuitBuilder_ &&other) noexcept
std::vector< uint32_t > used_witnesses
std::array< uint32_t, 5 > evaluate_non_native_field_addition(add_simple limb0, add_simple limb1, add_simple limb2, add_simple limb3, std::tuple< uint32_t, uint32_t, FF > limbp)
size_t get_num_constant_gates() const override
size_t create_ROM_array(const size_t array_size)
Create a new read-only memory region.
void create_balanced_add_gate(const add_quad_< FF > &in)
plookup::ReadData< uint32_t > create_gates_from_plookup_accumulators(const plookup::MultiTableId &id, const plookup::ReadData< FF > &read_values, const uint32_t key_a_index, std::optional< uint32_t > key_b_index=std::nullopt)
Perform a series of lookups, one for each 'row' in read_values.
std::array< uint32_t, 2 > decompose_non_native_field_double_width_limb(const uint32_t limb_idx, const size_t num_limb_bits=(2 *DEFAULT_NON_NATIVE_FIELD_LIMB_BITS))
Decompose a single witness into two, where the lowest is DEFAULT_NON_NATIVE_FIELD_LIMB_BITS (68) rang...
plookup::BasicTable & get_table(const plookup::BasicTableId id)
Get the basic table with provided ID from the set of tables for the present circuit; create it if it ...
static constexpr std::string_view NAME_STRING
void apply_nnf_selectors(const NNF_SELECTORS type)
Enable the nnf gate of particular type.
void create_bool_gate(const uint32_t a) override
Generate an arithmetic gate equivalent to x^2 - x = 0, which forces x to be 0 or 1.
void get_num_estimated_gates_split_into_components(size_t &count, size_t &rangecount, size_t &romcount, size_t &ramcount, size_t &nnfcount) const
Get the final number of gates in a circuit, which consists of the sum of: 1) Current number number of...
void create_ecc_add_gate(const ecc_add_gate_< FF > &in)
Create an elliptic curve addition gate.
void finalize_circuit(const bool ensure_nonzero)
void create_sort_constraint(const std::vector< uint32_t > &variable_index)
void create_poly_gate(const poly_triple_< FF > &in) override
A plonk gate with disabled (set to zero) fourth wire. q_m * a * b + q_1 * a + q_2 * b + q_3.
void create_poseidon2_external_gate(const poseidon2_external_gate_< FF > &in)
Poseidon2 external round gate, activates the q_poseidon2_external selector and relation.
std::array< uint32_t, 2 > evaluate_non_native_field_multiplication(const non_native_multiplication_witnesses< FF > &input)
Queue up non-native field multiplication data.
UltraCircuitBuilder_(const size_t size_hint, auto &witness_values, const std::vector< uint32_t > &public_inputs, size_t varnum, bool recursive=false)
Constructor from data generated from ACIR.
size_t get_estimated_num_finalized_gates() const override
Get the final number of gates in a circuit, which consists of the sum of: 1) Current number number of...
static constexpr size_t UINT_LOG2_BASE
std::vector< uint32_t > get_used_witnesses() const
void populate_public_inputs_block()
Copy the public input idx data into the public inputs trace block.
void create_range_constraint(const uint32_t variable_index, const size_t num_bits, std::string const &msg)
uint32_t read_ROM_array(const size_t rom_id, const uint32_t index_witness)
Read a single element from ROM.
RangeList create_range_list(const uint64_t target_range)
void assign_tag(const uint32_t variable_index, const uint32_t tag)
uint32_t put_constant_variable(const FF &variable)
void set_ROM_element(const size_t rom_id, const size_t index_value, const uint32_t value_witness)
Initialize a rom cell to equal value_witness
~UltraCircuitBuilder_() override=default
UltraCircuitBuilder_(const UltraCircuitBuilder_ &other)=default
std::vector< uint32_t > decompose_into_default_range_better_for_oddlimbnum(const uint32_t variable_index, const size_t num_bits, std::string const &msg="decompose_into_default_range_better_for_oddlimbnum")
std::vector< uint32_t > memory_read_records
void create_mul_gate(const mul_triple_< FF > &in) override
Create a multiplication gate with q_m * a * b + q_3 * c + q_const = 0.
void update_used_witnesses(uint32_t var_idx)
void check_selector_length_consistency()
Debug helper method for ensuring all selectors have the same size.
std::vector< uint32_t > memory_write_records
void write_RAM_array(const size_t ram_id, const uint32_t index_witness, const uint32_t value_witness)
void create_dummy_constraints(const std::vector< uint32_t > &variable_index)
void set_ROM_element_pair(const size_t rom_id, const size_t index_value, const std::array< uint32_t, 2 > &value_witnesses)
Initialize a ROM array element with a pair of witness values.
std::array< uint32_t, 2 > read_ROM_array_pair(const size_t rom_id, const uint32_t index_witness)
Read a pair of elements from ROM.
static constexpr merkle::HashType merkle_hash_type
static constexpr CircuitType CIRCUIT_TYPE
UltraCircuitBuilder_(const size_t size_hint=0)
void assert_equal_constant(const uint32_t a_idx, const FF &b, std::string const &msg="assert equal constant")
ExecutionTrace_ ExecutionTrace
void create_dummy_gate(auto &block, const uint32_t &idx_1, const uint32_t &idx_2, const uint32_t &idx_3, const uint32_t &idx_4)
Create a gate with no constraints but with possibly non-trivial wire values.
std::pair< uint32_t, FF > scaled_witness
std::array< uint32_t, 2 > queue_partial_non_native_field_multiplication(const non_native_partial_multiplication_witnesses< FF > &input)
static constexpr size_t program_width
uint32_t create_tag(const uint32_t tag_index, const uint32_t tau_index)
UltraCircuitBuilder_(UltraCircuitBuilder_ &&other) noexcept
std::array< uint32_t, 5 > evaluate_non_native_field_subtraction(add_simple limb0, add_simple limb1, add_simple limb2, add_simple limb3, std::tuple< uint32_t, uint32_t, FF > limbp)
void apply_memory_selectors(const MEMORY_SELECTORS type)
Enable the memory gate of particular type.
size_t get_finalized_total_circuit_size() const
Get the actual finalized size of a circuit. Assumes the circuit is finalized already.
static constexpr size_t DEFAULT_PLOOKUP_RANGE_SIZE
void create_big_add_gate_with_bit_extraction(const add_quad_< FF > &in)
A legacy method that was used to extract a bit from c-4d by using gate selectors in the Turboplonk,...
std::vector< fr > ipa_proof
void process_non_native_field_multiplications()
Called in compute_proving_key when finalizing circuit. Iterates over the cached_non_native_field_mult...
static constexpr size_t DEFAULT_PLOOKUP_RANGE_BITNUM
static constexpr size_t NUMBER_OF_GATES_PER_RAM_ACCESS
void create_new_range_constraint(const uint32_t variable_index, const uint64_t target_range, std::string const msg="create_new_range_constraint")
Constrain a variable to a range.
size_t get_tables_size() const
Get combined size of all tables used in circuit.
static constexpr size_t DEFAULT_PLOOKUP_RANGE_STEP_SIZE
Container type for lookup table reads.
Entry point for Barretenberg command-line interface.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
bool operator==(const RangeList &other) const noexcept
std::vector< uint32_t > variable_indices
size_t operator()(const cached_partial_non_native_field_multiplication &obj) const
Used to store instructions to create partial_non_native_field_multiplication gates....
static void deduplicate(std::vector< cached_partial_non_native_field_multiplication > &vec, UltraCircuitBuilder_< ExecutionTrace > *circuit_builder)
Dedupilcate cache entries which represent multiplication of the same witnesses.
bool operator<(const cached_partial_non_native_field_multiplication &other) const
std::array< uint32_t, 4 > b
std::array< uint32_t, 4 > a
bool operator==(const cached_partial_non_native_field_multiplication &other) const
static constexpr field zero()
std::array< uint32_t, 4 > a
std::array< uint32_t, 4 > q
std::array< uint32_t, 4 > b
std::array< uint32_t, 4 > r
std::array< FF, 4 > neg_modulus
std::array< uint32_t, 4 > b
std::array< uint32_t, 4 > a
A basic table from which we can perform lookups (for example, an xor table)
Container for managing multiple BasicTables plus the data needed to combine basic table outputs (e....