Speed up loading trusted setup (#299)
* Replace g1 points with g1 lagrange points * Swap out validate_kzg_g1 with blst funcs * Update minimal preset too * Fix java & nodejs bindings * Put variables in smaller scope * Update some comments * Remove FFTSettings (#2) * Fix issue when expanding roots of unity * Fix formatting * Revert back to using intermediate array * Add missing c_kzg_free * Fix some nits * Replace free_kzg_settings with free_trusted_setup * Add parens to NUM_ELEMENTS Co-authored-by: George Kadianakis <desnacked@riseup.net> * Move memcpy to the end * Revert "Move memcpy to the end" This reverts commit 5331c7feadc92e4b5dd5d4e7512e4be563d7f386. * Add comment about free_trusted_setup * Move check before alloc * Add remark * Delete unnecessary blank line * Fix asn's nits * Update comment for roots_of_unity in header Co-authored-by: Gottfried Herold <GottfriedHerold@users.noreply.github.com> * Fix formatting * Update comment about max_scale Co-authored-by: Gottfried Herold <GottfriedHerold@users.noreply.github.com> --------- Co-authored-by: Suphanat Chunhapanya <haxx.pop@gmail.com> Co-authored-by: George Kadianakis <desnacked@riseup.net> Co-authored-by: Gottfried Herold <GottfriedHerold@users.noreply.github.com>
This commit is contained in:
parent
8e3dd60424
commit
6d21a0ea98
|
@ -11,10 +11,7 @@ void reset_trusted_setup()
|
|||
{
|
||||
if (settings)
|
||||
{
|
||||
if (settings->fs)
|
||||
{
|
||||
free_trusted_setup(settings);
|
||||
}
|
||||
free_trusted_setup(settings);
|
||||
free(settings);
|
||||
settings = NULL;
|
||||
}
|
||||
|
@ -51,7 +48,8 @@ KZGSettings *allocate_settings(JNIEnv *env)
|
|||
}
|
||||
else
|
||||
{
|
||||
s->fs = NULL;
|
||||
s->max_width = 0;
|
||||
s->roots_of_unity = NULL;
|
||||
s->g1_values = NULL;
|
||||
s->g2_values = NULL;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,9 @@
|
|||
4
|
||||
65
|
||||
97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb
|
||||
854262641262cb9e056a8512808ea6864d903dbcad713fd6da8dddfa5ce40d85612c912063ace060ed8c4bf005bab839
|
||||
86f708eee5ae0cf40be36993e760d9cb3b2371f22db3209947c5d21ea68e55186b30871c50bf11ef29e5248bf42d5678
|
||||
94f9c0bafb23cbbf34a93a64243e3e0f934b57593651f3464de7dc174468123d9698f1b9dfa22bb5b6eb96eae002f29f
|
||||
91131b2e3c1e5f0b51df8970e67080032f411571b66d301436c46f25bbfddf9ca16756430dc470bdb0d85b47fedcdbc1
|
||||
934d35b2a46e169915718b77127b0d4efbacdad7fdde4593af7d21d37ebcb77fe6c8dde6b8a9537854d70ef1f291a585
|
||||
9410ca1d0342fe7419f02194281df45e1c1ff42fd8b439de5644cc312815c21ddd2e3eeb63fb807cf837e68b76668bd5
|
||||
b163df7e9baeb60f69b6ee5faa538c3a564b62eb8cde6a3616083c8cb2171eedd583c9143e7e916df59bf27da5e024e8
|
||||
93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8
|
||||
99aca9fb2f7760cecb892bf7262c176b334824f5727f680bba701a33e322cb6667531410dfc7c8e4321a3f0ea8af48cb1436638a2093123f046f0f504cc2a864825542873edbbc5d7ed17af125a4f2cf6433c6f4f61b81173726981dd989761d
|
||||
88e2e982982bf8231e747e9dfcd14c05bd02623d1332734d2af26246c6869fb56ee6c994843f593178a040495ba61f4a083b0e18110b1d9f5224783d8f9a895e8ee744e87929430e9ba96bd29251cbf61240b256d1525600f3d562894d93d659
|
||||
|
|
|
@ -23,7 +23,7 @@ function transformTrustedSetupJson(filePath) {
|
|||
const setupText =
|
||||
bindings.FIELD_ELEMENTS_PER_BLOB +
|
||||
"\n65\n" +
|
||||
trustedSetup.setup_G1.map((p) => p.substring(2)).join("\n") +
|
||||
trustedSetup.setup_G1_lagrange.map((p) => p.substring(2)).join("\n") +
|
||||
"\n" +
|
||||
trustedSetup.setup_G2.map((p) => p.substring(2)).join("\n");
|
||||
const outputPath = filePath.replace(".json", ".txt");
|
||||
|
|
|
@ -492,10 +492,8 @@ impl Deref for KZGCommitment {
|
|||
}
|
||||
}
|
||||
|
||||
/// Safety: FFTSettings is initialized once on calling `load_trusted_setup`. After
|
||||
/// that, the struct is never modified. The memory for the arrays within `FFTSettings` and
|
||||
/// `g1_values` and `g2_values` are only freed on calling `free_trusted_setup` which only happens
|
||||
/// when we drop the struct.
|
||||
/// Safety: The memory for `roots_of_unity` and `g1_values` and `g2_values` are only freed on
|
||||
/// calling `free_trusted_setup` which only happens when we drop the struct.
|
||||
unsafe impl Sync for KZGSettings {}
|
||||
unsafe impl Send for KZGSettings {}
|
||||
|
||||
|
|
|
@ -11,4 +11,4 @@ pub use bindings::{
|
|||
FIELD_ELEMENTS_PER_BLOB, BYTES_PER_G1_POINT, BYTES_PER_G2_POINT
|
||||
};
|
||||
// Expose the remaining relevant types.
|
||||
pub use bindings::{Blob, Bytes32, Bytes48, Error, FFTSettings};
|
||||
pub use bindings::{Blob, Bytes32, Bytes48, Error};
|
||||
|
|
286
src/c_kzg_4844.c
286
src/c_kzg_4844.c
|
@ -34,6 +34,9 @@
|
|||
#define CHECK(cond) \
|
||||
if (!(cond)) return C_KZG_BADARGS
|
||||
|
||||
/** Returns number of elements in a statically defined array. */
|
||||
#define NUM_ELEMENTS(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
/**
|
||||
* Helper macro to release memory allocated on the heap. Unlike free(),
|
||||
* c_kzg_free() macro sets the pointer value to NULL after freeing it.
|
||||
|
@ -813,7 +816,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->fs->roots_of_unity;
|
||||
const fr_t *roots_of_unity = s->roots_of_unity;
|
||||
|
||||
ret = new_fr_array(&inverses_in, FIELD_ELEMENTS_PER_BLOB);
|
||||
if (ret != C_KZG_OK) goto out;
|
||||
|
@ -1056,7 +1059,7 @@ static C_KZG_RET compute_kzg_proof_impl(
|
|||
|
||||
fr_t tmp;
|
||||
Polynomial q;
|
||||
const fr_t *roots_of_unity = s->fs->roots_of_unity;
|
||||
const fr_t *roots_of_unity = s->roots_of_unity;
|
||||
uint64_t i;
|
||||
/* m != 0 indicates that the evaluation point z equals root_of_unity[m-1] */
|
||||
uint64_t m = 0;
|
||||
|
@ -1563,79 +1566,7 @@ static C_KZG_RET bit_reversal_permutation(
|
|||
}
|
||||
|
||||
/**
|
||||
* Fast Fourier Transform.
|
||||
*
|
||||
* Recursively divide and conquer.
|
||||
*
|
||||
* @param[out] out The results (array of length @p n)
|
||||
* @param[in] in The input data (array of length @p n * @p stride)
|
||||
* @param[in] stride The input data stride
|
||||
* @param[in] roots Roots of unity
|
||||
* (array of length @p n * @p roots_stride)
|
||||
* @param[in] roots_stride The stride interval among the roots of unity
|
||||
* @param[in] n Length of the FFT, must be a power of two
|
||||
*/
|
||||
static void fft_g1_fast(
|
||||
g1_t *out,
|
||||
const g1_t *in,
|
||||
uint64_t stride,
|
||||
const fr_t *roots,
|
||||
uint64_t roots_stride,
|
||||
uint64_t n
|
||||
) {
|
||||
uint64_t half = n / 2;
|
||||
if (half > 0) { /* Tunable parameter */
|
||||
fft_g1_fast(out, in, stride * 2, roots, roots_stride * 2, half);
|
||||
fft_g1_fast(
|
||||
out + half, in + stride, stride * 2, roots, roots_stride * 2, half
|
||||
);
|
||||
for (uint64_t i = 0; i < half; i++) {
|
||||
g1_t y_times_root;
|
||||
if (fr_is_one(&roots[i * roots_stride])) {
|
||||
/* Don't do the scalar multiplication if the scalar is one */
|
||||
y_times_root = out[i + half];
|
||||
} else {
|
||||
g1_mul(&y_times_root, &out[i + half], &roots[i * roots_stride]);
|
||||
}
|
||||
g1_sub(&out[i + half], &out[i], &y_times_root);
|
||||
blst_p1_add_or_double(&out[i], &out[i], &y_times_root);
|
||||
}
|
||||
} else {
|
||||
*out = *in;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The main entry point for forward and reverse FFTs over the finite field.
|
||||
*
|
||||
* @param[out] out The results (array of length @p n)
|
||||
* @param[in] in The input data (array of length @p n)
|
||||
* @param[in] inverse False for forward transform, true for inverse transform
|
||||
* @param[in] n Length of the FFT, must be a power of two
|
||||
* @param[in] fs The FFTSettings
|
||||
*/
|
||||
static C_KZG_RET fft_g1(
|
||||
g1_t *out, const g1_t *in, bool inverse, uint64_t n, const FFTSettings *fs
|
||||
) {
|
||||
uint64_t stride = fs->max_width / n;
|
||||
CHECK(n <= fs->max_width);
|
||||
CHECK(is_power_of_two(n));
|
||||
if (inverse) {
|
||||
fr_t inv_len;
|
||||
fr_from_uint64(&inv_len, n);
|
||||
blst_fr_eucl_inverse(&inv_len, &inv_len);
|
||||
fft_g1_fast(out, in, 1, fs->reverse_roots_of_unity, stride, n);
|
||||
for (uint64_t i = 0; i < n; i++) {
|
||||
g1_mul(&out[i], &out[i], &inv_len);
|
||||
}
|
||||
} else {
|
||||
fft_g1_fast(out, in, 1, fs->expanded_roots_of_unity, stride, n);
|
||||
}
|
||||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate powers of a root of unity in the field for use in the FFTs.
|
||||
* Generate powers of a root of unity in the field.
|
||||
*
|
||||
* @remark @p root must be such that @p root ^ @p width is equal to one, but
|
||||
* no smaller power of @p root is equal to one.
|
||||
|
@ -1661,91 +1592,77 @@ static C_KZG_RET expand_root_of_unity(
|
|||
}
|
||||
|
||||
/**
|
||||
* Initialise an FFTSettings structure.
|
||||
* Initialize the roots of unity.
|
||||
*
|
||||
* Space is allocated for, and arrays are populated with, powers of the
|
||||
* roots of unity. The two arrays contain the same values in reverse order
|
||||
* for convenience in inverse FFTs.
|
||||
* @remark `roots_of_unity_out` may be modified even if there's an error.
|
||||
*
|
||||
* `max_width` is the maximum size of FFT that can be calculated with these
|
||||
* settings, and is a power of two by construction. The same settings may be
|
||||
* used to calculated FFTs of smaller power sizes.
|
||||
*
|
||||
* @remark As with all functions prefixed `new_`, this allocates memory that
|
||||
* needs to be reclaimed by calling the corresponding `free_` function. In
|
||||
* this case, free_fft_settings().
|
||||
*
|
||||
* @remark These settings may be used for FFTs on both field elements and G1
|
||||
* group elements.
|
||||
*
|
||||
* @param[out] fs The new settings
|
||||
* @param[in] max_scale Log base 2 of the max FFT size to be used with
|
||||
* these settings
|
||||
* @param[out] roots_of_unity_out The roots of unity
|
||||
* @param[in] max_scale Log base 2 of the number of roots of unity to
|
||||
* be initialized
|
||||
*/
|
||||
static C_KZG_RET new_fft_settings(FFTSettings *fs, unsigned int max_scale) {
|
||||
static C_KZG_RET compute_roots_of_unity(
|
||||
fr_t *roots_of_unity_out, uint32_t max_scale
|
||||
) {
|
||||
C_KZG_RET ret;
|
||||
uint64_t max_width;
|
||||
fr_t root_of_unity;
|
||||
fr_t *expanded_roots = NULL;
|
||||
|
||||
fs->max_width = 1ULL << max_scale;
|
||||
fs->expanded_roots_of_unity = NULL;
|
||||
fs->reverse_roots_of_unity = NULL;
|
||||
fs->roots_of_unity = NULL;
|
||||
/* Calculate the max width */
|
||||
max_width = 1ULL << max_scale;
|
||||
|
||||
CHECK((
|
||||
max_scale < sizeof SCALE2_ROOT_OF_UNITY / sizeof SCALE2_ROOT_OF_UNITY[0]
|
||||
));
|
||||
/* Get the root of unity */
|
||||
CHECK(max_scale < NUM_ELEMENTS(SCALE2_ROOT_OF_UNITY));
|
||||
blst_fr_from_uint64(&root_of_unity, SCALE2_ROOT_OF_UNITY[max_scale]);
|
||||
|
||||
/* Allocate space for the roots of unity */
|
||||
ret = new_fr_array(&fs->expanded_roots_of_unity, fs->max_width + 1);
|
||||
if (ret != C_KZG_OK) goto out_error;
|
||||
ret = new_fr_array(&fs->reverse_roots_of_unity, fs->max_width + 1);
|
||||
if (ret != C_KZG_OK) goto out_error;
|
||||
ret = new_fr_array(&fs->roots_of_unity, fs->max_width);
|
||||
if (ret != C_KZG_OK) goto out_error;
|
||||
/*
|
||||
* Allocate an array to store the expanded roots of unity. We do this
|
||||
* instead of re-using roots_of_unity_out because the expansion requires
|
||||
* max_width+1 elements.
|
||||
*/
|
||||
ret = new_fr_array(&expanded_roots, max_width + 1);
|
||||
if (ret != C_KZG_OK) goto out;
|
||||
|
||||
/* Populate the roots of unity */
|
||||
ret = expand_root_of_unity(
|
||||
fs->expanded_roots_of_unity, &root_of_unity, fs->max_width
|
||||
);
|
||||
if (ret != C_KZG_OK) goto out_error;
|
||||
ret = expand_root_of_unity(expanded_roots, &root_of_unity, max_width);
|
||||
if (ret != C_KZG_OK) goto out;
|
||||
|
||||
/* Populate reverse roots of unity */
|
||||
for (uint64_t i = 0; i <= fs->max_width; i++) {
|
||||
fs->reverse_roots_of_unity[i] =
|
||||
fs->expanded_roots_of_unity[fs->max_width - i];
|
||||
}
|
||||
/* Copy all but the last root to the roots of unity */
|
||||
memcpy(roots_of_unity_out, expanded_roots, sizeof(fr_t) * max_width);
|
||||
|
||||
/* Permute the roots of unity */
|
||||
memcpy(
|
||||
fs->roots_of_unity,
|
||||
fs->expanded_roots_of_unity,
|
||||
sizeof(fr_t) * fs->max_width
|
||||
);
|
||||
ret = bit_reversal_permutation(
|
||||
fs->roots_of_unity, sizeof(fr_t), fs->max_width
|
||||
);
|
||||
if (ret != C_KZG_OK) goto out_error;
|
||||
ret = bit_reversal_permutation(roots_of_unity_out, sizeof(fr_t), max_width);
|
||||
if (ret != C_KZG_OK) goto out;
|
||||
|
||||
goto out_success;
|
||||
|
||||
out_error:
|
||||
c_kzg_free(fs->expanded_roots_of_unity);
|
||||
c_kzg_free(fs->reverse_roots_of_unity);
|
||||
c_kzg_free(fs->roots_of_unity);
|
||||
out_success:
|
||||
out:
|
||||
c_kzg_free(expanded_roots);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a trusted setup (KZGSettings).
|
||||
*
|
||||
* @remark It's a NOP if `s` is NULL.
|
||||
*
|
||||
* @param[in] s The trusted setup to free
|
||||
*/
|
||||
void free_trusted_setup(KZGSettings *s) {
|
||||
if (s == NULL) return;
|
||||
s->max_width = 0;
|
||||
c_kzg_free(s->roots_of_unity);
|
||||
c_kzg_free(s->g1_values);
|
||||
c_kzg_free(s->g2_values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load trusted setup into a KZGSettings.
|
||||
*
|
||||
* @remark Free after use with free_trusted_setup().
|
||||
*
|
||||
* @param[out] out Pointer to the stored trusted setup data
|
||||
* @param[in] g1_bytes Array of G1 points
|
||||
* @param[in] g1_bytes Array of G1 points in Lagrange form
|
||||
* @param[in] n1 Number of `g1` points in g1_bytes
|
||||
* @param[in] g2_bytes Array of G2 points
|
||||
* @param[in] g2_bytes Array of G2 points in monomial form
|
||||
* @param[in] n2 Number of `g2` points in g2_bytes
|
||||
*/
|
||||
C_KZG_RET load_trusted_setup(
|
||||
|
@ -1755,12 +1672,10 @@ C_KZG_RET load_trusted_setup(
|
|||
const uint8_t *g2_bytes,
|
||||
size_t n2
|
||||
) {
|
||||
uint64_t i;
|
||||
blst_p2_affine g2_affine;
|
||||
g1_t *g1_projective = NULL;
|
||||
C_KZG_RET ret;
|
||||
|
||||
out->fs = NULL;
|
||||
out->max_width = 0;
|
||||
out->roots_of_unity = NULL;
|
||||
out->g1_values = NULL;
|
||||
out->g2_values = NULL;
|
||||
|
||||
|
@ -1768,24 +1683,38 @@ C_KZG_RET load_trusted_setup(
|
|||
CHECK(n1 == TRUSTED_SETUP_NUM_G1_POINTS);
|
||||
CHECK(n2 == TRUSTED_SETUP_NUM_G2_POINTS);
|
||||
|
||||
/* 1<<max_scale is the smallest power of 2 >= n1 */
|
||||
uint32_t max_scale = 0;
|
||||
while ((1ULL << max_scale) < n1)
|
||||
max_scale++;
|
||||
|
||||
/* Set the max_width */
|
||||
out->max_width = 1ULL << max_scale;
|
||||
|
||||
/* Allocate all of our arrays */
|
||||
ret = new_fr_array(&out->roots_of_unity, out->max_width);
|
||||
if (ret != C_KZG_OK) goto out_error;
|
||||
ret = new_g1_array(&out->g1_values, n1);
|
||||
if (ret != C_KZG_OK) goto out_error;
|
||||
ret = new_g2_array(&out->g2_values, n2);
|
||||
if (ret != C_KZG_OK) goto out_error;
|
||||
ret = new_g1_array(&g1_projective, n1);
|
||||
if (ret != C_KZG_OK) goto out_error;
|
||||
|
||||
/* Convert all g1 bytes to g1 points */
|
||||
for (i = 0; i < n1; i++) {
|
||||
ret = validate_kzg_g1(
|
||||
&g1_projective[i], (Bytes48 *)&g1_bytes[BYTES_PER_G1 * i]
|
||||
for (uint64_t i = 0; i < n1; i++) {
|
||||
blst_p1_affine g1_affine;
|
||||
BLST_ERROR err = blst_p1_uncompress(
|
||||
&g1_affine, &g1_bytes[BYTES_PER_G1 * i]
|
||||
);
|
||||
if (ret != C_KZG_OK) goto out_error;
|
||||
if (err != BLST_SUCCESS) {
|
||||
ret = C_KZG_BADARGS;
|
||||
goto out_error;
|
||||
}
|
||||
blst_p1_from_affine(&out->g1_values[i], &g1_affine);
|
||||
}
|
||||
|
||||
/* Convert all g2 bytes to g2 points */
|
||||
for (i = 0; i < n2; i++) {
|
||||
for (uint64_t i = 0; i < n2; i++) {
|
||||
blst_p2_affine g2_affine;
|
||||
BLST_ERROR err = blst_p2_uncompress(
|
||||
&g2_affine, &g2_bytes[BYTES_PER_G2 * i]
|
||||
);
|
||||
|
@ -1796,17 +1725,8 @@ C_KZG_RET load_trusted_setup(
|
|||
blst_p2_from_affine(&out->g2_values[i], &g2_affine);
|
||||
}
|
||||
|
||||
/* It's the smallest power of 2 >= n1 */
|
||||
unsigned int max_scale = 0;
|
||||
while ((1ULL << max_scale) < n1)
|
||||
max_scale++;
|
||||
|
||||
/* Initialize the KZGSettings struct */
|
||||
ret = c_kzg_malloc((void **)&out->fs, sizeof(FFTSettings));
|
||||
if (ret != C_KZG_OK) goto out_error;
|
||||
ret = new_fft_settings(out->fs, max_scale);
|
||||
if (ret != C_KZG_OK) goto out_error;
|
||||
ret = fft_g1(out->g1_values, g1_projective, true, n1, out->fs);
|
||||
/* Compute roots of unity and permute the G1 trusted setup */
|
||||
ret = compute_roots_of_unity(out->roots_of_unity, max_scale);
|
||||
if (ret != C_KZG_OK) goto out_error;
|
||||
ret = bit_reversal_permutation(out->g1_values, sizeof(g1_t), n1);
|
||||
if (ret != C_KZG_OK) goto out_error;
|
||||
|
@ -1814,11 +1734,13 @@ C_KZG_RET load_trusted_setup(
|
|||
goto out_success;
|
||||
|
||||
out_error:
|
||||
c_kzg_free(out->fs);
|
||||
c_kzg_free(out->g1_values);
|
||||
c_kzg_free(out->g2_values);
|
||||
/*
|
||||
* Note: this only frees the fields in the KZGSettings structure
|
||||
* (roots_of_unity, g1_values, g2_values). It does not free the KZGSettings
|
||||
* structure memory. If necessary, that must be done by the caller.
|
||||
*/
|
||||
free_trusted_setup(out);
|
||||
out_success:
|
||||
c_kzg_free(g1_projective);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1871,45 +1793,3 @@ C_KZG_RET load_trusted_setup_file(KZGSettings *out, FILE *in) {
|
|||
TRUSTED_SETUP_NUM_G2_POINTS
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the memory that was previously allocated by new_fft_settings().
|
||||
*
|
||||
* @remark It's a NOP if `fs` is NULL.
|
||||
*
|
||||
* @param[in] fs The settings to be freed
|
||||
*/
|
||||
static void free_fft_settings(FFTSettings *fs) {
|
||||
if (fs == NULL) return;
|
||||
c_kzg_free(fs->expanded_roots_of_unity);
|
||||
c_kzg_free(fs->reverse_roots_of_unity);
|
||||
c_kzg_free(fs->roots_of_unity);
|
||||
fs->max_width = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the memory that was previously allocated by new_kzg_settings().
|
||||
*
|
||||
* @remark It's a NOP if `s` is NULL.
|
||||
*
|
||||
* @param[in] s The settings to be freed
|
||||
*/
|
||||
static void free_kzg_settings(KZGSettings *s) {
|
||||
if (s == NULL) return;
|
||||
c_kzg_free(s->fs);
|
||||
c_kzg_free(s->g1_values);
|
||||
c_kzg_free(s->g2_values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a trusted setup (KZGSettings).
|
||||
*
|
||||
* @remark It's a NOP if `s` is NULL.
|
||||
*
|
||||
* @param[in] s The trusted setup to free
|
||||
*/
|
||||
void free_trusted_setup(KZGSettings *s) {
|
||||
if (s == NULL) return;
|
||||
free_fft_settings(s->fs);
|
||||
free_kzg_settings(s);
|
||||
}
|
||||
|
|
|
@ -129,43 +129,20 @@ typedef enum {
|
|||
C_KZG_MALLOC, /**< Could not allocate memory. */
|
||||
} C_KZG_RET;
|
||||
|
||||
/**
|
||||
* Stores the setup and parameters needed for performing FFTs.
|
||||
*/
|
||||
typedef struct {
|
||||
/** The maximum size of FFT these settings support, a power of 2. */
|
||||
uint64_t max_width;
|
||||
/**
|
||||
* We fix a given primitive roots of unity w of order `max_width` via
|
||||
* `SCALE2_ROOT_OF_UNITY`. Then `expanded_roots_of_unity[i]` == w^i and
|
||||
* `reverse_roots_of_unity[i]` == w^{-i}. Unusually, both
|
||||
* `expanded_roots_of_unity` and `reverse_roots_of_unity` have length
|
||||
* `max_width + 1`. By the above, `expanded_roots_of_unity[max_width] ==
|
||||
* expanded_roots_of_unity[0] == 1` and similarly for
|
||||
* `reverse_roots_of_unity`. The redundant element is just there to simplify
|
||||
* index calculations in some formulas.
|
||||
*/
|
||||
|
||||
/** Ascending powers of the root of unity, length `max_width + 1`. */
|
||||
fr_t *expanded_roots_of_unity;
|
||||
/** Descending powers of the root of unity, length `max_width + 1`. */
|
||||
fr_t *reverse_roots_of_unity;
|
||||
/** Powers of the root of unity in bit-reversal permutation order, length
|
||||
* `max_width`. */
|
||||
fr_t *roots_of_unity;
|
||||
} FFTSettings;
|
||||
|
||||
/**
|
||||
* Stores the setup and parameters needed for computing KZG proofs.
|
||||
*/
|
||||
typedef struct {
|
||||
/** The corresponding settings for performing FFTs. */
|
||||
FFTSettings *fs;
|
||||
/** 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;
|
||||
/** G1 group elements from the trusted setup,
|
||||
* in Lagrange form bit-reversal permutation. */
|
||||
g1_t *g1_values;
|
||||
/** G2 group elements from the trusted setup;
|
||||
* both arrays have `FIELD_ELEMENTS_PER_BLOB` elements. */
|
||||
/** G2 group elements from the trusted setup. */
|
||||
g2_t *g2_values;
|
||||
} KZGSettings;
|
||||
|
||||
|
|
|
@ -1006,7 +1006,7 @@ test_evaluate_polynomial_in_evaluation_form__constant_polynomial_in_range(void
|
|||
fr_t x, y, c;
|
||||
|
||||
get_rand_fr(&c);
|
||||
x = s.fs->roots_of_unity[123];
|
||||
x = s.roots_of_unity[123];
|
||||
|
||||
for (size_t i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) {
|
||||
p.evals[i] = c;
|
||||
|
@ -1030,7 +1030,7 @@ static void test_evaluate_polynomial_in_evaluation_form__random_polynomial(void
|
|||
}
|
||||
|
||||
for (size_t i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) {
|
||||
eval_poly(&p.evals[i], poly_coefficients, &s.fs->roots_of_unity[i]);
|
||||
eval_poly(&p.evals[i], poly_coefficients, &s.roots_of_unity[i]);
|
||||
}
|
||||
|
||||
get_rand_fr(&x);
|
||||
|
@ -1041,7 +1041,7 @@ static void test_evaluate_polynomial_in_evaluation_form__random_polynomial(void
|
|||
|
||||
ASSERT("evaluation methods match", fr_equal(&y, &check));
|
||||
|
||||
x = s.fs->roots_of_unity[123];
|
||||
x = s.roots_of_unity[123];
|
||||
|
||||
eval_poly(&check, poly_coefficients, &x);
|
||||
|
||||
|
@ -1220,7 +1220,7 @@ static void test_compute_and_verify_kzg_proof__succeeds_within_domain(void) {
|
|||
ret = blob_to_polynomial(&poly, &blob);
|
||||
ASSERT_EQUALS(ret, C_KZG_OK);
|
||||
|
||||
z_fr = s.fs->roots_of_unity[i];
|
||||
z_fr = s.roots_of_unity[i];
|
||||
bytes_from_bls_field(&z, &z_fr);
|
||||
|
||||
/* Compute the proof */
|
||||
|
@ -1688,47 +1688,6 @@ static void test_verify_kzg_proof_batch__fails_invalid_blob(void) {
|
|||
ASSERT_EQUALS(ret, C_KZG_BADARGS);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Tests for fft_g1
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void test_fft_g1__succeeds_round_trip(void) {
|
||||
C_KZG_RET ret;
|
||||
g1_t original[MAX_WIDTH], transformed[MAX_WIDTH], inversed[MAX_WIDTH];
|
||||
|
||||
for (size_t i = 0; i < MAX_WIDTH; i++) {
|
||||
get_rand_g1(&original[i]);
|
||||
}
|
||||
|
||||
ret = fft_g1(transformed, original, false, MAX_WIDTH, s.fs);
|
||||
ASSERT_EQUALS(ret, C_KZG_OK);
|
||||
|
||||
ret = fft_g1(inversed, transformed, true, MAX_WIDTH, s.fs);
|
||||
ASSERT_EQUALS(ret, C_KZG_OK);
|
||||
|
||||
for (size_t i = 0; i < MAX_WIDTH; i++) {
|
||||
ASSERT(
|
||||
"same as original", blst_p1_is_equal(&original[i], &inversed[i])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_fft_g1__n_not_power_of_two(void) {
|
||||
C_KZG_RET ret;
|
||||
g1_t original[MAX_WIDTH], transformed[MAX_WIDTH];
|
||||
|
||||
ret = fft_g1(transformed, original, false, MAX_WIDTH - 1, s.fs);
|
||||
ASSERT_EQUALS(ret, C_KZG_BADARGS);
|
||||
}
|
||||
|
||||
static void test_fft_g1__n_too_large(void) {
|
||||
C_KZG_RET ret;
|
||||
g1_t original[MAX_WIDTH], transformed[MAX_WIDTH];
|
||||
|
||||
ret = fft_g1(transformed, original, false, 2 * s.fs->max_width, s.fs);
|
||||
ASSERT_EQUALS(ret, C_KZG_BADARGS);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Tests for expand_root_of_unity
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1970,9 +1929,6 @@ int main(void) {
|
|||
RUN(test_verify_kzg_proof_batch__fails_proof_not_in_g1);
|
||||
RUN(test_verify_kzg_proof_batch__fails_commitment_not_in_g1);
|
||||
RUN(test_verify_kzg_proof_batch__fails_invalid_blob);
|
||||
RUN(test_fft_g1__succeeds_round_trip);
|
||||
RUN(test_fft_g1__n_not_power_of_two);
|
||||
RUN(test_fft_g1__n_too_large);
|
||||
RUN(test_expand_root_of_unity__succeeds_with_root);
|
||||
RUN(test_expand_root_of_unity__fails_not_root_of_unity);
|
||||
RUN(test_expand_root_of_unity__fails_wrong_root_of_unity);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,9 @@
|
|||
4
|
||||
65
|
||||
97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb
|
||||
854262641262cb9e056a8512808ea6864d903dbcad713fd6da8dddfa5ce40d85612c912063ace060ed8c4bf005bab839
|
||||
86f708eee5ae0cf40be36993e760d9cb3b2371f22db3209947c5d21ea68e55186b30871c50bf11ef29e5248bf42d5678
|
||||
94f9c0bafb23cbbf34a93a64243e3e0f934b57593651f3464de7dc174468123d9698f1b9dfa22bb5b6eb96eae002f29f
|
||||
91131b2e3c1e5f0b51df8970e67080032f411571b66d301436c46f25bbfddf9ca16756430dc470bdb0d85b47fedcdbc1
|
||||
934d35b2a46e169915718b77127b0d4efbacdad7fdde4593af7d21d37ebcb77fe6c8dde6b8a9537854d70ef1f291a585
|
||||
9410ca1d0342fe7419f02194281df45e1c1ff42fd8b439de5644cc312815c21ddd2e3eeb63fb807cf837e68b76668bd5
|
||||
b163df7e9baeb60f69b6ee5faa538c3a564b62eb8cde6a3616083c8cb2171eedd583c9143e7e916df59bf27da5e024e8
|
||||
93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8
|
||||
99aca9fb2f7760cecb892bf7262c176b334824f5727f680bba701a33e322cb6667531410dfc7c8e4321a3f0ea8af48cb1436638a2093123f046f0f504cc2a864825542873edbbc5d7ed17af125a4f2cf6433c6f4f61b81173726981dd989761d
|
||||
88e2e982982bf8231e747e9dfcd14c05bd02623d1332734d2af26246c6869fb56ee6c994843f593178a040495ba61f4a083b0e18110b1d9f5224783d8f9a895e8ee744e87929430e9ba96bd29251cbf61240b256d1525600f3d562894d93d659
|
||||
|
|
Loading…
Reference in New Issue