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

Add LOG_EXPANSION_FACTOR constant #515

Merged
merged 7 commits into from
Oct 15, 2024
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
2 changes: 2 additions & 0 deletions src/common/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "common/utils.h"
#include "common/alloc.h"

#include <assert.h> /* For assert */
#include <stddef.h> /* For size_t */
#include <stdlib.h> /* For NULL */
#include <string.h> /* For memcpy */
Expand Down Expand Up @@ -116,6 +117,7 @@ C_KZG_RET bit_reversal_permutation(void *values, size_t size, size_t n) {

/* Reorder elements */
uint64_t unused_bit_len = 64 - log2_pow2(n);
assert(unused_bit_len <= 63);
for (size_t i = 0; i < n; i++) {
uint64_t r = reverse_bits(i) >> unused_bit_len;
if (r > i) {
Expand Down
9 changes: 8 additions & 1 deletion src/eip7594/cell.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,15 @@
/** The number of bytes in a single cell. */
#define BYTES_PER_CELL (FIELD_ELEMENTS_PER_CELL * BYTES_PER_FIELD_ELEMENT)

/**
* The logarithm (base 2) of the expansion factor of our Reed-Solomon code.
* In other words, this defines the rate of the Reed-Solomon code (blob / extended blob).
* Note that our codebase is not guaranteed to work anymore if this is changed.
*/
#define LOG_EXPANSION_FACTOR 1

/** The number of field elements in an extended blob. */
#define FIELD_ELEMENTS_PER_EXT_BLOB (FIELD_ELEMENTS_PER_BLOB * 2)
#define FIELD_ELEMENTS_PER_EXT_BLOB (FIELD_ELEMENTS_PER_BLOB << LOG_EXPANSION_FACTOR)

/** The number of cells in a blob. */
#define CELLS_PER_BLOB (FIELD_ELEMENTS_PER_BLOB / FIELD_ELEMENTS_PER_CELL)
Expand Down
6 changes: 3 additions & 3 deletions src/eip7594/eip7594.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ C_KZG_RET compute_cells_and_kzg_proofs(
ret = poly_lagrange_to_monomial(poly_monomial, poly_lagrange, FIELD_ELEMENTS_PER_BLOB, s);
if (ret != C_KZG_OK) goto out;

/* Ensure the upper half of the field elements are still zero */
/* Ensure that only the first FIELD_ELEMENTS_PER_BLOB elements can be non-zero */
for (size_t i = FIELD_ELEMENTS_PER_BLOB; i < FIELD_ELEMENTS_PER_EXT_BLOB; i++) {
assert(fr_equal(&poly_monomial[i], &FR_ZERO));
}
Expand Down Expand Up @@ -180,7 +180,7 @@ C_KZG_RET compute_cells_and_kzg_proofs(
* @param[in] num_cells The number of available cells provided
* @param[in] s The trusted setup
*
* @remark At least 50% of CELLS_PER_EXT_BLOB cells must be provided.
* @remark At least CELLS_PER_BLOB cells must be provided.
* @remark Recovery is faster if there are fewer missing cells.
* @remark If recovered_proofs is NULL, they will not be recomputed.
*/
Expand All @@ -203,7 +203,7 @@ C_KZG_RET recover_cells_and_kzg_proofs(
}

/* Check if it's possible to recover */
if (num_cells < CELLS_PER_EXT_BLOB / 2) {
if (num_cells < CELLS_PER_BLOB) {
ret = C_KZG_BADARGS;
goto out;
}
Expand Down
41 changes: 22 additions & 19 deletions src/eip7594/fk20.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ static void toeplitz_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 *p, const KZGSettings *s) {
C_KZG_RET ret;
size_t k, k2;
size_t circulant_domain_size;

blst_scalar *scalars = NULL;
fr_t **coeffs = NULL;
Expand All @@ -71,18 +71,21 @@ C_KZG_RET compute_fk20_cell_proofs(g1_t *out, const fr_t *p, const KZGSettings *
limb_t *scratch = NULL;
bool precompute = s->wbits != 0;

/* Initialize length variables */
k = FIELD_ELEMENTS_PER_BLOB / FIELD_ELEMENTS_PER_CELL;
k2 = k * 2;
/*
* Note: this constant 2 is not related to `LOG_EXPANSION_FACTOR`.
* Instead, it is related to circulant matrices used in FK20, see
* Section 2.2 and 3.2 in https://eprint.iacr.org/2023/033.pdf.
*/
circulant_domain_size = CELLS_PER_BLOB * 2;

/* Do allocations */
ret = new_fr_array(&toeplitz_coeffs, k2);
ret = new_fr_array(&toeplitz_coeffs, circulant_domain_size);
if (ret != C_KZG_OK) goto out;
ret = new_fr_array(&toeplitz_coeffs_fft, k2);
ret = new_fr_array(&toeplitz_coeffs_fft, circulant_domain_size);
if (ret != C_KZG_OK) goto out;
ret = new_g1_array(&h_ext_fft, k2);
ret = new_g1_array(&h_ext_fft, circulant_domain_size);
if (ret != C_KZG_OK) goto out;
ret = new_g1_array(&h, k2);
ret = new_g1_array(&h, circulant_domain_size);
if (ret != C_KZG_OK) goto out;

if (precompute) {
Expand All @@ -94,30 +97,30 @@ C_KZG_RET compute_fk20_cell_proofs(g1_t *out, const fr_t *p, const KZGSettings *
}

/* Allocate 2d array for coefficients by column */
ret = c_kzg_calloc((void **)&coeffs, k2, sizeof(void *));
ret = c_kzg_calloc((void **)&coeffs, circulant_domain_size, sizeof(void *));
if (ret != C_KZG_OK) goto out;
for (size_t i = 0; i < k2; i++) {
ret = new_fr_array(&coeffs[i], k);
for (size_t i = 0; i < circulant_domain_size; i++) {
ret = new_fr_array(&coeffs[i], CELLS_PER_BLOB);
if (ret != C_KZG_OK) goto out;
}

/* Initialize values to zero */
for (size_t i = 0; i < k2; i++) {
for (size_t i = 0; i < circulant_domain_size; i++) {
h_ext_fft[i] = G1_IDENTITY;
}

/* Compute toeplitz coefficients and organize by column */
for (size_t i = 0; i < FIELD_ELEMENTS_PER_CELL; i++) {
toeplitz_coeffs_stride(toeplitz_coeffs, p, i);
ret = fr_fft(toeplitz_coeffs_fft, toeplitz_coeffs, k2, s);
ret = fr_fft(toeplitz_coeffs_fft, toeplitz_coeffs, circulant_domain_size, s);
if (ret != C_KZG_OK) goto out;
for (size_t j = 0; j < k2; j++) {
for (size_t j = 0; j < circulant_domain_size; j++) {
coeffs[j][i] = toeplitz_coeffs_fft[j];
}
}

/* Compute h_ext_fft via MSM */
for (size_t i = 0; i < k2; i++) {
for (size_t i = 0; i < circulant_domain_size; i++) {
if (precompute) {
/* Transform the field elements to 255-bit scalars */
for (size_t j = 0; j < FIELD_ELEMENTS_PER_CELL; j++) {
Expand All @@ -144,21 +147,21 @@ C_KZG_RET compute_fk20_cell_proofs(g1_t *out, const fr_t *p, const KZGSettings *
}
}

ret = g1_ifft(h, h_ext_fft, k2, s);
ret = g1_ifft(h, h_ext_fft, circulant_domain_size, s);
if (ret != C_KZG_OK) goto out;

/* Zero the second half of h */
for (size_t i = k; i < k2; i++) {
for (size_t i = CELLS_PER_BLOB; i < circulant_domain_size; i++) {
h[i] = G1_IDENTITY;
}

ret = g1_fft(out, h, k2, s);
ret = g1_fft(out, h, circulant_domain_size, s);
if (ret != C_KZG_OK) goto out;

out:
c_kzg_free(scalars);
if (coeffs != NULL) {
for (size_t i = 0; i < k2; i++) {
for (size_t i = 0; i < circulant_domain_size; i++) {
c_kzg_free(coeffs[i]);
}
c_kzg_free(coeffs);
Expand Down
7 changes: 5 additions & 2 deletions src/eip7594/recovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,11 @@ C_KZG_RET recover_cells(
}
}

/* Check that we have enough cells */
assert(len_missing <= CELLS_PER_EXT_BLOB / 2);
/*
* Check that we have enough cells to recover.
* Concretely, we need to have at least CELLS_PER_BLOB many cells.
*/
assert(CELLS_PER_EXT_BLOB - len_missing >= CELLS_PER_BLOB);

/*
* Compute Z(x) in monomial form.
Expand Down
50 changes: 31 additions & 19 deletions src/setup/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@
* for (size_t i = 0; i < 4; i++)
* printf("%#018llxL,\n", root_of_unity.l[i]);
* @endcode
*
* @remark this constant is tied to LOG_EXPANSION_FACTOR = 1, i.e., if the expansion
* factor changes, this constant is no longer correct.
*/
static const fr_t ROOT_OF_UNITY = {
0xa33d279ff0ccffc9L, 0x41fac79f59e91972L, 0x065d227fead1139bL, 0x71db41abda03e055L
Expand Down Expand Up @@ -197,23 +200,29 @@ void free_trusted_setup(KZGSettings *s) {
*/
static C_KZG_RET toeplitz_part_1(g1_t *out, const g1_t *x, size_t n, const KZGSettings *s) {
C_KZG_RET ret;
size_t n2 = n * 2;

/*
* Note: this constant 2 is not related to `LOG_EXPANSION_FACTOR`.
* Instead, it is related to circulant matrices used in FK20, see
* Section 2.2 and 3.2 in https://eprint.iacr.org/2023/033.pdf.
*/
size_t circulant_domain_size = n * 2;
g1_t *x_ext;

/* Create extended array of points */
ret = new_g1_array(&x_ext, n2);
ret = new_g1_array(&x_ext, circulant_domain_size);
if (ret != C_KZG_OK) goto out;

/* Copy x & extend with zero */
for (size_t i = 0; i < n; i++) {
x_ext[i] = x[i];
}
for (size_t i = n; i < n2; i++) {
for (size_t i = n; i < circulant_domain_size; i++) {
x_ext[i] = G1_IDENTITY;
}

/* Peform forward transformation */
ret = g1_fft(out, x_ext, n2, s);
ret = g1_fft(out, x_ext, circulant_domain_size, s);
if (ret != C_KZG_OK) goto out;

out:
Expand All @@ -228,57 +237,60 @@ static C_KZG_RET toeplitz_part_1(g1_t *out, const g1_t *x, size_t n, const KZGSe
*/
static C_KZG_RET init_fk20_multi_settings(KZGSettings *s) {
C_KZG_RET ret;
size_t n, k, k2;
size_t circulant_domain_size;
g1_t *x = NULL;
g1_t *points = NULL;
blst_p1_affine *p_affine = NULL;
bool precompute = s->wbits != 0;

n = FIELD_ELEMENTS_PER_EXT_BLOB / 2;
k = n / FIELD_ELEMENTS_PER_CELL;
k2 = 2 * k;
/*
* Note: this constant 2 is not related to `LOG_EXPANSION_FACTOR`.
* Instead, it is related to circulant matrices used in FK20, see
* Section 2.2 and 3.2 in https://eprint.iacr.org/2023/033.pdf.
*/
circulant_domain_size = 2 * CELLS_PER_BLOB;

if (FIELD_ELEMENTS_PER_CELL >= NUM_G2_POINTS) {
ret = C_KZG_BADARGS;
goto out;
}

/* Allocate space for arrays */
ret = new_g1_array(&x, k);
ret = new_g1_array(&x, CELLS_PER_BLOB);
if (ret != C_KZG_OK) goto out;
ret = new_g1_array(&points, k2);
ret = new_g1_array(&points, circulant_domain_size);
if (ret != C_KZG_OK) goto out;

/* Allocate space for array of pointers, this is a 2D array */
ret = c_kzg_calloc((void **)&s->x_ext_fft_columns, k2, sizeof(void *));
ret = c_kzg_calloc((void **)&s->x_ext_fft_columns, circulant_domain_size, sizeof(void *));
if (ret != C_KZG_OK) goto out;
for (size_t i = 0; i < k2; i++) {
for (size_t i = 0; i < circulant_domain_size; i++) {
ret = new_g1_array(&s->x_ext_fft_columns[i], FIELD_ELEMENTS_PER_CELL);
if (ret != C_KZG_OK) goto out;
}

for (size_t offset = 0; offset < FIELD_ELEMENTS_PER_CELL; offset++) {
/* Compute x, sections of the g1 values */
size_t start = n - FIELD_ELEMENTS_PER_CELL - 1 - offset;
for (size_t i = 0; i < k - 1; i++) {
size_t start = FIELD_ELEMENTS_PER_BLOB - FIELD_ELEMENTS_PER_CELL - 1 - offset;
for (size_t i = 0; i < CELLS_PER_BLOB - 1; i++) {
size_t j = start - i * FIELD_ELEMENTS_PER_CELL;
x[i] = s->g1_values_monomial[j];
}
x[k - 1] = G1_IDENTITY;
x[CELLS_PER_BLOB - 1] = G1_IDENTITY;

/* Compute points, the fft of an extended x */
ret = toeplitz_part_1(points, x, k, s);
ret = toeplitz_part_1(points, x, CELLS_PER_BLOB, s);
if (ret != C_KZG_OK) goto out;

/* Reorganize from rows into columns */
for (size_t row = 0; row < k2; row++) {
for (size_t row = 0; row < circulant_domain_size; row++) {
s->x_ext_fft_columns[row][offset] = points[row];
}
}

if (precompute) {
/* Allocate space for precomputed tables */
ret = c_kzg_calloc((void **)&s->tables, k2, sizeof(void *));
ret = c_kzg_calloc((void **)&s->tables, circulant_domain_size, sizeof(void *));
if (ret != C_KZG_OK) goto out;

/* Allocate space for points in affine representation */
Expand All @@ -290,7 +302,7 @@ static C_KZG_RET init_fk20_multi_settings(KZGSettings *s) {
s->wbits, FIELD_ELEMENTS_PER_CELL
);

for (size_t i = 0; i < k2; i++) {
for (size_t i = 0; i < circulant_domain_size; i++) {
/* Transform the points to affine representation */
const blst_p1 *p_arg[2] = {s->x_ext_fft_columns[i], NULL};
blst_p1s_to_affine(p_affine, p_arg, FIELD_ELEMENTS_PER_CELL);
Expand Down
Loading