Skip to content

Commit

Permalink
initial version of reporter of gates
Browse files Browse the repository at this point in the history
Co-authored-by: Leila Wang <[email protected]>
Co-authored-by: Michael Connor <[email protected]>
  • Loading branch information
3 people committed Jun 6, 2024
1 parent 06f03fd commit f6d65af
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 46 deletions.
2 changes: 2 additions & 0 deletions barretenberg/cpp/src/barretenberg/bb/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,8 @@ void gateCount(const std::string& bytecodePath, bool honk_recursion)
constraint_system.num_acir_opcodes,
",\n \"circuit_size\": ",
circuit_size,
",\n \"gates_per_opcode\": ",
constraint_system.gates_per_opcode,
"\n }");

// Attach a comma if we still circuit reports to generate
Expand Down
132 changes: 105 additions & 27 deletions barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,114 +14,192 @@ template class DSLBigInts<MegaCircuitBuilder>;

template <typename Builder>
void build_constraints(Builder& builder,
AcirFormat const& constraint_system,
AcirFormat& constraint_system,
bool has_valid_witness_assignments,
bool honk_recursion)
{
constraint_system.gates_per_opcode = std::vector<size_t>(constraint_system.num_acir_opcodes);
size_t prev_gate_count = 0;

auto compute_gate_diff = [&]() {
size_t new_gate_count = builder.get_total_circuit_size();
size_t diff = new_gate_count - prev_gate_count;
prev_gate_count = new_gate_count;
return diff;
};

// Add arithmetic gates
for (const auto& constraint : constraint_system.poly_triple_constraints) {
for (size_t i = 0; i < constraint_system.poly_triple_constraints.size(); ++i) {
const auto& constraint = constraint_system.poly_triple_constraints[i];
builder.create_poly_gate(constraint);
constraint_system.gates_per_opcode[constraint_system.poly_triple_constraints_original_index[i]] =
compute_gate_diff();
}
for (const auto& constraint : constraint_system.quad_constraints) {
for (size_t i = 0; i < constraint_system.quad_constraints.size(); ++i) {
const auto& constraint = constraint_system.quad_constraints[i];
builder.create_big_mul_gate(constraint);
constraint_system.gates_per_opcode[constraint_system.quad_constraints_original_index[i]] = compute_gate_diff();
}

// Add logic constraint
for (const auto& constraint : constraint_system.logic_constraints) {
for (size_t i = 0; i < constraint_system.logic_constraints.size(); ++i) {
const auto& constraint = constraint_system.logic_constraints[i];
create_logic_gate(
builder, constraint.a, constraint.b, constraint.result, constraint.num_bits, constraint.is_xor_gate);
constraint_system.gates_per_opcode[constraint_system.logic_constraints_original_index[i]] = compute_gate_diff();
}

// Add range constraint
for (const auto& constraint : constraint_system.range_constraints) {
for (size_t i = 0; i < constraint_system.range_constraints.size(); ++i) {
const auto& constraint = constraint_system.range_constraints[i];
builder.create_range_constraint(constraint.witness, constraint.num_bits, "");
constraint_system.gates_per_opcode[constraint_system.range_constraints_original_index[i]] = compute_gate_diff();
}

// Add aes128 constraints
for (const auto& constraint : constraint_system.aes128_constraints) {
for (size_t i = 0; i < constraint_system.aes128_constraints.size(); ++i) {
const auto& constraint = constraint_system.aes128_constraints[i];
create_aes128_constraints(builder, constraint);
constraint_system.gates_per_opcode[constraint_system.aes128_constraints_original_index[i]] =
compute_gate_diff();
}

// Add sha256 constraints
for (const auto& constraint : constraint_system.sha256_constraints) {
for (size_t i = 0; i < constraint_system.sha256_constraints.size(); ++i) {
const auto& constraint = constraint_system.sha256_constraints[i];
create_sha256_constraints(builder, constraint);
constraint_system.gates_per_opcode[constraint_system.sha256_constraints_original_index[i]] =
compute_gate_diff();
}
for (const auto& constraint : constraint_system.sha256_compression) {
for (size_t i = 0; i < constraint_system.sha256_compression.size(); ++i) {
const auto& constraint = constraint_system.sha256_compression[i];
create_sha256_compression_constraints(builder, constraint);
constraint_system.gates_per_opcode[constraint_system.sha256_compression_original_index[i]] =
compute_gate_diff();
}

// Add schnorr constraints
for (const auto& constraint : constraint_system.schnorr_constraints) {
for (size_t i = 0; i < constraint_system.schnorr_constraints.size(); ++i) {
const auto& constraint = constraint_system.schnorr_constraints[i];
create_schnorr_verify_constraints(builder, constraint);
constraint_system.gates_per_opcode[constraint_system.schnorr_constraints_original_index[i]] =
compute_gate_diff();
}

// Add ECDSA k1 constraints
for (const auto& constraint : constraint_system.ecdsa_k1_constraints) {
for (size_t i = 0; i < constraint_system.ecdsa_k1_constraints.size(); ++i) {
const auto& constraint = constraint_system.ecdsa_k1_constraints[i];
create_ecdsa_k1_verify_constraints(builder, constraint, has_valid_witness_assignments);
constraint_system.gates_per_opcode[constraint_system.ecdsa_k1_constraints_original_index[i]] =
compute_gate_diff();
}

// Add ECDSA r1 constraints
for (const auto& constraint : constraint_system.ecdsa_r1_constraints) {
for (size_t i = 0; i < constraint_system.ecdsa_r1_constraints.size(); ++i) {
const auto& constraint = constraint_system.ecdsa_r1_constraints[i];
create_ecdsa_r1_verify_constraints(builder, constraint, has_valid_witness_assignments);
constraint_system.gates_per_opcode[constraint_system.ecdsa_r1_constraints_original_index[i]] =
compute_gate_diff();
}

// Add blake2s constraints
for (const auto& constraint : constraint_system.blake2s_constraints) {
for (size_t i = 0; i < constraint_system.blake2s_constraints.size(); ++i) {
const auto& constraint = constraint_system.blake2s_constraints[i];
create_blake2s_constraints(builder, constraint);
constraint_system.gates_per_opcode[constraint_system.blake2s_constraints_original_index[i]] =
compute_gate_diff();
}

// Add blake3 constraints
for (const auto& constraint : constraint_system.blake3_constraints) {
for (size_t i = 0; i < constraint_system.blake3_constraints.size(); ++i) {
const auto& constraint = constraint_system.blake3_constraints[i];
create_blake3_constraints(builder, constraint);
constraint_system.gates_per_opcode[constraint_system.blake3_constraints_original_index[i]] =
compute_gate_diff();
}

// Add keccak constraints
for (const auto& constraint : constraint_system.keccak_constraints) {
for (size_t i = 0; i < constraint_system.keccak_constraints.size(); ++i) {
const auto& constraint = constraint_system.keccak_constraints[i];
create_keccak_constraints(builder, constraint);
constraint_system.gates_per_opcode[constraint_system.keccak_constraints_original_index[i]] =
compute_gate_diff();
}
for (const auto& constraint : constraint_system.keccak_permutations) {
for (size_t i = 0; i < constraint_system.keccak_permutations.size(); ++i) {
const auto& constraint = constraint_system.keccak_permutations[i];
create_keccak_permutations(builder, constraint);
constraint_system.gates_per_opcode[constraint_system.keccak_permutations_original_index[i]] =
compute_gate_diff();
}

// Add pedersen constraints
for (const auto& constraint : constraint_system.pedersen_constraints) {
for (size_t i = 0; i < constraint_system.pedersen_constraints.size(); ++i) {
const auto& constraint = constraint_system.pedersen_constraints[i];
create_pedersen_constraint(builder, constraint);
constraint_system.gates_per_opcode[constraint_system.pedersen_constraints_original_index[i]] =
compute_gate_diff();
}

for (const auto& constraint : constraint_system.pedersen_hash_constraints) {
for (size_t i = 0; i < constraint_system.pedersen_hash_constraints.size(); ++i) {
const auto& constraint = constraint_system.pedersen_hash_constraints[i];
create_pedersen_hash_constraint(builder, constraint);
constraint_system.gates_per_opcode[constraint_system.pedersen_hash_constraints_original_index[i]] =
compute_gate_diff();
}

for (const auto& constraint : constraint_system.poseidon2_constraints) {
for (size_t i = 0; i < constraint_system.poseidon2_constraints.size(); ++i) {
const auto& constraint = constraint_system.poseidon2_constraints[i];
create_poseidon2_permutations(builder, constraint);
constraint_system.gates_per_opcode[constraint_system.poseidon2_constraints_original_index[i]] =
compute_gate_diff();
}

// Add multi scalar mul constraints
for (const auto& constraint : constraint_system.multi_scalar_mul_constraints) {
for (size_t i = 0; i < constraint_system.multi_scalar_mul_constraints.size(); ++i) {
const auto& constraint = constraint_system.multi_scalar_mul_constraints[i];
create_multi_scalar_mul_constraint(builder, constraint);
constraint_system.gates_per_opcode[constraint_system.multi_scalar_mul_constraints_original_index[i]] =
compute_gate_diff();
}

// Add ec add constraints
for (const auto& constraint : constraint_system.ec_add_constraints) {
for (size_t i = 0; i < constraint_system.ec_add_constraints.size(); ++i) {
const auto& constraint = constraint_system.ec_add_constraints[i];
create_ec_add_constraint(builder, constraint, has_valid_witness_assignments);
constraint_system.gates_per_opcode[constraint_system.ec_add_constraints_original_index[i]] =
compute_gate_diff();
}

// Add block constraints
for (const auto& constraint : constraint_system.block_constraints) {
for (size_t i = 0; i < constraint_system.block_constraints.size(); ++i) {
const auto& constraint = constraint_system.block_constraints[i];
create_block_constraints(builder, constraint, has_valid_witness_assignments);
size_t delta_gates = compute_gate_diff();
size_t avg_gates_per_opcode = delta_gates / constraint_system.block_constraints_indices[i].size();
for (size_t opcode_index : constraint_system.block_constraints_indices[i]) {
constraint_system.gates_per_opcode[opcode_index] = avg_gates_per_opcode;
}
}

// Add big_int constraints
DSLBigInts<Builder> dsl_bigints;
dsl_bigints.set_builder(&builder);
for (const auto& constraint : constraint_system.bigint_from_le_bytes_constraints) {
for (size_t i = 0; i < constraint_system.bigint_from_le_bytes_constraints.size(); ++i) {
const auto& constraint = constraint_system.bigint_from_le_bytes_constraints[i];
create_bigint_from_le_bytes_constraint(builder, constraint, dsl_bigints);
constraint_system.gates_per_opcode[constraint_system.bigint_from_le_bytes_constraints_original_index[i]] =
compute_gate_diff();
}
for (const auto& constraint : constraint_system.bigint_operations) {
for (size_t i = 0; i < constraint_system.bigint_operations.size(); ++i) {
const auto& constraint = constraint_system.bigint_operations[i];
create_bigint_operations_constraint<Builder>(constraint, dsl_bigints, has_valid_witness_assignments);
constraint_system.gates_per_opcode[constraint_system.bigint_operations_original_index[i]] = compute_gate_diff();
}
for (const auto& constraint : constraint_system.bigint_to_le_bytes_constraints) {
for (size_t i = 0; i < constraint_system.bigint_to_le_bytes_constraints.size(); ++i) {
const auto& constraint = constraint_system.bigint_to_le_bytes_constraints[i];
create_bigint_to_le_bytes_constraint(builder, constraint, dsl_bigints);
constraint_system.gates_per_opcode[constraint_system.bigint_to_le_bytes_constraints_original_index[i]] =
compute_gate_diff();
}

// RecursionConstraint
Expand Down Expand Up @@ -319,7 +397,7 @@ void build_constraints(Builder& builder,
* @return Builder
*/
template <>
UltraCircuitBuilder create_circuit(const AcirFormat& constraint_system,
UltraCircuitBuilder create_circuit(AcirFormat& constraint_system,
size_t size_hint,
WitnessVector const& witness,
bool honk_recursion,
Expand All @@ -345,7 +423,7 @@ UltraCircuitBuilder create_circuit(const AcirFormat& constraint_system,
* @return Builder
*/
template <>
MegaCircuitBuilder create_circuit(const AcirFormat& constraint_system,
MegaCircuitBuilder create_circuit(AcirFormat& constraint_system,
[[maybe_unused]] size_t size_hint,
WitnessVector const& witness,
bool honk_recursion,
Expand All @@ -361,6 +439,6 @@ MegaCircuitBuilder create_circuit(const AcirFormat& constraint_system,
return builder;
};

template void build_constraints<MegaCircuitBuilder>(MegaCircuitBuilder&, AcirFormat const&, bool, bool);
template void build_constraints<MegaCircuitBuilder>(MegaCircuitBuilder&, AcirFormat&, bool, bool);

} // namespace acir_format
38 changes: 36 additions & 2 deletions barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,38 +39,72 @@ struct AcirFormat {
std::vector<uint32_t> public_inputs;

std::vector<LogicConstraint> logic_constraints;
// the index (in the opcodes array) of each constraint in logic_constraints.
// maybe rename to : "opcode_index_of_logic_constraints"
std::vector<size_t> logic_constraints_original_index;
std::vector<RangeConstraint> range_constraints;
std::vector<size_t> range_constraints_original_index;
std::vector<AES128Constraint> aes128_constraints;
std::vector<size_t> aes128_constraints_original_index;
std::vector<Sha256Constraint> sha256_constraints;
std::vector<size_t> sha256_constraints_original_index;
std::vector<Sha256Compression> sha256_compression;
std::vector<size_t> sha256_compression_original_index;
std::vector<SchnorrConstraint> schnorr_constraints;
std::vector<size_t> schnorr_constraints_original_index;
std::vector<EcdsaSecp256k1Constraint> ecdsa_k1_constraints;
std::vector<size_t> ecdsa_k1_constraints_original_index;
std::vector<EcdsaSecp256r1Constraint> ecdsa_r1_constraints;
std::vector<size_t> ecdsa_r1_constraints_original_index;
std::vector<Blake2sConstraint> blake2s_constraints;
std::vector<size_t> blake2s_constraints_original_index;
std::vector<Blake3Constraint> blake3_constraints;
std::vector<size_t> blake3_constraints_original_index;
std::vector<KeccakConstraint> keccak_constraints;
std::vector<size_t> keccak_constraints_original_index;
std::vector<Keccakf1600> keccak_permutations;
std::vector<size_t> keccak_permutations_original_index;
std::vector<PedersenConstraint> pedersen_constraints;
std::vector<size_t> pedersen_constraints_original_index;
std::vector<PedersenHashConstraint> pedersen_hash_constraints;
std::vector<size_t> pedersen_hash_constraints_original_index;
std::vector<Poseidon2Constraint> poseidon2_constraints;
std::vector<size_t> poseidon2_constraints_original_index;
std::vector<MultiScalarMul> multi_scalar_mul_constraints;
std::vector<size_t> multi_scalar_mul_constraints_original_index;
std::vector<EcAdd> ec_add_constraints;
std::vector<size_t> ec_add_constraints_original_index;
std::vector<RecursionConstraint> recursion_constraints;
std::vector<size_t> recursion_constraints_original_index;
std::vector<HonkRecursionConstraint> honk_recursion_constraints;
std::vector<size_t> honk_recursion_constraints_original_index;
std::vector<BigIntFromLeBytes> bigint_from_le_bytes_constraints;
std::vector<size_t> bigint_from_le_bytes_constraints_original_index;
std::vector<BigIntToLeBytes> bigint_to_le_bytes_constraints;
std::vector<size_t> bigint_to_le_bytes_constraints_original_index;
std::vector<BigIntOperation> bigint_operations;
std::vector<size_t> bigint_operations_original_index;

// A standard plonk arithmetic constraint, as defined in the poly_triple struct, consists of selector values
// for q_M,q_L,q_R,q_O,q_C and indices of three variables taking the role of left, right and output wire
// This could be a large vector so use slab allocator, we don't expect the blackbox implementations to be so large.
std::vector<bb::poly_triple_<bb::curve::BN254::ScalarField>,
bb::ContainerSlabAllocator<bb::poly_triple_<bb::curve::BN254::ScalarField>>>
poly_triple_constraints;
std::vector<size_t> poly_triple_constraints_original_index;

std::vector<bb::mul_quad_<bb::curve::BN254::ScalarField>,
bb::ContainerSlabAllocator<bb::mul_quad_<bb::curve::BN254::ScalarField>>>
quad_constraints;
std::vector<size_t> quad_constraints_original_index;

std::vector<BlockConstraint> block_constraints;
// vec of blocks => vec of opcode indices:
std::vector<std::vector<size_t>> block_constraints_indices;

// Number of gates added to the circuit per original opcode.
// Has the same length as the opcode vector.
std::vector<size_t> gates_per_opcode;

// For serialization, update with any new fields
MSGPACK_FIELDS(varnum,
Expand Down Expand Up @@ -142,15 +176,15 @@ struct AcirProgramStack {
};

template <typename Builder = bb::UltraCircuitBuilder>
Builder create_circuit(const AcirFormat& constraint_system,
Builder create_circuit(AcirFormat& constraint_system,
size_t size_hint = 0,
WitnessVector const& witness = {},
bool honk_recursion = false,
std::shared_ptr<bb::ECCOpQueue> op_queue = std::make_shared<bb::ECCOpQueue>());

template <typename Builder>
void build_constraints(Builder& builder,
AcirFormat const& constraint_system,
AcirFormat& constraint_system,
bool has_valid_witness_assignments,
bool honk_recursion = false); // honk_recursion means we will honk to recursively verify this
// circuit. This distinction is needed to not add the default
Expand Down
Loading

0 comments on commit f6d65af

Please sign in to comment.