Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: clean up translator circuit builder function definitions #10944

Merged
merged 9 commits into from
Dec 24, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#include "barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp"
#include <cstddef>
namespace bb {
using ECCVMOperation = ECCOpQueue::ECCVMOperation;

/**
* @brief Given the transcript values from the EccOpQueue, the values of the previous accumulator, batching challenge
Expand All @@ -34,40 +33,31 @@ using ECCVMOperation = ECCOpQueue::ECCVMOperation;
* @param evaluation_input_x The value at which we evaluate the polynomials
* @return TranslatorCircuitBuilder::AccumulationInput
*/
template <typename Fq, typename Fr>
TranslatorCircuitBuilder::AccumulationInput generate_witness_values(Fr op_code,
Fr p_x_lo,
Fr p_x_hi,
Fr p_y_lo,
Fr p_y_hi,
Fr z1,
Fr z2,
Fq previous_accumulator,
Fq batching_challenge_v,
Fq evaluation_input_x)
TranslatorCircuitBuilder::AccumulationInput TranslatorCircuitBuilder::generate_witness_values(
const Fr op_code,
const Fr p_x_lo,
const Fr p_x_hi,
const Fr p_y_lo,
const Fr p_y_hi,
const Fr z1,
const Fr z2,
const Fq previous_accumulator,
const Fq batching_challenge_v,
const Fq evaluation_input_x)
{
// All parameters are well-described in the header, this is just for convenience
constexpr size_t NUM_LIMB_BITS = TranslatorCircuitBuilder::NUM_LIMB_BITS;
constexpr size_t NUM_BINARY_LIMBS = TranslatorCircuitBuilder::NUM_BINARY_LIMBS;
constexpr size_t NUM_MICRO_LIMBS = TranslatorCircuitBuilder::NUM_MICRO_LIMBS;
constexpr size_t NUM_LAST_LIMB_BITS = TranslatorCircuitBuilder::NUM_LAST_LIMB_BITS;
constexpr size_t MICRO_LIMB_BITS = TranslatorCircuitBuilder::MICRO_LIMB_BITS;
constexpr size_t TOP_STANDARD_MICROLIMB_BITS = NUM_LAST_LIMB_BITS % MICRO_LIMB_BITS;
constexpr size_t NUM_Z_BITS = TranslatorCircuitBuilder::NUM_Z_BITS;
constexpr size_t TOP_Z_MICROLIMB_BITS = (NUM_Z_BITS % NUM_LIMB_BITS) % MICRO_LIMB_BITS;
constexpr size_t TOP_QUOTIENT_MICROLIMB_BITS =
(TranslatorCircuitBuilder::NUM_QUOTIENT_BITS % NUM_LIMB_BITS) % MICRO_LIMB_BITS;
constexpr auto shift_1 = TranslatorCircuitBuilder::SHIFT_1;
constexpr auto neg_modulus_limbs = TranslatorCircuitBuilder::NEGATIVE_MODULUS_LIMBS;
constexpr auto shift_2_inverse = TranslatorCircuitBuilder::SHIFT_2_INVERSE;

/**
* @brief A small function to transform a native element Fq into its bigfield representation in Fr scalars
*
* @details We transform Fq into an integer and then split it into 68-bit limbs, then convert them to Fr.
*
*/
auto base_element_to_limbs = [](Fq& original) {
auto base_element_to_limbs = [](const Fq& original) {
uint256_t original_uint = original;
return std::array<Fr, NUM_BINARY_LIMBS>({
Fr(original_uint.slice(0, NUM_LIMB_BITS)),
Expand All @@ -83,7 +73,7 @@ TranslatorCircuitBuilder::AccumulationInput generate_witness_values(Fr op_code,
* convert to Fr
*
*/
auto uint512_t_to_limbs = [](uint512_t& original) {
auto uint512_t_to_limbs = [](const uint512_t& original) {
return std::array<Fr, NUM_BINARY_LIMBS>{ Fr(original.slice(0, NUM_LIMB_BITS).lo),
Fr(original.slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS).lo),
Fr(original.slice(2 * NUM_LIMB_BITS, 3 * NUM_LIMB_BITS).lo),
Expand All @@ -94,16 +84,15 @@ TranslatorCircuitBuilder::AccumulationInput generate_witness_values(Fr op_code,
* @brief A method for splitting wide limbs (P_x_lo, P_y_hi, etc) into two limbs
*
*/
auto split_wide_limb_into_2_limbs = [](Fr& wide_limb) {
return std::array<Fr, TranslatorCircuitBuilder::NUM_Z_LIMBS>{ Fr(uint256_t(wide_limb).slice(0, NUM_LIMB_BITS)),
Fr(uint256_t(wide_limb).slice(
NUM_LIMB_BITS, 2 * NUM_LIMB_BITS)) };
auto split_wide_limb_into_2_limbs = [](const Fr& wide_limb) {
return std::array<Fr, NUM_Z_LIMBS>{ Fr(uint256_t(wide_limb).slice(0, NUM_LIMB_BITS)),
Fr(uint256_t(wide_limb).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS)) };
};
/**
* @brief A method to split a full 68-bit limb into 5 14-bit limb and 1 shifted limb for a more secure constraint
*
*/
auto split_standard_limb_into_micro_limbs = [](Fr& limb) {
auto split_standard_limb_into_micro_limbs = [](const Fr& limb) {
static_assert(MICRO_LIMB_BITS == 14);
return std::array<Fr, NUM_MICRO_LIMBS>{
uint256_t(limb).slice(0, MICRO_LIMB_BITS),
Expand All @@ -121,7 +110,7 @@ TranslatorCircuitBuilder::AccumulationInput generate_witness_values(Fr op_code,
* (plus there is 1 extra space for other constraints)
*
*/
auto split_top_limb_into_micro_limbs = [](Fr& limb, size_t last_limb_bits) {
auto split_top_limb_into_micro_limbs = [](const Fr& limb, const size_t last_limb_bits) {
static_assert(MICRO_LIMB_BITS == 14);
return std::array<Fr, NUM_MICRO_LIMBS>{ uint256_t(limb).slice(0, MICRO_LIMB_BITS),
uint256_t(limb).slice(MICRO_LIMB_BITS, 2 * MICRO_LIMB_BITS),
Expand All @@ -137,7 +126,7 @@ TranslatorCircuitBuilder::AccumulationInput generate_witness_values(Fr op_code,
* the last limb)
*
*/
auto split_top_z_limb_into_micro_limbs = [](Fr& limb, size_t last_limb_bits) {
auto split_top_z_limb_into_micro_limbs = [](const Fr& limb, const size_t last_limb_bits) {
static_assert(MICRO_LIMB_BITS == 14);
return std::array<Fr, NUM_MICRO_LIMBS>{ uint256_t(limb).slice(0, MICRO_LIMB_BITS),
uint256_t(limb).slice(MICRO_LIMB_BITS, 2 * MICRO_LIMB_BITS),
Expand All @@ -153,7 +142,7 @@ TranslatorCircuitBuilder::AccumulationInput generate_witness_values(Fr op_code,
* ensure non-overflow of the modulus)
*
*/
auto split_relation_limb_into_micro_limbs = [](Fr& limb) {
auto split_relation_limb_into_micro_limbs = [](const Fr& limb) {
static_assert(MICRO_LIMB_BITS == 14);
return std::array<Fr, 6>{
uint256_t(limb).slice(0, MICRO_LIMB_BITS),
Expand Down Expand Up @@ -237,7 +226,7 @@ TranslatorCircuitBuilder::AccumulationInput generate_witness_values(Fr op_code,
Fr low_wide_relation_limb_part_1 = previous_accumulator_limbs[0] * x_witnesses[0] + op_code +
v_witnesses[0] * p_x_limbs[0] + v_squared_witnesses[0] * p_y_limbs[0] +
v_cubed_witnesses[0] * z_1_limbs[0] + v_quarted_witnesses[0] * z_2_limbs[0] +
quotient_limbs[0] * neg_modulus_limbs[0] -
quotient_limbs[0] * NEGATIVE_MODULUS_LIMBS[0] -
remainder_limbs[0]; // This covers the lowest limb

Fr low_wide_relation_limb =
Expand All @@ -246,14 +235,14 @@ TranslatorCircuitBuilder::AccumulationInput generate_witness_values(Fr op_code,
v_witnesses[1] * p_x_limbs[0] + p_x_limbs[1] * v_witnesses[0] + v_squared_witnesses[1] * p_y_limbs[0] +
v_squared_witnesses[0] * p_y_limbs[1] + v_cubed_witnesses[1] * z_1_limbs[0] +
z_1_limbs[1] * v_cubed_witnesses[0] + v_quarted_witnesses[1] * z_2_limbs[0] +
v_quarted_witnesses[0] * z_2_limbs[1] + quotient_limbs[0] * neg_modulus_limbs[1] +
quotient_limbs[1] * neg_modulus_limbs[0] - remainder_limbs[1]) *
shift_1;
v_quarted_witnesses[0] * z_2_limbs[1] + quotient_limbs[0] * NEGATIVE_MODULUS_LIMBS[1] +
quotient_limbs[1] * NEGATIVE_MODULUS_LIMBS[0] - remainder_limbs[1]) *
SHIFT_1;

// Low bits have to be zero
ASSERT(uint256_t(low_wide_relation_limb).slice(0, 2 * NUM_LIMB_BITS) == 0);

Fr low_wide_relation_limb_divided = low_wide_relation_limb * shift_2_inverse;
Fr low_wide_relation_limb_divided = low_wide_relation_limb * SHIFT_2_INVERSE;

// The high relation limb is the accumulation of the low limb divided by 2¹³⁶ and the combination of limbs with
// indices (0*2,1*1,2*0) with limbs with indices (0*3,1*2,2*1,3*0) multiplied by 2⁶⁸
Expand All @@ -265,28 +254,29 @@ TranslatorCircuitBuilder::AccumulationInput generate_witness_values(Fr op_code,
v_squared_witnesses[2] * p_y_limbs[0] + v_squared_witnesses[1] * p_y_limbs[1] +
v_squared_witnesses[0] * p_y_limbs[2] + v_cubed_witnesses[2] * z_1_limbs[0] +
v_cubed_witnesses[1] * z_1_limbs[1] + v_quarted_witnesses[2] * z_2_limbs[0] +
v_quarted_witnesses[1] * z_2_limbs[1] + quotient_limbs[2] * neg_modulus_limbs[0] +
quotient_limbs[1] * neg_modulus_limbs[1] + quotient_limbs[0] * neg_modulus_limbs[2] - remainder_limbs[2] +
v_quarted_witnesses[1] * z_2_limbs[1] + quotient_limbs[2] * NEGATIVE_MODULUS_LIMBS[0] +
quotient_limbs[1] * NEGATIVE_MODULUS_LIMBS[1] + quotient_limbs[0] * NEGATIVE_MODULUS_LIMBS[2] -
remainder_limbs[2] +
(previous_accumulator_limbs[3] * x_witnesses[0] + previous_accumulator_limbs[2] * x_witnesses[1] +
previous_accumulator_limbs[1] * x_witnesses[2] + previous_accumulator_limbs[0] * x_witnesses[3] +
v_witnesses[3] * p_x_limbs[0] + v_witnesses[2] * p_x_limbs[1] + v_witnesses[1] * p_x_limbs[2] +
v_witnesses[0] * p_x_limbs[3] + v_squared_witnesses[3] * p_y_limbs[0] + v_squared_witnesses[2] * p_y_limbs[1] +
v_squared_witnesses[1] * p_y_limbs[2] + v_squared_witnesses[0] * p_y_limbs[3] +
v_cubed_witnesses[3] * z_1_limbs[0] + v_cubed_witnesses[2] * z_1_limbs[1] +
v_quarted_witnesses[3] * z_2_limbs[0] + v_quarted_witnesses[2] * z_2_limbs[1] +
quotient_limbs[3] * neg_modulus_limbs[0] + quotient_limbs[2] * neg_modulus_limbs[1] +
quotient_limbs[1] * neg_modulus_limbs[2] + quotient_limbs[0] * neg_modulus_limbs[3] - remainder_limbs[3]) *
shift_1;
quotient_limbs[3] * NEGATIVE_MODULUS_LIMBS[0] + quotient_limbs[2] * NEGATIVE_MODULUS_LIMBS[1] +
quotient_limbs[1] * NEGATIVE_MODULUS_LIMBS[2] + quotient_limbs[0] * NEGATIVE_MODULUS_LIMBS[3] -
remainder_limbs[3]) *
SHIFT_1;

// Check that the results lower 136 bits are zero
ASSERT(uint256_t(high_wide_relation_limb).slice(0, 2 * NUM_LIMB_BITS) == 0);

// Get divided version
auto high_wide_relation_limb_divided = high_wide_relation_limb * shift_2_inverse;
auto high_wide_relation_limb_divided = high_wide_relation_limb * SHIFT_2_INVERSE;

const auto last_limb_index = TranslatorCircuitBuilder::NUM_BINARY_LIMBS - 1;
const auto last_limb_index = NUM_BINARY_LIMBS - 1;

const auto NUM_Z_LIMBS = TranslatorCircuitBuilder::NUM_Z_LIMBS;
std::array<std::array<Fr, NUM_MICRO_LIMBS>, NUM_BINARY_LIMBS> P_x_microlimbs;
std::array<std::array<Fr, NUM_MICRO_LIMBS>, NUM_BINARY_LIMBS> P_y_microlimbs;
std::array<std::array<Fr, NUM_MICRO_LIMBS>, NUM_Z_LIMBS> z_1_microlimbs;
Expand All @@ -312,10 +302,10 @@ TranslatorCircuitBuilder::AccumulationInput generate_witness_values(Fr op_code,
z_1_microlimbs[i] = split_standard_limb_into_micro_limbs(z_1_limbs[i]);
z_2_microlimbs[i] = split_standard_limb_into_micro_limbs(z_2_limbs[i]);
}
z_1_microlimbs[TranslatorCircuitBuilder::NUM_Z_LIMBS - 1] =
split_top_z_limb_into_micro_limbs(z_1_limbs[TranslatorCircuitBuilder::NUM_Z_LIMBS - 1], TOP_Z_MICROLIMB_BITS);
z_2_microlimbs[TranslatorCircuitBuilder::NUM_Z_LIMBS - 1] =
split_top_z_limb_into_micro_limbs(z_2_limbs[TranslatorCircuitBuilder::NUM_Z_LIMBS - 1], TOP_Z_MICROLIMB_BITS);
z_1_microlimbs[NUM_Z_LIMBS - 1] =
split_top_z_limb_into_micro_limbs(z_1_limbs[NUM_Z_LIMBS - 1], TOP_Z_MICROLIMB_BITS);
z_2_microlimbs[NUM_Z_LIMBS - 1] =
split_top_z_limb_into_micro_limbs(z_2_limbs[NUM_Z_LIMBS - 1], TOP_Z_MICROLIMB_BITS);

// Split current accumulator into microlimbs for range constraining
for (size_t i = 0; i < last_limb_index; i++) {
Expand All @@ -332,7 +322,7 @@ TranslatorCircuitBuilder::AccumulationInput generate_witness_values(Fr op_code,
split_top_limb_into_micro_limbs(quotient_limbs[last_limb_index], TOP_QUOTIENT_MICROLIMB_BITS);

// Start filling the witness container
TranslatorCircuitBuilder::AccumulationInput input{
AccumulationInput input{
.op_code = op_code,
.P_x_lo = p_x_lo,
.P_x_hi = p_x_hi,
Expand Down Expand Up @@ -561,14 +551,13 @@ void TranslatorCircuitBuilder::create_accumulation_gate(const AccumulationInput
* @tparam Fq
* @return TranslatorCircuitBuilder::AccumulationInput
*/
template <typename Fq>
TranslatorCircuitBuilder::AccumulationInput compute_witness_values_for_one_ecc_op(const ECCVMOperation& ecc_op,
Fq previous_accumulator,
Fq batching_challenge_v,
Fq evaluation_input_x)
{
using Fr = bb::fr;

TranslatorCircuitBuilder::AccumulationInput TranslatorCircuitBuilder::compute_witness_values_for_one_ecc_op(
const ECCVMOperation& ecc_op,
const Fq previous_accumulator,
const Fq batching_challenge_v,
const Fq evaluation_input_x)
{
// Get the Opcode value
Fr op(ecc_op.get_opcode_value());
Fr p_x_lo(0);
Expand All @@ -582,12 +571,10 @@ TranslatorCircuitBuilder::AccumulationInput compute_witness_values_for_one_ecc_o
// the original in-circuit coordinate values are also zero
const auto [x_256, y_256] = ecc_op.get_base_point_standard_form();

p_x_lo = Fr(uint256_t(x_256).slice(0, 2 * TranslatorCircuitBuilder::NUM_LIMB_BITS));
p_x_hi = Fr(uint256_t(x_256).slice(2 * TranslatorCircuitBuilder::NUM_LIMB_BITS,
4 * TranslatorCircuitBuilder::NUM_LIMB_BITS));
p_y_lo = Fr(uint256_t(y_256).slice(0, 2 * TranslatorCircuitBuilder::NUM_LIMB_BITS));
p_y_hi = Fr(uint256_t(y_256).slice(2 * TranslatorCircuitBuilder::NUM_LIMB_BITS,
4 * TranslatorCircuitBuilder::NUM_LIMB_BITS));
p_x_lo = Fr(uint256_t(x_256).slice(0, 2 * NUM_LIMB_BITS));
p_x_hi = Fr(uint256_t(x_256).slice(2 * NUM_LIMB_BITS, 4 * NUM_LIMB_BITS));
p_y_lo = Fr(uint256_t(y_256).slice(0, 2 * NUM_LIMB_BITS));
p_y_hi = Fr(uint256_t(y_256).slice(2 * NUM_LIMB_BITS, 4 * NUM_LIMB_BITS));

// Generate the full witness values
return generate_witness_values(op,
Expand All @@ -601,7 +588,7 @@ TranslatorCircuitBuilder::AccumulationInput compute_witness_values_for_one_ecc_o
batching_challenge_v,
evaluation_input_x);
}
void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(std::shared_ptr<ECCOpQueue> ecc_op_queue)
void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ptr<ECCOpQueue> ecc_op_queue)
{
using Fq = bb::fq;
const auto& raw_ops = ecc_op_queue->get_raw_ops();
Expand Down Expand Up @@ -1068,6 +1055,4 @@ bool TranslatorCircuitBuilder::check_circuit()
}
return true;
};
template TranslatorCircuitBuilder::AccumulationInput generate_witness_values(
bb::fr, bb::fr, bb::fr, bb::fr, bb::fr, bb::fr, bb::fr, bb::fq, bb::fq, bb::fq);
} // namespace bb
Loading
Loading