Simplify `fr_batch_inv` and reject zero inputs (#215)

This commit is contained in:
George Kadianakis 2023-03-16 19:52:59 +02:00 committed by GitHub
parent 2ba8f35dc4
commit 903a13fb98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 26 deletions

View File

@ -254,6 +254,20 @@ static bool fr_is_one(const fr_t *p) {
return a[0] == 1 && a[1] == 0 && a[2] == 0 && a[3] == 0;
}
/**
* Test whether the operand is zero in the finite field.
*
* @param[in] p The field element to be checked
*
* @retval true The element is zero
* @retval false The element is not zero
*/
static bool fr_is_zero(const fr_t *p) {
uint64_t a[4];
blst_uint64_from_fr(a, p);
return a[0] == 0 && a[1] == 0 && a[2] == 0 && a[3] == 0;
}
/**
* Test whether two field elements are equal.
*
@ -332,42 +346,43 @@ static void fr_from_uint64(fr_t *out, uint64_t n) {
/**
* Montgomery batch inversion in finite field.
*
* @remark Return C_KZG_BADARGS if a zero is found in the input.
*
* @remark This function does not support in-place computation (i.e. `a` MUST
* NOT point to the same place as `out`)
*
* @remark This function only supports len > 0.
*
* @param[out] out The inverses of @p a, length @p len
* @param[in] a A vector of field elements, length @p len
* @param[in] len The number of field elements
*/
static C_KZG_RET fr_batch_inv(fr_t *out, const fr_t *a, size_t len) {
C_KZG_RET ret;
fr_t *prod = NULL;
fr_t inv;
size_t i;
static C_KZG_RET fr_batch_inv(fr_t *out, const fr_t *a, int len) {
int i;
assert(len > 0);
assert(a != out);
ret = new_fr_array(&prod, len);
if (ret != C_KZG_OK) goto out;
fr_t accumulator = FR_ONE;
prod[0] = a[0];
for (i = 1; i < len; i++) {
blst_fr_mul(&prod[i], &a[i], &prod[i - 1]);
for (i = 0; i < len; i++) {
out[i] = accumulator;
blst_fr_mul(&accumulator, &accumulator, &a[i]);
}
blst_fr_eucl_inverse(&inv, &prod[len - 1]);
for (i = len - 1; i > 0; i--) {
blst_fr_mul(&out[i], &inv, &prod[i - 1]);
blst_fr_mul(&inv, &a[i], &inv);
/* Bail on any zero input */
if (fr_is_zero(&accumulator)) {
return C_KZG_BADARGS;
}
out[0] = inv;
out:
c_kzg_free(prod);
return ret;
blst_fr_eucl_inverse(&accumulator, &accumulator);
for (i = len - 1; i >= 0; i--) {
blst_fr_mul(&out[i], &out[i], &accumulator);
blst_fr_mul(&accumulator, &accumulator, &a[i]);
}
return C_KZG_OK;
}
/**

View File

@ -287,6 +287,7 @@ static void test_fr_batch_inv__test_consistent(void) {
}
}
/** Make sure that batch inverse doesn't support zeroes */
static void test_fr_batch_inv__test_zero(void) {
C_KZG_RET ret;
fr_t a[32], batch_inverses[32];
@ -298,12 +299,7 @@ static void test_fr_batch_inv__test_zero(void) {
a[5] = FR_ZERO;
ret = fr_batch_inv(batch_inverses, a, 32);
ASSERT_EQUALS(ret, C_KZG_OK);
for (size_t i = 0; i < 32; i++) {
bool ok = fr_equal(&batch_inverses[i], &FR_ZERO);
ASSERT_EQUALS(ok, true);
}
ASSERT_EQUALS(ret, C_KZG_BADARGS);
}
///////////////////////////////////////////////////////////////////////////////