Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 3 additions & 9 deletions src/eip7594/fft.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ static void g1_fft_fast(
*
* @remark Will do nothing if given a zero length array.
* @remark The array lengths must be a power of two.
* @remark Use g1_ifft() for inverse transformation.
* @remark Use g1_ifft_unscaled() for inverse transformation.
*/
C_KZG_RET g1_fft(g1_t *out, const g1_t *in, size_t n, const KZGSettings *s) {
/* Handle zero length input */
Expand Down Expand Up @@ -222,8 +222,9 @@ C_KZG_RET g1_fft(g1_t *out, const g1_t *in, size_t n, const KZGSettings *s) {
* @remark Will do nothing if given a zero length array.
* @remark The array lengths must be a power of two.
* @remark Use g1_fft() for forward transformation.
* @remark The result is not scaled by 1/n. The caller must account for the missing factor.
*/
C_KZG_RET g1_ifft(g1_t *out, const g1_t *in, size_t n, const KZGSettings *s) {
C_KZG_RET g1_ifft_unscaled(g1_t *out, const g1_t *in, size_t n, const KZGSettings *s) {
/* Handle zero length input */
if (n == 0) return C_KZG_OK;

Expand All @@ -235,13 +236,6 @@ C_KZG_RET g1_ifft(g1_t *out, const g1_t *in, size_t n, const KZGSettings *s) {
size_t stride = FIELD_ELEMENTS_PER_EXT_BLOB / n;
g1_fft_fast(out, in, 1, s->reverse_roots_of_unity, stride, n);

fr_t inv_n;
fr_from_uint64(&inv_n, n);
blst_fr_eucl_inverse(&inv_n, &inv_n);
for (size_t i = 0; i < n; i++) {
g1_mul(&out[i], &out[i], &inv_n);
}

return C_KZG_OK;
}

Expand Down
2 changes: 1 addition & 1 deletion src/eip7594/fft.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ C_KZG_RET fr_fft(fr_t *out, const fr_t *in, size_t n, const KZGSettings *s);
C_KZG_RET fr_ifft(fr_t *out, const fr_t *in, size_t n, const KZGSettings *s);

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);
C_KZG_RET g1_ifft_unscaled(g1_t *out, const g1_t *in, size_t n, const KZGSettings *s);

C_KZG_RET coset_fft(fr_t *out, const fr_t *in, size_t n, const KZGSettings *s);
C_KZG_RET coset_ifft(fr_t *out, const fr_t *in, size_t n, const KZGSettings *s);
Expand Down
19 changes: 15 additions & 4 deletions src/eip7594/fk20.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ static void circulant_coeffs_stride(fr_t *out, const fr_t *in, size_t offset) {
C_KZG_RET compute_fk20_cell_proofs(g1_t *out, const fr_t *poly, const KZGSettings *s) {
C_KZG_RET ret;
size_t circulant_domain_size;
fr_t inv_domain_size;

blst_scalar *scalars = NULL;
fr_t **coeffs = NULL;
Expand Down Expand Up @@ -185,15 +186,24 @@ C_KZG_RET compute_fk20_cell_proofs(g1_t *out, const fr_t *poly, const KZGSetting
u[i] = G1_IDENTITY;
}

/* Phase 1, step 4: Compute the w_i columns */
/*
* Phase 1, step 4: Compute the w_i columns and prescale by 1/circulant_domain_size.
*
* The prescaling absorbs the 1/n factor from the IFFT (step 6) into cheap field
* multiplications, avoiding 128 expensive EC scalar multiplications that would otherwise be
* needed in the IFFT scaling step.
*/
fr_from_uint64(&inv_domain_size, circulant_domain_size);
blst_fr_eucl_inverse(&inv_domain_size, &inv_domain_size);
for (size_t i = 0; i < FIELD_ELEMENTS_PER_CELL; i++) {
/* Select the coefficients c_i of poly that form the i-th circulant matrix */
circulant_coeffs_stride(circulant_coeffs, poly, i);
/* Apply FFT to get w_i */
ret = fr_fft(circulant_coeffs_fft, circulant_coeffs, circulant_domain_size, s);
if (ret != C_KZG_OK) goto out;
/* Transpose and prescale by 1/n in one pass */
for (size_t j = 0; j < circulant_domain_size; j++) {
coeffs[j][i] = circulant_coeffs_fft[j];
blst_fr_mul(&coeffs[j][i], &circulant_coeffs_fft[j], &inv_domain_size);
}
}

Expand Down Expand Up @@ -236,13 +246,14 @@ C_KZG_RET compute_fk20_cell_proofs(g1_t *out, const fr_t *poly, const KZGSetting
}

/*
* Phase 1, step 6: Apply the inverse FFT to the u vector.
* Phase 1, step 6: Apply the inverse FFT to the u vector (without 1/n scaling, since we
* already prescaled the coefficients by 1/n in the field).
*
* The result is almost the final v vector: the second half of the vector should be set to the
* identity elements (commitments to zero coefficients). The v polynomial actually has degree
* r-1, which is guaranteed by setting the last r+1 elements of c_i vectors to be identities.
*/
ret = g1_ifft(v, u, circulant_domain_size, s);
ret = g1_ifft_unscaled(v, u, circulant_domain_size, s);
if (ret != C_KZG_OK) goto out;

/*
Expand Down
Loading