Skip to content

Commit

Permalink
Add new poly_t type
Browse files Browse the repository at this point in the history
  • Loading branch information
jtraglia committed Sep 7, 2023
1 parent 2734dfd commit ff405ca
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 85 deletions.
127 changes: 83 additions & 44 deletions src/c_kzg_4844.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@
(p) = NULL; \
} while (0)

///////////////////////////////////////////////////////////////////////////////
// Types
///////////////////////////////////////////////////////////////////////////////

/** Internal representation of a polynomial. */
typedef struct {
fr_t *evals;
uint64_t length;
} poly_t;

///////////////////////////////////////////////////////////////////////////////
// Constants
///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -214,6 +224,31 @@ static C_KZG_RET new_fr_array(fr_t **x, size_t n) {
return c_kzg_calloc((void **)x, n, sizeof(fr_t));
}

/**
* Allocate memory for a polynomial.
*
* @remark Free the space later using free_poly().
*
* @param[out] out Pointer to the poly_t struct
* @param[in] length The length of the polynomial
*/
static C_KZG_RET new_poly(poly_t *out, uint64_t length) {
C_KZG_RET ret;
out->length = 0;
ret = new_fr_array(&out->evals, length);
if (ret == C_KZG_OK) out->length = length;
return ret;
}

/**
* Free a polynomial.
*
* @param[in] p Pointer to the poly_t struct
*/
static void free_poly(poly_t *p) {
c_kzg_free(p->evals);
}

///////////////////////////////////////////////////////////////////////////////
// Helper Functions
///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -579,20 +614,20 @@ static C_KZG_RET bytes_to_kzg_proof(g1_t *out, const Bytes48 *b) {
}

/**
* Deserialize a Blob (array of bytes) into a Polynomial (array of field
* Deserialize a Blob (array of bytes) into a polynomial (array of field
* elements).
*
* @param[out] p The output polynomial (array of field elements)
* @param[in] blob The blob (an array of bytes)
* @param[in] s The trusted setup
*/
static C_KZG_RET blob_to_polynomial(
fr_t *p, const uint8_t *blob, const KZGSettings *s
poly_t *p, const uint8_t *blob, const KZGSettings *s
) {
C_KZG_RET ret;
for (size_t i = 0; i < s->field_elements_per_blob; i++) {
ret = bytes_to_bls_field(
&p[i], (Bytes32 *)&blob[i * BYTES_PER_FIELD_ELEMENT]
&p->evals[i], (Bytes32 *)&blob[i * BYTES_PER_FIELD_ELEMENT]
);
if (ret != C_KZG_OK) return ret;
}
Expand Down Expand Up @@ -788,7 +823,7 @@ static void compute_powers(fr_t *out, const fr_t *x, uint64_t n) {
* @param[in] s The trusted setup
*/
static C_KZG_RET evaluate_polynomial_in_evaluation_form(
fr_t *out, const fr_t *p, const fr_t *x, const KZGSettings *s
fr_t *out, const poly_t *p, const fr_t *x, const KZGSettings *s
) {
C_KZG_RET ret;
fr_t tmp;
Expand All @@ -810,7 +845,7 @@ static C_KZG_RET evaluate_polynomial_in_evaluation_form(
* would divide by zero otherwise.
*/
if (fr_equal(x, &roots_of_unity[i])) {
*out = p[i];
*out = p->evals[i];
ret = C_KZG_OK;
goto out;
}
Expand All @@ -823,7 +858,7 @@ static C_KZG_RET evaluate_polynomial_in_evaluation_form(
*out = FR_ZERO;
for (i = 0; i < s->field_elements_per_blob; i++) {
blst_fr_mul(&tmp, &inverses[i], &roots_of_unity[i]);
blst_fr_mul(&tmp, &tmp, &p[i]);
blst_fr_mul(&tmp, &tmp, &p->evals[i]);
blst_fr_add(out, out, &tmp);
}
fr_from_uint64(&tmp, s->field_elements_per_blob);
Expand All @@ -850,9 +885,11 @@ static C_KZG_RET evaluate_polynomial_in_evaluation_form(
* @param[in] s The trusted setup
*/
static C_KZG_RET poly_to_kzg_commitment(
g1_t *out, const fr_t *p, const KZGSettings *s
g1_t *out, const poly_t *p, const KZGSettings *s
) {
return g1_lincomb_fast(out, s->g1_values, p, s->field_elements_per_blob);
return g1_lincomb_fast(
out, s->g1_values, p->evals, s->field_elements_per_blob
);
}

/**
Expand All @@ -866,19 +903,19 @@ C_KZG_RET blob_to_kzg_commitment(
KZGCommitment *out, const uint8_t *blob, const KZGSettings *s
) {
C_KZG_RET ret;
fr_t *p = NULL;
poly_t p;
g1_t commitment;

ret = new_fr_array(&p, s->field_elements_per_blob);
ret = new_poly(&p, s->field_elements_per_blob);
if (ret != C_KZG_OK) goto out;
ret = blob_to_polynomial(p, blob, s);
ret = blob_to_polynomial(&p, blob, s);
if (ret != C_KZG_OK) goto out;
ret = poly_to_kzg_commitment(&commitment, p, s);
ret = poly_to_kzg_commitment(&commitment, &p, s);
if (ret != C_KZG_OK) goto out;
bytes_from_g1(out, &commitment);

out:
c_kzg_free(p);
free_poly(&p);
return ret;
}

Expand Down Expand Up @@ -976,7 +1013,7 @@ static C_KZG_RET verify_kzg_proof_impl(
static C_KZG_RET compute_kzg_proof_impl(
KZGProof *proof_out,
fr_t *y_out,
const fr_t *polynomial,
const poly_t *polynomial,
const fr_t *z,
const KZGSettings *s
);
Expand All @@ -999,21 +1036,21 @@ C_KZG_RET compute_kzg_proof(
const KZGSettings *s
) {
C_KZG_RET ret;
fr_t *polynomial = NULL;
poly_t polynomial;
fr_t frz, fry;

ret = new_fr_array(&polynomial, s->field_elements_per_blob);
ret = new_poly(&polynomial, s->field_elements_per_blob);
if (ret != C_KZG_OK) goto out;
ret = blob_to_polynomial(polynomial, blob, s);
ret = blob_to_polynomial(&polynomial, blob, s);
if (ret != C_KZG_OK) goto out;
ret = bytes_to_bls_field(&frz, z_bytes);
if (ret != C_KZG_OK) goto out;
ret = compute_kzg_proof_impl(proof_out, &fry, polynomial, &frz, s);
ret = compute_kzg_proof_impl(proof_out, &fry, &polynomial, &frz, s);
if (ret != C_KZG_OK) goto out;
bytes_from_bls_field(y_out, &fry);

out:
c_kzg_free(polynomial);
free_poly(&polynomial);
return ret;
}

Expand All @@ -1031,16 +1068,16 @@ C_KZG_RET compute_kzg_proof(
static C_KZG_RET compute_kzg_proof_impl(
KZGProof *proof_out,
fr_t *y_out,
const fr_t *polynomial,
const poly_t *polynomial,
const fr_t *z,
const KZGSettings *s
) {
C_KZG_RET ret;
fr_t *inverses_in = NULL;
fr_t *inverses = NULL;
fr_t *q = NULL;
poly_t q;

ret = new_fr_array(&q, s->field_elements_per_blob);
ret = new_poly(&q, s->field_elements_per_blob);
if (ret != C_KZG_OK) goto out;

ret = evaluate_polynomial_in_evaluation_form(y_out, polynomial, z, s);
Expand All @@ -1065,19 +1102,19 @@ static C_KZG_RET compute_kzg_proof_impl(
continue;
}
// (p_i - y) / (ω_i - z)
blst_fr_sub(&q[i], &polynomial[i], y_out);
blst_fr_sub(&q.evals[i], &polynomial->evals[i], y_out);
blst_fr_sub(&inverses_in[i], &roots_of_unity[i], z);
}

ret = fr_batch_inv(inverses, inverses_in, s->field_elements_per_blob);
if (ret != C_KZG_OK) goto out;

for (i = 0; i < s->field_elements_per_blob; i++) {
blst_fr_mul(&q[i], &q[i], &inverses[i]);
blst_fr_mul(&q.evals[i], &q.evals[i], &inverses[i]);
}

if (m != 0) { /* ω_{m-1} == z */
q[--m] = FR_ZERO;
q.evals[--m] = FR_ZERO;
for (i = 0; i < s->field_elements_per_blob; i++) {
if (i == m) continue;
/* Build denominator: z * (z - ω_i) */
Expand All @@ -1091,22 +1128,24 @@ static C_KZG_RET compute_kzg_proof_impl(
for (i = 0; i < s->field_elements_per_blob; i++) {
if (i == m) continue;
/* Build numerator: ω_i * (p_i - y) */
blst_fr_sub(&tmp, &polynomial[i], y_out);
blst_fr_sub(&tmp, &polynomial->evals[i], y_out);
blst_fr_mul(&tmp, &tmp, &roots_of_unity[i]);
/* Do the division: (p_i - y) * ω_i / (z * (z - ω_i)) */
blst_fr_mul(&tmp, &tmp, &inverses[i]);
blst_fr_add(&q[m], &q[m], &tmp);
blst_fr_add(&q.evals[m], &q.evals[m], &tmp);
}
}

g1_t out_g1;
ret = g1_lincomb_fast(&out_g1, s->g1_values, q, s->field_elements_per_blob);
ret = g1_lincomb_fast(
&out_g1, s->g1_values, q.evals, s->field_elements_per_blob
);
if (ret != C_KZG_OK) goto out;

bytes_from_g1(proof_out, &out_g1);

out:
c_kzg_free(q);
free_poly(&q);
c_kzg_free(inverses_in);
c_kzg_free(inverses);
return ret;
Expand All @@ -1131,16 +1170,16 @@ C_KZG_RET compute_blob_kzg_proof(
C_KZG_RET ret;
g1_t commitment_g1;
fr_t evaluation_challenge_fr;
fr_t *polynomial = NULL;
poly_t polynomial;
fr_t y;

ret = new_fr_array(&polynomial, s->field_elements_per_blob);
ret = new_poly(&polynomial, s->field_elements_per_blob);
if (ret != C_KZG_OK) goto out;

/* Do conversions first to fail fast, compute_challenge is expensive */
ret = bytes_to_kzg_commitment(&commitment_g1, commitment_bytes);
if (ret != C_KZG_OK) goto out;
ret = blob_to_polynomial(polynomial, blob, s);
ret = blob_to_polynomial(&polynomial, blob, s);
if (ret != C_KZG_OK) goto out;

/* Compute the challenge for the given blob/commitment */
Expand All @@ -1149,12 +1188,12 @@ C_KZG_RET compute_blob_kzg_proof(

/* Call helper function to compute proof and y */
ret = compute_kzg_proof_impl(
out, &y, polynomial, &evaluation_challenge_fr, s
out, &y, &polynomial, &evaluation_challenge_fr, s
);
if (ret != C_KZG_OK) goto out;

out:
c_kzg_free(polynomial);
free_poly(&polynomial);
return ret;
}

Expand All @@ -1178,18 +1217,18 @@ C_KZG_RET verify_blob_kzg_proof(
C_KZG_RET ret;
fr_t evaluation_challenge_fr, y_fr;
g1_t commitment_g1, proof_g1;
fr_t *polynomial = NULL;
poly_t polynomial;

*ok = false;

/* Allocate a new polynomial */
ret = new_fr_array(&polynomial, s->field_elements_per_blob);
ret = new_poly(&polynomial, s->field_elements_per_blob);
if (ret != C_KZG_OK) goto out;

/* Do conversions first to fail fast, compute_challenge is expensive */
ret = bytes_to_kzg_commitment(&commitment_g1, commitment_bytes);
if (ret != C_KZG_OK) goto out;
ret = blob_to_polynomial(polynomial, blob, s);
ret = blob_to_polynomial(&polynomial, blob, s);
if (ret != C_KZG_OK) goto out;
ret = bytes_to_kzg_proof(&proof_g1, proof_bytes);
if (ret != C_KZG_OK) goto out;
Expand All @@ -1200,7 +1239,7 @@ C_KZG_RET verify_blob_kzg_proof(

/* Evaluate challenge to get y */
ret = evaluate_polynomial_in_evaluation_form(
&y_fr, polynomial, &evaluation_challenge_fr, s
&y_fr, &polynomial, &evaluation_challenge_fr, s
);
if (ret != C_KZG_OK) goto out;

Expand All @@ -1210,7 +1249,7 @@ C_KZG_RET verify_blob_kzg_proof(
);

out:
c_kzg_free(polynomial);
free_poly(&polynomial);
return ret;
}

Expand Down Expand Up @@ -1404,7 +1443,7 @@ C_KZG_RET verify_blob_kzg_proof_batch(
g1_t *proofs_g1 = NULL;
fr_t *evaluation_challenges_fr = NULL;
fr_t *ys_fr = NULL;
fr_t *polynomial = NULL;
poly_t polynomial;

/* Exit early if we are given zero blobs */
if (n == 0) {
Expand All @@ -1428,7 +1467,7 @@ C_KZG_RET verify_blob_kzg_proof_batch(
if (ret != C_KZG_OK) goto out;
ret = new_fr_array(&ys_fr, n);
if (ret != C_KZG_OK) goto out;
ret = new_fr_array(&polynomial, s->field_elements_per_blob);
ret = new_poly(&polynomial, s->field_elements_per_blob);
if (ret != C_KZG_OK) goto out;

for (size_t i = 0; i < n; i++) {
Expand All @@ -1439,7 +1478,7 @@ C_KZG_RET verify_blob_kzg_proof_batch(
if (ret != C_KZG_OK) goto out;

/* Convert each blob from bytes to a poly */
ret = blob_to_polynomial(polynomial, &blobs[i * s->bytes_per_blob], s);
ret = blob_to_polynomial(&polynomial, &blobs[i * s->bytes_per_blob], s);
if (ret != C_KZG_OK) goto out;

ret = compute_challenge(
Expand All @@ -1451,7 +1490,7 @@ C_KZG_RET verify_blob_kzg_proof_batch(
if (ret != C_KZG_OK) goto out;

ret = evaluate_polynomial_in_evaluation_form(
&ys_fr[i], polynomial, &evaluation_challenges_fr[i], s
&ys_fr[i], &polynomial, &evaluation_challenges_fr[i], s
);
if (ret != C_KZG_OK) goto out;

Expand All @@ -1468,7 +1507,7 @@ C_KZG_RET verify_blob_kzg_proof_batch(
c_kzg_free(proofs_g1);
c_kzg_free(evaluation_challenges_fr);
c_kzg_free(ys_fr);
c_kzg_free(polynomial);
free_poly(&polynomial);
return ret;
}

Expand Down
2 changes: 1 addition & 1 deletion src/c_kzg_4844.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ typedef struct {
/** Number of field elements in a blob. */
uint64_t field_elements_per_blob;
/** Number of bytes in a blob. */
size_t bytes_per_blob;
uint64_t bytes_per_blob;
/** The length of `roots_of_unity`, a power of 2. */
uint64_t max_width;
/** Powers of the primitive root of unity determined by
Expand Down
Loading

0 comments on commit ff405ca

Please sign in to comment.