34 using Ts::operator()...;
39 BB_ASSERT_EQ(
buffer.size(), 32U,
"acir_format::from_buffer_with_bound_checks: buffer size must be 32 bytes.");
47 .
index = e.value.value,
54 .
index = bb::stdlib::IS_CONSTANT,
66 "acir_format::get_witness_from_function_input: input must be a Witness variant. An error here means "
67 "there was a serialization error.");
74 if (witness_idx != stdlib::IS_CONSTANT) {
82 for (
const auto& mul_term : expr.
mul_terms) {
101 auto update_max_witness_index_from_witness = [&](
const Acir::Witness& witness) {
110 update_max_witness_index_from_function_input(bb_arg.lhs);
111 update_max_witness_index_from_function_input(bb_arg.rhs);
112 update_max_witness_index_from_witness(bb_arg.output);
115 update_max_witness_index_from_function_input(bb_arg.lhs);
116 update_max_witness_index_from_function_input(bb_arg.rhs);
117 update_max_witness_index_from_witness(bb_arg.output);
120 update_max_witness_index_from_function_input(bb_arg.input);
123 for (
const auto& input : bb_arg.inputs) {
124 update_max_witness_index_from_function_input(input);
126 for (
const auto& input : *bb_arg.iv) {
127 update_max_witness_index_from_function_input(input);
129 for (
const auto& input : *bb_arg.key) {
130 update_max_witness_index_from_function_input(input);
132 for (
const auto& output : bb_arg.outputs) {
133 update_max_witness_index_from_witness(output);
137 for (
const auto& input : *bb_arg.inputs) {
138 update_max_witness_index_from_function_input(input);
140 for (
const auto& input : *bb_arg.hash_values) {
141 update_max_witness_index_from_function_input(input);
143 for (
const auto& output : *bb_arg.outputs) {
144 update_max_witness_index_from_witness(output);
148 for (
const auto& input : bb_arg.inputs) {
149 update_max_witness_index_from_function_input(input);
151 for (
const auto& output : *bb_arg.outputs) {
152 update_max_witness_index_from_witness(output);
156 for (
const auto& input : bb_arg.inputs) {
157 update_max_witness_index_from_function_input(input);
159 for (
const auto& output : *bb_arg.outputs) {
160 update_max_witness_index_from_witness(output);
164 for (
const auto& input : *bb_arg.public_key_x) {
165 update_max_witness_index_from_function_input(input);
167 for (
const auto& input : *bb_arg.public_key_y) {
168 update_max_witness_index_from_function_input(input);
170 for (
const auto& input : *bb_arg.signature) {
171 update_max_witness_index_from_function_input(input);
173 for (
const auto& input : *bb_arg.hashed_message) {
174 update_max_witness_index_from_function_input(input);
176 update_max_witness_index_from_function_input(bb_arg.predicate);
177 update_max_witness_index_from_witness(bb_arg.output);
180 for (
const auto& input : *bb_arg.public_key_x) {
181 update_max_witness_index_from_function_input(input);
183 for (
const auto& input : *bb_arg.public_key_y) {
184 update_max_witness_index_from_function_input(input);
186 for (
const auto& input : *bb_arg.signature) {
187 update_max_witness_index_from_function_input(input);
189 for (
const auto& input : *bb_arg.hashed_message) {
190 update_max_witness_index_from_function_input(input);
192 update_max_witness_index_from_function_input(bb_arg.predicate);
193 update_max_witness_index_from_witness(bb_arg.output);
196 for (
const auto& input : bb_arg.points) {
197 update_max_witness_index_from_function_input(input);
199 for (
const auto& input : bb_arg.scalars) {
200 update_max_witness_index_from_function_input(input);
202 update_max_witness_index_from_function_input(bb_arg.predicate);
203 for (
const auto& output : *bb_arg.outputs) {
204 update_max_witness_index_from_witness(output);
208 for (
const auto& input : *bb_arg.input1) {
209 update_max_witness_index_from_function_input(input);
211 for (
const auto& input : *bb_arg.input2) {
212 update_max_witness_index_from_function_input(input);
214 update_max_witness_index_from_function_input(bb_arg.predicate);
215 for (
const auto& output : *bb_arg.outputs) {
216 update_max_witness_index_from_witness(output);
220 for (
const auto& input : *bb_arg.inputs) {
221 update_max_witness_index_from_function_input(input);
223 for (
const auto& output : *bb_arg.outputs) {
224 update_max_witness_index_from_witness(output);
228 for (
const auto& input : bb_arg.verification_key) {
229 update_max_witness_index_from_function_input(input);
231 for (
const auto& input : bb_arg.proof) {
232 update_max_witness_index_from_function_input(input);
234 for (
const auto& input : bb_arg.public_inputs) {
235 update_max_witness_index_from_function_input(input);
237 update_max_witness_index_from_function_input(bb_arg.key_hash);
238 update_max_witness_index_from_function_input(bb_arg.predicate);
241 for (
const auto& input : bb_arg.inputs) {
242 update_max_witness_index_from_function_input(input);
244 for (
const auto& output : bb_arg.outputs) {
245 update_max_witness_index_from_witness(output);
251 for (
const auto&
init : arg.init) {
252 update_max_witness_index_from_witness(
init);
256 update_max_witness_index_from_witness(arg.op.index);
257 update_max_witness_index_from_witness(arg.op.value);
260 for (
const auto& input : arg.inputs) {
266 for (
const auto& expr : e.value) {
276 for (
const auto& output : arg.outputs) {
279 update_max_witness_index_from_witness(e.value);
282 for (
const auto& witness : e.value) {
283 update_max_witness_index_from_witness(witness);
292 bb::assert_failure(
"acir_format::update_max_witness_index_from_opcode: Call opcode is not supported.");
303 BB_ASSERT(!buf.empty(),
"deserialize_msgpack_compact: buffer is empty");
306 const uint8_t FORMAT_MSGPACK = 2;
307 const uint8_t FORMAT_MSGPACK_COMPACT = 3;
308 const uint8_t FORMAT_MSGPACK_TAGGED = 4;
309 uint8_t format_u8 = buf[0];
310 BB_ASSERT(format_u8 == FORMAT_MSGPACK || format_u8 == FORMAT_MSGPACK_COMPACT || format_u8 == FORMAT_MSGPACK_TAGGED,
311 "deserialize_msgpack_compact: expected msgpack format marker (2, 3 or 4), got " +
315 const char*
buffer = &
reinterpret_cast<const char*
>(buf.data())[1];
316 size_t size = buf.size() - 1;
318 auto oh = msgpack::unpack(
buffer, size);
322 if (format_u8 == FORMAT_MSGPACK_COMPACT) {
323 BB_ASSERT(o.type == msgpack::type::ARRAY,
324 "deserialize_msgpack_compact: expected ARRAY type, got " +
std::to_string(o.type));
327 return decode_msgpack(o);
333 circuit.
opcodes.size(), UINT32_MAX,
"acir_format::circuit_serde_to_acir_format: too many opcodes in circuit.");
340 update_max_witness_index(e.value, af);
345 update_max_witness_index(e.value, af);
359 for (
size_t i = 0; i < circuit.
opcodes.size(); ++i) {
360 const auto& gate = circuit.
opcodes[i];
370 uint32_t block_id = arg.block_id.value;
371 block_id_to_block_constraint[block_id] = { block, { i } };
374 auto block = block_id_to_block_constraint.find(arg.block_id.value);
375 if (block == block_id_to_block_constraint.end()) {
376 bb::assert_failure(
"acir_format::circuit_serde_to_acir_format: unitialized MemoryOp.");
379 block->second.second.push_back(i);
383 bb::assert_failure(
"acir_format::circuit_serde_to_acir_format: Call opcode is not supported.");
392 for (
const auto& [_, block] : block_id_to_block_constraint) {
399 "Max witness index above UINT32_MAX, this value is reserved for unset witnesses that will be replaced "
400 "with the zero index.");
408 auto program = deserialize_msgpack_compact<Acir::ProgramWithoutBrillig>(
414 o.convert(program_wob);
415 }
catch (
const msgpack::type_error&) {
418 "acir_format::circuit_buf_to_acir_format: failed to convert msgpack data to Program");
422 BB_ASSERT_EQ(program.functions.size(), 1U,
"circuit_buf_to_acir_format: expected single function in ACIR program");
435 auto witness_stack = deserialize_msgpack_compact<Witnesses::WitnessStack>(
std::move(buf), [](
auto o) {
438 o.convert(witness_stack);
439 }
catch (
const msgpack::type_error&) {
442 "acir_format::witness_buf_to_witness_vector: failed to convert msgpack data to WitnessStack");
444 return witness_stack;
448 "acir_format::witness_buf_to_witness_vector: expected single WitnessMap in WitnessStack");
459 for (
size_t index = 0;
const auto& e : witness_map.
value) {
465 while (
index < e.first.value) {
473 return witness_vector;
484 idx, bb::stdlib::IS_CONSTANT,
"Attempting to override a non-constant witness index in mul_quad_ gate");
485 idx = linear_terms.begin()->first;
486 scaling += linear_terms.begin()->second;
487 linear_terms.erase(idx);
495 SIZE_MAX - linear_terms.size(),
496 "split_into_mul_quad_gates: overflow when reserving space for mul_quad_ gates.");
500 for (
const auto& mul_term : arg.
mul_terms) {
504 .c = bb::stdlib::IS_CONSTANT,
505 .d = bb::stdlib::IS_CONSTANT,
515 auto& mul_quad =
result.back();
516 if (linear_terms.contains(mul_quad.a)) {
517 mul_quad.a_scaling += linear_terms.at(mul_quad.a);
518 linear_terms.erase(mul_quad.a);
520 if (linear_terms.contains(mul_quad.b)) {
522 mul_quad.b_scaling += linear_terms.at(mul_quad.b);
523 linear_terms.erase(mul_quad.b);
528 bool is_first_gate =
true;
529 for (
auto& mul_quad :
result) {
530 if (!linear_terms.empty()) {
531 add_linear_term_and_erase(mul_quad.c, mul_quad.c_scaling, linear_terms);
537 if (!linear_terms.empty()) {
538 add_linear_term_and_erase(mul_quad.d, mul_quad.d_scaling, linear_terms);
540 is_first_gate =
false;
545 while (!linear_terms.empty()) {
548 .
a = bb::stdlib::IS_CONSTANT,
549 .b = bb::stdlib::IS_CONSTANT,
550 .c = bb::stdlib::IS_CONSTANT,
551 .d = bb::stdlib::IS_CONSTANT,
559 if (!linear_terms.empty()) {
560 add_linear_term_and_erase(mul_quad.
a, mul_quad.
a_scaling, linear_terms);
562 if (!linear_terms.empty()) {
563 add_linear_term_and_erase(mul_quad.
b, mul_quad.
b_scaling, linear_terms);
565 if (!linear_terms.empty()) {
566 add_linear_term_and_erase(mul_quad.
c, mul_quad.
c_scaling, linear_terms);
571 if (!linear_terms.empty()) {
572 add_linear_term_and_erase(mul_quad.
d, mul_quad.
d_scaling, linear_terms);
574 is_first_gate =
false;
577 result.emplace_back(mul_quad);
581 "split_into_mul_quad_gates: resulted in zero gates. This means that there is an expression with no "
582 "multiplication terms and no linear terms.");
596 uint32_t shared_index = bb::stdlib::IS_CONSTANT;
597 size_t num_shared_indices = 0;
600 auto process_witness_index = [&](uint32_t w) {
601 if (w == c || w == d) {
603 ++num_shared_indices;
607 process_witness_index(
a);
610 process_witness_index(
b);
616 if (num_shared_indices != 1) {
621 shared_index, bb::stdlib::IS_CONSTANT,
"acir_format::resolve_shared_wire_products: no matched shared_index.");
623 w_r = (
a == shared_index) ?
b :
a;
624 w_o = (c == shared_index) ? d : c;
633 uint32_t w_l = bb::stdlib::IS_CONSTANT;
634 uint32_t w_r = bb::stdlib::IS_CONSTANT;
635 uint32_t w_o = bb::stdlib::IS_CONSTANT;
641 bool extra_seen =
false;
642 for (
const auto& [witness, coeff] : linear_terms) {
643 if (witness == w_l || witness == w_r || witness == w_o) {
656 return arg.
mul_terms.empty() && !linear_terms.empty() && linear_terms.size() <= 2;
662 uint32_t w_l = bb::stdlib::IS_CONSTANT;
663 uint32_t w_r = bb::stdlib::IS_CONSTANT;
664 uint32_t w_o = bb::stdlib::IS_CONSTANT;
666 BB_ASSERT(resolved,
"acir_format::build_bilinear_constraint: the two products must share exactly one wire.");
670 uint32_t w_4 = bb::stdlib::IS_CONSTANT;
677 for (
const auto& [w, c] : linear_terms) {
680 }
else if (w == w_r) {
682 }
else if (w == w_o) {
686 BB_ASSERT(w_4 == bb::stdlib::IS_CONSTANT,
687 "acir_format::build_bilinear_constraint: more than one linear-only witness.");
712 BB_ASSERT(!linear_terms.empty() && linear_terms.size() <= 2,
"BatchedEq gate requires at most two linear terms.");
714 .
w1 = bb::stdlib::IS_CONSTANT,
715 .w2 = bb::stdlib::IS_CONSTANT,
719 .opcode_index = opcode_index,
721 auto it = linear_terms.begin();
722 entry.w1 = it->first;
723 entry.c1 = it->second;
724 if (++it != linear_terms.end()) {
725 entry.w2 = it->first;
726 entry.c2 = it->second;
734 bool entry2_has_value = entry2.has_value();
738 .c = entry2_has_value ? entry2->w1 : bb::stdlib::IS_CONSTANT,
739 .d = entry2_has_value ? entry2->w2 : bb::stdlib::IS_CONSTANT,
742 .q_o = entry2_has_value ? entry2->c1 :
fr::zero(),
743 .q_4 = entry2_has_value ? entry2->c2 :
fr::zero(),
745 .q_m = entry2_has_value ? entry2->q_c :
fr::zero(),
751 for (
size_t i = 0; i + 1 < pending.size(); i += 2) {
754 { pending[i].opcode_index, pending[i + 1].opcode_index });
756 if (pending.size() % 2 == 1) {
771 return ((gate.mul_scaling ==
fr(0)) && (gate.a_scaling ==
fr(0)) && (gate.b_scaling ==
fr(0)) &&
772 (gate.c_scaling ==
fr(0)) && (gate.d_scaling ==
fr(0)) && (gate.const_scaling ==
fr(0)));
777 return (gate.c1 ==
fr(0) && gate.c2 ==
fr(0) && gate.q_c ==
fr(0));
788 "circuit is unsatisfiable. An AssertZero opcode contains no variables but has a non-zero "
789 "constant, which can never equal zero.");
799 throw_or_abort(
"acir_format::assert_zero_to_constraint: selected AssertZeroGate::Bilinear variant "
800 "when using UltraCircuitBuilder.");
808 throw_or_abort(
"acir_format::assert_zero_to_constraint: selected AssertZeroGate::BatchedEq variant "
809 "when using UltraCircuitBuilder.");
812 BB_ASSERT(!is_zero_batched_eq_gate(batched_eq_assert_zeros.back()),
813 "acir_format::asser_zero_to_constraints: produced a BatcheqEq zero gate");
818 BB_ASSERT_EQ(mul_quads.size(), 1U,
"acir_format::assert_zero_to_constraints: expected a single gate.");
820 "acir_format::assert_zero_to_constraints: produced a SingleArithmetic zero gate.");
828 mul_quads.size(), 1U,
"acir_format::assert_zero_to_constraints: expected multiple gates but found one.");
829 for (
auto const& mul_quad : mul_quads) {
831 "acir_format::assert_zero_to_constraints: produced a MultiArithmetic zero gate.");
845 auto to_witness = [](
const Acir::Witness& e) {
return e.value; };
853 .result = to_witness(arg.output),
854 .num_bits = arg.num_bits,
855 .is_xor_gate =
false,
863 .result = to_witness(arg.output),
864 .num_bits = arg.num_bits,
872 .num_bits = arg.num_bits,
888 .hash_values =
transform::map(*arg.hash_values, to_witness_or_constant),
910 .hashed_message =
transform::map(*arg.hashed_message, to_witness_from_input),
911 .signature =
transform::map(*arg.signature, to_witness_from_input),
912 .pub_x_indices =
transform::map(*arg.public_key_x, to_witness_from_input),
913 .pub_y_indices =
transform::map(*arg.public_key_y, to_witness_from_input),
915 .result = to_witness(arg.output),
922 .hashed_message =
transform::map(*arg.hashed_message, to_witness_from_input),
923 .signature =
transform::map(*arg.signature, to_witness_from_input),
924 .pub_x_indices =
transform::map(*arg.public_key_x, to_witness_from_input),
925 .pub_y_indices =
transform::map(*arg.public_key_y, to_witness_from_input),
927 .result = to_witness(arg.output),
936 .out_point_x = to_witness((*arg.outputs)[0]),
937 .out_point_y = to_witness((*arg.outputs)[1]),
948 .result_x = to_witness((*arg.outputs)[0]),
949 .result_y = to_witness((*arg.outputs)[1]),
962 if (predicate.is_constant && predicate.value.is_zero()) {
969 .public_inputs =
transform::map(arg.public_inputs, to_witness_from_input),
971 .proof_type = arg.proof_type,
972 .predicate = predicate,
976 switch (c.proof_type) {
1000 "acir_format::handle_black_box_fun_call: Invalid PROOF_TYPE in RecursionConstraint.");
1024 for (
const auto&
init : mem_init.
init) {
1025 block.init.push_back(
init.value);
1033 MAX_APPS_PER_KERNEL,
1034 "acir_format::handle_memory_init: calldata id exceeds kernel + MAX_APPS_PER_KERNEL app columns");
1037 block.calldata_id =
static_cast<CallDataType>(calldata_id);
1061 block.
trace.push_back(acir_mem_op);
1067 if (linear_terms.size() > NUM_WIRES) {
1090 size_t num_witnesses_to_be_put_in_wires = 2 + linear_terms.size();
1095 bool lhs_is_distinct_from_linear_terms = !linear_terms.contains(witness_idx_lhs);
1096 bool rhs_is_distinct_from_linear_terms = !linear_terms.contains(witness_idx_rhs);
1098 if (witness_idx_lhs != witness_idx_rhs) {
1099 num_witnesses_to_be_put_in_wires -= lhs_is_distinct_from_linear_terms ? 0U : 1U;
1100 num_witnesses_to_be_put_in_wires -= rhs_is_distinct_from_linear_terms ? 0U : 1U;
1102 num_witnesses_to_be_put_in_wires -= lhs_is_distinct_from_linear_terms ? 0U : 1U;
1105 return num_witnesses_to_be_put_in_wires <= NUM_WIRES;
1108 return linear_terms.size() <= NUM_WIRES;
1134 uint32_t witness_idx =
std::get<1>(linear_term).value;
1135 if (linear_terms.contains(witness_idx)) {
1136 linear_terms[witness_idx] += selector_value;
1138 linear_terms[witness_idx] = selector_value;
1141 return linear_terms;
#define BB_ASSERT(expression,...)
#define BB_ASSERT_GT(left, right,...)
#define BB_ASSERT_NEQ(actual, expected,...)
#define BB_ASSERT_EQ(actual, expected,...)
#define BB_ASSERT_LTE(left, right,...)
#define BB_ASSERT_LT(left, right,...)
std::unique_ptr< uint8_t[]> buffer
Entry point for Barretenberg command-line interface.
field< Bn254FrParams > fr
void assert_failure(std::string const &err)
C join(std::initializer_list< C > to_join)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::string to_string(bb::avm2::ValueTag tag)
std::variant< AES128Encrypt, AND, XOR, RANGE, Blake2s, Blake3, EcdsaSecp256k1, EcdsaSecp256r1, MultiScalarMul, EmbeddedCurveAdd, Keccakf1600, RecursiveAggregation, Poseidon2Permutation, Sha256Compression > value
std::variant< Memory, CallData, ReturnData > value
Acir::PublicInputs return_values
std::vector< Acir::Opcode > opcodes
Acir::PublicInputs public_parameters
std::vector< std::tuple< std::vector< uint8_t >, Acir::Witness > > linear_combinations
std::vector< uint8_t > q_c
std::vector< std::tuple< std::vector< uint8_t >, Acir::Witness, Acir::Witness > > mul_terms
Acir::BlackBoxFuncCall value
std::vector< Acir::Witness > init
Acir::BlockType block_type
std::variant< AssertZero, BlackBoxFuncCall, MemoryOp, MemoryInit, BrilligCall, Call > value
std::map< Witnesses::Witness, std::vector< uint8_t > > value
Linear AssertZero (≤2 witnesses + constant)
static field random_element(numeric::RNG *engine=nullptr) noexcept
static field serialize_from_buffer(const uint8_t *buffer)
static constexpr field zero()
void throw_or_abort(std::string const &err)