Skip to content

Commit

Permalink
amortising table gates over all opcodes which use the table... ish
Browse files Browse the repository at this point in the history
  • Loading branch information
iAmMichaelConnor committed Jun 7, 2024
1 parent f6d65af commit 14aa792
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 29 deletions.
135 changes: 107 additions & 28 deletions barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "acir_format.hpp"
#include "barretenberg/common/log.hpp"
#include "barretenberg/common/throw_or_abort.hpp"
#include "barretenberg/stdlib/primitives/field/field_conversion.hpp"
#include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp"
#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp"
Expand All @@ -20,161 +21,211 @@ void build_constraints(Builder& builder,
{
constraint_system.gates_per_opcode = std::vector<size_t>(constraint_system.num_acir_opcodes);
size_t prev_gate_count = 0;
size_t prev_table_size = 0;

auto compute_gate_diff = [&]() {
auto compute_gate_diff = [&](size_t const num_constraints_of_this_type, size_t& table_size_of_this_type) -> size_t {
size_t new_gate_count = builder.get_total_circuit_size();
size_t diff = new_gate_count - prev_gate_count;
size_t new_table_size = builder.get_tables_size();
size_t gate_diff = new_gate_count - prev_gate_count;
size_t table_diff = new_table_size - prev_table_size;

if (table_diff > 0 && table_size_of_this_type > 0) {
throw_or_abort(
"My current understanding is that tables shouldn't grow in size if the opcode has already been "
"encountered earlier.");
}

if (gate_diff < table_diff) {
throw_or_abort("Unexpected error");
}

table_size_of_this_type += table_diff;
size_t amortised_gate_diff =
(gate_diff - table_diff) + (table_size_of_this_type / num_constraints_of_this_type);

prev_gate_count = new_gate_count;
return diff;
prev_table_size = new_table_size;
return amortised_gate_diff;
};

// Add arithmetic gates
size_t table_size_for_poly_triple_constraints = 0;
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();
compute_gate_diff(constraint_system.poly_triple_constraints.size(), table_size_for_poly_triple_constraints);
}

size_t table_size_for_quad_constraints = 0;
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();
constraint_system.gates_per_opcode[constraint_system.quad_constraints_original_index[i]] =
compute_gate_diff(constraint_system.quad_constraints.size(), table_size_for_quad_constraints);
}

// Add logic constraint
size_t table_size_for_logic_constraints = 0;
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();
constraint_system.gates_per_opcode[constraint_system.logic_constraints_original_index[i]] =
compute_gate_diff(constraint_system.logic_constraints.size(), table_size_for_logic_constraints);
}

// Add range constraint
size_t table_size_for_range_constraints = 0;
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();
constraint_system.gates_per_opcode[constraint_system.range_constraints_original_index[i]] =
compute_gate_diff(constraint_system.range_constraints.size(), table_size_for_range_constraints);
}

// Add aes128 constraints
size_t table_size_for_aes128_constraints = 0;
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();
compute_gate_diff(constraint_system.aes128_constraints.size(), table_size_for_aes128_constraints);
}

// Add sha256 constraints
size_t table_size_for_sha256_constraints = 0;
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();
compute_gate_diff(constraint_system.sha256_constraints.size(), table_size_for_sha256_constraints);
}

size_t table_size_for_sha256_compression_constraints = 0;
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();
constraint_system.gates_per_opcode[constraint_system.sha256_compression_original_index[i]] = compute_gate_diff(
constraint_system.sha256_compression.size(), table_size_for_sha256_compression_constraints);
}

// Add schnorr constraints
size_t table_size_for_schnorr_constraints = 0;
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();
compute_gate_diff(constraint_system.schnorr_constraints.size(), table_size_for_schnorr_constraints);
}

// Add ECDSA k1 constraints
size_t table_size_for_ecdsa_k1_constraints = 0;
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();
compute_gate_diff(constraint_system.ecdsa_k1_constraints.size(), table_size_for_ecdsa_k1_constraints);
}

// Add ECDSA r1 constraints
size_t table_size_for_ecdsa_r1_constraints = 0;
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();
compute_gate_diff(constraint_system.ecdsa_r1_constraints.size(), table_size_for_ecdsa_r1_constraints);
}

// Add blake2s constraints
size_t table_size_for_blake2s_constraints = 0;
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();
compute_gate_diff(constraint_system.blake2s_constraints.size(), table_size_for_blake2s_constraints);
}

// Add blake3 constraints
size_t table_size_for_blake3_constraints = 0;
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();
compute_gate_diff(constraint_system.blake3_constraints.size(), table_size_for_blake3_constraints);
}

// Add keccak constraints
size_t table_size_for_keccak_constraints = 0;
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();
compute_gate_diff(constraint_system.keccak_constraints.size(), table_size_for_keccak_constraints);
}

size_t table_size_for_keccak_permutations = 0;
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();
compute_gate_diff(constraint_system.keccak_permutations.size(), table_size_for_keccak_permutations);
}

// Add pedersen constraints
size_t table_size_for_pedersen_constraints = 0;
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();
compute_gate_diff(constraint_system.pedersen_constraints.size(), table_size_for_pedersen_constraints);
}

size_t table_size_for_pedersen_hash_constraints = 0;
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();
compute_gate_diff(constraint_system.pedersen_hash_constraints.size(),
table_size_for_pedersen_hash_constraints);
}

size_t table_size_for_poseidon2_constraints = 0;
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();
compute_gate_diff(constraint_system.poseidon2_constraints.size(), table_size_for_poseidon2_constraints);
}

// Add multi scalar mul constraints
size_t table_size_for_multi_scalar_mul_constraints = 0;
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();
compute_gate_diff(constraint_system.multi_scalar_mul_constraints.size(),
table_size_for_multi_scalar_mul_constraints);
}

// Add ec add constraints
size_t table_size_for_ec_add_constraints = 0;
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();
compute_gate_diff(constraint_system.ec_add_constraints.size(), table_size_for_ec_add_constraints);
}

// Add block constraints
for (size_t i = 0; i < constraint_system.block_constraints.size(); ++i) {
size_t block_constraints_size = constraint_system.block_constraints.size();
std::vector<size_t> table_sizes_for_block_constraints(block_constraints_size, size_t(0));
for (size_t i = 0; i < 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();
// Note sure about taking the size of `init`, like this. Got confused with all the vectors.
size_t delta_gates =
compute_gate_diff(constraint_system.block_constraints[i].init.size(), table_sizes_for_block_constraints[i]);
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;
Expand All @@ -184,22 +235,30 @@ void build_constraints(Builder& builder,
// Add big_int constraints
DSLBigInts<Builder> dsl_bigints;
dsl_bigints.set_builder(&builder);
size_t table_size_for_bigint_from_le_bytes_constraints = 0;
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();
compute_gate_diff(constraint_system.bigint_from_le_bytes_constraints.size(),
table_size_for_bigint_from_le_bytes_constraints);
}

size_t table_size_for_bigint_operations = 0;
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();
constraint_system.gates_per_opcode[constraint_system.bigint_operations_original_index[i]] =
compute_gate_diff(constraint_system.bigint_operations.size(), table_size_for_bigint_operations);
}

size_t table_size_for_bigint_to_le_bytes_constraints = 0;
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();
compute_gate_diff(constraint_system.bigint_to_le_bytes_constraints.size(),
table_size_for_bigint_to_le_bytes_constraints);
}

// RecursionConstraint
Expand Down Expand Up @@ -230,6 +289,7 @@ void build_constraints(Builder& builder,
auto proof_size_no_pub_inputs = recursion_proof_size_without_public_inputs();

// Add recursion constraints
size_t table_size_for_recursion_constraints = 0;
for (auto constraint : constraint_system.recursion_constraints) {
// A proof passed into the constraint should be stripped of its public inputs, except in the case where a
// proof contains an aggregation object itself. We refer to this as the `nested_aggregation_object`. The
Expand Down Expand Up @@ -265,12 +325,15 @@ void build_constraints(Builder& builder,
constraint.proof.begin() +
static_cast<std::ptrdiff_t>(RecursionConstraint::AGGREGATION_OBJECT_SIZE));
}

current_output_aggregation_object = create_recursion_constraints(builder,
constraint,
current_input_aggregation_object,
nested_aggregation_object,
has_valid_witness_assignments);
current_input_aggregation_object = current_output_aggregation_object;

compute_gate_diff(constraint_system.recursion_constraints.size(), table_size_for_recursion_constraints);
}

// Now that the circuit has been completely built, we add the output aggregation as public
Expand Down Expand Up @@ -310,6 +373,7 @@ void build_constraints(Builder& builder,
};

// Add recursion constraints
size_t table_size_for_honk_recursion_constraints = 0;
for (auto constraint : constraint_system.honk_recursion_constraints) {
// A proof passed into the constraint should be stripped of its inner public inputs, but not the nested
// aggregation object itself. The verifier circuit requires that the indices to a nested proof aggregation
Expand All @@ -334,6 +398,9 @@ void build_constraints(Builder& builder,
current_aggregation_object,
nested_aggregation_object,
has_valid_witness_assignments);

compute_gate_diff(constraint_system.honk_recursion_constraints.size(),
table_size_for_honk_recursion_constraints);
}

// Now that the circuit has been completely built, we add the output aggregation as public
Expand Down Expand Up @@ -410,6 +477,18 @@ UltraCircuitBuilder create_circuit(AcirFormat& constraint_system,
bool has_valid_witness_assignments = !witness.empty();
build_constraints(builder, constraint_system, has_valid_witness_assignments, honk_recursion);

// I was doing this to check whether the final gate count matches the sum of the amortised gate counts. It doesn't.
// size_t sum = 0;
// for (size_t i : constraint_system.gates_per_opcode) {
// sum += i;
// }
// // if (builder.get_total_circuit_size() != sum) {
// // throw_or_abort("Badly counted num gates!!");
// // }
// constraint_system.gates_per_opcode[constraint_system.gates_per_opcode.size() - 1] =
// builder.get_total_circuit_size();
// constraint_system.gates_per_opcode[constraint_system.gates_per_opcode.size() - 2] = sum;

return builder;
};

Expand Down
Loading

0 comments on commit 14aa792

Please sign in to comment.