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

Cleanup roots of unity in KZGSettings #467

Merged
merged 10 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,11 +662,11 @@ static void g1_fft_fast(
*/
C_KZG_RET g1_fft(g1_t *out, const g1_t *in, size_t n, const KZGSettings *s) {
/* Ensure the length is valid */
if (n > s->max_width || !is_power_of_two(n)) {
if (n > s->domain_size || !is_power_of_two(n)) {
return C_KZG_BADARGS;
}

uint64_t stride = s->max_width / n;
uint64_t stride = s->domain_size / n;
g1_fft_fast(out, in, 1, s->expanded_roots_of_unity, stride, n);

return C_KZG_OK;
Expand All @@ -685,11 +685,11 @@ C_KZG_RET g1_fft(g1_t *out, const g1_t *in, size_t n, const KZGSettings *s) {
*/
C_KZG_RET g1_ifft(g1_t *out, const g1_t *in, size_t n, const KZGSettings *s) {
/* Ensure the length is valid */
if (n > s->max_width || !is_power_of_two(n)) {
if (n > s->domain_size || !is_power_of_two(n)) {
return C_KZG_BADARGS;
}

uint64_t stride = s->max_width / n;
uint64_t stride = s->domain_size / n;
g1_fft_fast(out, in, 1, s->reverse_roots_of_unity, stride, n);

fr_t inv_len;
Expand Down
18 changes: 11 additions & 7 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,18 @@ typedef Bytes48 KZGProof;

/** Stores the setup and parameters needed for computing KZG proofs. */
typedef struct {
/** The length of `roots_of_unity`, a power of 2. */
uint64_t max_width;
/** Powers of the primitive root of unity determined by `SCALE2_ROOT_OF_UNITY` in bit-reversal
* permutation order, length `max_width`. */
fr_t *roots_of_unity;
/** The expanded roots of unity. */
/** The size of our multiplicative subgroup (the roots of unity). This is the size of
* the extended domain (after the RS encoding has been applied), so the size of
* the subgroup is FIELD_ELEMENTS_PER_EXT_BLOB. */
uint64_t domain_size;
/** Roots of unity in bit-reversal permutation order.
asn-d6 marked this conversation as resolved.
Show resolved Hide resolved
* The array contains `domain_size` elements. */
fr_t *brp_roots_of_unity;
asn-d6 marked this conversation as resolved.
Show resolved Hide resolved
/** Roots of unity for the subgroup of size `domain_size`.
* The array contains `domain_size + 1` elements, it starts and ends with Fr::one(). */
fr_t *expanded_roots_of_unity;
/** The bit-reversal permuted roots of unity. */
/** Roots of unity for the subgroup of size `domain_size` reversed. Only used in FFTs.
* The array contains `domain_size + 1` elements: it starts and ends with Fr::one(). */
fr_t *reverse_roots_of_unity;
asn-d6 marked this conversation as resolved.
Show resolved Hide resolved
/** G1 group elements from the trusted setup in monomial form. */
asn-d6 marked this conversation as resolved.
Show resolved Hide resolved
g1_t *g1_values_monomial;
Expand Down
18 changes: 9 additions & 9 deletions src/eip4844.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ static C_KZG_RET evaluate_polynomial_in_evaluation_form(
fr_t *inverses_in = NULL;
fr_t *inverses = NULL;
uint64_t i;
const fr_t *roots_of_unity = s->roots_of_unity;
const fr_t *brp_roots_of_unity = s->brp_roots_of_unity;

ret = new_fr_array(&inverses_in, FIELD_ELEMENTS_PER_BLOB);
if (ret != C_KZG_OK) goto out;
Expand All @@ -210,20 +210,20 @@ static C_KZG_RET evaluate_polynomial_in_evaluation_form(
* given, we can just return the result directly. Note that special-casing this is
* necessary, as the formula below would divide by zero otherwise.
*/
if (fr_equal(x, &roots_of_unity[i])) {
if (fr_equal(x, &brp_roots_of_unity[i])) {
*out = p->evals[i];
ret = C_KZG_OK;
goto out;
}
blst_fr_sub(&inverses_in[i], x, &roots_of_unity[i]);
blst_fr_sub(&inverses_in[i], x, &brp_roots_of_unity[i]);
}

ret = fr_batch_inv(inverses, inverses_in, FIELD_ELEMENTS_PER_BLOB);
if (ret != C_KZG_OK) goto out;

*out = FR_ZERO;
for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) {
blst_fr_mul(&tmp, &inverses[i], &roots_of_unity[i]);
blst_fr_mul(&tmp, &inverses[i], &brp_roots_of_unity[i]);
blst_fr_mul(&tmp, &tmp, &p->evals[i]);
blst_fr_add(out, out, &tmp);
}
Expand Down Expand Up @@ -428,7 +428,7 @@ static C_KZG_RET compute_kzg_proof_impl(

fr_t tmp;
Polynomial q;
const fr_t *roots_of_unity = s->roots_of_unity;
const fr_t *brp_roots_of_unity = s->brp_roots_of_unity;
uint64_t i;
/* m != 0 indicates that the evaluation point z equals root_of_unity[m-1] */
uint64_t m = 0;
Expand All @@ -439,15 +439,15 @@ static C_KZG_RET compute_kzg_proof_impl(
if (ret != C_KZG_OK) goto out;

for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) {
if (fr_equal(z, &roots_of_unity[i])) {
if (fr_equal(z, &brp_roots_of_unity[i])) {
/* We are asked to compute a KZG proof inside the domain */
m = i + 1;
inverses_in[i] = FR_ONE;
continue;
}
// (p_i - y) / (ω_i - z)
blst_fr_sub(&q.evals[i], &polynomial->evals[i], y_out);
blst_fr_sub(&inverses_in[i], &roots_of_unity[i], z);
blst_fr_sub(&inverses_in[i], &brp_roots_of_unity[i], z);
}

ret = fr_batch_inv(inverses, inverses_in, FIELD_ELEMENTS_PER_BLOB);
Expand All @@ -462,7 +462,7 @@ static C_KZG_RET compute_kzg_proof_impl(
for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) {
if (i == m) continue;
/* Build denominator: z * (z - ω_i) */
blst_fr_sub(&tmp, z, &roots_of_unity[i]);
blst_fr_sub(&tmp, z, &brp_roots_of_unity[i]);
blst_fr_mul(&inverses_in[i], &tmp, z);
}

Expand All @@ -473,7 +473,7 @@ static C_KZG_RET compute_kzg_proof_impl(
if (i == m) continue;
/* Build numerator: ω_i * (p_i - y) */
blst_fr_sub(&tmp, &polynomial->evals[i], y_out);
blst_fr_mul(&tmp, &tmp, &roots_of_unity[i]);
blst_fr_mul(&tmp, &tmp, &brp_roots_of_unity[i]);
/* Do the division: (p_i - y) * ω_i / (z * (z - ω_i)) */
blst_fr_mul(&tmp, &tmp, &inverses[i]);
blst_fr_add(&q.evals[m], &q.evals[m], &tmp);
Expand Down
58 changes: 29 additions & 29 deletions src/eip7594.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,11 @@ static void fr_fft_fast(
*/
static C_KZG_RET fr_fft(fr_t *out, const fr_t *in, size_t n, const KZGSettings *s) {
/* Ensure the length is valid */
if (n > s->max_width || !is_power_of_two(n)) {
if (n > s->domain_size || !is_power_of_two(n)) {
return C_KZG_BADARGS;
}

size_t stride = s->max_width / n;
size_t stride = s->domain_size / n;
fr_fft_fast(out, in, 1, s->expanded_roots_of_unity, stride, n);

return C_KZG_OK;
Expand All @@ -177,11 +177,11 @@ static C_KZG_RET fr_fft(fr_t *out, const fr_t *in, size_t n, const KZGSettings *
*/
static C_KZG_RET fr_ifft(fr_t *out, const fr_t *in, size_t n, const KZGSettings *s) {
/* Ensure the length is valid */
if (n > s->max_width || !is_power_of_two(n)) {
if (n > s->domain_size || !is_power_of_two(n)) {
return C_KZG_BADARGS;
}

size_t stride = s->max_width / n;
size_t stride = s->domain_size / n;
fr_fft_fast(out, in, 1, s->reverse_roots_of_unity, stride, n);

fr_t inv_len;
Expand Down Expand Up @@ -285,8 +285,8 @@ static C_KZG_RET vanishing_polynomial_for_missing_cells(
ret = new_fr_array(&short_vanishing_poly, (len_missing_cells + 1));
if (ret != C_KZG_OK) goto out;

/* Check if max_width is divisible by CELLS_PER_EXT_BLOB */
assert(s->max_width % CELLS_PER_EXT_BLOB == 0);
/* Check if domain_size is divisible by CELLS_PER_EXT_BLOB */
assert(s->domain_size % CELLS_PER_EXT_BLOB == 0);

/*
* For each missing cell index, choose the corresponding root of unity from the subgroup of
Expand All @@ -295,7 +295,7 @@ static C_KZG_RET vanishing_polynomial_for_missing_cells(
* In other words, if the missing index is `i`, then we add \omega^i to the roots array, where
* \omega is a primitive `CELLS_PER_EXT_BLOB` root of unity.
*/
size_t stride = s->max_width / CELLS_PER_EXT_BLOB;
size_t stride = s->domain_size / CELLS_PER_EXT_BLOB;
for (size_t i = 0; i < len_missing_cells; i++) {
roots[i] = s->expanded_roots_of_unity[missing_cell_indices[i] * stride];
}
Expand Down Expand Up @@ -457,28 +457,28 @@ static C_KZG_RET recover_cells_impl(
fr_t *cells_brp = NULL;

/* Allocate space for arrays */
ret = c_kzg_calloc((void **)&missing_cell_indices, s->max_width, sizeof(uint64_t));
ret = c_kzg_calloc((void **)&missing_cell_indices, s->domain_size, sizeof(uint64_t));
if (ret != C_KZG_OK) goto out;
ret = new_fr_array(&vanishing_poly_eval, s->max_width);
ret = new_fr_array(&vanishing_poly_eval, s->domain_size);
if (ret != C_KZG_OK) goto out;
ret = new_fr_array(&vanishing_poly_coeff, s->max_width);
ret = new_fr_array(&vanishing_poly_coeff, s->domain_size);
if (ret != C_KZG_OK) goto out;
ret = new_fr_array(&extended_evaluation_times_zero, s->max_width);
ret = new_fr_array(&extended_evaluation_times_zero, s->domain_size);
if (ret != C_KZG_OK) goto out;
ret = new_fr_array(&extended_evaluation_times_zero_coeffs, s->max_width);
ret = new_fr_array(&extended_evaluation_times_zero_coeffs, s->domain_size);
if (ret != C_KZG_OK) goto out;
ret = new_fr_array(&extended_evaluations_over_coset, s->max_width);
ret = new_fr_array(&extended_evaluations_over_coset, s->domain_size);
if (ret != C_KZG_OK) goto out;
ret = new_fr_array(&vanishing_poly_over_coset, s->max_width);
ret = new_fr_array(&vanishing_poly_over_coset, s->domain_size);
if (ret != C_KZG_OK) goto out;
ret = new_fr_array(&reconstructed_poly_coeff, s->max_width);
ret = new_fr_array(&reconstructed_poly_coeff, s->domain_size);
if (ret != C_KZG_OK) goto out;
ret = new_fr_array(&cells_brp, s->max_width);
ret = new_fr_array(&cells_brp, s->domain_size);
if (ret != C_KZG_OK) goto out;

/* Bit-reverse the data points, stored in new array */
memcpy(cells_brp, cells, s->max_width * sizeof(fr_t));
ret = bit_reversal_permutation(cells_brp, sizeof(fr_t), s->max_width);
memcpy(cells_brp, cells, s->domain_size * sizeof(fr_t));
ret = bit_reversal_permutation(cells_brp, sizeof(fr_t), s->domain_size);
if (ret != C_KZG_OK) goto out;

/* Identify missing cells */
Expand All @@ -505,11 +505,11 @@ static C_KZG_RET recover_cells_impl(
if (ret != C_KZG_OK) goto out;

/* Convert Z(x) to evaluation form */
ret = fr_fft(vanishing_poly_eval, vanishing_poly_coeff, s->max_width, s);
ret = fr_fft(vanishing_poly_eval, vanishing_poly_coeff, s->domain_size, s);
if (ret != C_KZG_OK) goto out;

/* Compute (E*Z)(x) = E(x) * Z(x) in evaluation form over the FFT domain */
for (size_t i = 0; i < s->max_width; i++) {
for (size_t i = 0; i < s->domain_size; i++) {
if (fr_is_null(&cells_brp[i])) {
extended_evaluation_times_zero[i] = FR_ZERO;
} else {
Expand All @@ -519,7 +519,7 @@ static C_KZG_RET recover_cells_impl(

/* Convert (E*Z)(x) to monomial form */
ret = fr_ifft(
extended_evaluation_times_zero_coeffs, extended_evaluation_times_zero, s->max_width, s
extended_evaluation_times_zero_coeffs, extended_evaluation_times_zero, s->domain_size, s
);
if (ret != C_KZG_OK) goto out;

Expand All @@ -530,15 +530,15 @@ static C_KZG_RET recover_cells_impl(
* Q3 = D(k * x)
*/
ret = coset_fft(
extended_evaluations_over_coset, extended_evaluation_times_zero_coeffs, s->max_width, s
extended_evaluations_over_coset, extended_evaluation_times_zero_coeffs, s->domain_size, s
);
if (ret != C_KZG_OK) goto out;

ret = coset_fft(vanishing_poly_over_coset, vanishing_poly_coeff, s->max_width, s);
ret = coset_fft(vanishing_poly_over_coset, vanishing_poly_coeff, s->domain_size, s);
if (ret != C_KZG_OK) goto out;

/* The result of the division is Q3 */
for (size_t i = 0; i < s->max_width; i++) {
for (size_t i = 0; i < s->domain_size; i++) {
fr_div(
&extended_evaluations_over_coset[i],
&extended_evaluations_over_coset[i],
Expand All @@ -552,18 +552,18 @@ static C_KZG_RET recover_cells_impl(
*/

/* Convert the evaluations back to coefficents */
ret = coset_ifft(reconstructed_poly_coeff, extended_evaluations_over_coset, s->max_width, s);
ret = coset_ifft(reconstructed_poly_coeff, extended_evaluations_over_coset, s->domain_size, s);
if (ret != C_KZG_OK) goto out;

/*
* After unscaling the reconstructed polynomial, we have D(x) which evaluates to our original
* data at the roots of unity. Next, we evaluate the polynomial to get the original data.
*/
ret = fr_fft(reconstructed_data_out, reconstructed_poly_coeff, s->max_width, s);
ret = fr_fft(reconstructed_data_out, reconstructed_poly_coeff, s->domain_size, s);
if (ret != C_KZG_OK) goto out;

/* Bit-reverse the recovered data points */
ret = bit_reversal_permutation(reconstructed_data_out, sizeof(fr_t), s->max_width);
ret = bit_reversal_permutation(reconstructed_data_out, sizeof(fr_t), s->domain_size);
if (ret != C_KZG_OK) goto out;

out:
Expand Down Expand Up @@ -1097,15 +1097,15 @@ C_KZG_RET recover_cells_and_kzg_proofs(
}

/* Do allocations */
ret = new_fr_array(&recovered_cells_fr, s->max_width);
ret = new_fr_array(&recovered_cells_fr, s->domain_size);
if (ret != C_KZG_OK) goto out;
ret = new_g1_array(&recovered_proofs_g1, CELLS_PER_EXT_BLOB);
if (ret != C_KZG_OK) goto out;
ret = c_kzg_malloc((void **)&blob, BYTES_PER_BLOB);
if (ret != C_KZG_OK) goto out;

/* Initialize all cells as missing */
for (size_t i = 0; i < s->max_width; i++) {
for (size_t i = 0; i < s->domain_size; i++) {
recovered_cells_fr[i] = FR_NULL;
}

Expand Down
38 changes: 19 additions & 19 deletions src/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,31 +84,31 @@ static C_KZG_RET compute_roots_of_unity(KZGSettings *s) {
fr_t root_of_unity;

uint32_t max_scale = 0;
while ((1ULL << max_scale) < s->max_width)
while ((1ULL << max_scale) < s->domain_size)
max_scale++;

/* Ensure this element will exist */
if (max_scale >= NUM_ELEMENTS(SCALE2_ROOT_OF_UNITY)) {
return C_KZG_BADARGS;
}

/* Get the root of unity */
/* Get the right subgroup generator */
blst_fr_from_uint64(&root_of_unity, SCALE2_ROOT_OF_UNITY[max_scale]);

/* Populate the roots of unity */
ret = expand_root_of_unity(s->expanded_roots_of_unity, &root_of_unity, s->max_width);
ret = expand_root_of_unity(s->expanded_roots_of_unity, &root_of_unity, s->domain_size);
if (ret != C_KZG_OK) goto out;

/* Copy all but the last root to the roots of unity */
memcpy(s->roots_of_unity, s->expanded_roots_of_unity, sizeof(fr_t) * s->max_width);
memcpy(s->brp_roots_of_unity, s->expanded_roots_of_unity, sizeof(fr_t) * s->domain_size);

/* Permute the roots of unity */
ret = bit_reversal_permutation(s->roots_of_unity, sizeof(fr_t), s->max_width);
/* Apply the bit reversal permutation to the roots of unity */
ret = bit_reversal_permutation(s->brp_roots_of_unity, sizeof(fr_t), s->domain_size);
if (ret != C_KZG_OK) goto out;

/* Populate reverse roots of unity */
for (uint64_t i = 0; i <= s->max_width; i++) {
s->reverse_roots_of_unity[i] = s->expanded_roots_of_unity[s->max_width - i];
for (uint64_t i = 0; i <= s->domain_size; i++) {
s->reverse_roots_of_unity[i] = s->expanded_roots_of_unity[s->domain_size - i];
}

out:
Expand All @@ -124,8 +124,8 @@ static C_KZG_RET compute_roots_of_unity(KZGSettings *s) {
*/
void free_trusted_setup(KZGSettings *s) {
if (s == NULL) return;
s->max_width = 0;
c_kzg_free(s->roots_of_unity);
s->domain_size = 0;
c_kzg_free(s->brp_roots_of_unity);
c_kzg_free(s->expanded_roots_of_unity);
c_kzg_free(s->reverse_roots_of_unity);
c_kzg_free(s->g1_values_monomial);
Expand Down Expand Up @@ -201,7 +201,7 @@ static C_KZG_RET init_fk20_multi_settings(KZGSettings *s) {
blst_p1_affine *p_affine = NULL;
bool precompute = s->wbits != 0;

n = s->max_width / 2;
n = s->domain_size / 2;
k = n / FIELD_ELEMENTS_PER_CELL;
k2 = 2 * k;

Expand Down Expand Up @@ -338,8 +338,8 @@ C_KZG_RET load_trusted_setup(
) {
C_KZG_RET ret;

out->max_width = 0;
out->roots_of_unity = NULL;
out->domain_size = 0;
out->brp_roots_of_unity = NULL;
out->expanded_roots_of_unity = NULL;
out->reverse_roots_of_unity = NULL;
out->g1_values_monomial = NULL;
Expand Down Expand Up @@ -375,18 +375,18 @@ C_KZG_RET load_trusted_setup(
while ((1ULL << max_scale) < NUM_G1_POINTS)
max_scale++;

/* Set the max_width */
out->max_width = 1ULL << max_scale;
/* Set the domain_size */
out->domain_size = 1ULL << max_scale;

/* For DAS reconstruction */
out->max_width *= 2;
out->domain_size *= 2;

/* Allocate all of our arrays */
ret = new_fr_array(&out->roots_of_unity, out->max_width);
ret = new_fr_array(&out->brp_roots_of_unity, out->domain_size);
if (ret != C_KZG_OK) goto out_error;
ret = new_fr_array(&out->expanded_roots_of_unity, out->max_width + 1);
ret = new_fr_array(&out->expanded_roots_of_unity, out->domain_size + 1);
if (ret != C_KZG_OK) goto out_error;
ret = new_fr_array(&out->reverse_roots_of_unity, out->max_width + 1);
ret = new_fr_array(&out->reverse_roots_of_unity, out->domain_size + 1);
if (ret != C_KZG_OK) goto out_error;
ret = new_g1_array(&out->g1_values_monomial, NUM_G1_POINTS);
if (ret != C_KZG_OK) goto out_error;
Expand Down
Loading
Loading