Add documentation for various internal/external functions (#79)

* Improve naming of outputs of compute_challenges()

Both are outputs

* Adjust arguments of verify_kzg_proof_impl() to match the spec

* Add documentation for all c-kzg functions

* fixup! Adjust arguments of verify_kzg_proof_impl() to match the spec

* fixup! Add documentation for all c-kzg functions

* Address review comments

Co-authored-by: Justin Traglia <95511699+jtraglia@users.noreply.github.com>
This commit is contained in:
George Kadianakis 2023-01-24 15:02:58 +01:00 committed by GitHub
parent ae81453aaa
commit 7043128428
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -476,10 +476,25 @@ static int log2_pow2(uint32_t n) {
// Bytes Conversion Helper Functions
///////////////////////////////////////////////////////////////////////////////
/**
* Serialize a G1 group element into bytes.
*
* @param[out] out A 48-byte array to store the serialized G1 element
* @param[in] in The G1 element to be serialized
*/
static void bytes_from_g1(uint8_t out[48], const g1_t *in) {
blst_p1_compress(out, in);
}
/**
* Deserialize bytes into a G1 group element.
*
* @param[out] out The G1 element to store the deserialized data
* @param[in] bytes A 48-byte array containing the serialized G1 element
* @retval C_KZG_OK Deserialization successful
* @retval C_KZG_BADARGS Input bytes were not a valid G1 element
*/
static C_KZG_RET bytes_to_g1(g1_t* out, const uint8_t bytes[48]) {
blst_p1_affine tmp;
if (blst_p1_uncompress(&tmp, bytes) != BLST_SUCCESS)
@ -488,10 +503,23 @@ static C_KZG_RET bytes_to_g1(g1_t* out, const uint8_t bytes[48]) {
return C_KZG_OK;
}
/**
* Serialize a BLS field element into bytes.
*
* @param[out] out A 32-byte array to store the serialized field element
* @param[in] in The field element to be serialized
*/
static void bytes_from_bls_field(uint8_t out[32], const fr_t *in) {
blst_scalar_from_fr((blst_scalar*)out, in);
}
/**
* Serialize a 64-bit unsigned integer into bytes.
* @param[out] out An 8-byte array to store the serialized integer
* @param[in] n The integer to be serialized
*/
static void bytes_of_uint64(uint8_t out[8], uint64_t n) {
for (int i = 0; i < 8; i++) {
out[i] = n & 0xFF;
@ -608,12 +636,27 @@ static C_KZG_RET bit_reversal_permutation(void *values, size_t size, uint64_t n)
// BLS12-381 Helper Functions
///////////////////////////////////////////////////////////////////////////////
/**
* Map bytes to a BLS field element.
*
* @param[out] out The field element to store the result
* @param[in] bytes A 32-byte array containing the input
*/
static void hash_to_bls_field(fr_t *out, const uint8_t bytes[32]) {
blst_scalar tmp;
blst_scalar_from_lendian(&tmp, bytes);
blst_fr_from_scalar(out, &tmp);
}
/**
* Deserialize bytes into a BLS field element.
*
* @param[out] out The field element to store the deserialized data
* @param[in] bytes A 32-byte array containing the serialized field element
* @retval C_KZG_OK Deserialization successful
* @retval C_KZG_BADARGS Input was not a valid scalar field element
*/
static C_KZG_RET bytes_to_bls_field(fr_t *out, const uint8_t bytes[32]) {
blst_scalar tmp;
blst_scalar_from_lendian(&tmp, bytes);
@ -622,6 +665,14 @@ static C_KZG_RET bytes_to_bls_field(fr_t *out, const uint8_t bytes[32]) {
return C_KZG_OK;
}
/**
* 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)
* @retval C_KZG_OK Deserialization successful
* @retval C_KZG_BADARGS Invalid input bytes
*/
static C_KZG_RET blob_to_polynomial(Polynomial *p, const Blob *blob) {
C_KZG_RET ret;
for (size_t i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) {
@ -634,7 +685,20 @@ static C_KZG_RET blob_to_polynomial(Polynomial *p, const Blob *blob) {
/* Forward function definition */
static void compute_powers(fr_t *out, fr_t *x, uint64_t n);
static C_KZG_RET compute_challenges(fr_t *out, fr_t *r_powers,
/**
* Return the Fiat-Shamir challenges required by the rest of the protocol.
*
* @remark This function should compute challenges even if `n==0`.
*
* @param[out] eval_challenge_out The evaluation challenge
* @param[out] r_powers_out The powers of r, where r is a randomly generated scalar
* @param[in] polys The array of polynomials
* @param[in] comms The array of commitments
* @param[in] n The number of polynomials and commitments
* @retval C_KZG_OK Challenge computation successful
* @retval C_KZG_MALLOC Memory allocation failed
*/
static C_KZG_RET compute_challenges(fr_t *eval_challenge_out, fr_t *r_powers_out,
const Polynomial *polys, const g1_t *comms, uint64_t n) {
size_t i;
uint64_t j;
@ -675,13 +739,13 @@ static C_KZG_RET compute_challenges(fr_t *out, fr_t *r_powers,
/* Compute r_powers */
fr_t r;
hash_to_bls_field(&r, r_bytes);
compute_powers(r_powers, &r, n);
compute_powers(r_powers_out, &r, n);
/* Compute eval_challenge */
uint8_t eval_challenge[32] = {0};
hash_input[32] = 0x1;
hash(eval_challenge, hash_input, 33);
hash_to_bls_field(out, eval_challenge);
hash_to_bls_field(eval_challenge_out, eval_challenge);
free(bytes);
return C_KZG_OK;
@ -754,6 +818,17 @@ static C_KZG_RET g1_lincomb(g1_t *out, const g1_t *p, const fr_t *coeffs, const
return C_KZG_OK;
}
/**
* Given an array of polynomials, interpret it as a 2D matrix and compute the linear combination
* of each column with a set of scalars: return the resulting polynomial.
*
* @remark If `n==0` then this function should return the zero polynomial.
*
* @param[out] out The result polynomial
* @param[in] vectors The array of polynomials to be combined
* @param[in] scalars The array of scalars to multiply the polynomials with
* @param[in] n The number of polynomials and scalars
*/
static void poly_lincomb(Polynomial *out, const Polynomial *vectors, const fr_t *scalars, uint64_t n) {
fr_t tmp;
uint64_t i, j;
@ -767,7 +842,15 @@ static void poly_lincomb(Polynomial *out, const Polynomial *vectors, const fr_t
}
}
/**
* Compute and return [ x^0, x^1, ..., x^{n-1} ].
*
* @remark `out` is left untouched if `n == 0`.
*
* @param[out] out The array to store the powers
* @param[in] x The field element to raise to powers
* @param[in] n The number of powers to compute
*/
static void compute_powers(fr_t *out, fr_t *x, uint64_t n) {
fr_t current_power = fr_one;
for (uint64_t i = 0; i < n; i++) {
@ -780,6 +863,16 @@ static void compute_powers(fr_t *out, fr_t *x, uint64_t n) {
// Polynomials Functions
///////////////////////////////////////////////////////////////////////////////
/**
* Evaluate a polynomial in evaluation form at a given point.
*
* @param[out] out The result of the evaluation
* @param[in] p The polynomial in evaluation form
* @param[in] x The point to evaluate the polynomial at
* @param[in] s The settings struct containing the roots of unity
* @retval C_KZG_OK Evaluation successful
* @retval C_KZG_MALLOC Memory allocation failed
*/
static C_KZG_RET evaluate_polynomial_in_evaluation_form(fr_t *out, const Polynomial *p, const fr_t *x, const KZGSettings *s) {
C_KZG_RET ret;
fr_t tmp;
@ -827,10 +920,29 @@ out:
// KZG Functions
///////////////////////////////////////////////////////////////////////////////
/**
* Compute a KZG commitment from a polynomial.
*
* @param[out] out The resulting commitment
* @param[in] p The polynomial to commit to
* @param[in] s The settings struct containing the commitment key (i.e. the trusted setup)
* @retval C_KZG_OK Commitment computation successful
* @retval C_KZG_MALLOC Memory allocation failed
*/
static C_KZG_RET poly_to_kzg_commitment(g1_t *out, const Polynomial *p, const KZGSettings *s) {
return g1_lincomb(out, s->g1_values, (const fr_t *)(&p->evals), FIELD_ELEMENTS_PER_BLOB);
}
/**
* Convert a blob to a KZG commitment.
*
* @param[out] out The resulting commitment
* @param[in] blob The blob representing the polynomial to be committed to
* @param[in] s The settings struct containing the commitment key (i.e. the trusted setup)
* @retval C_KZG_OK Commitment successful
* @retval C_KZG_BADARGS Invalid input blob
*/
C_KZG_RET blob_to_kzg_commitment(KZGCommitment *out, const Blob *blob, const KZGSettings *s) {
C_KZG_RET ret;
Polynomial p;
@ -848,6 +960,18 @@ C_KZG_RET blob_to_kzg_commitment(KZGCommitment *out, const Blob *blob, const KZG
static C_KZG_RET verify_kzg_proof_impl(bool *out, const g1_t *commitment, const fr_t *x, const fr_t *y,
const g1_t *proof, const KZGSettings *ks);
/**
* Verify a KZG proof claiming that `p(z) == y`.
*
* @param[out] out `true` if the proof is valid, `false` if not
* @param[in] commitment The KZG commitment corresponding to polynomial p(x)
* @param[in] z The evaluation point
* @param[in] y The claimed evaluation result
* @param[in] kzg_proof The KZG proof
* @param[in] s The settings struct containing the commitment verification key (i.e. trusted setup)
* @retval C_KZG_OK Verification successful
* @retval C_KZG_BADARGS Invalid inputs
*/
C_KZG_RET verify_kzg_proof(bool *out,
const KZGCommitment *commitment,
const BLSFieldElement *z,
@ -871,23 +995,23 @@ C_KZG_RET verify_kzg_proof(bool *out,
}
/**
* Check a KZG proof at a point against a commitment.
* Helper function: Verify KZG proof claiming that `p(z) == y`.
*
* Given a @p commitment to a polynomial, a @p proof for @p x, and the claimed value @p y at @p x, verify the claim.
* Given a @p commitment to a polynomial, a @p proof for @p z, and the claimed value @p y at @p z, verify the claim.
*
* @param[out] out `true` if the proof is valid, `false` if not
* @param[in] commitment The commitment to a polynomial
* @param[in] x The point at which the proof is to be checked (opened)
* @param[in] z The point at which the proof is to be checked (opened)
* @param[in] y The claimed value of the polynomial at @p x
* @param[in] proof A proof of the value of the polynomial at the point @p x
* @param[in] ks The settings containing the secrets, previously initialised with #new_kzg_settings
* @retval C_CZK_OK All is well
*/
static C_KZG_RET verify_kzg_proof_impl(bool *out, const g1_t *commitment, const fr_t *x, const fr_t *y,
static C_KZG_RET verify_kzg_proof_impl(bool *out, const g1_t *commitment, const fr_t *z, const fr_t *y,
const g1_t *proof, const KZGSettings *ks) {
g2_t x_g2, s_minus_x;
g1_t y_g1, commitment_minus_y;
g2_mul(&x_g2, &g2_generator, x);
g2_mul(&x_g2, &g2_generator, z);
g2_sub(&s_minus_x, &ks->g2_values[1], &x_g2);
g1_mul(&y_g1, &g1_generator, y);
g1_sub(&commitment_minus_y, commitment, &y_g1);
@ -902,18 +1026,18 @@ static C_KZG_RET verify_kzg_proof_impl(bool *out, const g1_t *commitment, const
*
* @param[out] out The combined proof as a single G1 element
* @param[in] p The polynomial in Lagrange form
* @param[in] x The generator x-value for the evaluation points
* @param[in] z The evaluation point
* @param[in] s The settings containing the secrets, previously initialised with #new_kzg_settings
* @retval C_KZG_OK All is well
* @retval C_KZG_MALLOC Memory allocation failed
*/
static C_KZG_RET compute_kzg_proof(g1_t *out, const Polynomial *p, const fr_t *x, const KZGSettings *s) {
static C_KZG_RET compute_kzg_proof(g1_t *out, const Polynomial *p, const fr_t *z, const KZGSettings *s) {
C_KZG_RET ret;
fr_t y;
fr_t *inverses_in = NULL;
fr_t *inverses = NULL;
ret = evaluate_polynomial_in_evaluation_form(&y, p, x, s);
ret = evaluate_polynomial_in_evaluation_form(&y, p, z, s);
if (ret != C_KZG_OK) goto out;
fr_t tmp;
@ -927,13 +1051,13 @@ static C_KZG_RET compute_kzg_proof(g1_t *out, const Polynomial *p, const fr_t *x
if (ret != C_KZG_OK) goto out;
for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) {
if (fr_equal(x, &roots_of_unity[i])) {
if (fr_equal(z, &roots_of_unity[i])) {
m = i + 1;
continue;
}
// (p_i - y) / (ω_i - x)
// (p_i - y) / (ω_i - z)
blst_fr_sub(&q.evals[i], &p->evals[i], &y);
blst_fr_sub(&inverses_in[i], &roots_of_unity[i], x);
blst_fr_sub(&inverses_in[i], &roots_of_unity[i], z);
}
ret = fr_batch_inv(inverses, inverses_in, FIELD_ELEMENTS_PER_BLOB);
@ -943,13 +1067,13 @@ static C_KZG_RET compute_kzg_proof(g1_t *out, const Polynomial *p, const fr_t *x
blst_fr_mul(&q.evals[i], &q.evals[i], &inverses[i]);
}
if (m) { // ω_m == x
if (m) { // ω_m == z
q.evals[--m] = fr_zero;
for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) {
if (i == m) continue;
// (p_i - y) * ω_i / (x * (x - ω_i))
blst_fr_sub(&tmp, x, &roots_of_unity[i]);
blst_fr_mul(&inverses_in[i], &tmp, x);
// (p_i - y) * ω_i / (z * (z - ω_i))
blst_fr_sub(&tmp, z, &roots_of_unity[i]);
blst_fr_mul(&inverses_in[i], &tmp, z);
}
ret = fr_batch_inv(inverses, inverses_in, FIELD_ELEMENTS_PER_BLOB);
if (ret != C_KZG_OK) goto out;
@ -969,6 +1093,23 @@ out:
return ret;
}
/**
* Given a list of polynomials and commitments, compute and return:
* 1. the aggregated polynomial
* 2. the aggregated KZG commitment,
* 3. the polynomial evaluation random challenge.
*
* @remark This function should work even if `n==0`.
*
* @param[out] poly_out The output aggregated polynomial
* @param[out] comm_out The output aggregated commitment
* @param[out] chal_out The output evaluation challenge
* @param[in] polys Array of polynomials
* @param[in] kzg_commitments Array of KZG commitments
* @param[in] n Number of polynomials and commitments
* @retval C_KZG_OK Operation successful
* @retval C_KZG_MALLOC Memory allocation failed
*/
static C_KZG_RET compute_aggregated_poly_and_commitment(Polynomial *poly_out, g1_t *comm_out, fr_t *chal_out,
const Polynomial *polys,
const g1_t *kzg_commitments,
@ -989,6 +1130,19 @@ out:
return C_KZG_OK;
}
/**
* Computes aggregate KZG proof given for multiple blobs.
*
* @remark This function should work even if `n==0`.
*
* @param[out] out The output aggregate KZG proof.
* @param[in] blobs Array of Blob objects to compute the aggregate proof for.
* @param[in] n The number of blobs in the array.
* @param[in] s The settings struct containing the commitment key (i.e. the trusted setup)
* @retval C_KZG_OK Operation successful
* @retval C_KZG_MALLOC Memory allocation failed
* @retval C_KZG_BADARGS Invalid input blob bytes
*/
C_KZG_RET compute_aggregate_kzg_proof(KZGProof *out,
const Blob *blobs,
size_t n,
@ -1033,6 +1187,17 @@ out:
return ret;
}
/**
* Computes the aggregate KZG proof for multiple blobs.
*
* @param[out] out `true` if the proof is valid, `false` if not
* @param[in] blobs Array of Blob objects to compute the aggregate proof for.
* @param[in] n The number of blobs in the array.
* @param[in] s The settings struct containing the commitment verification key (i.e. the trusted setup)
* @retval C_KZG_OK Operation successful
* @retval C_KZG_MALLOC Memory allocation failed
* @retval C_KZG_BADARGS Invalid input
*/
C_KZG_RET verify_aggregate_kzg_proof(bool *out,
const Blob *blobs,
const KZGCommitment *expected_kzg_commitments,