34 BB_ASSERT_EQ(
buffer.size(), 32U,
"acir_format::from_buffer_with_bound_checks: buffer size must be 32 bytes.");
45 .
index = e.value.value,
51 .
index = bb::stdlib::IS_CONSTANT,
56 bb::assert_failure(
"acir_format::parse_input: unrecognized Acir::FunctionInput variant. An error here "
57 "means there was a serialization error.");
67 "acir_format::get_witness_from_function_input: input must be a Witness variant. An error here means "
68 "there was a serialization error.");
75 if (witness_idx != stdlib::IS_CONSTANT) {
83 for (
const auto& mul_term : expr.
mul_terms) {
102 auto update_max_witness_index_from_witness = [&](
const Acir::Witness& witness) {
117 update_max_witness_index_from_function_input(bb_arg.lhs);
118 update_max_witness_index_from_function_input(bb_arg.rhs);
119 update_max_witness_index_from_witness(bb_arg.output);
121 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);
136 for (
const auto& input : *bb_arg.inputs) {
137 update_max_witness_index_from_function_input(input);
139 for (
const auto& input : *bb_arg.hash_values) {
140 update_max_witness_index_from_function_input(input);
142 for (
const auto& output : *bb_arg.outputs) {
143 update_max_witness_index_from_witness(output);
147 for (
const auto& input : bb_arg.inputs) {
148 update_max_witness_index_from_function_input(input);
150 for (
const auto& output : *bb_arg.outputs) {
151 update_max_witness_index_from_witness(output);
155 for (
const auto& input : *bb_arg.public_key_x) {
156 update_max_witness_index_from_function_input(input);
158 for (
const auto& input : *bb_arg.public_key_y) {
159 update_max_witness_index_from_function_input(input);
161 for (
const auto& input : *bb_arg.signature) {
162 update_max_witness_index_from_function_input(input);
164 for (
const auto& input : *bb_arg.hashed_message) {
165 update_max_witness_index_from_function_input(input);
167 update_max_witness_index_from_function_input(bb_arg.predicate);
168 update_max_witness_index_from_witness(bb_arg.output);
170 for (
const auto& input : bb_arg.points) {
171 update_max_witness_index_from_function_input(input);
173 for (
const auto& input : bb_arg.scalars) {
174 update_max_witness_index_from_function_input(input);
176 update_max_witness_index_from_function_input(bb_arg.predicate);
177 for (
const auto& output : *bb_arg.outputs) {
178 update_max_witness_index_from_witness(output);
181 for (
const auto& input : *bb_arg.input1) {
182 update_max_witness_index_from_function_input(input);
184 for (
const auto& input : *bb_arg.input2) {
185 update_max_witness_index_from_function_input(input);
187 update_max_witness_index_from_function_input(bb_arg.predicate);
188 for (
const auto& output : *bb_arg.outputs) {
189 update_max_witness_index_from_witness(output);
192 for (
const auto& input : *bb_arg.inputs) {
193 update_max_witness_index_from_function_input(input);
195 for (
const auto& output : *bb_arg.outputs) {
196 update_max_witness_index_from_witness(output);
199 for (
const auto& input : bb_arg.verification_key) {
200 update_max_witness_index_from_function_input(input);
202 for (
const auto& input : bb_arg.proof) {
203 update_max_witness_index_from_function_input(input);
205 for (
const auto& input : bb_arg.public_inputs) {
206 update_max_witness_index_from_function_input(input);
208 update_max_witness_index_from_function_input(bb_arg.key_hash);
209 update_max_witness_index_from_function_input(bb_arg.predicate);
211 for (
const auto& input : bb_arg.inputs) {
212 update_max_witness_index_from_function_input(input);
214 for (
const auto& output : bb_arg.outputs) {
215 update_max_witness_index_from_witness(output);
221 for (
const auto&
init : arg.init) {
222 update_max_witness_index_from_witness(
init);
230 for (
const auto& input : arg.inputs) {
237 for (
const auto& expr : e.value) {
246 for (
const auto& output : arg.outputs) {
251 update_max_witness_index_from_witness(e.value);
253 for (
const auto& witness : e.value) {
254 update_max_witness_index_from_witness(witness);
261 if (arg.predicate.has_value()) {
265 bb::assert_failure(
"acir_format::update_max_witness_index_from_opcode: Unrecognized opcode.");
275 std::function<T(msgpack::object
const&)> decode_msgpack,
276 std::function<T(std::vector<uint8_t>)> decode_bincode)
294 const uint8_t FORMAT_MSGPACK = 2;
295 const uint8_t FORMAT_MSGPACK_COMPACT = 3;
297 if (
format == FORMAT_MSGPACK ||
format == FORMAT_MSGPACK_COMPACT) {
299 const char*
buffer = &
reinterpret_cast<const char*
>(
buf.data())[1];
300 size_t size =
buf.size() - 1;
301 msgpack::null_visitor probe;
302 if (msgpack::parse(
buffer, size, probe)) {
303 auto oh = msgpack::unpack(
buffer, size);
309 if (o.type == msgpack::type::MAP || o.type == msgpack::type::ARRAY) {
310 return decode_msgpack(o);
325 circuit.
opcodes.size(), UINT32_MAX,
"acir_format::circuit_serde_to_acir_format: too many opcodes in circuit.");
332 update_max_witness_index(e.value, af);
337 update_max_witness_index(e.value, af);
347 for (
size_t i = 0; i < circuit.
opcodes.size(); ++i) {
348 const auto& gate = circuit.
opcodes[i];
359 uint32_t block_id = arg.block_id.value;
360 block_id_to_block_constraint[block_id] = { block, { i } };
362 auto block = block_id_to_block_constraint.find(arg.block_id.value);
363 if (block == block_id_to_block_constraint.end()) {
364 bb::assert_failure(
"acir_format::circuit_serder_to_acir_format: unitialized MemoryOp.");
367 block->second.second.push_back(i);
371 bb::assert_failure(
"acir_format::circuit_serde_to_acir_format: Unrecognized Acir Opcode. An error "
372 "here means there was a serialization error.");
378 for (
const auto& [_, block] : block_id_to_block_constraint) {
389 auto program = deserialize_any_format<Acir::Program>(
397 o.convert(program_wob);
399 }
catch (
const msgpack::type_error&) {
402 "acir_format::circuit_buf_to_acir_format: failed to convert msgpack data to Program");
407 BB_ASSERT_EQ(program.functions.size(), 1U,
"circuit_buf_to_acir_format: expected single function in ACIR program");
415 auto witness_stack = deserialize_any_format<Witnesses::WitnessStack>(
420 o.convert(witness_stack);
421 }
catch (
const msgpack::type_error&) {
424 "acir_format::witness_buf_to_witness_vector: failed to convert msgpack data to WitnessStack");
426 return witness_stack;
431 "acir_format::witness_buf_to_witness_vector: expected single WitnessMap in WitnessStack");
442 for (
size_t index = 0;
const auto& e : witness_map.
value) {
448 while (
index < e.first.value) {
456 return witness_vector;
467 idx, bb::stdlib::IS_CONSTANT,
"Attempting to override a non-constant witness index in mul_quad_ gate");
468 idx = linear_terms.begin()->first;
469 scaling += linear_terms.begin()->second;
470 linear_terms.erase(idx);
478 SIZE_MAX - linear_terms.size(),
479 "split_into_mul_quad_gates: overflow when reserving space for mul_quad_ gates.");
480 result.reserve(arg.
mul_terms.size() + linear_terms.size());
483 for (
const auto& mul_term : arg.
mul_terms) {
487 .c = bb::stdlib::IS_CONSTANT,
488 .d = bb::stdlib::IS_CONSTANT,
498 auto& mul_quad = result.back();
499 if (linear_terms.contains(mul_quad.a)) {
500 mul_quad.a_scaling += linear_terms.at(mul_quad.a);
501 linear_terms.erase(mul_quad.a);
503 if (linear_terms.contains(mul_quad.b)) {
505 mul_quad.b_scaling += linear_terms.at(mul_quad.b);
506 linear_terms.erase(mul_quad.b);
511 bool is_first_gate =
true;
512 for (
auto& mul_quad : result) {
513 if (!linear_terms.empty()) {
514 add_linear_term_and_erase(mul_quad.c, mul_quad.c_scaling, linear_terms);
520 if (!linear_terms.empty()) {
521 add_linear_term_and_erase(mul_quad.d, mul_quad.d_scaling, linear_terms);
523 is_first_gate =
false;
528 while (!linear_terms.empty()) {
531 .
a = bb::stdlib::IS_CONSTANT,
532 .b = bb::stdlib::IS_CONSTANT,
533 .c = bb::stdlib::IS_CONSTANT,
534 .d = bb::stdlib::IS_CONSTANT,
542 if (!linear_terms.empty()) {
543 add_linear_term_and_erase(mul_quad.
a, mul_quad.
a_scaling, linear_terms);
545 if (!linear_terms.empty()) {
546 add_linear_term_and_erase(mul_quad.
b, mul_quad.
b_scaling, linear_terms);
548 if (!linear_terms.empty()) {
549 add_linear_term_and_erase(mul_quad.
c, mul_quad.
c_scaling, linear_terms);
554 if (!linear_terms.empty()) {
555 add_linear_term_and_erase(mul_quad.
d, mul_quad.
d_scaling, linear_terms);
557 is_first_gate =
false;
560 result.emplace_back(mul_quad);
564 "split_into_mul_quad_gates: resulted in zero gates. This means that there is an expression with no "
565 "multiplication terms and no linear terms.");
566 result.shrink_to_fit();
575 return ((gate.mul_scaling ==
fr(0)) && (gate.a_scaling ==
fr(0)) && (gate.b_scaling ==
fr(0)) &&
576 (gate.c_scaling ==
fr(0)) && (gate.d_scaling ==
fr(0)) && (gate.const_scaling ==
fr(0)));
583 if (is_single_gate) {
584 BB_ASSERT_EQ(mul_quads.size(), 1U,
"acir_format::assert_zero_to_quad_constraints: expected a single gate.");
585 auto mul_quad = mul_quads[0];
592 "acir_format::assert_zero_to_quad_constraints: expected multiple gates but found one.");
597 for (
auto const& mul_quad : mul_quads) {
599 "acir_format::assert_zero_to_quad_constraints: produced an arithmetic zero gate.");
608 auto to_witness = [&](
const Acir::Witness& e) {
return e.value; };
618 .result = to_witness(arg.output),
619 .num_bits = arg.num_bits,
620 .is_xor_gate =
false,
627 .result = to_witness(arg.output),
628 .num_bits = arg.num_bits,
635 .num_bits = arg.num_bits,
649 .hash_values =
transform::map(*arg.hash_values, to_witness_or_constant),
658 .blackbox_input = parse_input(e),
669 [&](
auto& e) { return Blake3Input{ .blackbox_input = parse_input(e), .num_bits = 8 }; }),
674 af.ecdsa_k1_constraints.push_back(EcdsaConstraint{
676 .hashed_message =
transform::map(*arg.hashed_message, to_witness_from_input),
677 .signature =
transform::map(*arg.signature, to_witness_from_input),
678 .pub_x_indices =
transform::map(*arg.public_key_x, to_witness_from_input),
679 .pub_y_indices =
transform::map(*arg.public_key_y, to_witness_from_input),
681 .result = to_witness(arg.output),
683 af.original_opcode_indices.ecdsa_k1_constraints.push_back(opcode_index);
685 af.ecdsa_r1_constraints.push_back(EcdsaConstraint{
687 .hashed_message =
transform::map(*arg.hashed_message, to_witness_from_input),
688 .signature =
transform::map(*arg.signature, to_witness_from_input),
689 .pub_x_indices =
transform::map(*arg.public_key_x, to_witness_from_input),
690 .pub_y_indices =
transform::map(*arg.public_key_y, to_witness_from_input),
692 .result = to_witness(arg.output),
694 af.original_opcode_indices.ecdsa_r1_constraints.push_back(opcode_index);
696 af.multi_scalar_mul_constraints.push_back(MultiScalarMul{
700 .out_point_x = to_witness((*arg.outputs)[0]),
701 .out_point_y = to_witness((*arg.outputs)[1]),
702 .out_point_is_infinite = to_witness((*arg.outputs)[2]),
704 af.original_opcode_indices.multi_scalar_mul_constraints.push_back(opcode_index);
706 af.ec_add_constraints.push_back(EcAdd{
714 .result_x = to_witness((*arg.outputs)[0]),
715 .result_y = to_witness((*arg.outputs)[1]),
716 .result_infinite = to_witness((*arg.outputs)[2]),
718 af.original_opcode_indices.ec_add_constraints.push_back(opcode_index);
720 af.keccak_permutations.push_back(Keccakf1600{
724 af.original_opcode_indices.keccak_permutations.push_back(opcode_index);
727 if (predicate.is_constant && predicate.value.is_zero()) {
731 auto c = RecursionConstraint{
732 .key =
transform::map(arg.verification_key, to_witness_from_input),
734 .public_inputs =
transform::map(arg.public_inputs, to_witness_from_input),
736 .proof_type = arg.proof_type,
737 .predicate = predicate,
741 switch (c.proof_type) {
746 af.honk_recursion_constraints.push_back(c);
747 af.original_opcode_indices.honk_recursion_constraints.push_back(opcode_index);
753 af.hn_recursion_constraints.push_back(c);
754 af.original_opcode_indices.hn_recursion_constraints.push_back(opcode_index);
757 af.avm_recursion_constraints.push_back(c);
758 af.original_opcode_indices.avm_recursion_constraints.push_back(opcode_index);
761 af.chonk_recursion_constraints.push_back(c);
762 af.original_opcode_indices.chonk_recursion_constraints.push_back(opcode_index);
766 "acir_format::handle_black_box_fun_call: Invalid PROOF_TYPE in RecursionConstraint.");
769 af.poseidon2_constraints.push_back(Poseidon2Constraint{
773 af.original_opcode_indices.poseidon2_constraints.push_back(opcode_index);
775 bb::assert_failure(
"acir_format::handle_blackbox_func_call: Unrecognized BlackBoxFuncCall variant. An "
776 "error here means there was a serialization error.");
789 .type = BlockType::ROM,
790 .calldata_id = CallDataType::None,
793 for (
const auto&
init : mem_init.
init) {
794 block.init.push_back(
init.value);
801 BB_ASSERT(calldata_id == 0 || calldata_id == 1,
"acir_format::handle_memory_init: Unsupported calldata id");
803 block.type = BlockType::CallData;
804 block.calldata_id = calldata_id == 0 ? CallDataType::Primary : CallDataType::Secondary;
806 block.type = BlockType::ReturnData;
815 auto acir_expression_to_witness_or_constant = [&](
const Acir::Expression& expr) {
818 BB_ASSERT(expr.mul_terms.empty(),
"MemoryOp should not have multiplication terms");
819 BB_ASSERT_LTE(expr.linear_combinations.size(), 1U,
"MemoryOp should have at most one linear term");
821 const fr a_scaling = expr.linear_combinations.size() == 1
826 bool is_witness = a_scaling ==
fr::one() && constant_term ==
fr::zero();
827 bool is_constant = a_scaling ==
fr::zero();
828 BB_ASSERT(is_witness || is_constant,
"MemoryOp expression must be a witness or a constant");
831 .
index = is_witness ?
std::get<1>(expr.linear_combinations[0]).value : bb::stdlib::IS_CONSTANT,
832 .value = is_constant ? constant_term :
fr::zero(),
833 .is_constant = is_constant,
839 BB_ASSERT(expr.mul_terms.empty(),
"MemoryOp expression should not have multiplication terms");
840 BB_ASSERT(expr.linear_combinations.empty(),
"MemoryOp expression should not have linear terms");
845 "MemoryOp expression should be either zero or one");
851 AccessType access_type = is_read_operation(mem_op.
op.
operation) ? AccessType::Read : AccessType::Write;
852 if (access_type == AccessType::Write) {
854 BB_ASSERT((block.
type != BlockType::CallData) && (block.
type != BlockType::ReturnData));
856 block.
type = BlockType::RAM;
864 block.
trace.push_back(acir_mem_op);
869 static constexpr size_t NUM_WIRES = 4;
872 if (linear_terms.size() > NUM_WIRES) {
895 size_t num_witnesses_to_be_put_in_wires = 2 + linear_terms.size();
900 bool lhs_is_distinct_from_linear_terms = !linear_terms.contains(witness_idx_lhs);
901 bool rhs_is_distinct_from_linear_terms = !linear_terms.contains(witness_idx_rhs);
903 if (witness_idx_lhs != witness_idx_rhs) {
904 num_witnesses_to_be_put_in_wires -= lhs_is_distinct_from_linear_terms ? 0U : 1U;
905 num_witnesses_to_be_put_in_wires -= rhs_is_distinct_from_linear_terms ? 0U : 1U;
907 num_witnesses_to_be_put_in_wires -= lhs_is_distinct_from_linear_terms ? 0U : 1U;
910 return num_witnesses_to_be_put_in_wires <= NUM_WIRES;
913 return linear_terms.size() <= NUM_WIRES;
921 uint32_t witness_idx =
std::get<1>(linear_term).value;
922 if (linear_terms.contains(witness_idx)) {
923 linear_terms[witness_idx] += selector_value;
925 linear_terms[witness_idx] = selector_value;
#define BB_ASSERT(expression,...)
#define BB_ASSERT_GT(left, right,...)
#define BB_ASSERT_EQ(actual, expected,...)
#define BB_ASSERT_LTE(left, right,...)
#define BB_ASSERT_LT(left, right,...)
std::string format(Args... args)
uint8_t buffer[RANDOM_BUFFER_SIZE]
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::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::Expression operation
std::vector< Acir::Witness > init
Acir::BlockType block_type
std::variant< AssertZero, BlackBoxFuncCall, MemoryOp, MemoryInit, BrilligCall, Call > value
std::vector< Acir::Circuit > functions
static Program bincodeDeserialize(std::vector< uint8_t >)
std::vector< Acir::Circuit > functions
std::map< Witnesses::Witness, std::vector< uint8_t > > value
static WitnessStack bincodeDeserialize(std::vector< uint8_t >)
static constexpr field one()
static field random_element(numeric::RNG *engine=nullptr) noexcept
static field serialize_from_buffer(const uint8_t *buffer)
static constexpr field zero()