Revamp error handling and memory management
This commit is contained in:
parent
d22bbcca62
commit
cfe5fa6e49
29
src/c_kzg.h
29
src/c_kzg.h
|
@ -46,9 +46,23 @@ typedef enum {
|
|||
printf("\n%s:%d: Failed ASSERT: %s\n", __FILE__, __LINE__, #cond); \
|
||||
abort(); \
|
||||
}
|
||||
#define TRY(result) \
|
||||
{ \
|
||||
C_KZG_RET ret = (result); \
|
||||
if (ret != C_KZG_OK) { \
|
||||
printf("\n%s:%d: Failed TRY: %s, result = %d\n", __FILE__, __LINE__, #result, ret); \
|
||||
abort(); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define ASSERT(cond, ret) \
|
||||
if (!(cond)) return (ret)
|
||||
#define TRY(result) \
|
||||
{ \
|
||||
C_KZG_RET ret = (result); \
|
||||
if (ret == C_KZG_MALLOC) return ret; \
|
||||
if (ret != C_KZG_OK) return C_KZG_ERROR; \
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
/** @def ASSERT
|
||||
|
@ -56,7 +70,8 @@ typedef enum {
|
|||
* Handle errors.
|
||||
*
|
||||
* This macro comes in two versions according to whether `DEBUG` is defined or not (`-DDEBUG` compiler flag).
|
||||
* - `DEBUG` is undefined: when @p cond is false, return from the function with the value @p ret, otherwise continue.
|
||||
* - `DEBUG` is undefined: when @p cond is false, return from the current function with the value @p ret, otherwise
|
||||
* continue.
|
||||
* - `DEBUG` is defined: when @p cond is false, print file and line number information and abort the run. This is very
|
||||
* useful for dubugging. The @p ret parameter is ignored in this case.
|
||||
*
|
||||
|
@ -64,4 +79,16 @@ typedef enum {
|
|||
* @param ret The return code to be returned in case the condition is false
|
||||
*/
|
||||
|
||||
/** @def TRY
|
||||
*
|
||||
* Handle errors.
|
||||
*
|
||||
* This macro comes in two versions according to whether `DEBUG` is defined or not (`-DDEBUG` compiler flag).
|
||||
* - `DEBUG` is undefined: if the @p result is not `C_KZG_OK`, return immediately with either `C_KZG_MALLOC` or
|
||||
* `C_KZG_ERROR`. Otherwise continue.
|
||||
* - `DEBUG` is defined: if @p result is not `C_KZG_OK`, print file and line number information and abort the run.
|
||||
* This is very useful for dubugging.
|
||||
*
|
||||
* @param result The function call result to be tested
|
||||
*/
|
||||
#endif // C_KZG_H
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
* Utilities useful across the library.
|
||||
*/
|
||||
|
||||
#include <stdlib.h> // malloc
|
||||
#include "c_kzg_util.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
/** @file c_kzg_util.c */
|
||||
|
||||
#include <stdlib.h> // free()
|
||||
#include "c_kzg.h"
|
||||
|
||||
C_KZG_RET c_kzg_malloc(void **p, size_t n);
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
* Code shared between the FFTs over field elements and FFTs over G1 group elements.
|
||||
*/
|
||||
|
||||
#include <stdlib.h> // free()
|
||||
#include "fft_common.h"
|
||||
#include "blst_util.h"
|
||||
#include "c_kzg_util.h"
|
||||
|
@ -73,7 +72,8 @@ C_KZG_RET expand_root_of_unity(blst_fr *out, const blst_fr *root, uint64_t width
|
|||
* `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 This structure *must* be deallocated after use by calling #free_fft_settings.
|
||||
* @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
|
||||
|
@ -90,16 +90,11 @@ C_KZG_RET new_fft_settings(FFTSettings *fs, unsigned int max_scale) {
|
|||
blst_fr_from_uint64(&fs->root_of_unity, scale2_root_of_unity[max_scale]);
|
||||
|
||||
// Allocate space for the roots of unity
|
||||
ASSERT(c_kzg_malloc((void **)&fs->expanded_roots_of_unity,
|
||||
(fs->max_width + 1) * sizeof *fs->expanded_roots_of_unity) == C_KZG_OK,
|
||||
C_KZG_MALLOC);
|
||||
ASSERT(c_kzg_malloc((void **)&fs->reverse_roots_of_unity,
|
||||
(fs->max_width + 1) * sizeof *fs->reverse_roots_of_unity) == C_KZG_OK,
|
||||
C_KZG_MALLOC);
|
||||
TRY(c_kzg_malloc((void **)&fs->expanded_roots_of_unity, (fs->max_width + 1) * sizeof *fs->expanded_roots_of_unity));
|
||||
TRY(c_kzg_malloc((void **)&fs->reverse_roots_of_unity, (fs->max_width + 1) * sizeof *fs->reverse_roots_of_unity));
|
||||
|
||||
// Populate the roots of unity
|
||||
ASSERT(expand_root_of_unity(fs->expanded_roots_of_unity, &fs->root_of_unity, fs->max_width) == C_KZG_OK,
|
||||
C_KZG_ERROR);
|
||||
TRY(expand_root_of_unity(fs->expanded_roots_of_unity, &fs->root_of_unity, fs->max_width));
|
||||
|
||||
// Populate reverse roots of unity
|
||||
for (uint64_t i = 0; i <= fs->max_width; i++) {
|
||||
|
|
35
src/fft_fr.c
35
src/fft_fr.c
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "fft_fr.h"
|
||||
#include "blst_util.h"
|
||||
#include "c_kzg_util.h"
|
||||
|
||||
/**
|
||||
* Slow Fourier Transform.
|
||||
|
@ -112,3 +113,37 @@ C_KZG_RET fft_fr(blst_fr *out, const blst_fr *in, bool inverse, uint64_t n, cons
|
|||
}
|
||||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for #fft_fr that allocates memory for the output.
|
||||
*
|
||||
* @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_fr.
|
||||
*
|
||||
* @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 Pointer to previously initialised FFTSettings structure with `max_width` at least @p n.
|
||||
* @retval C_CZK_OK All is well
|
||||
* @retval C_CZK_BADARGS Invalid parameters were supplied
|
||||
* @retval C_CZK_MALLOC Memory allocation failed
|
||||
*/
|
||||
C_KZG_RET new_fft_fr(blst_fr **out, const blst_fr *in, bool inverse, uint64_t n, const FFTSettings *fs) {
|
||||
C_KZG_RET ret;
|
||||
TRY(c_kzg_malloc((void **)out, n * sizeof **out));
|
||||
ret = fft_fr(*out, in, inverse, n, fs);
|
||||
if (ret == C_KZG_BADARGS) {
|
||||
free_fft_fr(*out);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recover memory allocated by #new_fft_fr.
|
||||
*
|
||||
* @param x The array to be freed
|
||||
*/
|
||||
void free_fft_fr(blst_fr *x) {
|
||||
free(x);
|
||||
}
|
||||
|
|
|
@ -23,3 +23,5 @@ void fft_fr_slow(blst_fr *out, const blst_fr *in, uint64_t stride, const blst_fr
|
|||
void fft_fr_fast(blst_fr *out, const blst_fr *in, uint64_t stride, const blst_fr *roots, uint64_t roots_stride,
|
||||
uint64_t n);
|
||||
C_KZG_RET fft_fr(blst_fr *out, const blst_fr *in, bool inverse, uint64_t n, const FFTSettings *fs);
|
||||
C_KZG_RET new_fft_fr(blst_fr **out, const blst_fr *in, bool inverse, uint64_t n, const FFTSettings *fs);
|
||||
void free_fft_fr(blst_fr *x);
|
||||
|
|
35
src/fft_g1.c
35
src/fft_g1.c
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "fft_g1.h"
|
||||
#include "blst_util.h"
|
||||
#include "c_kzg_util.h"
|
||||
|
||||
/**
|
||||
* Slow Fourier Transform.
|
||||
|
@ -113,3 +114,37 @@ C_KZG_RET fft_g1(blst_p1 *out, const blst_p1 *in, bool inverse, uint64_t n, cons
|
|||
}
|
||||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for #fft_g1 that allocates memory for the output.
|
||||
*
|
||||
* @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_g1.
|
||||
*
|
||||
* @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 Pointer to previously initialised FFTSettings structure with `max_width` at least @p n.
|
||||
* @retval C_CZK_OK All is well
|
||||
* @retval C_CZK_BADARGS Invalid parameters were supplied
|
||||
* @retval C_CZK_MALLOC Memory allocation failed
|
||||
*/
|
||||
C_KZG_RET new_fft_g1(blst_p1 **out, const blst_p1 *in, bool inverse, uint64_t n, const FFTSettings *fs) {
|
||||
C_KZG_RET ret;
|
||||
TRY(c_kzg_malloc((void **)out, n * sizeof **out));
|
||||
ret = fft_g1(*out, in, inverse, n, fs);
|
||||
if (ret == C_KZG_BADARGS) {
|
||||
free_fft_g1(*out);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recover memory allocated by #new_fft_g1.
|
||||
*
|
||||
* @param x The array to be freed
|
||||
*/
|
||||
void free_fft_g1(blst_p1 *x) {
|
||||
free(x);
|
||||
}
|
||||
|
|
|
@ -23,3 +23,5 @@ void fft_g1_slow(blst_p1 *out, const blst_p1 *in, uint64_t stride, const blst_fr
|
|||
void fft_g1_fast(blst_p1 *out, const blst_p1 *in, uint64_t stride, const blst_fr *roots, uint64_t roots_stride,
|
||||
uint64_t n);
|
||||
C_KZG_RET fft_g1(blst_p1 *out, const blst_p1 *in, bool inverse, uint64_t n, const FFTSettings *fs);
|
||||
C_KZG_RET new_fft_g1(blst_p1 **out, const blst_p1 *in, bool inverse, uint64_t n, const FFTSettings *fs);
|
||||
void free_fft_g1(blst_p1 *x);
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
* paper](https://github.com/khovratovich/Kate/blob/master/Kate_amortized.pdf).
|
||||
*/
|
||||
|
||||
#include <stdlib.h> // free()
|
||||
#include <string.h> // memcpy()
|
||||
#include "fk20_proofs.h"
|
||||
#include "fft_g1.h"
|
||||
|
@ -109,8 +108,6 @@ C_KZG_RET reverse_bit_order(void *values, size_t size, uint64_t n) {
|
|||
* The first part of the Toeplitz matrix multiplication algorithm: the Fourier
|
||||
* transform of the vector @p x extended.
|
||||
*
|
||||
* Used in #new_fk20_single_settings to calculate `x_ext_fft`.
|
||||
*
|
||||
* @param[out] out The FFT of the extension of @p x, size @p n * 2
|
||||
* @param[in] x The input vector, size @p n
|
||||
* @param[in] n The length of the input vector @p x
|
||||
|
@ -123,8 +120,7 @@ C_KZG_RET toeplitz_part_1(blst_p1 *out, const blst_p1 *x, uint64_t n, const FFTS
|
|||
uint64_t n2 = n * 2;
|
||||
blst_p1 *x_ext;
|
||||
|
||||
ASSERT(c_kzg_malloc((void **)&x_ext, n2 * sizeof *x_ext) == C_KZG_OK, C_KZG_MALLOC);
|
||||
|
||||
TRY(c_kzg_malloc((void **)&x_ext, n2 * sizeof *x_ext));
|
||||
for (uint64_t i = 0; i < n; i++) {
|
||||
x_ext[i] = x[i];
|
||||
}
|
||||
|
@ -132,12 +128,41 @@ C_KZG_RET toeplitz_part_1(blst_p1 *out, const blst_p1 *x, uint64_t n, const FFTS
|
|||
x_ext[i] = g1_identity;
|
||||
}
|
||||
|
||||
ASSERT(fft_g1(out, x_ext, false, n2, fs) == C_KZG_OK, C_KZG_ERROR);
|
||||
TRY(fft_g1(out, x_ext, false, n2, fs));
|
||||
|
||||
free(x_ext);
|
||||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for #toeplitz_part_1 that allocates memory for the output.
|
||||
*
|
||||
* @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_toeplitz_part_1.
|
||||
*
|
||||
* @param[out] out The FFT of the extension of @p x, size @p n * 2
|
||||
* @param[in] x The input vector, size @p n
|
||||
* @param[in] n The length of the input vector @p x
|
||||
* @param[in] fs The FFT settings previously initialised with #new_fft_settings
|
||||
* @retval C_CZK_OK All is well
|
||||
* @retval C_CZK_ERROR An internal error occurred
|
||||
* @retval C_CZK_MALLOC Memory allocation failed
|
||||
*/
|
||||
C_KZG_RET new_toeplitz_part_1(blst_p1 **out, const blst_p1 *x, uint64_t n, const FFTSettings *fs) {
|
||||
TRY(c_kzg_malloc((void **)out, n * 2 * sizeof **out));
|
||||
TRY(toeplitz_part_1(*out, x, n, fs));
|
||||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recover memory allocated by #new_toeplitz_part_1.
|
||||
*
|
||||
* @param x The array to be freed
|
||||
*/
|
||||
void free_toeplitz_part_1(blst_p1 *x) {
|
||||
free(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* The second part of the Toeplitz matrix multiplication algorithm.
|
||||
*
|
||||
|
@ -153,21 +178,50 @@ C_KZG_RET toeplitz_part_2(blst_p1 *out, const poly *toeplitz_coeffs, const FK20S
|
|||
blst_fr *toeplitz_coeffs_fft;
|
||||
|
||||
ASSERT(toeplitz_coeffs->length == fk->x_ext_fft_len, C_KZG_BADARGS);
|
||||
ASSERT(c_kzg_malloc((void **)&toeplitz_coeffs_fft, toeplitz_coeffs->length * sizeof *toeplitz_coeffs_fft) ==
|
||||
C_KZG_OK,
|
||||
C_KZG_MALLOC);
|
||||
|
||||
ASSERT(fft_fr(toeplitz_coeffs_fft, toeplitz_coeffs->coeffs, false, toeplitz_coeffs->length, fk->ks->fs) == C_KZG_OK,
|
||||
C_KZG_ERROR);
|
||||
TRY(new_fft_fr(&toeplitz_coeffs_fft, toeplitz_coeffs->coeffs, false, toeplitz_coeffs->length, fk->ks->fs));
|
||||
|
||||
for (uint64_t i = 0; i < toeplitz_coeffs->length; i++) {
|
||||
p1_mul(&out[i], &fk->x_ext_fft[i], &toeplitz_coeffs_fft[i]);
|
||||
}
|
||||
|
||||
free(toeplitz_coeffs_fft);
|
||||
free_fft_fr(toeplitz_coeffs_fft);
|
||||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for #toeplitz_part_2 that allocates memory for the output.
|
||||
*
|
||||
* @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_toeplitz_part_2.
|
||||
*
|
||||
* @param[out] out Array of G1 group elements, length `n`
|
||||
* @param[in] toeplitz_coeffs Toeplitz coefficients, a polynomial length `n`
|
||||
* @param[in] fk FK20 single settings previously initialised by #new_fk20_single_settings
|
||||
* @retval C_CZK_OK All is well
|
||||
* @retval C_CZK_BADARGS Invalid parameters were supplied
|
||||
* @retval C_CZK_ERROR An internal error occurred
|
||||
* @retval C_CZK_MALLOC Memory allocation failed
|
||||
*/
|
||||
C_KZG_RET new_toeplitz_part_2(blst_p1 **out, const poly *toeplitz_coeffs, const FK20SingleSettings *fk) {
|
||||
C_KZG_RET ret;
|
||||
TRY(c_kzg_malloc((void **)out, toeplitz_coeffs->length * sizeof **out));
|
||||
ret = toeplitz_part_2(*out, toeplitz_coeffs, fk);
|
||||
if (ret == C_KZG_BADARGS) {
|
||||
free_toeplitz_part_2(*out);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recover memory allocated by #new_toeplitz_part_2.
|
||||
*
|
||||
* @param x The array to be freed
|
||||
*/
|
||||
void free_toeplitz_part_2(blst_p1 *x) {
|
||||
free(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* The third part of the Toeplitz matrix multiplication algorithm: transform back and zero the top half.
|
||||
*
|
||||
|
@ -181,7 +235,7 @@ C_KZG_RET toeplitz_part_2(blst_p1 *out, const poly *toeplitz_coeffs, const FK20S
|
|||
C_KZG_RET toeplitz_part_3(blst_p1 *out, const blst_p1 *h_ext_fft, uint64_t n2, const FK20SingleSettings *fk) {
|
||||
uint64_t n = n2 / 2;
|
||||
|
||||
ASSERT(fft_g1(out, h_ext_fft, true, n2, fk->ks->fs) == C_KZG_OK, C_KZG_ERROR);
|
||||
TRY(fft_g1(out, h_ext_fft, true, n2, fk->ks->fs));
|
||||
|
||||
// Zero the second half of h
|
||||
for (uint64_t i = n; i < n2; i++) {
|
||||
|
@ -191,10 +245,40 @@ C_KZG_RET toeplitz_part_3(blst_p1 *out, const blst_p1 *h_ext_fft, uint64_t n2, c
|
|||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for #toeplitz_part_3 that allocates memory for the output.
|
||||
*
|
||||
* @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_toeplitz_part_3.
|
||||
*
|
||||
* @param[out] out Array of G1 group elements, length @p n2
|
||||
* @param[in] h_ext_fft FFT of the extended `h` values, length @p n2
|
||||
* @param[in] n2 Size of the arrays
|
||||
* @param[in] fk FK20 single settings previously initialised by #new_fk20_single_settings
|
||||
* @retval C_CZK_OK All is well
|
||||
* @retval C_CZK_ERROR An internal error occurred
|
||||
* @retval C_CZK_MALLOC Memory allocation failed
|
||||
*/
|
||||
C_KZG_RET new_toeplitz_part_3(blst_p1 **out, const blst_p1 *h_ext_fft, uint64_t n2, const FK20SingleSettings *fk) {
|
||||
TRY(c_kzg_malloc((void **)out, n2 * sizeof **out));
|
||||
TRY(toeplitz_part_3(*out, h_ext_fft, n2, fk));
|
||||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recover memory allocated by #new_toeplitz_part_3.
|
||||
*
|
||||
* @param x The array to be freed
|
||||
*/
|
||||
void free_toeplitz_part_3(blst_p1 *x) {
|
||||
free(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder and extend polynomial coefficients for the toeplitz method.
|
||||
*
|
||||
* @remark Allocates space for the return polynomial that needs to be freed by calling #free_poly.
|
||||
* @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_toeplitz_coeffs_step.
|
||||
*
|
||||
* @param[out] out The reordered polynomial, size `n * 2`
|
||||
* @param[in] in The input polynomial, size `n`
|
||||
|
@ -204,7 +288,7 @@ C_KZG_RET toeplitz_part_3(blst_p1 *out, const blst_p1 *h_ext_fft, uint64_t n2, c
|
|||
C_KZG_RET new_toeplitz_coeffs_step(poly *out, const poly *in) {
|
||||
uint64_t n = in->length, n2 = n * 2;
|
||||
|
||||
ASSERT(new_poly(out, n2) == C_KZG_OK, C_KZG_MALLOC);
|
||||
TRY(new_poly(out, n2));
|
||||
|
||||
out->coeffs[0] = in->coeffs[n - 1];
|
||||
for (uint64_t i = 1; i <= n + 1; i++) {
|
||||
|
@ -249,25 +333,18 @@ C_KZG_RET fk20_single_da_opt(blst_p1 *out, const poly *p, const FK20SingleSettin
|
|||
uint64_t n = p->length, n2 = n * 2;
|
||||
blst_p1 *h, *h_ext_fft;
|
||||
poly toeplitz_coeffs;
|
||||
C_KZG_RET ret;
|
||||
|
||||
ASSERT(n2 <= fk->ks->fs->max_width, C_KZG_BADARGS);
|
||||
ASSERT(is_power_of_two(n), C_KZG_BADARGS);
|
||||
|
||||
ASSERT(new_toeplitz_coeffs_step(&toeplitz_coeffs, p) == C_KZG_OK, C_KZG_MALLOC);
|
||||
TRY(new_toeplitz_coeffs_step(&toeplitz_coeffs, p));
|
||||
TRY(new_toeplitz_part_2(&h_ext_fft, &toeplitz_coeffs, fk));
|
||||
TRY(new_toeplitz_part_3(&h, h_ext_fft, n2, fk));
|
||||
TRY(fft_g1(out, h, false, n2, fk->ks->fs));
|
||||
|
||||
ASSERT(c_kzg_malloc((void **)&h_ext_fft, toeplitz_coeffs.length * sizeof *h_ext_fft) == C_KZG_OK, C_KZG_MALLOC);
|
||||
ASSERT((ret = toeplitz_part_2(h_ext_fft, &toeplitz_coeffs, fk)) == C_KZG_OK,
|
||||
ret == C_KZG_MALLOC ? ret : C_KZG_ERROR);
|
||||
|
||||
ASSERT(c_kzg_malloc((void **)&h, toeplitz_coeffs.length * sizeof *h) == C_KZG_OK, C_KZG_MALLOC);
|
||||
ASSERT(toeplitz_part_3(h, h_ext_fft, n2, fk) == C_KZG_OK, C_KZG_ERROR);
|
||||
|
||||
ASSERT(fft_g1(out, h, false, n2, fk->ks->fs) == C_KZG_OK, C_KZG_ERROR);
|
||||
|
||||
free(h);
|
||||
free(h_ext_fft);
|
||||
free_toeplitz_coeffs_step(&toeplitz_coeffs);
|
||||
free_toeplitz_part_2(h_ext_fft);
|
||||
free_toeplitz_part_3(h);
|
||||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
|
@ -293,8 +370,8 @@ C_KZG_RET da_using_fk20_single(blst_p1 *out, const poly *p, const FK20SingleSett
|
|||
ASSERT(n2 <= fk->ks->fs->max_width, C_KZG_BADARGS);
|
||||
ASSERT(is_power_of_two(n), C_KZG_BADARGS);
|
||||
|
||||
ASSERT(fk20_single_da_opt(out, p, fk) == C_KZG_OK, C_KZG_ERROR);
|
||||
ASSERT(reverse_bit_order(out, sizeof out[0], n2) == C_KZG_OK, C_KZG_ERROR);
|
||||
TRY(fk20_single_da_opt(out, p, fk));
|
||||
TRY(reverse_bit_order(out, sizeof out[0], n2));
|
||||
|
||||
return C_KZG_OK;
|
||||
}
|
||||
|
@ -319,7 +396,8 @@ void fk20_multi(void) {}
|
|||
/**
|
||||
* Initialise settings for an FK20 single proof.
|
||||
*
|
||||
* #free_fk20_single_settings must be called to deallocate this structure.
|
||||
* @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_fk20_single_settings.
|
||||
*
|
||||
* @param[out] fk The initialised settings
|
||||
* @param[in] n2 The desired size of `x_ext_fft`, a power of two
|
||||
|
@ -340,15 +418,13 @@ C_KZG_RET new_fk20_single_settings(FK20SingleSettings *fk, uint64_t n2, const KZ
|
|||
fk->ks = ks;
|
||||
fk->x_ext_fft_len = n2;
|
||||
|
||||
ASSERT(c_kzg_malloc((void **)&x, n * sizeof *x) == C_KZG_OK, C_KZG_MALLOC);
|
||||
ASSERT(c_kzg_malloc((void **)&fk->x_ext_fft, fk->x_ext_fft_len * sizeof *fk->x_ext_fft) == C_KZG_OK, C_KZG_MALLOC);
|
||||
|
||||
TRY(c_kzg_malloc((void **)&x, n * sizeof *x));
|
||||
for (uint64_t i = 0; i < n - 1; i++) {
|
||||
x[i] = ks->secret_g1[n - 2 - i];
|
||||
}
|
||||
x[n - 1] = g1_identity;
|
||||
|
||||
ASSERT(toeplitz_part_1(fk->x_ext_fft, x, n, ks->fs) == C_KZG_OK, C_KZG_ERROR);
|
||||
TRY(new_toeplitz_part_1(&fk->x_ext_fft, x, n, ks->fs));
|
||||
|
||||
free(x);
|
||||
return C_KZG_OK;
|
||||
|
@ -357,10 +433,12 @@ C_KZG_RET new_fk20_single_settings(FK20SingleSettings *fk, uint64_t n2, const KZ
|
|||
/**
|
||||
* Initialise settings for an FK20 multi proof.
|
||||
*
|
||||
* #free_fk20_single_settings must be called to deallocate this structure.
|
||||
* @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_fk20_multi_settings.
|
||||
*
|
||||
* @param[out] fk The initialised settings
|
||||
* @param[in] n2 The desired size of `x_ext_fft`, a power of two
|
||||
* @param[in] chunk_len TODO
|
||||
* @param[in] ks KZGSettings that have already been initialised
|
||||
* @retval C_CZK_OK All is well
|
||||
* @retval C_CZK_BADARGS Invalid parameters were supplied
|
||||
|
@ -370,7 +448,6 @@ C_KZG_RET new_fk20_single_settings(FK20SingleSettings *fk, uint64_t n2, const KZ
|
|||
C_KZG_RET new_fk20_multi_settings(FK20MultiSettings *fk, uint64_t n2, uint64_t chunk_len, const KZGSettings *ks) {
|
||||
uint64_t n, k;
|
||||
blst_p1 *x;
|
||||
C_KZG_RET ret;
|
||||
|
||||
ASSERT(n2 <= ks->fs->max_width, C_KZG_BADARGS);
|
||||
ASSERT(is_power_of_two(n2), C_KZG_BADARGS);
|
||||
|
@ -385,11 +462,9 @@ C_KZG_RET new_fk20_multi_settings(FK20MultiSettings *fk, uint64_t n2, uint64_t c
|
|||
fk->ks = ks;
|
||||
fk->chunk_len = chunk_len;
|
||||
|
||||
ASSERT(c_kzg_malloc((void **)&fk->x_ext_fft_files, chunk_len * sizeof *fk->x_ext_fft_files) == C_KZG_OK,
|
||||
C_KZG_MALLOC);
|
||||
TRY(c_kzg_malloc((void **)&fk->x_ext_fft_files, chunk_len * sizeof *fk->x_ext_fft_files));
|
||||
|
||||
// Temporary array
|
||||
ASSERT(c_kzg_malloc((void **)&x, k * sizeof *x) == C_KZG_OK, C_KZG_MALLOC);
|
||||
TRY(c_kzg_malloc((void **)&x, k * sizeof *x));
|
||||
for (uint64_t offset = 0; offset < chunk_len; offset++) {
|
||||
uint64_t start = n - chunk_len - 1 - offset;
|
||||
for (uint64_t i = 0, j = start; i + 1 < k; i++, j -= chunk_len) {
|
||||
|
@ -397,12 +472,7 @@ C_KZG_RET new_fk20_multi_settings(FK20MultiSettings *fk, uint64_t n2, uint64_t c
|
|||
}
|
||||
x[k - 1] = g1_identity;
|
||||
|
||||
ASSERT(c_kzg_malloc((void **)&fk->x_ext_fft_files[offset], 2 * k * sizeof *fk->x_ext_fft_files[offset]) ==
|
||||
C_KZG_OK,
|
||||
C_KZG_MALLOC);
|
||||
|
||||
ASSERT(ret = toeplitz_part_1(fk->x_ext_fft_files[offset], x, k, ks->fs) == C_KZG_OK,
|
||||
ret == C_KZG_MALLOC ? ret : C_KZG_ERROR);
|
||||
TRY(new_toeplitz_part_1(&fk->x_ext_fft_files[offset], x, k, ks->fs));
|
||||
}
|
||||
|
||||
free(x);
|
||||
|
@ -415,7 +485,7 @@ C_KZG_RET new_fk20_multi_settings(FK20MultiSettings *fk, uint64_t n2, uint64_t c
|
|||
* @param fk The settings to be freed
|
||||
*/
|
||||
void free_fk20_single_settings(FK20SingleSettings *fk) {
|
||||
free(fk->x_ext_fft);
|
||||
free_toeplitz_part_1(fk->x_ext_fft);
|
||||
fk->x_ext_fft_len = 0;
|
||||
}
|
||||
|
||||
|
@ -426,7 +496,7 @@ void free_fk20_single_settings(FK20SingleSettings *fk) {
|
|||
*/
|
||||
void free_fk20_multi_settings(FK20MultiSettings *fk) {
|
||||
for (uint64_t i = 0; i < fk->chunk_len; i++) {
|
||||
free((fk->x_ext_fft_files)[i]);
|
||||
free_toeplitz_part_1((fk->x_ext_fft_files)[i]);
|
||||
}
|
||||
free(fk->x_ext_fft_files);
|
||||
fk->chunk_len = 0;
|
||||
|
|
|
@ -47,17 +47,17 @@
|
|||
typedef struct {
|
||||
const KZGSettings *ks; /**< The corresponding settings for performing KZG proofs */
|
||||
blst_p1 *x_ext_fft; /**< The output of the first part of the Toeplitz process */
|
||||
uint64_t x_ext_fft_len; /**< The length of the `x_ext_fft_len` array */
|
||||
uint64_t x_ext_fft_len; /**< The length of the `x_ext_fft_len` array (TODO - do we need this?)*/
|
||||
} FK20SingleSettings;
|
||||
|
||||
/**
|
||||
* Stores the setup and parameters needed for computing FK20 multi proofs.
|
||||
*/
|
||||
typedef struct {
|
||||
const KZGSettings *ks; /**< The corresponding settings for performing KZG proofs */
|
||||
uint64_t chunk_len;
|
||||
blst_p1 **x_ext_fft_files;
|
||||
uint64_t length;
|
||||
const KZGSettings *ks; /**< The corresponding settings for performing KZG proofs */
|
||||
uint64_t chunk_len; /**< TODO */
|
||||
blst_p1 **x_ext_fft_files; /**< TODO */
|
||||
uint64_t length; /**< TODO */
|
||||
} FK20MultiSettings;
|
||||
|
||||
int log2_pow2(uint32_t n);
|
||||
|
@ -65,9 +65,16 @@ uint32_t reverse_bits(uint32_t a);
|
|||
uint32_t reverse_bits_limited(uint32_t n, uint32_t value);
|
||||
C_KZG_RET reverse_bit_order(void *values, size_t size, uint64_t n);
|
||||
C_KZG_RET toeplitz_part_1(blst_p1 *out, const blst_p1 *x, uint64_t n, const FFTSettings *fs);
|
||||
C_KZG_RET new_toeplitz_part_1(blst_p1 **out, const blst_p1 *x, uint64_t n, const FFTSettings *fs);
|
||||
void free_toeplitz_part_1(blst_p1 *x);
|
||||
C_KZG_RET toeplitz_part_2(blst_p1 *out, const poly *toeplitz_coeffs, const FK20SingleSettings *fk);
|
||||
C_KZG_RET new_toeplitz_part_2(blst_p1 **out, const poly *toeplitz_coeffs, const FK20SingleSettings *fk);
|
||||
void free_toeplitz_part_2(blst_p1 *x);
|
||||
C_KZG_RET toeplitz_part_3(blst_p1 *out, const blst_p1 *h_ext_fft, uint64_t n2, const FK20SingleSettings *fk);
|
||||
C_KZG_RET new_toeplitz_part_3(blst_p1 **out, const blst_p1 *h_ext_fft, uint64_t n2, const FK20SingleSettings *fk);
|
||||
void free_toeplitz_part_3(blst_p1 *x);
|
||||
C_KZG_RET new_toeplitz_coeffs_step(poly *out, const poly *in);
|
||||
void free_toeplitz_coeffs_step(poly *p);
|
||||
C_KZG_RET fk20_single_da_opt(blst_p1 *out, const poly *p, const FK20SingleSettings *fk);
|
||||
C_KZG_RET da_using_fk20_single(blst_p1 *out, const poly *p, const FK20SingleSettings *fk);
|
||||
C_KZG_RET new_fk20_single_settings(FK20SingleSettings *fk, uint64_t n2, const KZGSettings *ks);
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
*/
|
||||
|
||||
#include <stddef.h> // NULL
|
||||
#include <stdlib.h> // free()
|
||||
#include "kzg_proofs.h"
|
||||
#include "c_kzg_util.h"
|
||||
|
||||
|
@ -104,7 +103,7 @@ C_KZG_RET compute_proof_multi(blst_p1 *out, const poly *p, const blst_fr *x0, ui
|
|||
ASSERT(is_power_of_two(n), C_KZG_BADARGS);
|
||||
|
||||
// Construct x^n - x0^n = (x - w^0)(x - w^1)...(x - w^(n-1))
|
||||
ASSERT(new_poly(&divisor, n + 1) == C_KZG_OK, C_KZG_MALLOC);
|
||||
TRY(new_poly(&divisor, n + 1));
|
||||
|
||||
// -(x0^n)
|
||||
fr_pow(&x_pow_n, x0, n);
|
||||
|
@ -119,7 +118,7 @@ C_KZG_RET compute_proof_multi(blst_p1 *out, const poly *p, const blst_fr *x0, ui
|
|||
divisor.coeffs[n] = fr_one;
|
||||
|
||||
// Calculate q = p / (x^n - x0^n)
|
||||
ASSERT(new_poly_long_div(&q, p, &divisor) == C_KZG_OK, C_KZG_ERROR);
|
||||
TRY(new_poly_long_div(&q, p, &divisor));
|
||||
|
||||
commit_to_poly(out, &q, ks);
|
||||
|
||||
|
@ -157,8 +156,8 @@ C_KZG_RET check_proof_multi(bool *out, const blst_p1 *commitment, const blst_p1
|
|||
ASSERT(is_power_of_two(n), C_KZG_BADARGS);
|
||||
|
||||
// Interpolate at a coset.
|
||||
ASSERT(new_poly(&interp, n) == C_KZG_OK, C_KZG_MALLOC);
|
||||
ASSERT(fft_fr(interp.coeffs, ys, true, n, ks->fs) == C_KZG_OK, C_KZG_ERROR);
|
||||
TRY(new_poly(&interp, n));
|
||||
TRY(fft_fr(interp.coeffs, ys, true, n, ks->fs));
|
||||
|
||||
// Because it is a coset, not the subgroup, we have to multiply the polynomial coefficients by x^-i
|
||||
blst_fr_eucl_inverse(&inv_x, x);
|
||||
|
@ -192,7 +191,8 @@ C_KZG_RET check_proof_multi(bool *out, const blst_p1 *commitment, const blst_p1
|
|||
*
|
||||
* Space is allocated for the provided secrets (the "trusted setup"), and copies of the secrets are made.
|
||||
*
|
||||
* @remark This structure *must* be deallocated after use by calling #free_kzg_settings.
|
||||
* @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_kzg_settings.
|
||||
*
|
||||
* @param[out] ks The new settings
|
||||
* @param[in] secret_g1 The G1 points from the trusted setup (an array of length at least @p length)
|
||||
|
@ -210,8 +210,8 @@ C_KZG_RET new_kzg_settings(KZGSettings *ks, const blst_p1 *secret_g1, const blst
|
|||
ks->length = length;
|
||||
|
||||
// Allocate space for the secrets
|
||||
ASSERT(c_kzg_malloc((void **)&ks->secret_g1, ks->length * sizeof *ks->secret_g1) == C_KZG_OK, C_KZG_MALLOC);
|
||||
ASSERT(c_kzg_malloc((void **)&ks->secret_g2, ks->length * sizeof *ks->secret_g2) == C_KZG_OK, C_KZG_MALLOC);
|
||||
TRY(c_kzg_malloc((void **)&ks->secret_g1, ks->length * sizeof *ks->secret_g1));
|
||||
TRY(c_kzg_malloc((void **)&ks->secret_g2, ks->length * sizeof *ks->secret_g2));
|
||||
|
||||
// Populate the secrets
|
||||
for (uint64_t i = 0; i < ks->length; i++) {
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
* Operations on polynomials defined over the finite field.
|
||||
*/
|
||||
|
||||
#include <stdlib.h> // NULL, free()
|
||||
#include "c_kzg_util.h"
|
||||
#include "poly.h"
|
||||
|
||||
|
@ -92,7 +91,7 @@ C_KZG_RET new_poly_long_div(poly *out, const poly *dividend, const poly *divisor
|
|||
ASSERT(divisor->length > 0, C_KZG_BADARGS);
|
||||
|
||||
// Initialise the output polynomial
|
||||
ASSERT(new_poly(out, poly_quotient_length(dividend, divisor)) == C_KZG_OK, C_KZG_MALLOC);
|
||||
TRY(new_poly(out, poly_quotient_length(dividend, divisor)));
|
||||
|
||||
// If the divisor is larger than the dividend, the result is zero-length
|
||||
if (out->length == 0) return C_KZG_OK;
|
||||
|
@ -144,7 +143,7 @@ C_KZG_RET new_poly(poly *out, uint64_t length) {
|
|||
* @retval C_CZK_MALLOC Memory allocation failed
|
||||
*/
|
||||
C_KZG_RET new_poly_with_coeffs(poly *out, const blst_fr *coeffs, uint64_t length) {
|
||||
ASSERT(new_poly(out, length) == C_KZG_OK, C_KZG_MALLOC);
|
||||
TRY(new_poly(out, length));
|
||||
for (uint64_t i = 0; i < length; i++) {
|
||||
out->coeffs[i] = coeffs[i];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue