19#include <unordered_set>
27 std::array<uint32_t, 4>
a;
28 std::array<uint32_t, 4>
b;
29 std::array<uint32_t, 4>
q;
30 std::array<uint32_t, 4>
r;
36 std::array<uint32_t, 4>
a;
37 std::array<uint32_t, 4>
b;
40template <
typename ExecutionTrace_>
44 using FF =
typename ExecutionTrace::FF;
47 static constexpr size_t NUM_WIRES = ExecutionTrace::NUM_WIRES;
49 static constexpr std::string_view
NAME_STRING =
"UltraCircuitBuilder";
96 std::array<uint32_t, 4>
a;
97 std::array<uint32_t, 4>
b;
105 for (
size_t i = 0; i < 4; ++i) {
106 valid = valid && (
a[i] == other.
a[i]);
107 valid = valid && (
b[i] == other.
b[i]);
128 for (
const auto& item : vec) {
129 auto [existing_element, not_in_set] = seen.insert(item);
132 uniqueVec.push_back(item);
135 circuit_builder->
assert_equal(item.lo_0, (*existing_element).lo_0);
136 circuit_builder->
assert_equal(item.hi_0, (*existing_element).hi_0);
137 circuit_builder->
assert_equal(item.hi_1, (*existing_element).hi_1);
161 size_t combined_hash = 0;
168 auto hash_combiner = [](
size_t lhs,
size_t rhs) {
169 return lhs ^ (rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2));
172 for (
const auto& elem : obj.
a) {
175 for (
const auto& elem : obj.
b) {
179 return combined_hash;
219 { DUMMY_TAG, DUMMY_TAG });
240 const std::vector<FF>& witness_values,
245 for (
const auto value : witness_values) {
255 this->
_tau.insert({ DUMMY_TAG, DUMMY_TAG });
275 for (
auto& block :
blocks.get()) {
276 const auto& block_selectors = block.get_selectors();
277 size_t nominal_size = block_selectors[0].size();
278 for (
size_t idx = 1; idx < block_selectors.size(); ++idx) {
279 BB_ASSERT_EQ(block_selectors[idx].size(), nominal_size);
299 void fix_witness(
const uint32_t witness_index,
const FF& witness_value);
302 const uint64_t target_range,
303 std::string
const msg =
"create_new_range_constraint");
374 size_t tables_size = 0;
376 tables_size += table.size();
420 const uint32_t key_a_index,
424 const uint32_t variable_index,
425 const uint64_t num_bits,
427 std::string
const& msg =
"decompose_into_default_range");
438 auto& block,
const uint32_t& idx_1,
const uint32_t& idx_2,
const uint32_t& idx_3,
const uint32_t& idx_4)
440 block.populate_wires(idx_1, idx_2, idx_3, idx_4);
441 block.q_m().emplace_back(0);
442 block.q_1().emplace_back(0);
443 block.q_2().emplace_back(0);
444 block.q_3().emplace_back(0);
445 block.q_c().emplace_back(0);
446 block.q_4().emplace_back(0);
447 block.set_gate_selector(0);
483 this->
_tau.insert({ tag_index, tau_index });
518 const uint32_t hi_idx,
521 std::string
const& msg =
"range_constrain_two_limbs");
543 void set_ROM_element(
const size_t rom_id,
const size_t index_value,
const uint32_t value_witness);
545 const size_t index_value,
546 const std::array<uint32_t, 2>& value_witnesses);
548 uint32_t
read_ROM_array(
const size_t rom_id,
const uint32_t index_witness);
549 std::array<uint32_t, 2>
read_ROM_array_pair(
const size_t rom_id,
const uint32_t index_witness);
552 void init_RAM_element(
const size_t ram_id,
const size_t index_value,
const uint32_t value_witness);
554 uint32_t
read_RAM_array(
const size_t ram_id,
const uint32_t index_witness);
555 void write_RAM_array(
const size_t ram_id,
const uint32_t index_witness,
const uint32_t value_witness);
598 for (
const auto& it : used_indices) {
621 for (
const auto& it : finalize_indices) {
#define BB_ASSERT(expression,...)
#define BB_ASSERT_EQ(actual, expected,...)
#define BB_ASSERT_LTE(left, right,...)
bool is_write_vk_mode() const
virtual uint32_t add_variable(const FF &in)
Add a variable to variables.
std::unordered_map< uint32_t, uint32_t > _tau
The permutation on variable tags, as a constituent of the generalized permutation argument.
void failure(std::string msg)
void initialize_public_inputs(const std::vector< uint32_t > &public_inputs)
Directly initialize the public inputs vector.
const std::vector< uint32_t > & public_inputs() const
size_t num_public_inputs() const
std::vector< uint32_t > real_variable_tags
real_variable_tags is the tagging mechanism for the the multiset-equality check.
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}.
void increment_num_gates(size_t count=1)
std::vector< uint32_t > real_variable_index
Map from witness index to real variable index.
void set_zero_idx(uint32_t value)
ROM/RAM logic handler for UltraCircuitBuilder.
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.
void create_ecc_dbl_gate(const ecc_dbl_gate_< FF > &in)
Create an elliptic curve doubling gate.
std::map< uint64_t, RangeList > range_lists
UltraCircuitBuilder_ & operator=(UltraCircuitBuilder_ &&other)=default
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...
const std::unordered_set< uint32_t > & get_finalize_witnesses() const
UltraCircuitBuilder_(UltraCircuitBuilder_ &&other)=default
void update_used_witnesses(const std::vector< uint32_t > &used_indices)
Add a list of witness indices to the boomerang exclusion list.
plookup::MultiTable & get_multitable(const plookup::MultiTableId id)
void process_range_list(RangeList &list)
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.
UltraCircuitBuilder_(const size_t size_hint=0, bool is_write_vk_mode=false)
static constexpr size_t DEFAULT_NON_NATIVE_FIELD_LIMB_BITS
void create_unconstrained_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.
void set_tau_at_index(const uint32_t tag_index, const uint32_t tau_index)
Set the tau(tag_index) = tau_index.
void update_finalize_witnesses(const std::vector< uint32_t > &finalize_indices)
Add a list of witness indices to the finalize exclusion list.
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()
std::unordered_set< uint32_t > finalize_witnesses
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::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_unconstrained_gates(const std::vector< uint32_t > &variable_index)
void create_add_gate(const add_triple_< FF > &in)
Create an addition gate, where in.a * in.a_scaling + in.b * in.b_scaling + in.c * in....
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....
RomRamLogic rom_ram_logic
typename ExecutionTrace::FF FF
const std::vector< uint32_t > & get_used_witnesses() const
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)
Construct gates for non-native field addition.
const std::deque< plookup::BasicTable > & get_lookup_tables() const
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 (a.k.a. ROM table)
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)
Create gates from pre-computed accumulator values which simultaneously establish individual basic-tab...
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_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_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)
Create gates for a full non-native field multiplication identity a * b = q * p + r.
size_t get_num_lookup_tables() 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
std::unordered_map< FF, uint32_t > constant_variable_indices
~UltraCircuitBuilder_() override=default
void create_bool_gate(const uint32_t a)
Generate an arithmetic gate equivalent to x^2 - x = 0, which forces x to be 0 or 1.
void update_finalize_witnesses(uint32_t var_idx)
Add a witness index to the finalize exclusion list.
void set_tau_transposition(const uint32_t tag_index_1, const uint32_t tag_index_2)
Add a transposition to tau.
UltraCircuitBuilder_(const UltraCircuitBuilder_ &other)=default
std::vector< uint32_t > memory_read_records
void update_used_witnesses(uint32_t var_idx)
Add a witness index to the boomerang exclusion list.
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 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.
void assert_equal_constant(const uint32_t a_idx, const FF &b, std::string const &msg="assert equal constant")
ExecutionTrace_ ExecutionTrace
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, std::string const &msg="range_constrain_two_limbs")
std::pair< uint32_t, FF > scaled_witness
UltraCircuitBuilder_(const size_t size_hint, const std::vector< FF > &witness_values, const std::vector< uint32_t > &public_inputs, const bool is_write_vk_mode)
Constructor from data generated from ACIR.
std::array< uint32_t, 2 > queue_partial_non_native_field_multiplication(const non_native_partial_multiplication_witnesses< FF > &input)
Queue the addition of gates constraining the limb-multiplication part of a non native field mul.
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)
Construct gates for non-native field subtraction.
void apply_memory_selectors(const MEMORY_SELECTORS type)
Enable the memory gate of particular type.
std::deque< plookup::BasicTable > lookup_tables
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
std::vector< fr > ipa_proof
void process_non_native_field_multiplications()
Iterates over the cached_non_native_field_multiplication objects, removes duplicates,...
static constexpr size_t DEFAULT_PLOOKUP_RANGE_BITNUM
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.
void create_arithmetic_gate(const arithmetic_triple_< FF > &in)
A plonk gate with disabled (set to zero) fourth wire. q_m * a * b + q_1 * a + q_2 * b + q_3.
size_t get_num_finalized_gates_inefficient(bool ensure_nonzero=true) const
Get the number of gates in the finalized version of the circuit.
std::deque< plookup::BasicTable > & get_lookup_tables()
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.
UltraCircuitBuilder_< UltraExecutionTraceBlocks > UltraCircuitBuilder
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....