mirror of
https://github.com/status-im/c-kzg-4844.git
synced 2025-02-28 17:50:32 +00:00
Use bit-reversal permutation
This commit is contained in:
parent
efef81bdf1
commit
48903d567f
@ -55,6 +55,7 @@ typedef struct {
|
|||||||
fr_t root_of_unity; /**< The root of unity used to generate the lists in the structure. */
|
fr_t root_of_unity; /**< The root of unity used to generate the lists in the structure. */
|
||||||
fr_t *expanded_roots_of_unity; /**< Ascending powers of the root of unity, size `width + 1`. */
|
fr_t *expanded_roots_of_unity; /**< Ascending powers of the root of unity, size `width + 1`. */
|
||||||
fr_t *reverse_roots_of_unity; /**< Descending powers of the root of unity, size `width + 1`. */
|
fr_t *reverse_roots_of_unity; /**< Descending powers of the root of unity, size `width + 1`. */
|
||||||
|
fr_t *bitrevp_roots_of_unity; /**< Powers of the root of unity in bit-reversal permutation, size `width`. */
|
||||||
} FFTSettings;
|
} FFTSettings;
|
||||||
|
|
||||||
C_KZG_RET new_fft_settings(FFTSettings *out, unsigned int max_scale);
|
C_KZG_RET new_fft_settings(FFTSettings *out, unsigned int max_scale);
|
||||||
@ -87,9 +88,9 @@ typedef struct {
|
|||||||
} poly;
|
} poly;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
fr_t *values; /**< `values[i]` is value of the polynomial at `ω^i`. */
|
fr_t *values; /**< `values[i]` is value of the polynomial at `ω^brp(i)`. */
|
||||||
uint64_t length; /**< One more than the polynomial's degree */
|
uint64_t length; /**< One more than the polynomial's degree */
|
||||||
} poly_l; // Lagrange form
|
} poly_l; // Lagrange form, under bit-reversal permutation
|
||||||
|
|
||||||
void eval_poly(fr_t *out, const poly *p, const fr_t *x);
|
void eval_poly(fr_t *out, const poly *p, const fr_t *x);
|
||||||
C_KZG_RET eval_poly_l(fr_t *out, const poly_l *p, const fr_t *x, const FFTSettings *fs);
|
C_KZG_RET eval_poly_l(fr_t *out, const poly_l *p, const fr_t *x, const FFTSettings *fs);
|
||||||
@ -117,7 +118,7 @@ void fr_vector_lincomb(fr_t out[], const fr_t *vectors, const fr_t *scalars, uin
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
const FFTSettings *fs; /**< The corresponding settings for performing FFTs */
|
const FFTSettings *fs; /**< The corresponding settings for performing FFTs */
|
||||||
g1_t *secret_g1; /**< G1 group elements from the trusted setup */
|
g1_t *secret_g1; /**< G1 group elements from the trusted setup */
|
||||||
g1_t *secret_g1_l; /**< secret_g1 in Lagrange form */
|
g1_t *secret_g1_l; /**< secret_g1 in Lagrange form, in bit-reversal permutation */
|
||||||
g2_t *secret_g2; /**< G2 group elements from the trusted setup */
|
g2_t *secret_g2; /**< G2 group elements from the trusted setup */
|
||||||
uint64_t length; /**< The number of elements in secret_g1 and secret_g2 */
|
uint64_t length; /**< The number of elements in secret_g1 and secret_g2 */
|
||||||
} KZGSettings;
|
} KZGSettings;
|
||||||
|
@ -20,8 +20,10 @@
|
|||||||
* Code shared between the FFTs over field elements and FFTs over G1 group elements.
|
* Code shared between the FFTs over field elements and FFTs over G1 group elements.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h> // memcpy
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "c_kzg_alloc.h"
|
#include "c_kzg_alloc.h"
|
||||||
|
#include "utility.h" // reverse_bit_order
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The first 32 roots of unity in the finite field F_r.
|
* The first 32 roots of unity in the finite field F_r.
|
||||||
@ -131,6 +133,7 @@ C_KZG_RET new_fft_settings(FFTSettings *fs, unsigned int max_scale) {
|
|||||||
// Allocate space for the roots of unity
|
// Allocate space for the roots of unity
|
||||||
TRY(new_fr_array(&fs->expanded_roots_of_unity, fs->max_width + 1));
|
TRY(new_fr_array(&fs->expanded_roots_of_unity, fs->max_width + 1));
|
||||||
TRY(new_fr_array(&fs->reverse_roots_of_unity, fs->max_width + 1));
|
TRY(new_fr_array(&fs->reverse_roots_of_unity, fs->max_width + 1));
|
||||||
|
TRY(new_fr_array(&fs->bitrevp_roots_of_unity, fs->max_width));
|
||||||
|
|
||||||
// Populate the roots of unity
|
// Populate the roots of unity
|
||||||
TRY(expand_root_of_unity(fs->expanded_roots_of_unity, &fs->root_of_unity, fs->max_width));
|
TRY(expand_root_of_unity(fs->expanded_roots_of_unity, &fs->root_of_unity, fs->max_width));
|
||||||
@ -140,6 +143,10 @@ C_KZG_RET new_fft_settings(FFTSettings *fs, unsigned int max_scale) {
|
|||||||
fs->reverse_roots_of_unity[i] = fs->expanded_roots_of_unity[fs->max_width - i];
|
fs->reverse_roots_of_unity[i] = fs->expanded_roots_of_unity[fs->max_width - i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Permute the roots of unity
|
||||||
|
memcpy(fs->bitrevp_roots_of_unity, fs->expanded_roots_of_unity, sizeof(fr_t) * fs->max_width);
|
||||||
|
TRY(reverse_bit_order(fs->bitrevp_roots_of_unity, sizeof(fr_t), fs->max_width));
|
||||||
|
|
||||||
return C_KZG_OK;
|
return C_KZG_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,6 +158,7 @@ C_KZG_RET new_fft_settings(FFTSettings *fs, unsigned int max_scale) {
|
|||||||
void free_fft_settings(FFTSettings *fs) {
|
void free_fft_settings(FFTSettings *fs) {
|
||||||
free(fs->expanded_roots_of_unity);
|
free(fs->expanded_roots_of_unity);
|
||||||
free(fs->reverse_roots_of_unity);
|
free(fs->reverse_roots_of_unity);
|
||||||
|
free(fs->bitrevp_roots_of_unity);
|
||||||
fs->max_width = 0;
|
fs->max_width = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +166,6 @@ void free_fft_settings(FFTSettings *fs) {
|
|||||||
|
|
||||||
#include "../inc/acutest.h"
|
#include "../inc/acutest.h"
|
||||||
#include "test_util.h"
|
#include "test_util.h"
|
||||||
#include "utility.h"
|
|
||||||
|
|
||||||
#define NUM_ROOTS 32
|
#define NUM_ROOTS 32
|
||||||
|
|
||||||
|
@ -142,13 +142,13 @@ C_KZG_RET compute_proof_single_l(g1_t *out, const poly_l *p, const fr_t *x, cons
|
|||||||
TRY(new_fr_array(&inverses, p->length));
|
TRY(new_fr_array(&inverses, p->length));
|
||||||
|
|
||||||
for (i = 0; i < q.length; i++) {
|
for (i = 0; i < q.length; i++) {
|
||||||
if (fr_equal(x, &ks->fs->expanded_roots_of_unity[i])) {
|
if (fr_equal(x, &ks->fs->bitrevp_roots_of_unity[i])) {
|
||||||
m = i + 1;
|
m = i + 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// (p_i - y) / (ω_i - x)
|
// (p_i - y) / (ω_i - x)
|
||||||
fr_sub(&q.values[i], &p->values[i], y);
|
fr_sub(&q.values[i], &p->values[i], y);
|
||||||
fr_sub(&inverses_in[i], &ks->fs->expanded_roots_of_unity[i], x);
|
fr_sub(&inverses_in[i], &ks->fs->bitrevp_roots_of_unity[i], x);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY(fr_batch_inv(inverses, inverses_in, q.length));
|
TRY(fr_batch_inv(inverses, inverses_in, q.length));
|
||||||
@ -161,14 +161,14 @@ C_KZG_RET compute_proof_single_l(g1_t *out, const poly_l *p, const fr_t *x, cons
|
|||||||
for (i=0; i < q.length; i++) {
|
for (i=0; i < q.length; i++) {
|
||||||
if (i == m) continue;
|
if (i == m) continue;
|
||||||
// (p_i - y) * ω_i / (x * (x - ω_i))
|
// (p_i - y) * ω_i / (x * (x - ω_i))
|
||||||
fr_sub(&tmp, x, &ks->fs->expanded_roots_of_unity[i]);
|
fr_sub(&tmp, x, &ks->fs->bitrevp_roots_of_unity[i]);
|
||||||
fr_mul(&inverses_in[i], &tmp, x);
|
fr_mul(&inverses_in[i], &tmp, x);
|
||||||
}
|
}
|
||||||
TRY(fr_batch_inv(inverses, inverses_in, q.length));
|
TRY(fr_batch_inv(inverses, inverses_in, q.length));
|
||||||
for (i=0; i < q.length; i++) {
|
for (i=0; i < q.length; i++) {
|
||||||
fr_sub(&tmp2, &p->values[i], y);
|
fr_sub(&tmp2, &p->values[i], y);
|
||||||
fr_mul(&tmp, &tmp2, &inverses[i]);
|
fr_mul(&tmp, &tmp2, &inverses[i]);
|
||||||
fr_mul(&tmp, &tmp, &ks->fs->expanded_roots_of_unity[i]);
|
fr_mul(&tmp, &tmp, &ks->fs->bitrevp_roots_of_unity[i]);
|
||||||
fr_add(&q.values[m], &q.values[m], &tmp);
|
fr_add(&q.values[m], &q.values[m], &tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -318,8 +318,9 @@ C_KZG_RET new_kzg_settings(KZGSettings *ks, const g1_t *secret_g1, const g2_t *s
|
|||||||
}
|
}
|
||||||
ks->fs = fs;
|
ks->fs = fs;
|
||||||
|
|
||||||
// Add Lagrange form (and return its success)
|
// Add Lagrange form
|
||||||
return fft_g1(ks->secret_g1_l, ks->secret_g1, true, length, fs);
|
TRY(fft_g1(ks->secret_g1_l, ks->secret_g1, true, length, fs));
|
||||||
|
return reverse_bit_order(ks->secret_g1_l, sizeof(g1_t), length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
10
src/poly.c
10
src/poly.c
@ -117,19 +117,19 @@ C_KZG_RET eval_poly_l(fr_t *out, const poly_l *p, const fr_t *x, const FFTSettin
|
|||||||
TRY(new_fr_array(&inverses_in, p->length));
|
TRY(new_fr_array(&inverses_in, p->length));
|
||||||
TRY(new_fr_array(&inverses, p->length));
|
TRY(new_fr_array(&inverses, p->length));
|
||||||
for (i = 0; i < p->length; i++) {
|
for (i = 0; i < p->length; i++) {
|
||||||
if (fr_equal(x, &fs->expanded_roots_of_unity[i * stride])) {
|
if (fr_equal(x, &fs->bitrevp_roots_of_unity[i * stride])) {
|
||||||
*out = p->values[i];
|
*out = p->values[i];
|
||||||
free(inverses_in);
|
free(inverses_in);
|
||||||
free(inverses);
|
free(inverses);
|
||||||
return C_KZG_OK;
|
return C_KZG_OK;
|
||||||
}
|
}
|
||||||
fr_sub(&inverses_in[i], x, &fs->expanded_roots_of_unity[i * stride]);
|
fr_sub(&inverses_in[i], x, &fs->bitrevp_roots_of_unity[i * stride]);
|
||||||
}
|
}
|
||||||
TRY(fr_batch_inv(inverses, inverses_in, p->length));
|
TRY(fr_batch_inv(inverses, inverses_in, p->length));
|
||||||
|
|
||||||
*out = fr_zero;
|
*out = fr_zero;
|
||||||
for (i = 0; i < p->length; i++) {
|
for (i = 0; i < p->length; i++) {
|
||||||
fr_mul(&tmp, &inverses[i], &fs->expanded_roots_of_unity[i * stride]);
|
fr_mul(&tmp, &inverses[i], &fs->bitrevp_roots_of_unity[i * stride]);
|
||||||
fr_mul(&tmp, &tmp, &p->values[i]);
|
fr_mul(&tmp, &tmp, &p->values[i]);
|
||||||
fr_add(out, out, &tmp);
|
fr_add(out, out, &tmp);
|
||||||
}
|
}
|
||||||
@ -635,7 +635,7 @@ C_KZG_RET new_poly_with_coeffs(poly *out, const fr_t *coeffs, uint64_t length) {
|
|||||||
C_KZG_RET new_poly_l_from_poly(poly_l *out, const poly *in, const KZGSettings *ks) {
|
C_KZG_RET new_poly_l_from_poly(poly_l *out, const poly *in, const KZGSettings *ks) {
|
||||||
TRY(new_poly_l(out, ks->length));
|
TRY(new_poly_l(out, ks->length));
|
||||||
if (out->length <= in->length) {
|
if (out->length <= in->length) {
|
||||||
return fft_fr(out->values, in->coeffs, false, out->length, ks->fs);
|
fft_fr(out->values, in->coeffs, false, out->length, ks->fs);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int i;
|
int i;
|
||||||
@ -649,8 +649,8 @@ C_KZG_RET new_poly_l_from_poly(poly_l *out, const poly *in, const KZGSettings *k
|
|||||||
}
|
}
|
||||||
TRY(fft_fr(out->values, coeffs, false, out->length, ks->fs));
|
TRY(fft_fr(out->values, coeffs, false, out->length, ks->fs));
|
||||||
free(coeffs);
|
free(coeffs);
|
||||||
return C_KZG_OK;
|
|
||||||
}
|
}
|
||||||
|
return reverse_bit_order(out->values, sizeof(fr_t), out->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user