Initial work on switch to new simplified API

This commit is contained in:
Ramana Kumar 2022-10-19 22:31:14 +01:00
parent db402fcdd4
commit 14d5c8e6f8
No known key found for this signature in database
GPG Key ID: ED471C788B900433
2 changed files with 175 additions and 126 deletions

View File

@ -712,7 +712,6 @@ static void free_fft_settings(FFTSettings *fs) {
static void free_kzg_settings(KZGSettings *ks) { static void free_kzg_settings(KZGSettings *ks) {
free(ks->g1_values); free(ks->g1_values);
free(ks->g2_values); free(ks->g2_values);
ks->length = 0;
} }
@ -765,36 +764,29 @@ C_KZG_RET bytes_to_g1(g1_t* out, const uint8_t bytes[48]) {
return C_KZG_OK; return C_KZG_OK;
} }
void uint64s_from_BLSFieldElement(uint64_t out[4], const BLSFieldElement *in) {
blst_uint64_from_fr(out, in);
}
void bytes_from_bls_field(uint8_t out[32], const BLSFieldElement *in) { void bytes_from_bls_field(uint8_t out[32], const BLSFieldElement *in) {
blst_scalar_from_fr((blst_scalar*)out, in); blst_scalar_from_fr((blst_scalar*)out, in);
} }
C_KZG_RET load_trusted_setup(KZGSettings *out, FILE *in) { C_KZG_RET load_trusted_setup(KZGSettings *out, FILE *in) {
uint64_t n2, i; uint64_t i;
int j; uint8_t c[96]; int j; uint8_t c[96];
blst_p2_affine g2_affine; blst_p2_affine g2_affine;
g1_t *g1_projective; g1_t *g1_projective;
fscanf(in, "%" SCNu64, &out->length); TRY(new_g1_array(&out->g1_values, FIELD_ELEMENTS_PER_BLOB));
fscanf(in, "%" SCNu64, &n2); TRY(new_g2_array(&out->g2_values, FIELD_ELEMENTS_PER_BLOB));
TRY(new_g1_array(&out->g1_values, out->length)); TRY(new_g1_array(&g1_projective, FIELD_ELEMENTS_PER_BLOB));
TRY(new_g2_array(&out->g2_values, n2));
TRY(new_g1_array(&g1_projective, out->length)); for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) {
for (i = 0; i < out->length; i++) {
for (j = 0; j < 48; j++) { for (j = 0; j < 48; j++) {
fscanf(in, "%2hhx", &c[j]); fscanf(in, "%2hhx", &c[j]);
} }
bytes_to_g1(&g1_projective[i], c); bytes_to_g1(&g1_projective[i], c);
} }
for (i = 0; i < n2; i++) { for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) {
for (j = 0; j < 96; j++) { for (j = 0; j < 96; j++) {
fscanf(in, "%2hhx", &c[j]); fscanf(in, "%2hhx", &c[j]);
} }
@ -802,16 +794,17 @@ C_KZG_RET load_trusted_setup(KZGSettings *out, FILE *in) {
blst_p2_from_affine(&out->g2_values[i], &g2_affine); blst_p2_from_affine(&out->g2_values[i], &g2_affine);
} }
// TODO: precompute
unsigned int max_scale = 0; unsigned int max_scale = 0;
while (((uint64_t)1 << max_scale) < out->length) max_scale++; while (((uint64_t)1 << max_scale) < FIELD_ELEMENTS_PER_BLOB) max_scale++;
out->fs = (FFTSettings*)malloc(sizeof(FFTSettings)); out->fs = (FFTSettings*)malloc(sizeof(FFTSettings));
TRY(new_fft_settings((FFTSettings*)out->fs, max_scale)); TRY(new_fft_settings((FFTSettings*)out->fs, max_scale));
TRY(fft_g1(out->g1_values, g1_projective, true, out->length, out->fs)); TRY(fft_g1(out->g1_values, g1_projective, true, FIELD_ELEMENTS_PER_BLOB, out->fs));
TRY(reverse_bit_order(out->g1_values, sizeof(g1_t), out->length)); TRY(reverse_bit_order(out->g1_values, sizeof(g1_t), FIELD_ELEMENTS_PER_BLOB));
free(g1_projective); free(g1_projective);
@ -823,10 +816,10 @@ void free_trusted_setup(KZGSettings *s) {
free_kzg_settings(s); free_kzg_settings(s);
} }
void compute_powers(fr_t out[], const fr_t *x, uint64_t n) { static void compute_powers(fr_t out[], uint64_t n) {
uint64_t i = 0; uint64_t i = 0;
out[i] = fr_one; out[++i] = fr_one;
while (++i < n) fr_mul(&out[i], &out[i-1], x); while (++i < n) fr_mul(&out[i], &out[i-1], &out[1]);
} }
void bytes_to_bls_field(BLSFieldElement *out, const uint8_t bytes[32]) { void bytes_to_bls_field(BLSFieldElement *out, const uint8_t bytes[32]) {
@ -835,17 +828,14 @@ void bytes_to_bls_field(BLSFieldElement *out, const uint8_t bytes[32]) {
blst_fr_from_scalar(out, &tmp); blst_fr_from_scalar(out, &tmp);
} }
/** static void vector_lincomb(Polynomial out, const Polynomial vectors[], const fr_t scalars[], uint64_t n) {
* Compute linear combinations of a sequence of vectors with some scalars
*/
void vector_lincomb(fr_t out[], const fr_t vectors[], const fr_t scalars[], uint64_t n, uint64_t m) {
fr_t tmp; fr_t tmp;
uint64_t i, j; uint64_t i, j;
for (j = 0; j < m; j++) for (j = 0; j < FIELD_ELEMENTS_PER_BLOB; j++)
out[j] = fr_zero; out[j] = fr_zero;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
for (j = 0; j < m; j++) { for (j = 0; j < FIELD_ELEMENTS_PER_BLOB; j++) {
fr_mul(&tmp, &scalars[i], &vectors[i * m + j]); fr_mul(&tmp, &scalars[i], &vectors[i][j]);
fr_add(&out[j], &out[j], &tmp); fr_add(&out[j], &out[j], &tmp);
} }
} }
@ -871,7 +861,7 @@ void vector_lincomb(fr_t out[], const fr_t vectors[], const fr_t scalars[], uint
* *
* We do the second of these to save memory here. * We do the second of these to save memory here.
*/ */
void g1_lincomb(g1_t *out, const g1_t *p, const fr_t *coeffs, const uint64_t len) { static void g1_lincomb(g1_t *out, const g1_t *p, const fr_t *coeffs, const uint64_t len) {
if (len < 8) { // Tunable parameter: must be at least 2 since Blst fails for 0 or 1 if (len < 8) { // Tunable parameter: must be at least 2 since Blst fails for 0 or 1
// Direct approach // Direct approach
g1_t tmp; g1_t tmp;
@ -907,8 +897,8 @@ void g1_lincomb(g1_t *out, const g1_t *p, const fr_t *coeffs, const uint64_t len
} }
} }
void blob_to_kzg_commitment(KZGCommitment *out, const BLSFieldElement blob[], const KZGSettings *s) { void blob_to_kzg_commitment(KZGCommitment *out, const Polynomial blob, const KZGSettings *s) {
g1_lincomb(out, s->g1_values, blob, s->length); g1_lincomb(out, s->g1_values, blob, FIELD_ELEMENTS_PER_BLOB);
} }
/** /**
@ -924,7 +914,7 @@ void blob_to_kzg_commitment(KZGCommitment *out, const BLSFieldElement blob[], co
* @param[in] ks The settings containing the secrets, previously initialised with #new_kzg_settings * @param[in] ks The settings containing the secrets, previously initialised with #new_kzg_settings
* @retval C_CZK_OK All is well * @retval C_CZK_OK All is well
*/ */
C_KZG_RET verify_kzg_proof(bool *out, const g1_t *commitment, const fr_t *x, const fr_t *y, static C_KZG_RET verify_kzg_proof(bool *out, const g1_t *commitment, const fr_t *x, const fr_t *y,
const g1_t *proof, const KZGSettings *ks) { const g1_t *proof, const KZGSettings *ks) {
g2_t x_g2, s_minus_x; g2_t x_g2, s_minus_x;
g1_t y_g1, commitment_minus_y; g1_t y_g1, commitment_minus_y;
@ -938,14 +928,40 @@ C_KZG_RET verify_kzg_proof(bool *out, const g1_t *commitment, const fr_t *x, con
return C_KZG_OK; return C_KZG_OK;
} }
C_KZG_RET alloc_polynomial(PolynomialEvalForm *out, uint64_t length) { static C_KZG_RET evaluate_polynomial_in_evaluation_form(BLSFieldElement *out, const Polynomial p, const BLSFieldElement *x, const KZGSettings *s) {
out->length = length; fr_t tmp, *inverses_in, *inverses;
return new_fr_array(&out->values, length); uint64_t i;
} const fr_t *roots_of_unity = s->fs->roots_of_unity;
void free_polynomial(PolynomialEvalForm *p) { TRY(new_fr_array(&inverses_in, FIELD_ELEMENTS_PER_BLOB));
p->length = 0; TRY(new_fr_array(&inverses, FIELD_ELEMENTS_PER_BLOB));
free(p->values); for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) {
if (fr_equal(x, &roots_of_unity[i])) {
*out = p[i];
free(inverses_in);
free(inverses);
return C_KZG_OK;
}
fr_sub(&inverses_in[i], x, &roots_of_unity[i]);
}
TRY(fr_batch_inv(inverses, inverses_in, FIELD_ELEMENTS_PER_BLOB));
*out = fr_zero;
for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) {
fr_mul(&tmp, &inverses[i], &roots_of_unity[i]);
fr_mul(&tmp, &tmp, &p[i]);
fr_add(out, out, &tmp);
}
fr_from_uint64(&tmp, FIELD_ELEMENTS_PER_BLOB);
fr_div(out, out, &tmp);
fr_pow(&tmp, x, FIELD_ELEMENTS_PER_BLOB);
fr_sub(&tmp, &tmp, &fr_one);
fr_mul(out, out, &tmp);
free(inverses_in);
free(inverses);
return C_KZG_OK;
} }
/** /**
@ -959,97 +975,142 @@ void free_polynomial(PolynomialEvalForm *p) {
* @retval C_KZG_ERROR An internal error occurred * @retval C_KZG_ERROR An internal error occurred
* @retval C_KZG_MALLOC Memory allocation failed * @retval C_KZG_MALLOC Memory allocation failed
*/ */
C_KZG_RET compute_kzg_proof(KZGProof *out, const PolynomialEvalForm *p, const BLSFieldElement *x, const KZGSettings *s) { static C_KZG_RET compute_kzg_proof(KZGProof *out, const Polynomial p, const BLSFieldElement *x, const KZGSettings *s) {
CHECK(p->length <= s->length);
BLSFieldElement y; BLSFieldElement y;
TRY(evaluate_polynomial_in_evaluation_form(&y, p, x, s)); TRY(evaluate_polynomial_in_evaluation_form(&y, p, x, s));
fr_t tmp; fr_t tmp;
PolynomialEvalForm q; Polynomial q;
const fr_t *roots_of_unity = s->fs->roots_of_unity; const fr_t *roots_of_unity = s->fs->roots_of_unity;
uint64_t i, m = 0; uint64_t i, m = 0;
TRY(alloc_polynomial(&q, p->length));
fr_t *inverses_in, *inverses; fr_t *inverses_in, *inverses;
TRY(new_fr_array(&inverses_in, p->length)); TRY(new_fr_array(&inverses_in, FIELD_ELEMENTS_PER_BLOB));
TRY(new_fr_array(&inverses, p->length)); TRY(new_fr_array(&inverses, FIELD_ELEMENTS_PER_BLOB));
for (i = 0; i < q.length; i++) { for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) {
if (fr_equal(x, &roots_of_unity[i])) { if (fr_equal(x, &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[i], &p[i], &y);
fr_sub(&inverses_in[i], &roots_of_unity[i], x); fr_sub(&inverses_in[i], &roots_of_unity[i], x);
} }
TRY(fr_batch_inv(inverses, inverses_in, q.length)); TRY(fr_batch_inv(inverses, inverses_in, FIELD_ELEMENTS_PER_BLOB));
for (i = 0; i < q.length; i++) { for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) {
fr_mul(&q.values[i], &q.values[i], &inverses[i]); fr_mul(&q[i], &q[i], &inverses[i]);
} }
if (m) { // ω_m == x if (m) { // ω_m == x
q.values[--m] = fr_zero; q[--m] = fr_zero;
for (i = 0; i < q.length; i++) { for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; 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, &roots_of_unity[i]); fr_sub(&tmp, x, &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, FIELD_ELEMENTS_PER_BLOB));
for (i = 0; i < q.length; i++) { for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) {
fr_sub(&tmp, &p->values[i], &y); fr_sub(&tmp, &p[i], &y);
fr_mul(&tmp, &tmp, &roots_of_unity[i]); fr_mul(&tmp, &tmp, &roots_of_unity[i]);
fr_mul(&tmp, &tmp, &inverses[i]); fr_mul(&tmp, &tmp, &inverses[i]);
fr_add(&q.values[m], &q.values[m], &tmp); fr_add(&q[m], &q[m], &tmp);
} }
} }
free(inverses_in); free(inverses_in);
free(inverses); free(inverses);
g1_lincomb(out, s->g1_values, q.values, q.length); g1_lincomb(out, s->g1_values, q, FIELD_ELEMENTS_PER_BLOB);
return C_KZG_OK; return C_KZG_OK;
} }
C_KZG_RET evaluate_polynomial_in_evaluation_form(BLSFieldElement *out, const PolynomialEvalForm *p, const BLSFieldElement *x, const KZGSettings *s) { typedef struct {
fr_t tmp, *inverses_in, *inverses; unsigned int h[8];
uint64_t i; unsigned long long N;
const fr_t *roots_of_unity = s->fs->roots_of_unity; unsigned char buf[64];
size_t off;
} SHA256_CTX;
TRY(new_fr_array(&inverses_in, p->length)); extern void sha256_init(SHA256_CTX *ctx);
TRY(new_fr_array(&inverses, p->length)); extern void sha256_update(SHA256_CTX *ctx, const void *_inp, size_t len);
for (i = 0; i < p->length; i++) { extern void sha256_final(unsigned char md[32], SHA256_CTX *ctx);
if (fr_equal(x, &roots_of_unity[i])) {
*out = p->values[i];
free(inverses_in);
free(inverses);
return C_KZG_OK;
}
fr_sub(&inverses_in[i], x, &roots_of_unity[i]);
}
TRY(fr_batch_inv(inverses, inverses_in, p->length));
*out = fr_zero; static void hash(uint8_t md[32], uint8_t input[], size_t n) {
for (i = 0; i < p->length; i++) { SHA256_CTX ctx;
fr_mul(&tmp, &inverses[i], &roots_of_unity[i]); sha256_init(&ctx);
fr_mul(&tmp, &tmp, &p->values[i]); sha256_update(&ctx, input, n);
fr_add(out, out, &tmp); sha256_final(md, &ctx);
} }
fr_from_uint64(&tmp, p->length);
fr_div(out, out, &tmp); static void hash_to_bls_field(BLSFieldElement *out, const Polynomial polys[], const KZGCommitment comms[], size_t n) {
fr_pow(&tmp, x, p->length); size_t i, np = n * FIELD_ELEMENTS_PER_BLOB * 32;
fr_sub(&tmp, &tmp, &fr_one); uint64_t j; uint8_t h[32];
fr_mul(out, out, &tmp);
uint8_t bytes[np + n * 48];
free(inverses_in);
free(inverses); for(i = 0; i < n; i++)
for(j = 0; j < FIELD_ELEMENTS_PER_BLOB; j++)
return C_KZG_OK; bytes_from_bls_field(&bytes[i * 32], &polys[i][j]);
for(i = 0; i < n; i++)
bytes_from_g1(&bytes[np + i * 48], &comms[i]);
hash(h, bytes, np + n * 48);
bytes_to_bls_field(out, h);
}
static void compute_aggregated_poly_and_commitment(Polynomial poly_out, KZGCommitment *comm_out,
const Polynomial blobs[],
const KZGCommitment kzg_commitments[],
size_t n) {
BLSFieldElement r_powers[n];
hash_to_bls_field(&r_powers[1], blobs, kzg_commitments, n);
compute_powers(r_powers, n);
vector_lincomb(poly_out, blobs, r_powers, n);
g1_lincomb(comm_out, kzg_commitments, r_powers, n);
}
C_KZG_RET compute_aggregate_kzg_proof(KZGProof *out,
const Polynomial blobs[],
size_t n,
const KZGSettings *s) {
KZGCommitment commitments[n];
for (size_t i = 0; i < n; i++)
blob_to_kzg_commitment(&commitments[i], blobs[i], s);
Polynomial aggregated_poly;
KZGCommitment aggregated_poly_commitment;
compute_aggregated_poly_and_commitment(aggregated_poly, &aggregated_poly_commitment, blobs, commitments, n);
BLSFieldElement x;
hash_to_bls_field(&x, &aggregated_poly, &aggregated_poly_commitment, 1);
return compute_kzg_proof(out, aggregated_poly, &x, s);
}
C_KZG_RET verify_aggregate_kzg_proof(bool *out,
const Polynomial blobs[],
const KZGCommitment expected_kzg_commitments[],
size_t n,
const KZGProof *kzg_aggregated_proof,
const KZGSettings *s) {
Polynomial aggregated_poly;
KZGCommitment aggregated_poly_commitment;
compute_aggregated_poly_and_commitment(aggregated_poly, &aggregated_poly_commitment, blobs, expected_kzg_commitments, n);
BLSFieldElement x, y;
hash_to_bls_field(&x, &aggregated_poly, &aggregated_poly_commitment, 1);
TRY(evaluate_polynomial_in_evaluation_form(&y, aggregated_poly, &x, s));
return verify_kzg_proof(out, &aggregated_poly_commitment, &x, &y, kzg_aggregated_proof, s);
} }

View File

@ -29,6 +29,8 @@
#include "blst.h" #include "blst.h"
#define FIELD_ELEMENTS_PER_BLOB 4096
typedef blst_p1 g1_t; /**< Internal G1 group element type */ typedef blst_p1 g1_t; /**< Internal G1 group element type */
typedef blst_p2 g2_t; /**< Internal G2 group element type */ typedef blst_p2 g2_t; /**< Internal G2 group element type */
typedef blst_fr fr_t; /**< Internal Fr field element type */ typedef blst_fr fr_t; /**< Internal Fr field element type */
@ -36,6 +38,7 @@ typedef blst_fr fr_t; /**< Internal Fr field element type */
typedef g1_t KZGCommitment; typedef g1_t KZGCommitment;
typedef g1_t KZGProof; typedef g1_t KZGProof;
typedef fr_t BLSFieldElement; typedef fr_t BLSFieldElement;
typedef BLSFieldElement Polynomial[FIELD_ELEMENTS_PER_BLOB];
/** /**
* The common return type for all routines in which something can go wrong. * The common return type for all routines in which something can go wrong.
@ -58,14 +61,10 @@ void bytes_from_g1(uint8_t out[48], const g1_t*);
C_KZG_RET bytes_to_g1(g1_t* out, const uint8_t[48]); C_KZG_RET bytes_to_g1(g1_t* out, const uint8_t[48]);
/** /**
* BLSFieldElements are communicated directly to/from clients, * BLSFieldElements can be recovered as 32 bytes
* so we need to expose the functions for translating between this
* type and uint256. BLST represents uint256 as uint64[4].
* TODO: remove the uint64s version?
* For conversion to BLSFieldElement use bytes_to_bls_field.
*/ */
void uint64s_from_BLSFieldElement(uint64_t out[4], const BLSFieldElement*);
void bytes_from_bls_field(uint8_t out[32], const BLSFieldElement*); void bytes_from_bls_field(uint8_t out[32], const BLSFieldElement*);
void bytes_to_bls_field(BLSFieldElement *out, const uint8_t bytes[32]);
/** /**
* Stores the setup and parameters needed for performing FFTs. * Stores the setup and parameters needed for performing FFTs.
@ -83,44 +82,33 @@ typedef struct {
typedef struct { typedef struct {
const FFTSettings *fs; /**< The corresponding settings for performing FFTs */ const FFTSettings *fs; /**< The corresponding settings for performing FFTs */
g1_t *g1_values; /**< G1 group elements from the trusted setup, in Lagrange form bit-reversal permutation */ g1_t *g1_values; /**< G1 group elements from the trusted setup, in Lagrange form bit-reversal permutation */
g2_t *g2_values; /**< G2 group elements from the trusted setup */ g2_t *g2_values; /**< G2 group elements from the trusted setup; both arrays have FIELD_ELEMENTS_PER_BLOB elements */
uint64_t length; /**< The number of elements in g1_values */
} KZGSettings; } KZGSettings;
/**
* Lagrange form polynomial, with values under the bit-reversal permutation
*/
typedef struct {
fr_t *values; /**< `values[i]` is value of the polynomial at `ω^brp(i)` */
uint64_t length; /**< One more than the polynomial's degree */
} PolynomialEvalForm;
C_KZG_RET alloc_polynomial(PolynomialEvalForm *out, uint64_t length);
void free_polynomial(PolynomialEvalForm *p);
/** /**
* Interface functions * Interface functions
*/ */
C_KZG_RET load_trusted_setup(KZGSettings *out, FILE *in); C_KZG_RET load_trusted_setup(KZGSettings *out,
FILE *in);
void free_trusted_setup(KZGSettings *s); void free_trusted_setup(
KZGSettings *s);
void bytes_to_bls_field(BLSFieldElement *out, const uint8_t bytes[32]); C_KZG_RET compute_aggregate_kzg_proof(KZGProof *out,
const Polynomial blobs[],
size_t n,
const KZGSettings *s);
void vector_lincomb(BLSFieldElement out[], const BLSFieldElement vectors[], const BLSFieldElement scalars[], uint64_t num_vectors, uint64_t vector_len); C_KZG_RET verify_aggregate_kzg_proof(bool *out,
const Polynomial blobs[],
const KZGCommitment expected_kzg_commitments[],
size_t n,
const KZGProof *kzg_aggregated_proof,
const KZGSettings *s);
void g1_lincomb(KZGCommitment *out, const KZGCommitment points[], const BLSFieldElement scalars[], uint64_t num_points); void blob_to_kzg_commitment(KZGCommitment *out,
const Polynomial blob,
void blob_to_kzg_commitment(KZGCommitment *out, const BLSFieldElement blob[], const KZGSettings *s); const KZGSettings *s);
C_KZG_RET verify_kzg_proof(bool *out, const KZGCommitment *polynomial_kzg, const BLSFieldElement *z, const BLSFieldElement *y, const KZGProof *kzg_proof, const KZGSettings *s);
C_KZG_RET compute_kzg_proof(KZGProof *out, const PolynomialEvalForm *polynomial, const BLSFieldElement *z, const KZGSettings *s);
C_KZG_RET evaluate_polynomial_in_evaluation_form(BLSFieldElement *out, const PolynomialEvalForm *polynomial, const BLSFieldElement *z, const KZGSettings *s);
void compute_powers(BLSFieldElement out[], const BLSFieldElement *x, uint64_t n);
#endif // C_KZG_4844_H #endif // C_KZG_4844_H