Handle malloc() errors

This commit is contained in:
Ben Edgington 2021-02-07 09:22:37 +00:00
parent ff014c293f
commit 7d5f0fcbd0
11 changed files with 126 additions and 31 deletions

View File

@ -1,6 +1,6 @@
TESTS = blst_util_test fft_common_test fft_fr_test fft_g1_test \
TESTS = blst_util_test c_kzg_util_test fft_common_test fft_fr_test fft_g1_test \
kzg_proofs_test poly_test
LIB_SRC = blst_util.c fft_common.c fft_fr.c fft_g1.c kzg_proofs.c poly.c
LIB_SRC = blst_util.c c_kzg_util.c fft_common.c fft_fr.c fft_g1.c kzg_proofs.c poly.c
LIB_OBJ = $(LIB_SRC:.c=.o)
CFLAGS = -g

View File

@ -17,15 +17,16 @@
#ifndef C_KZG_H
#define C_KZG_H
#include <stdbool.h>
#include "../inc/blst.h"
typedef enum {
C_KZG_OK = 0, // Success!
C_KZG_BADARGS, // The supplied data is invalid in some way
C_KZG_ERROR, // Internal error - should never occur
C_KZG_MALLOC, // Could not allocate memory
} C_KZG_RET;
#include <stdbool.h>
#include "../inc/blst.h"
#ifdef DEBUG
#include <stdlib.h>
#include <stdio.h>

27
src/c_kzg_util.c Normal file
View File

@ -0,0 +1,27 @@
/*
* Copyright 2021 Benjamin Edgington
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h> // malloc
#include "c_kzg_util.h"
C_KZG_RET c_kzg_malloc(void **p, size_t n) {
if (n > 0) {
*p = malloc(n);
return *p != NULL ? C_KZG_OK : C_KZG_MALLOC;
}
*p = NULL;
return C_KZG_OK;
}

19
src/c_kzg_util.h Normal file
View File

@ -0,0 +1,19 @@
/*
* Copyright 2021 Benjamin Edgington
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "c_kzg.h"
C_KZG_RET c_kzg_malloc(void **p, size_t n);

39
src/c_kzg_util_test.c Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright 2021 Benjamin Edgington
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../inc/acutest.h"
#include "debug_util.h"
#include "c_kzg_util.h"
void title(void) {;}
void malloc_works(void) {
int *p;
TEST_CHECK(C_KZG_OK == c_kzg_malloc((void **)&p, 4));
}
void malloc_huge_fails(void) {
int *p;
TEST_CHECK(C_KZG_MALLOC == c_kzg_malloc((void **)&p, -1));
}
TEST_LIST =
{
{"C_KZG_UTIL_TEST", title},
{"malloc_works", malloc_works},
{"malloc_huge_fails", malloc_huge_fails},
{ NULL, NULL } /* zero record marks the end of the list */
};

View File

@ -14,9 +14,9 @@
* limitations under the License.
*/
#include <stdlib.h>
#include "fft_common.h"
#include "blst_util.h"
#include "c_kzg_util.h"
bool is_power_of_two(const uint64_t n) {
return (n & (n - 1)) == 0;
@ -51,8 +51,9 @@ C_KZG_RET new_fft_settings(FFTSettings *fs, const unsigned int max_scale) {
C_KZG_RET ret;
fs->max_width = (uint64_t)1 << max_scale;
blst_fr_from_uint64(&fs->root_of_unity, scale2_root_of_unity[max_scale]);
fs->expanded_roots_of_unity = malloc((fs->max_width + 1) * sizeof(blst_fr));
fs->reverse_roots_of_unity = malloc((fs->max_width + 1) * sizeof(blst_fr));
ASSERT(c_kzg_malloc((void **)&fs->expanded_roots_of_unity, (fs->max_width + 1) * sizeof(blst_fr)) == C_KZG_OK, C_KZG_MALLOC);
ASSERT(c_kzg_malloc((void **)&fs->reverse_roots_of_unity, (fs->max_width + 1) * sizeof(blst_fr)) == C_KZG_OK, C_KZG_MALLOC);
ret = expand_root_of_unity(fs->expanded_roots_of_unity, &fs->root_of_unity, fs->max_width);
if (ret != C_KZG_OK) return ret;

View File

@ -14,13 +14,14 @@
* limitations under the License.
*/
#include <stddef.h> // NULL
#include "kzg_proofs.h"
C_KZG_RET new_kzg_settings(KZGSettings *ks, FFTSettings *fs, blst_p1 *secret_g1, blst_p2 *secret_g2, uint64_t length) {
ASSERT(length >= fs->max_width, C_KZG_BADARGS);
ks->fs = fs;
ks->secret_g1 = secret_g1;
ks->extended_secret_g1 = NULL;
ks->extended_secret_g1 = NULL; // What's this for?
ks->secret_g2 = secret_g2;
ks->length = length;
return C_KZG_OK;
@ -35,7 +36,7 @@ C_KZG_RET compute_proof_single(blst_p1 *out, const KZGSettings *ks, poly *p, con
return compute_proof_multi(out, ks, p, x0, 1);
}
bool check_proof_single(const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof, const blst_fr *x, blst_fr *y) {
C_KZG_RET check_proof_single(bool *out, const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof, const blst_fr *x, blst_fr *y) {
blst_p2 x_g2, s_minus_x;
blst_p1 y_g1, commitment_minus_y;
p2_mul(&x_g2, blst_p2_generator(), x);
@ -43,7 +44,9 @@ bool check_proof_single(const KZGSettings *ks, const blst_p1 *commitment, const
p1_mul(&y_g1, blst_p1_generator(), y);
p1_sub(&commitment_minus_y, commitment, &y_g1);
return pairings_verify(&commitment_minus_y, blst_p2_generator(), proof, &s_minus_x);
*out = pairings_verify(&commitment_minus_y, blst_p2_generator(), proof, &s_minus_x);
return C_KZG_OK;
}
// Compute KZG proof for polynomial in coefficient form at positions x * w^y where w is
@ -54,7 +57,7 @@ C_KZG_RET compute_proof_multi(blst_p1 *out, const KZGSettings *ks, poly *p, cons
blst_fr x_pow_n;
// Construct x^n - x0^n = (x - w^0)(x - w^1)...(x - w^(n-1))
init_poly(&divisor, n + 1);
ASSERT(init_poly(&divisor, n + 1) == C_KZG_OK, C_KZG_MALLOC);
// -(x0^n)
fr_pow(&x_pow_n, x0, n);
@ -81,17 +84,15 @@ C_KZG_RET compute_proof_multi(blst_p1 *out, const KZGSettings *ks, poly *p, cons
// Check a proof for a KZG commitment for an evaluation f(x w^i) = y_i
// The ys must have a power of 2 length
bool check_proof_multi(const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof, const blst_fr *x, const blst_fr *ys, uint64_t n) {
C_KZG_RET check_proof_multi(bool *out, const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof, const blst_fr *x, const blst_fr *ys, uint64_t n) {
poly interp;
blst_fr inv_x, inv_x_pow, x_pow;
blst_p2 xn2, xn_minus_yn;
blst_p1 is1, commit_minus_interp;
//C_KZG_RET ret; // TODO - error handling
// Interpolate at a coset.
init_poly(&interp, n);
fft_fr(interp.coeffs, ys, ks->fs, true, n);
// if (ret != C_KZG_OK) return ret;
ASSERT(init_poly(&interp, n) == C_KZG_OK, C_KZG_MALLOC);
ASSERT(fft_fr(interp.coeffs, ys, ks->fs, true, n) == C_KZG_OK, C_KZG_BADARGS);
// 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);
@ -114,7 +115,8 @@ bool check_proof_multi(const KZGSettings *ks, const blst_p1 *commitment, const b
// [commitment - interpolation_polynomial(s)]_1 = [commit]_1 - [interpolation_polynomial(s)]_1
p1_sub(&commit_minus_interp, commitment, &is1);
free_poly(&interp);
*out = pairings_verify(&commit_minus_interp, blst_p2_generator(), proof, &xn_minus_yn);
return pairings_verify(&commit_minus_interp, blst_p2_generator(), proof, &xn_minus_yn);
free_poly(&interp);
return C_KZG_OK;
}

View File

@ -29,6 +29,6 @@ typedef struct {
C_KZG_RET new_kzg_settings(KZGSettings *ks, FFTSettings *fs, blst_p1 *secret_g1, blst_p2 *secret_g2, uint64_t length);
void commit_to_poly(blst_p1 *out, const KZGSettings *ks, const poly *p);
C_KZG_RET compute_proof_single(blst_p1 *out, const KZGSettings *ks, poly *p, const blst_fr *x0);
bool check_proof_single(const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof, const blst_fr *x, blst_fr *y);
C_KZG_RET check_proof_single(bool *out, const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof, const blst_fr *x, blst_fr *y);
C_KZG_RET compute_proof_multi(blst_p1 *out, const KZGSettings *ks, poly *p, const blst_fr *x0, uint64_t n);
bool check_proof_multi(const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof, const blst_fr *x, const blst_fr *ys, uint64_t n);
C_KZG_RET check_proof_multi(bool *out, const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof, const blst_fr *x, const blst_fr *ys, uint64_t n);

View File

@ -53,6 +53,7 @@ void proof_single(void) {
blst_p1 *s1 = malloc(secrets_len * sizeof(blst_p1));
blst_p2 *s2 = malloc(secrets_len * sizeof(blst_p2));
blst_fr x, value;
bool result;
// Create the polynomial
init_poly(&p, poly_len);
@ -73,11 +74,13 @@ void proof_single(void) {
eval_poly(&value, &p, &x);
// Verify the proof that the (unknown) polynomial has y = value at x = 25
TEST_CHECK(true == check_proof_single(&ks, &commitment, &proof, &x, &value));
TEST_CHECK(C_KZG_OK == check_proof_single(&result, &ks, &commitment, &proof, &x, &value));
TEST_CHECK(true == result);
// Change the value and check that the proof fails
blst_fr_add(&value, &value, &fr_one);
TEST_CHECK(false == check_proof_single(&ks, &commitment, &proof, &x, &value));
TEST_CHECK(C_KZG_OK == check_proof_single(&result, &ks, &commitment, &proof, &x, &value));
TEST_CHECK(false == result);
free_fft_settings(&fs);
free_poly(&p);
@ -95,6 +98,7 @@ void proof_multi(void) {
poly p;
blst_p1 commitment, proof;
blst_fr x, tmp;
bool result;
// Compute proof at 2^coset_scale points
int coset_scale = 7, coset_len = (1 << coset_scale);
@ -132,11 +136,13 @@ void proof_multi(void) {
}
// Verify the proof that the (unknown) polynomial has value y_i at x_i
TEST_CHECK(true == check_proof_multi(&ks2, &commitment, &proof, &x, y, coset_len));
TEST_CHECK(C_KZG_OK == check_proof_multi(&result, &ks2, &commitment, &proof, &x, y, coset_len));
TEST_CHECK(true == result);
// Change a value and check that the proof fails
blst_fr_add(y + coset_len / 2, y + coset_len / 2, &fr_one);
TEST_CHECK(false == check_proof_multi(&ks2, &commitment, &proof, &x, y, coset_len));
TEST_CHECK(C_KZG_OK == check_proof_multi(&result, &ks2, &commitment, &proof, &x, y, coset_len));
TEST_CHECK(false == result);
free_fft_settings(&fs1);
free_fft_settings(&fs2);

View File

@ -14,6 +14,8 @@
* limitations under the License.
*/
#include <stdlib.h> // NULL, free()
#include "c_kzg_util.h"
#include "poly.h"
static void poly_factor_div(blst_fr *out, const blst_fr *a, const blst_fr *b) {
@ -21,10 +23,9 @@ static void poly_factor_div(blst_fr *out, const blst_fr *a, const blst_fr *b) {
blst_fr_mul(out, out, a);
}
void init_poly(poly *out, const uint64_t length) {
C_KZG_RET init_poly(poly *out, const uint64_t length) {
out->length = length;
out->coeffs = length > 0 ? malloc(length * sizeof(blst_fr)): NULL;
// TODO: check malloc return and handle accordingly
return c_kzg_malloc((void **)&out->coeffs, length * sizeof(blst_fr));
}
void free_poly(poly *p) {
@ -75,7 +76,7 @@ C_KZG_RET poly_long_div(poly *out, const poly *dividend, const poly *divisor) {
ASSERT(divisor->length > 0, C_KZG_BADARGS);
// Initialise the output polynomial
init_poly(out, poly_quotient_length(dividend, divisor));
ASSERT(init_poly(out, poly_quotient_length(dividend, divisor)) == C_KZG_OK, C_KZG_MALLOC);
// If the divisor is larger than the dividend, the result is zero-length
if (out->length == 0) return C_KZG_OK;

View File

@ -14,7 +14,6 @@
* limitations under the License.
*/
#include <stdlib.h> // malloc, free
#include "c_kzg.h"
#include "blst_util.h"
@ -23,7 +22,7 @@ typedef struct {
uint64_t length; // one more than the polynomial's degree
} poly;
void init_poly(poly *out, const uint64_t length);
C_KZG_RET init_poly(poly *out, const uint64_t length);
void free_poly(poly *p);
void eval_poly(blst_fr *out, const poly *p, const blst_fr *x);
uint64_t poly_quotient_length(const poly *dividend, const poly *divisor);