diff --git a/src/Makefile b/src/Makefile index d100f78..1d629d9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -51,4 +51,4 @@ clean: rm -f *.o test_c_kzg_4844 *.profraw *.profdata *.html format: - clang-format -i --sort-includes test_c_kzg_4844.c + clang-format -i --sort-includes c_kzg_4844.* test_c_kzg_4844.c diff --git a/src/c_kzg_4844.c b/src/c_kzg_4844.c index f15f7d5..6e5fdc7 100644 --- a/src/c_kzg_4844.c +++ b/src/c_kzg_4844.c @@ -14,7 +14,11 @@ * limitations under the License. */ -#include "blst.h" +/** + * @file c_kzg_4844.c + * + * Minimal implementation of the polynomial commitments API for EIP-4844. + */ #include "c_kzg_4844.h" #include @@ -38,62 +42,47 @@ // Constants /////////////////////////////////////////////////////////////////////////////// +// clang-format off + +/** The Fiat-Shamir protocol domain. */ +static const char *FIAT_SHAMIR_PROTOCOL_DOMAIN = "FSBLOBVERIFY_V1_"; + /** Deserialized form of the G1 identity/infinity point. */ -static const g1_t G1_IDENTITY = {{0L, 0L, 0L, 0L, 0L, 0L}, {0L, 0L, 0L, 0L, 0L, 0L}, {0L, 0L, 0L, 0L, 0L, 0L}}; +static const g1_t G1_IDENTITY = { + {0L, 0L, 0L, 0L, 0L, 0L}, + {0L, 0L, 0L, 0L, 0L, 0L}, + {0L, 0L, 0L, 0L, 0L, 0L}}; /** The G1 generator. */ -static const g1_t G1_GENERATOR = {{ - 0x5cb38790fd530c16L, 0x7817fc679976fff5L, 0x154f95c7143ba1c1L, 0xf0ae6acdf3d0e747L, - 0xedce6ecc21dbf440L, 0x120177419e0bfb75L - }, - { - 0xbaac93d50ce72271L, 0x8c22631a7918fd8eL, 0xdd595f13570725ceL, 0x51ac582950405194L, - 0x0e1c8c3fad0059c0L, 0x0bbc3efc5008a26aL - }, - { - 0x760900000002fffdL, 0xebf4000bc40c0002L, 0x5f48985753c758baL, 0x77ce585370525745L, - 0x5c071a97a256ec6dL, 0x15f65ec3fa80e493L - } -}; +static const g1_t G1_GENERATOR = { + {0x5cb38790fd530c16L, 0x7817fc679976fff5L, 0x154f95c7143ba1c1L, + 0xf0ae6acdf3d0e747L, 0xedce6ecc21dbf440L, 0x120177419e0bfb75L}, + {0xbaac93d50ce72271L, 0x8c22631a7918fd8eL, 0xdd595f13570725ceL, + 0x51ac582950405194L, 0x0e1c8c3fad0059c0L, 0x0bbc3efc5008a26aL}, + {0x760900000002fffdL, 0xebf4000bc40c0002L, 0x5f48985753c758baL, + 0x77ce585370525745L, 0x5c071a97a256ec6dL, 0x15f65ec3fa80e493L}}; /** The G2 generator. */ -static const g2_t G2_GENERATOR = {{{{ - 0xf5f28fa202940a10L, 0xb3f5fb2687b4961aL, 0xa1a893b53e2ae580L, 0x9894999d1a3caee9L, - 0x6f67b7631863366bL, 0x058191924350bcd7L - }, - { - 0xa5a9c0759e23f606L, 0xaaa0c59dbccd60c3L, 0x3bb17e18e2867806L, 0x1b1ab6cc8541b367L, - 0xc2b6ed0ef2158547L, 0x11922a097360edf3L - } - } - }, - { { { - 0x4c730af860494c4aL, 0x597cfa1f5e369c5aL, 0xe7e6856caa0a635aL, 0xbbefb5e96e0d495fL, - 0x07d3a975f0ef25a2L, 0x0083fd8e7e80dae5L - }, - { - 0xadc0fc92df64b05dL, 0x18aa270a2b1461dcL, 0x86adac6a3be4eba0L, 0x79495c4ec93da33aL, - 0xe7175850a43ccaedL, 0x0b2bc2a163de1bf2L - } - } - }, - { { { - 0x760900000002fffdL, 0xebf4000bc40c0002L, 0x5f48985753c758baL, 0x77ce585370525745L, - 0x5c071a97a256ec6dL, 0x15f65ec3fa80e493L - }, - { - 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, - 0x0000000000000000L, 0x0000000000000000L - } - } - } -}; +static const g2_t G2_GENERATOR = { + {{{0xf5f28fa202940a10L, 0xb3f5fb2687b4961aL, 0xa1a893b53e2ae580L, + 0x9894999d1a3caee9L, 0x6f67b7631863366bL, 0x058191924350bcd7L}, + {0xa5a9c0759e23f606L, 0xaaa0c59dbccd60c3L, 0x3bb17e18e2867806L, + 0x1b1ab6cc8541b367L, 0xc2b6ed0ef2158547L, 0x11922a097360edf3L}}}, + {{{0x4c730af860494c4aL, 0x597cfa1f5e369c5aL, 0xe7e6856caa0a635aL, + 0xbbefb5e96e0d495fL, 0x07d3a975f0ef25a2L, 0x0083fd8e7e80dae5L}, + {0xadc0fc92df64b05dL, 0x18aa270a2b1461dcL, 0x86adac6a3be4eba0L, + 0x79495c4ec93da33aL, 0xe7175850a43ccaedL, 0x0b2bc2a163de1bf2L}}}, + {{{0x760900000002fffdL, 0xebf4000bc40c0002L, 0x5f48985753c758baL, + 0x77ce585370525745L, 0x5c071a97a256ec6dL, 0x15f65ec3fa80e493L}, + {0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L, + 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L}}}}; /** * The first 32 roots of unity in the finite field F_r. * - * For element `{A, B, C, D}`, the field element value is `A + B * 2^64 + C * 2^128 + D * 2^192`. This format may be - * converted to an `fr_t` type via the #blst_fr_from_uint64 function. + * For element `{A, B, C, D}`, the field element value is + * `A + B * 2^64 + C * 2^128 + D * 2^192`. This format may be converted to + * an `fr_t` type via the #blst_fr_from_uint64 function. * * The decimal values may be calculated with the following Python code: * @code{.py} @@ -102,11 +91,13 @@ static const g2_t G2_GENERATOR = {{{{ * [pow(PRIMITIVE_ROOT, (MODULUS - 1) // (2**i), MODULUS) for i in range(32)] * @endcode * - * Note: Being a "primitive root" in this context means that r^k != 1 for any k < q-1 where q is the modulus. So - * powers of r generate the field. This is also known as being a "primitive element". + * Note: Being a "primitive root" in this context means that `r^k != 1` for any + * `k < q-1` where q is the modulus. So powers of r generate the field. This is + * also known as being a "primitive element". * - * This is easy to check for: we just require that r^((q-1)/2) != 1. Instead of 5, we could use 7, 10, 13, 14, 15, 20... - * to create the roots of unity below. There are a lot of primitive roots: + * This is easy to check for: we just require that r^((q-1)/2) != 1. Instead of + * 5, we could use 7, 10, 13, 14, 15, 20... to create the roots of unity below. + * There are a lot of primitive roots: * https://crypto.stanford.edu/pbc/notes/numbertheory/gen.html */ static const uint64_t SCALE2_ROOT_OF_UNITY[][4] = { @@ -141,14 +132,17 @@ static const uint64_t SCALE2_ROOT_OF_UNITY[][4] = { {0xd7b688830a4f2089L, 0x6558e9e3f6ac7b41L, 0x99e276b571905a7dL, 0x52dd465e2f094256L}, {0x474650359d8e211bL, 0x84d37b826214abc6L, 0x8da40c1ef2bb4598L, 0x0c83ea7744bf1beeL}, {0x694341f608c9dd56L, 0xed3a181fabb30adcL, 0x1339a815da8b398fL, 0x2c6d4e4511657e1eL}, - {0x63e7cb4906ffc93fL, 0xf070bb00e28a193dL, 0xad1715b02e5713b5L, 0x4b5371495990693fL} -}; + {0x63e7cb4906ffc93fL, 0xf070bb00e28a193dL, 0xad1715b02e5713b5L, 0x4b5371495990693fL}}; /** The zero field element. */ static const fr_t FR_ZERO = {0L, 0L, 0L, 0L}; /** This is 1 in Blst's `blst_fr` limb representation. Crazy but true. */ -static const fr_t FR_ONE = {0x00000001fffffffeL, 0x5884b7fa00034802L, 0x998c4fefecbc4ff5L, 0x1824b159acc5056fL}; +static const fr_t FR_ONE = { + 0x00000001fffffffeL, 0x5884b7fa00034802L, + 0x998c4fefecbc4ff5L, 0x1824b159acc5056fL}; + +// clang-format on /////////////////////////////////////////////////////////////////////////////// // Memory Allocation Functions @@ -159,8 +153,6 @@ static const fr_t FR_ONE = {0x00000001fffffffeL, 0x5884b7fa00034802L, 0x998c4fef * * @param[out] x Pointer to the allocated space * @param[in] n The number of bytes to be allocated - * @retval C_CZK_OK All is well - * @retval C_CZK_MALLOC Memory allocation failed */ static C_KZG_RET c_kzg_malloc(void **x, size_t n) { if (n > 0) { @@ -178,8 +170,6 @@ static C_KZG_RET c_kzg_malloc(void **x, size_t n) { * * @param[out] x Pointer to the allocated space * @param[in] n The number of G1 elements to be allocated - * @retval C_CZK_OK All is well - * @retval C_CZK_MALLOC Memory allocation failed */ static C_KZG_RET new_g1_array(g1_t **x, size_t n) { return c_kzg_malloc((void **)x, n * sizeof **x); @@ -192,8 +182,6 @@ static C_KZG_RET new_g1_array(g1_t **x, size_t n) { * * @param[out] x Pointer to the allocated space * @param[in] n The number of G2 elements to be allocated - * @retval C_CZK_OK All is well - * @retval C_CZK_MALLOC Memory allocation failed */ static C_KZG_RET new_g2_array(g2_t **x, size_t n) { return c_kzg_malloc((void **)x, n * sizeof **x); @@ -206,8 +194,6 @@ static C_KZG_RET new_g2_array(g2_t **x, size_t n) { * * @param[out] x Pointer to the allocated space * @param[in] n The number of field elements to be allocated - * @retval C_CZK_OK All is well - * @retval C_CZK_MALLOC Memory allocation failed */ static C_KZG_RET new_fr_array(fr_t **x, size_t n) { return c_kzg_malloc((void **)x, n * sizeof **x); @@ -221,6 +207,7 @@ static C_KZG_RET new_fr_array(fr_t **x, size_t n) { * Fast log base 2 of a byte. * * @param[in] b A non-zero byte + * * @return The index of the highest set bit */ STATIC int log_2_byte(byte b) { @@ -237,7 +224,8 @@ STATIC int log_2_byte(byte b) { /** * Test whether the operand is one in the finite field. * - * @param p The field element to be checked + * @param[in] p The field element to be checked + * * @retval true The element is one * @retval false The element is not one */ @@ -252,6 +240,7 @@ static bool fr_is_one(const fr_t *p) { * * @param[in] aa The first element * @param[in] bb The second element + * * @retval true if @p aa and @p bb are equal * @retval false otherwise */ @@ -302,10 +291,11 @@ static void fr_pow(fr_t *out, const fr_t *a, uint64_t n) { /** * Create a field element from a single 64-bit unsigned integer. * - * @remark This can only generate a tiny fraction of possible field elements, and is mostly useful for testing. + * @remark This can only generate a tiny fraction of possible field elements, + * and is mostly useful for testing. * - * @param out The field element equivalent of @p n - * @param n The 64-bit integer to be converted + * @param[out] out The field element equivalent of @p n + * @param[in] n The 64-bit integer to be converted */ static void fr_from_uint64(fr_t *out, uint64_t n) { uint64_t vals[] = {n, 0, 0, 0}; @@ -330,13 +320,13 @@ static C_KZG_RET fr_batch_inv(fr_t *out, const fr_t *a, size_t len) { prod[0] = a[0]; - for(i = 1; i < len; i++) { + for (i = 1; i < len; i++) { blst_fr_mul(&prod[i], &a[i], &prod[i - 1]); } blst_fr_eucl_inverse(&inv, &prod[len - 1]); - for(i = len - 1; i > 0; i--) { + for (i = len - 1; i > 0; i--) { blst_fr_mul(&out[i], &inv, &prod[i - 1]); blst_fr_mul(&inv, &a[i], &inv); } @@ -350,7 +340,8 @@ out: /** * Multiply a G1 group element by a field element. * - * This "undoes" the Blst constant-timedness. FFTs do a lot of multiplication by one, so constant time is rather slow. + * This "undoes" the Blst constant-timedness. FFTs do a lot of multiplication by + * one, so constant time is rather slow. * * @param[out] out [@p b]@p a * @param[in] a The G1 group element @@ -362,7 +353,8 @@ static void g1_mul(g1_t *out, const g1_t *a, const fr_t *b) { // Count the number of bytes to be multiplied. int i = sizeof(blst_scalar); - while (i && !s.b[i - 1]) --i; + while (i && !s.b[i - 1]) + --i; if (i == 0) { *out = G1_IDENTITY; } else if (i == 1 && s.b[0] == 1) { @@ -421,10 +413,13 @@ static void g2_mul(g2_t *out, const g2_t *a, const fr_t *b) { * @param[in] a2 A G2 group point for the first pairing * @param[in] b1 A G1 group point for the second pairing * @param[in] b2 A G2 group point for the second pairing + * * @retval true The pairings were equal * @retval false The pairings were not equal */ -static bool pairings_verify(const g1_t *a1, const g2_t *a2, const g1_t *b1, const g2_t *b2) { +static bool pairings_verify( + const g1_t *a1, const g2_t *a2, const g1_t *b1, const g2_t *b2 +) { blst_fp12 loop0, loop1, gt_point; blst_p1_affine aa1, bb1; blst_p2_affine aa2, bb2; @@ -456,10 +451,12 @@ static bool pairings_verify(const g1_t *a1, const g2_t *a2, const g1_t *b1, cons * @remark Works only for n a power of two, and only for n up to 2^31. * * @param[in] n The power of two + * * @return the log base two of n */ static int log2_pow2(uint32_t n) { - const uint32_t b[] = {0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000}; + const uint32_t b[] = { + 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000}; register uint32_t r; r = (n & b[0]) != 0; r |= ((n & b[1]) != 0) << 1; @@ -490,7 +487,7 @@ STATIC void bytes_from_g1(Bytes48 *out, const g1_t *in) { * @param[in] in The field element to be serialized */ STATIC void bytes_from_bls_field(Bytes32 *out, const fr_t *in) { - blst_scalar_from_fr((blst_scalar*)out->bytes, in); + blst_scalar_from_fr((blst_scalar *)out->bytes, in); } /** @@ -513,8 +510,8 @@ static void bytes_from_uint64(uint8_t out[8], uint64_t n) { /** * Utility function to test whether the argument is a power of two. * - * @remark This method returns `true` for `is_power_of_two(0)` which is a bit weird, but not an issue in the contexts in - * which we use it. + * @remark This method returns `true` for `is_power_of_two(0)` which is a bit + * weird, but not an issue in the contexts in which we use it. * * @param[in] n The number to test * @retval true if @p n is a power of two or zero @@ -527,9 +524,10 @@ static bool is_power_of_two(uint64_t n) { /** * Reverse the bits in a byte. * - * From https://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64BitsDiv + * From + * https://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64BitsDiv * - * @param a A byte + * @param[in] a A byte * @return A byte that is bit-reversed with respect to @p a */ #define rev_byte(a) ((((a)&0xff) * 0x0202020202ULL & 0x010884422010ULL) % 1023) @@ -537,10 +535,12 @@ static bool is_power_of_two(uint64_t n) { /** * Reverse the bits in a 32 bit word. * - * @param a A 32 bit unsigned integer + * @param[in] a A 32 bit unsigned integer * @return A 32 bit unsigned integer that is bit-reversed with respect to @p a */ -#define rev_4byte(a) (rev_byte(a) << 24 | rev_byte((a) >> 8) << 16 | rev_byte((a) >> 16) << 8 | rev_byte((a) >> 24)) +#define rev_4byte(a) \ + (rev_byte(a) << 24 | rev_byte((a) >> 8) << 16 | rev_byte((a) >> 16) << 8 | \ + rev_byte((a) >> 24) << 0) /** * Reverse the bit order in a 32 bit integer. @@ -562,15 +562,16 @@ STATIC uint32_t reverse_bits(uint32_t a) { * * @param[in,out] values The array, which is re-ordered in-place * @param[in] size The size in bytes of an element of the array - * @param[in] n The length of the array, must be a power of two less that 2^32 - * @retval C_CZK_OK All is well - * @retval C_CZK_BADARGS Invalid parameters were supplied + * @param[in] n The length of the array, must be a power of two + * less that 2^32 */ -static C_KZG_RET bit_reversal_permutation(void *values, size_t size, uint64_t n) { +static C_KZG_RET +bit_reversal_permutation(void *values, size_t size, uint64_t n) { CHECK(n >> 32 == 0); CHECK(is_power_of_two(n)); - // Pointer arithmetic on `void *` is naughty, so cast to something definite + // Pointer arithmetic on `void *` is naughty, so cast to something + // definite byte *v = values; byte tmp[size]; int unused_bit_len = 32 - log2_pow2(n); @@ -604,10 +605,12 @@ STATIC void hash_to_bls_field(fr_t *out, const Bytes32 *b) { } /** - * Convert untrusted bytes to a trusted and validated BLS scalar field element. + * Convert untrusted bytes to a trusted and validated BLS scalar 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 */ @@ -622,14 +625,15 @@ STATIC C_KZG_RET bytes_to_bls_field(fr_t *out, const Bytes32 *b) { /** * Perform BLS validation required by the types KZGProof and KZGCommitment. * + * @remark This function deviates from the spec because it returns (via an + * output argument) the g1 point. This way is more efficient (faster) + * but the function name is a bit misleading. + * * @param[out] out The output g1 point * @param[in] b The proof/commitment bytes + * * @retval C_KZG_OK Deserialization successful * @retval C_KZG_BADARGS Invalid input bytes - * - * @remark This function deviates from the spec because it returns (via an - * output argument) the g1 point. This way is more efficient (faster) but - * the function name is a bit misleading. */ STATIC C_KZG_RET validate_kzg_g1(g1_t *out, const Bytes48 *b) { /* Convert the bytes to a p1 point */ @@ -639,16 +643,13 @@ STATIC C_KZG_RET validate_kzg_g1(g1_t *out, const Bytes48 *b) { blst_p1_from_affine(out, &p1_affine); /* The point at infinity is accepted! */ - if (blst_p1_is_inf(out)) - return C_KZG_OK; + if (blst_p1_is_inf(out)) return C_KZG_OK; /* The point must be on the curve */ - if (!blst_p1_on_curve(out)) - return C_KZG_BADARGS; + if (!blst_p1_on_curve(out)) return C_KZG_BADARGS; /* The point must be on the right subgroup */ - if (!blst_p1_in_g1(out)) - return C_KZG_BADARGS; + if (!blst_p1_in_g1(out)) return C_KZG_BADARGS; return C_KZG_OK; } @@ -658,6 +659,7 @@ STATIC C_KZG_RET validate_kzg_g1(g1_t *out, const Bytes48 *b) { * * @param[out] out The output commitment * @param[in] b The commitment bytes + * * @retval C_KZG_OK Deserialization successful * @retval C_KZG_BADARGS Invalid input bytes */ @@ -670,6 +672,7 @@ static C_KZG_RET bytes_to_kzg_commitment(g1_t *out, const Bytes48 *b) { * * @param[out] out The output proof * @param[in] b The proof bytes + * * @retval C_KZG_OK Deserialization successful * @retval C_KZG_BADARGS Invalid input bytes */ @@ -678,17 +681,21 @@ 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 elements). + * 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++) { - ret = bytes_to_bls_field(&p->evals[i], (Bytes32 *)&blob->bytes[i * BYTES_PER_FIELD_ELEMENT]); + ret = bytes_to_bls_field( + &p->evals[i], (Bytes32 *)&blob->bytes[i * BYTES_PER_FIELD_ELEMENT] + ); if (ret != C_KZG_OK) return ret; } return C_KZG_OK; @@ -703,15 +710,22 @@ STATIC void compute_powers(fr_t *out, fr_t *x, uint64_t n); * @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[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) { +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; @@ -733,10 +747,10 @@ static C_KZG_RET compute_challenges(fr_t *eval_challenge_out, fr_t *r_powers_out /* Copy polynomials */ for (i = 0; i < n; i++) { - for (j = 0; j < FIELD_ELEMENTS_PER_BLOB; j++) { - bytes_from_bls_field((Bytes32 *)offset, &polys[i].evals[j]); - offset += BYTES_PER_FIELD_ELEMENT; - } + for (j = 0; j < FIELD_ELEMENTS_PER_BLOB; j++) { + bytes_from_bls_field((Bytes32 *)offset, &polys[i].evals[j]); + offset += BYTES_PER_FIELD_ELEMENT; + } } /* Copy commitments */ @@ -776,24 +790,27 @@ static C_KZG_RET compute_challenges(fr_t *eval_challenge_out, fr_t *r_powers_out /** * Calculate a linear combination of G1 group elements. * - * Calculates `[coeffs_0]p_0 + [coeffs_1]p_1 + ... + [coeffs_n]p_n` where `n` is `len - 1`. + * Calculates `[coeffs_0]p_0 + [coeffs_1]p_1 + ... + [coeffs_n]p_n` + * where `n` is `len - 1`. * * @param[out] out The resulting sum-product * @param[in] p Array of G1 group elements, length @p len * @param[in] coeffs Array of field elements, length @p len * @param[in] len The number of group/field elements * - * For the benefit of future generations (since Blst has no documentation to speak of), - * there are two ways to pass the arrays of scalars and points into `blst_p1s_mult_pippenger()`. + * For the benefit of future generations (since Blst has no documentation to + * speak of), there are two ways to pass the arrays of scalars and points + * into `blst_p1s_mult_pippenger()`. * - * 1. Pass `points` as an array of pointers to the points, and pass `scalars` as an array of pointers to the scalars, - * each of length @p len. - * 2. Pass an array where the first element is a pointer to the contiguous array of points and the second is null, and - * similarly for scalars. + * 1. Pass `points` as an array of pointers to the points, and pass + * `scalars` as an array of pointers to the scalars, each of length @p len. + * 2. Pass an array where the first element is a pointer to the contiguous + * array of points and the second is null, and similarly for scalars. * * We do the second of these to save memory here. */ -static C_KZG_RET g1_lincomb(g1_t *out, const g1_t *p, const fr_t *coeffs, const uint64_t len) { +static C_KZG_RET +g1_lincomb(g1_t *out, const g1_t *p, const fr_t *coeffs, const uint64_t len) { C_KZG_RET ret = C_KZG_MALLOC; void *scratch = NULL; blst_p1_affine *p_affine = NULL; @@ -829,7 +846,9 @@ static C_KZG_RET g1_lincomb(g1_t *out, const g1_t *p, const fr_t *coeffs, const // Call the Pippenger implementation const byte *scalars_arg[2] = {(byte *)scalars, NULL}; const blst_p1_affine *points_arg[2] = {p_affine, NULL}; - blst_p1s_mult_pippenger(out, points_arg, len, scalars_arg, 256, scratch); + blst_p1s_mult_pippenger( + out, points_arg, len, scalars_arg, 256, scratch + ); } ret = C_KZG_OK; @@ -842,8 +861,9 @@ out: } /** - * 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. + * 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. * @@ -852,7 +872,9 @@ out: * @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) { +static void poly_lincomb( + Polynomial *out, const Polynomial *vectors, const fr_t *scalars, uint64_t n +) { fr_t tmp; uint64_t i, j; for (j = 0; j < FIELD_ELEMENTS_PER_BLOB; j++) @@ -893,10 +915,13 @@ STATIC void compute_powers(fr_t *out, fr_t *x, uint64_t n) { * @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) { +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; fr_t *inverses_in = NULL; @@ -948,12 +973,17 @@ out: * * @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) + * @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); +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 + ); } /** @@ -961,11 +991,15 @@ static C_KZG_RET poly_to_kzg_commitment(g1_t *out, const Polynomial *p, const KZ * * @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) + * @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 blob_to_kzg_commitment( + KZGCommitment *out, const Blob *blob, const KZGSettings *s +) { C_KZG_RET ret; Polynomial p; g1_t commitment; @@ -979,27 +1013,38 @@ C_KZG_RET blob_to_kzg_commitment(KZGCommitment *out, const Blob *blob, const KZG } /* Forward function declaration */ -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); +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 +); /** * 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] 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) + * @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 Bytes48 *commitment_bytes, - const Bytes32 *z_bytes, - const Bytes32 *y_bytes, - const Bytes48 *proof_bytes, - const KZGSettings *s) { +C_KZG_RET verify_kzg_proof( + bool *out, + const Bytes48 *commitment_bytes, + const Bytes32 *z_bytes, + const Bytes32 *y_bytes, + const Bytes48 *proof_bytes, + const KZGSettings *s +) { C_KZG_RET ret; fr_t z_fr, y_fr; g1_t commitment_g1, proof_g1; @@ -1013,24 +1058,35 @@ C_KZG_RET verify_kzg_proof(bool *out, ret = bytes_to_kzg_proof(&proof_g1, proof_bytes); if (ret != C_KZG_OK) return ret; - return verify_kzg_proof_impl(out, &commitment_g1, &z_fr, &y_fr, &proof_g1, s); + return verify_kzg_proof_impl( + out, &commitment_g1, &z_fr, &y_fr, &proof_g1, s + ); } /** * Helper function: Verify KZG proof claiming that `p(z) == y`. * - * 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. + * 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] z 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 + * @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 */ -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) { +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, z); @@ -1038,13 +1094,19 @@ static C_KZG_RET verify_kzg_proof_impl(bool *out, const g1_t *commitment, const g1_mul(&y_g1, &G1_GENERATOR, y); g1_sub(&commitment_minus_y, commitment, &y_g1); - *out = pairings_verify(&commitment_minus_y, &G2_GENERATOR, proof, &s_minus_x); + *out = + pairings_verify(&commitment_minus_y, &G2_GENERATOR, proof, &s_minus_x); return C_KZG_OK; } /* Forward function declaration */ -C_KZG_RET compute_kzg_proof_impl(KZGProof *out, const Polynomial *polynomial, const fr_t *z, const KZGSettings *s); +C_KZG_RET compute_kzg_proof_impl( + KZGProof *out, + const Polynomial *polynomial, + const fr_t *z, + const KZGSettings *s +); /** * Compute KZG proof for polynomial in Lagrange form at position z. @@ -1052,11 +1114,15 @@ C_KZG_RET compute_kzg_proof_impl(KZGProof *out, const Polynomial *polynomial, co * @param[out] out The combined proof as a single G1 element * @param[in] blob The blob (polynomial) to generate a proof for * @param[in] z The generator z-value for the evaluation points - * @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 + * @param[in] s The settings containing the secrets, previously + * initialised with #new_kzg_settings */ -C_KZG_RET compute_kzg_proof(KZGProof *out, const Blob *blob, const Bytes32 *z_bytes, const KZGSettings *s) { +C_KZG_RET compute_kzg_proof( + KZGProof *out, + const Blob *blob, + const Bytes32 *z_bytes, + const KZGSettings *s +) { C_KZG_RET ret; Polynomial polynomial; fr_t frz; @@ -1073,16 +1139,21 @@ out: } /** - * Helper function for compute_kzg_proof() and compute_aggregate_kzg_proof(). + * Helper function for compute_kzg_proof() and + * compute_aggregate_kzg_proof(). * * @param[out] out The combined proof as a single G1 element * @param[in] polynomial The polynomial in Lagrange form * @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 + * @param[in] s The settings containing the secrets, previously + * initialised with #new_kzg_settings */ -C_KZG_RET compute_kzg_proof_impl(KZGProof *out, const Polynomial *polynomial, const fr_t *z, const KZGSettings *s) { +C_KZG_RET compute_kzg_proof_impl( + KZGProof *out, + const Polynomial *polynomial, + const fr_t *z, + const KZGSettings *s +) { C_KZG_RET ret; fr_t y; fr_t *inverses_in = NULL; @@ -1144,7 +1215,9 @@ C_KZG_RET compute_kzg_proof_impl(KZGProof *out, const Polynomial *polynomial, co } g1_t out_g1; - ret = g1_lincomb(&out_g1, s->g1_values, (const fr_t *)(&q.evals), FIELD_ELEMENTS_PER_BLOB); + ret = g1_lincomb( + &out_g1, s->g1_values, (const fr_t *)(&q.evals), FIELD_ELEMENTS_PER_BLOB + ); if (ret != C_KZG_OK) goto out; bytes_from_g1(out, &out_g1); @@ -1157,9 +1230,9 @@ out: /** * 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. + * 1. the aggregated polynomial + * 2. the aggregated KZG commitment, + * 3. the polynomial evaluation random challenge. * * @remark This function should work even if `n==0`. * @@ -1169,14 +1242,19 @@ out: * @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, - size_t n) { - fr_t* r_powers = calloc(n, sizeof(fr_t)); +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, + size_t n +) { + fr_t *r_powers = calloc(n, sizeof(fr_t)); if (n > 0 && r_powers == NULL) return C_KZG_MALLOC; C_KZG_RET ret; @@ -1199,20 +1277,21 @@ out: * @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) + * @param[in] blobs Array of blobs 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, - const KZGSettings *s) { +C_KZG_RET compute_aggregate_kzg_proof( + KZGProof *out, const Blob *blobs, size_t n, const KZGSettings *s +) { C_KZG_RET ret = C_KZG_MALLOC; - Polynomial* polys = NULL; - g1_t* commitments = NULL; + Polynomial *polys = NULL; + g1_t *commitments = NULL; commitments = calloc(n, sizeof(g1_t)); if (n > 0 && commitments == NULL) { @@ -1234,10 +1313,18 @@ C_KZG_RET compute_aggregate_kzg_proof(KZGProof *out, Polynomial aggregated_poly; g1_t aggregated_poly_commitment; fr_t evaluation_challenge; - ret = compute_aggregated_poly_and_commitment(&aggregated_poly, &aggregated_poly_commitment, &evaluation_challenge, polys, commitments, n); + ret = compute_aggregated_poly_and_commitment( + &aggregated_poly, + &aggregated_poly_commitment, + &evaluation_challenge, + polys, + commitments, + n + ); if (ret != C_KZG_OK) goto out; - ret = compute_kzg_proof_impl(out, &aggregated_poly, &evaluation_challenge, s); + ret = + compute_kzg_proof_impl(out, &aggregated_poly, &evaluation_challenge, s); if (ret != C_KZG_OK) goto out; out: @@ -1250,22 +1337,26 @@ out: * 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) + * @param[in] blobs Array of blobs 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 Bytes48 *commitments_bytes, - size_t n, - const Bytes48 *aggregated_proof_bytes, - const KZGSettings *s) { +C_KZG_RET verify_aggregate_kzg_proof( + bool *out, + const Blob *blobs, + const Bytes48 *commitments_bytes, + size_t n, + const Bytes48 *aggregated_proof_bytes, + const KZGSettings *s +) { C_KZG_RET ret = C_KZG_MALLOC; - g1_t* commitments = NULL; - Polynomial* polys = NULL; + g1_t *commitments = NULL; + Polynomial *polys = NULL; g1_t proof; ret = bytes_to_kzg_proof(&proof, aggregated_proof_bytes); @@ -1291,14 +1382,25 @@ C_KZG_RET verify_aggregate_kzg_proof(bool *out, Polynomial aggregated_poly; g1_t aggregated_poly_commitment; fr_t evaluation_challenge; - ret = compute_aggregated_poly_and_commitment(&aggregated_poly, &aggregated_poly_commitment, &evaluation_challenge, polys, commitments, n); + ret = compute_aggregated_poly_and_commitment( + &aggregated_poly, + &aggregated_poly_commitment, + &evaluation_challenge, + polys, + commitments, + n + ); if (ret != C_KZG_OK) goto out; fr_t y; - ret = evaluate_polynomial_in_evaluation_form(&y, &aggregated_poly, &evaluation_challenge, s); + ret = evaluate_polynomial_in_evaluation_form( + &y, &aggregated_poly, &evaluation_challenge, s + ); if (ret != C_KZG_OK) goto out; - ret = verify_kzg_proof_impl(out, &aggregated_poly_commitment, &evaluation_challenge, &y, &proof, s); + ret = verify_kzg_proof_impl( + out, &aggregated_poly_commitment, &evaluation_challenge, &y, &proof, s + ); out: free(commitments); @@ -1327,16 +1429,25 @@ out: * @param[out] out The results (array of length @p n) * @param[in] in The input data (array of length @p n * @p stride) * @param[in] stride The input data stride - * @param[in] roots Roots of unity (array of length @p n * @p roots_stride) + * @param[in] roots Roots of unity + * (array of length @p n * @p roots_stride) * @param[in] roots_stride The stride interval among the roots of unity * @param[in] n Length of the FFT, must be a power of two */ -static void fft_g1_fast(g1_t *out, const g1_t *in, uint64_t stride, const fr_t *roots, uint64_t roots_stride, - uint64_t n) { +static void fft_g1_fast( + g1_t *out, + const g1_t *in, + uint64_t stride, + const fr_t *roots, + uint64_t roots_stride, + uint64_t n +) { uint64_t half = n / 2; if (half > 0) { // Tunable parameter fft_g1_fast(out, in, stride * 2, roots, roots_stride * 2, half); - fft_g1_fast(out + half, in + stride, stride * 2, roots, roots_stride * 2, half); + fft_g1_fast( + out + half, in + stride, stride * 2, roots, roots_stride * 2, half + ); for (uint64_t i = 0; i < half; i++) { g1_t y_times_root; g1_mul(&y_times_root, &out[i + half], &roots[i * roots_stride]); @@ -1353,13 +1464,15 @@ static void fft_g1_fast(g1_t *out, const g1_t *in, uint64_t stride, const fr_t * * * @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] 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 + * @param[in] fs Pointer to previously initialised FFTSettings + * structure with `max_width` at least @p n */ -static C_KZG_RET fft_g1(g1_t *out, const g1_t *in, bool inverse, uint64_t n, const FFTSettings *fs) { +static C_KZG_RET fft_g1( + g1_t *out, const g1_t *in, bool inverse, uint64_t n, const FFTSettings *fs +) { uint64_t stride = fs->max_width / n; CHECK(n <= fs->max_width); CHECK(is_power_of_two(n)); @@ -1380,16 +1493,16 @@ static C_KZG_RET fft_g1(g1_t *out, const g1_t *in, bool inverse, uint64_t n, con /** * Generate powers of a root of unity in the field for use in the FFTs. * - * @remark @p root must be such that @p root ^ @p width is equal to one, but no smaller power of @p root is equal to - * one. + * @remark @p root must be such that @p root ^ @p width is equal to one, but + * no smaller power of @p root is equal to one. * - * @param[out] out The generated powers of the root of unity (array size @p width + 1) + * @param[out] out The generated powers of the root of unity + * (array size @p width + 1) * @param[in] root A root of unity * @param[in] width One less than the size of @p out - * @retval C_CZK_OK All is well - * @retval C_CZK_BADARGS Invalid parameters were supplied */ -static C_KZG_RET expand_root_of_unity(fr_t *out, const fr_t *root, uint64_t width) { +static C_KZG_RET +expand_root_of_unity(fr_t *out, const fr_t *root, uint64_t width) { out[0] = FR_ONE; out[1] = *root; @@ -1405,22 +1518,24 @@ static C_KZG_RET expand_root_of_unity(fr_t *out, const fr_t *root, uint64_t widt /** * Initialise an FFTSettings structure. * - * Space is allocated for, and arrays are populated with, powers of the roots of unity. The two arrays contain the same - * values in reverse order for convenience in inverse FFTs. + * Space is allocated for, and arrays are populated with, powers of the + * roots of unity. The two arrays contain the same values in reverse order + * for convenience in inverse FFTs. * - * `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. + * `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 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. + * @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 - * @param[in] max_scale Log base 2 of the max FFT size to be used with these 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 + * @param[in] max_scale Log base 2 of the max FFT size to be used with + * these settings */ static C_KZG_RET new_fft_settings(FFTSettings *fs, unsigned int max_scale) { C_KZG_RET ret; @@ -1431,7 +1546,9 @@ static C_KZG_RET new_fft_settings(FFTSettings *fs, unsigned int max_scale) { fs->reverse_roots_of_unity = NULL; fs->roots_of_unity = NULL; - CHECK((max_scale < sizeof SCALE2_ROOT_OF_UNITY / sizeof SCALE2_ROOT_OF_UNITY[0])); + CHECK(( + max_scale < sizeof SCALE2_ROOT_OF_UNITY / sizeof SCALE2_ROOT_OF_UNITY[0] + )); blst_fr_from_uint64(&root_of_unity, SCALE2_ROOT_OF_UNITY[max_scale]); // Allocate space for the roots of unity @@ -1443,17 +1560,26 @@ static C_KZG_RET new_fft_settings(FFTSettings *fs, unsigned int max_scale) { if (ret != C_KZG_OK) goto out_error; // Populate the roots of unity - ret = expand_root_of_unity(fs->expanded_roots_of_unity, &root_of_unity, fs->max_width); + ret = expand_root_of_unity( + fs->expanded_roots_of_unity, &root_of_unity, fs->max_width + ); if (ret != C_KZG_OK) goto out_error; // Populate reverse roots of unity for (uint64_t i = 0; i <= fs->max_width; i++) { - fs->reverse_roots_of_unity[i] = fs->expanded_roots_of_unity[fs->max_width - i]; + fs->reverse_roots_of_unity[i] = + fs->expanded_roots_of_unity[fs->max_width - i]; } // Permute the roots of unity - memcpy(fs->roots_of_unity, fs->expanded_roots_of_unity, sizeof(fr_t) * fs->max_width); - ret = bit_reversal_permutation(fs->roots_of_unity, sizeof(fr_t), fs->max_width); + memcpy( + fs->roots_of_unity, + fs->expanded_roots_of_unity, + sizeof(fr_t) * fs->max_width + ); + ret = bit_reversal_permutation( + fs->roots_of_unity, sizeof(fr_t), fs->max_width + ); if (ret != C_KZG_OK) goto out_error; goto out_success; @@ -1469,7 +1595,7 @@ out_success: /** * Free the memory that was previously allocated by #new_fft_settings. * - * @param fs The settings to be freed + * @param[in] fs The settings to be freed */ static void free_fft_settings(FFTSettings *fs) { free(fs->expanded_roots_of_unity); @@ -1481,10 +1607,10 @@ static void free_fft_settings(FFTSettings *fs) { /** * Free the memory that was previously allocated by #new_kzg_settings. * - * @param ks The settings to be freed + * @param[in] ks The settings to be freed */ static void free_kzg_settings(KZGSettings *ks) { - free((FFTSettings*)ks->fs); + free((FFTSettings *)ks->fs); free(ks->g1_values); free(ks->g2_values); } @@ -1494,17 +1620,19 @@ static void free_kzg_settings(KZGSettings *ks) { * * @remark Free after use with #free_trusted_setup. * - * @param[out] out Pointer to the stored trusted setup data - * @param g1_bytes Array of G1 elements - * @param n1 Length of `g1` - * @param g2_bytes Array of G2 elements - * @param n2 Length of `g2` - * @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 + * @param[out] out Pointer to the stored trusted setup data + * @param[in] g1_bytes Array of G1 elements + * @param[in] n1 Length of `g1` + * @param[in] g2_bytes Array of G2 elements + * @param[in] n2 Length of `g2` */ -C_KZG_RET load_trusted_setup(KZGSettings *out, const uint8_t *g1_bytes, size_t n1, const uint8_t *g2_bytes, size_t n2) { +C_KZG_RET load_trusted_setup( + KZGSettings *out, + const uint8_t *g1_bytes, + size_t n1, + const uint8_t *g2_bytes, + size_t n2 +) { uint64_t i; blst_p2_affine g2_affine; g1_t *g1_projective = NULL; @@ -1532,11 +1660,12 @@ C_KZG_RET load_trusted_setup(KZGSettings *out, const uint8_t *g1_bytes, size_t n } unsigned int max_scale = 0; - while (((uint64_t)1 << max_scale) < n1) max_scale++; + while (((uint64_t)1 << max_scale) < n1) + max_scale++; - ret = c_kzg_malloc((void**)&out->fs, sizeof(FFTSettings)); + ret = c_kzg_malloc((void **)&out->fs, sizeof(FFTSettings)); if (ret != C_KZG_OK) goto out_error; - ret = new_fft_settings((FFTSettings*)out->fs, max_scale); + ret = new_fft_settings((FFTSettings *)out->fs, max_scale); if (ret != C_KZG_OK) goto out_error; ret = fft_g1(out->g1_values, g1_projective, true, n1, out->fs); if (ret != C_KZG_OK) goto out_error; @@ -1554,12 +1683,13 @@ out_success: return ret; } -/* +/** * Load trusted setup from a file. * - * @remark The file format is n1 n2 g1_1 g1_2 ... g1_n1 g2_1 ... g2_n2 - * @remark where the first two numbers are in decimal and the remainder - * @remark are hexstrings and any whitespace can be used as separators. + * @remark The file format is `n1 n2 g1_1 g1_2 ... g1_n1 g2_1 ... g2_n2` where + * the first two numbers are in decimal and the remainder are hexstrings + * and any whitespace can be used as separators. + * * @remark See also #load_trusted_setup. * * @param[out] out Pointer to the loaded trusted setup data @@ -1589,13 +1719,17 @@ C_KZG_RET load_trusted_setup_file(KZGSettings *out, FILE *in) { CHECK(num_matches == 1); } - return load_trusted_setup(out, g1_bytes, FIELD_ELEMENTS_PER_BLOB, g2_bytes, 65); + return load_trusted_setup( + out, g1_bytes, FIELD_ELEMENTS_PER_BLOB, g2_bytes, 65 + ); } -/* +/** * Free a trusted setup (KZGSettings). + * + * @param[in] s The trusted setup to free */ void free_trusted_setup(KZGSettings *s) { - free_fft_settings((FFTSettings*)s->fs); + free_fft_settings((FFTSettings *)s->fs); free_kzg_settings(s); } diff --git a/src/c_kzg_4844.h b/src/c_kzg_4844.h index a210590..8ed1610 100644 --- a/src/c_kzg_4844.h +++ b/src/c_kzg_4844.h @@ -19,36 +19,74 @@ * * Minimal interface required for EIP-4844. */ - #ifndef C_KZG_4844_H #define C_KZG_4844_H -#include -#include #include +#include +#include #include "blst.h" -// Allow a library built from this code to be used from C++ #ifdef __cplusplus extern "C" { #endif +/////////////////////////////////////////////////////////////////////////////// +// Macros +/////////////////////////////////////////////////////////////////////////////// + #define BYTES_PER_COMMITMENT 48 #define BYTES_PER_PROOF 48 #define BYTES_PER_FIELD_ELEMENT 32 #define BYTES_PER_BLOB (FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT) -static const char *FIAT_SHAMIR_PROTOCOL_DOMAIN = "FSBLOBVERIFY_V1_"; -typedef blst_p1 g1_t; /**< Internal G1 group element type */ -typedef blst_p2 g2_t; /**< Internal G2 group element type */ -typedef blst_fr fr_t; /**< Internal Fr field element type */ +/////////////////////////////////////////////////////////////////////////////// +// Types +/////////////////////////////////////////////////////////////////////////////// -typedef struct { uint8_t bytes[32]; } Bytes32; -typedef struct { uint8_t bytes[48]; } Bytes48; -typedef struct { uint8_t bytes[BYTES_PER_BLOB]; } Blob; +typedef blst_p1 g1_t; /**< Internal G1 group element type. */ +typedef blst_p2 g2_t; /**< Internal G2 group element type. */ +typedef blst_fr fr_t; /**< Internal Fr field element type. */ +/** + * Internal representation of a polynomial. + */ +typedef struct { + fr_t evals[FIELD_ELEMENTS_PER_BLOB]; +} Polynomial; + +/** + * An array of 32 bytes. Represents an untrusted + * (potentially invalid) field element. + */ +typedef struct { + uint8_t bytes[32]; +} Bytes32; + +/** + * An array of 48 bytes. Represents an untrusted + * (potentially invalid) commitment/proof. + */ +typedef struct { + uint8_t bytes[48]; +} Bytes48; + +/** + * A basic blob data. + */ +typedef struct { + uint8_t bytes[BYTES_PER_BLOB]; +} Blob; + +/** + * A trusted (valid) KZG commitment. + */ typedef Bytes48 KZGCommitment; + +/** + * A trusted (valid) KZG proof. + */ typedef Bytes48 KZGProof; /** @@ -56,93 +94,106 @@ typedef Bytes48 KZGProof; */ typedef enum { C_KZG_OK = 0, /**< Success! */ - C_KZG_BADARGS, /**< The supplied data is invalid in some way */ - C_KZG_ERROR, /**< Internal error - this should never occur and may indicate a bug in the library */ - C_KZG_MALLOC, /**< Could not allocate memory */ + C_KZG_BADARGS, /**< The supplied data is invalid in some way. */ + C_KZG_ERROR, /**< Internal error - this should never occur. */ + C_KZG_MALLOC, /**< Could not allocate memory. */ } C_KZG_RET; /** * Stores the setup and parameters needed for performing FFTs. */ typedef struct { - uint64_t max_width; /**< The maximum size of FFT these settings support, a power of 2. */ - fr_t *expanded_roots_of_unity; /**< Ascending powers of the root of unity, size `width + 1`. */ - fr_t *reverse_roots_of_unity; /**< Descending powers of the root of unity, size `width + 1`. */ - fr_t *roots_of_unity; /**< Powers of the root of unity in bit-reversal permutation, size `width`. */ + /** The maximum size of FFT these settings support, a power of 2. */ + uint64_t max_width; + /** Ascending powers of the root of unity, size `width + 1`. */ + fr_t *expanded_roots_of_unity; + /** Descending powers of the root of unity, size `width + 1`. */ + fr_t *reverse_roots_of_unity; + /** Powers of the root of unity in bit-reversal permutation, + * size `width`. */ + fr_t *roots_of_unity; } FFTSettings; /** * Stores the setup and parameters needed for computing KZG proofs. */ typedef struct { - 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 */ - g2_t *g2_values; /**< G2 group elements from the trusted setup; both arrays have FIELD_ELEMENTS_PER_BLOB elements */ + /** The corresponding settings for performing FFTs. */ + const FFTSettings *fs; + /** G1 group elements from the trusted setup, + * in Lagrange form bit-reversal permutation. */ + g1_t *g1_values; + /** G2 group elements from the trusted setup; + * both arrays have `FIELD_ELEMENTS_PER_BLOB` elements. */ + g2_t *g2_values; } KZGSettings; -/** - * Interface functions - */ +/////////////////////////////////////////////////////////////////////////////// +// Interface functions +/////////////////////////////////////////////////////////////////////////////// -C_KZG_RET load_trusted_setup(KZGSettings *out, - const uint8_t *g1_bytes, /* n1 * 48 bytes */ - size_t n1, - const uint8_t *g2_bytes, /* n2 * 96 bytes */ - size_t n2); +C_KZG_RET load_trusted_setup( + KZGSettings *out, + const uint8_t *g1_bytes, /* n1 * 48 bytes */ + size_t n1, + const uint8_t *g2_bytes, /* n2 * 96 bytes */ + size_t n2 +); -C_KZG_RET load_trusted_setup_file(KZGSettings *out, - FILE *in); +C_KZG_RET load_trusted_setup_file(KZGSettings *out, FILE *in); -void free_trusted_setup( - KZGSettings *s); +void free_trusted_setup(KZGSettings *s); -C_KZG_RET compute_aggregate_kzg_proof(KZGProof *out, - const Blob *blobs, - size_t n, - const KZGSettings *s); +C_KZG_RET compute_aggregate_kzg_proof( + KZGProof *out, const Blob *blobs, size_t n, const KZGSettings *s +); -C_KZG_RET verify_aggregate_kzg_proof(bool *out, - const Blob *blobs, - const Bytes48 *commitments_bytes, - size_t n, - const Bytes48 *aggregated_proof_bytes, - const KZGSettings *s); +C_KZG_RET verify_aggregate_kzg_proof( + bool *out, + const Blob *blobs, + const Bytes48 *commitments_bytes, + size_t n, + const Bytes48 *aggregated_proof_bytes, + const KZGSettings *s +); -C_KZG_RET blob_to_kzg_commitment(KZGCommitment *out, - const Blob *blob, - const KZGSettings *s); +C_KZG_RET blob_to_kzg_commitment( + KZGCommitment *out, const Blob *blob, const KZGSettings *s +); -C_KZG_RET verify_kzg_proof(bool *out, - const Bytes48 *commitment_bytes, - const Bytes32 *z_bytes, - const Bytes32 *y_bytes, - const Bytes48 *proof_bytes, - const KZGSettings *s); +C_KZG_RET verify_kzg_proof( + bool *out, + const Bytes48 *commitment_bytes, + const Bytes32 *z_bytes, + const Bytes32 *y_bytes, + const Bytes48 *proof_bytes, + const KZGSettings *s +); -C_KZG_RET compute_kzg_proof(KZGProof *out, - const Blob *blob, - const Bytes32 *z_bytes, - const KZGSettings *s); - -typedef struct { fr_t evals[FIELD_ELEMENTS_PER_BLOB]; } Polynomial; +C_KZG_RET compute_kzg_proof( + KZGProof *out, + const Blob *blob, + const Bytes32 *z_bytes, + const KZGSettings *s +); #ifdef UNIT_TESTS - void hash_to_bls_field(fr_t *out, const Bytes32 *b); void bytes_from_bls_field(Bytes32 *out, const fr_t *in); C_KZG_RET validate_kzg_g1(g1_t *out, const Bytes48 *b); void bytes_from_g1(Bytes48 *out, const g1_t *in); -C_KZG_RET evaluate_polynomial_in_evaluation_form(fr_t *out, const Polynomial *p, const fr_t *x, const KZGSettings *s); +C_KZG_RET evaluate_polynomial_in_evaluation_form( + fr_t *out, const Polynomial *p, const fr_t *x, const KZGSettings *s +); C_KZG_RET blob_to_polynomial(Polynomial *p, const Blob *blob); C_KZG_RET bytes_to_bls_field(fr_t *out, const Bytes32 *b); uint32_t reverse_bits(uint32_t a); void compute_powers(fr_t *out, fr_t *x, uint64_t n); int log_2_byte(byte b); - #endif #ifdef __cplusplus } #endif -#endif // C_KZG_4844_H +#endif /* C_KZG_4844_H */