Implement polynomial multi proofs
This commit is contained in:
parent
1ab4d08861
commit
6242338bd8
|
@ -7,7 +7,8 @@ Initially, at least, this largely follows the [go-kzg](https://github.com/protol
|
|||
Done so far:
|
||||
- FFT and inverse FFT over the finite field.
|
||||
- FFTs over the G1 group
|
||||
- Single polynomial commitment and verification
|
||||
- Polynomial single commitment and verification
|
||||
- Polynomial multi commitment and verification
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
TESTS = blst_util_test fft_common_test fft_fr_test fft_g1_test \
|
||||
kzg_single_proofs_test poly_test
|
||||
LIB_SRC = blst_util.c fft_common.c fft_fr.c fft_g1.c kzg_common.c \
|
||||
kzg_single_proofs.c poly.c
|
||||
kzg_proofs_test poly_test
|
||||
LIB_SRC = blst_util.c fft_common.c fft_fr.c fft_g1.c kzg_proofs.c poly.c
|
||||
LIB_OBJ = $(LIB_SRC:.c=.o)
|
||||
|
||||
CFLAGS =
|
||||
|
|
|
@ -47,6 +47,19 @@ void fr_negate(blst_fr *out, const blst_fr *in) {
|
|||
blst_fr_cneg(out, in, true);
|
||||
}
|
||||
|
||||
void fr_pow(blst_fr *out, const blst_fr *a, uint64_t n) {
|
||||
blst_fr tmp = *a;
|
||||
*out = fr_one;
|
||||
|
||||
while (true) {
|
||||
if (n & 1) {
|
||||
blst_fr_mul(out, out, &tmp);
|
||||
}
|
||||
if ((n >>= 1) == 0) break;
|
||||
blst_fr_sqr(&tmp, &tmp);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Is there really no better way to do this?
|
||||
void p1_mul(blst_p1 *out, const blst_p1 *a, const blst_fr *b) {
|
||||
blst_scalar s;
|
||||
|
|
|
@ -30,6 +30,7 @@ bool fr_is_one(const blst_fr *p);
|
|||
void fr_from_uint64(blst_fr *a, const uint64_t n);
|
||||
bool fr_equal(const blst_fr *aa, const blst_fr *bb);
|
||||
void fr_negate(blst_fr *out, const blst_fr *in);
|
||||
void fr_pow(blst_fr *out, const blst_fr *a, const uint64_t n);
|
||||
void p1_mul(blst_p1 *out, const blst_p1 *a, const blst_fr *b);
|
||||
void p1_sub(blst_p1 *out, const blst_p1 *a, const blst_p1 *b);
|
||||
void p2_mul(blst_p2 *out, const blst_p2 *a, const blst_fr *b);
|
||||
|
|
|
@ -57,6 +57,24 @@ void fr_negate_works(void) {
|
|||
TEST_CHECK(fr_is_one(&res));
|
||||
}
|
||||
|
||||
void fr_pow_works(void) {
|
||||
// a^pow
|
||||
uint64_t pow = 123456;
|
||||
blst_fr a, expected, actual;
|
||||
fr_from_uint64(&a, 197);
|
||||
|
||||
// Do it the slow way
|
||||
expected = fr_one;
|
||||
for (uint64_t i = 0; i < pow; i++) {
|
||||
blst_fr_mul(&expected, &expected, &a);
|
||||
}
|
||||
|
||||
// Do it the quick way
|
||||
fr_pow(&actual, &a, pow);
|
||||
|
||||
TEST_CHECK(fr_equal(&expected, &actual));
|
||||
}
|
||||
|
||||
void p1_mul_works(void) {
|
||||
blst_fr minus1;
|
||||
blst_p1 g1_gen, g1_gen_neg, res;
|
||||
|
@ -167,6 +185,7 @@ TEST_LIST =
|
|||
{"fr_from_uint64_works", fr_from_uint64_works},
|
||||
{"fr_equal_works", fr_equal_works},
|
||||
{"fr_negate_works", fr_negate_works},
|
||||
{"fr_pow_works", fr_pow_works},
|
||||
{"p1_mul_works", p1_mul_works},
|
||||
{"p1_sub_works", p1_sub_works},
|
||||
{"p2_mul_works", p2_mul_works},
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "blst_util.h"
|
||||
|
||||
// Slow Fourier Transform (simple, good for small sizes)
|
||||
void fft_fr_slow(blst_fr *out, blst_fr *in, uint64_t stride, blst_fr *roots, uint64_t roots_stride, uint64_t l) {
|
||||
void fft_fr_slow(blst_fr *out, const blst_fr *in, uint64_t stride, const blst_fr *roots, uint64_t roots_stride, uint64_t l) {
|
||||
blst_fr v, last, jv, r;
|
||||
for (uint64_t i = 0; i < l; i++) {
|
||||
blst_fr_mul(&last, &in[0], &roots[0]);
|
||||
|
@ -33,7 +33,7 @@ void fft_fr_slow(blst_fr *out, blst_fr *in, uint64_t stride, blst_fr *roots, uin
|
|||
}
|
||||
|
||||
// Fast Fourier Transform
|
||||
void fft_fr_fast(blst_fr *out, blst_fr *in, uint64_t stride, blst_fr *roots, uint64_t roots_stride, uint64_t l) {
|
||||
void fft_fr_fast(blst_fr *out, const blst_fr *in, uint64_t stride, const blst_fr *roots, uint64_t roots_stride, uint64_t l) {
|
||||
uint64_t half = l / 2;
|
||||
if (half > 2) { // TODO: Tunable parameter
|
||||
fft_fr_fast(out, in, stride * 2, roots, roots_stride * 2, half);
|
||||
|
@ -51,7 +51,7 @@ void fft_fr_fast(blst_fr *out, blst_fr *in, uint64_t stride, blst_fr *roots, uin
|
|||
}
|
||||
|
||||
// The main entry point for forward and reverse FFTs
|
||||
C_KZG_RET fft_fr (blst_fr *out, blst_fr *in, FFTSettings *fs, bool inv, uint64_t n) {
|
||||
C_KZG_RET fft_fr (blst_fr *out, const blst_fr *in, const FFTSettings *fs, bool inv, uint64_t n) {
|
||||
uint64_t stride = fs->max_width / n;
|
||||
ASSERT(n <= fs->max_width, C_KZG_BADARGS);
|
||||
ASSERT(is_power_of_two(n), C_KZG_BADARGS);
|
||||
|
|
|
@ -17,6 +17,6 @@
|
|||
#include "c_kzg.h"
|
||||
#include "fft_common.h"
|
||||
|
||||
void fft_fr_slow(blst_fr *out, blst_fr *in, uint64_t stride, blst_fr *roots, uint64_t roots_stride, uint64_t l);
|
||||
void fft_fr_fast(blst_fr *out, blst_fr *in, uint64_t stride, blst_fr *roots, uint64_t roots_stride, uint64_t l);
|
||||
C_KZG_RET fft_fr (blst_fr *out, blst_fr *in, FFTSettings *fs, bool inv, uint64_t n);
|
||||
void fft_fr_slow(blst_fr *out, const blst_fr *in, uint64_t stride, const blst_fr *roots, uint64_t roots_stride, uint64_t l);
|
||||
void fft_fr_fast(blst_fr *out, const blst_fr *in, uint64_t stride, const blst_fr *roots, uint64_t roots_stride, uint64_t l);
|
||||
C_KZG_RET fft_fr (blst_fr *out, const blst_fr *in, const FFTSettings *fs, bool inv, uint64_t n);
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 Benjamin Edgington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "kzg_common.h"
|
||||
|
||||
C_KZG_RET new_kzg_settings(KZGSettings *ks, FFTSettings *fs, blst_p1 *secret_g1, blst_p2 *secret_g2, uint64_t length) {
|
||||
ASSERT(length >= fs->max_width, C_KZG_BADARGS);
|
||||
ks->fs = fs;
|
||||
ks->secret_g1 = secret_g1;
|
||||
ks->extended_secret_g1 = NULL;
|
||||
ks->secret_g2 = secret_g2;
|
||||
ks->length = length;
|
||||
return C_KZG_OK;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 Benjamin Edgington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "c_kzg.h"
|
||||
#include "fft_common.h"
|
||||
|
||||
typedef struct {
|
||||
FFTSettings *fs;
|
||||
blst_p1 *secret_g1;
|
||||
blst_p1 *extended_secret_g1;
|
||||
blst_p2 *secret_g2;
|
||||
uint64_t length;
|
||||
} KZGSettings;
|
||||
|
||||
C_KZG_RET new_kzg_settings(KZGSettings *ks, FFTSettings *fs, blst_p1 *secret_g1, blst_p2 *secret_g2, uint64_t length);
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright 2021 Benjamin Edgington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "kzg_proofs.h"
|
||||
|
||||
C_KZG_RET new_kzg_settings(KZGSettings *ks, FFTSettings *fs, blst_p1 *secret_g1, blst_p2 *secret_g2, uint64_t length) {
|
||||
ASSERT(length >= fs->max_width, C_KZG_BADARGS);
|
||||
ks->fs = fs;
|
||||
ks->secret_g1 = secret_g1;
|
||||
ks->extended_secret_g1 = NULL;
|
||||
ks->secret_g2 = secret_g2;
|
||||
ks->length = length;
|
||||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
void commit_to_poly(blst_p1 *out, const KZGSettings *ks, const poly *p) {
|
||||
linear_combination_g1(out, ks->secret_g1, p->coeffs, p->length);
|
||||
}
|
||||
|
||||
// Compute KZG proof for polynomial at position x0
|
||||
C_KZG_RET compute_proof_single(blst_p1 *out, const KZGSettings *ks, poly *p, const blst_fr *x0) {
|
||||
return compute_proof_multi(out, ks, p, x0, 1);
|
||||
}
|
||||
|
||||
bool check_proof_single(const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof, const blst_fr *x, blst_fr *y) {
|
||||
blst_p2 x_g2, s_minus_x;
|
||||
blst_p1 y_g1, commitment_minus_y;
|
||||
p2_mul(&x_g2, blst_p2_generator(), x);
|
||||
p2_sub(&s_minus_x, &ks->secret_g2[1], &x_g2);
|
||||
p1_mul(&y_g1, blst_p1_generator(), y);
|
||||
p1_sub(&commitment_minus_y, commitment, &y_g1);
|
||||
|
||||
return pairings_verify(&commitment_minus_y, blst_p2_generator(), proof, &s_minus_x);
|
||||
}
|
||||
|
||||
// Compute KZG proof for polynomial in coefficient form at positions x * w^y where w is
|
||||
// an n-th root of unity (this is the proof for one data availability sample, which consists
|
||||
// of several polynomial evaluations)
|
||||
C_KZG_RET compute_proof_multi(blst_p1 *out, const KZGSettings *ks, poly *p, const blst_fr *x0, uint64_t n) {
|
||||
poly divisor, q;
|
||||
uint64_t len;
|
||||
blst_fr x_pow_n;
|
||||
|
||||
ASSERT(p->length >= n + 1, C_KZG_BADARGS);
|
||||
|
||||
// Construct x^n - x0^n
|
||||
init_poly(&divisor, n + 1);
|
||||
|
||||
// -(x0^n)
|
||||
fr_pow(&x_pow_n, x0, n);
|
||||
fr_negate(&divisor.coeffs[0], &x_pow_n);
|
||||
|
||||
// Zeros
|
||||
for (uint64_t i = 1; i < n; i++) {
|
||||
divisor.coeffs[i] = fr_zero;
|
||||
}
|
||||
|
||||
// x^n
|
||||
divisor.coeffs[n] = fr_one;
|
||||
|
||||
// Calculate q = p / (x^n - x0^n)
|
||||
// Discard the return codes since we already checked above that all should be fine.
|
||||
poly_quotient_length(&len, p, &divisor);
|
||||
init_poly(&q, len);
|
||||
poly_long_div(&q, p, &divisor);
|
||||
|
||||
commit_to_poly(out, ks, &q);
|
||||
|
||||
free_poly(q);
|
||||
free_poly(divisor);
|
||||
|
||||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
// Check a proof for a KZG commitment for an evaluation f(x w^i) = y_i
|
||||
// The ys must have a power of 2 length
|
||||
bool check_proof_multi(const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof, const blst_fr *x, const blst_fr *ys, uint64_t n) {
|
||||
poly interp;
|
||||
blst_fr inv_x, inv_x_pow, x_pow;
|
||||
blst_p2 xn2, xn_minus_yn;
|
||||
blst_p1 is1, commit_minus_interp;
|
||||
//C_KZG_RET ret; // TODO - error handling
|
||||
|
||||
// Interpolate at a coset.
|
||||
init_poly(&interp, n);
|
||||
fft_fr(interp.coeffs, ys, ks->fs, true, n);
|
||||
// if (ret != C_KZG_OK) return ret;
|
||||
|
||||
// Because it is a coset, not the subgroup, we have to multiply the polynomial coefficients by x^i
|
||||
blst_fr_eucl_inverse(&inv_x, x);
|
||||
inv_x_pow = inv_x;
|
||||
for (uint64_t i = 1; i < n; i++) {
|
||||
blst_fr_mul(&interp.coeffs[i], &interp.coeffs[i], &inv_x_pow);
|
||||
blst_fr_mul(&inv_x_pow, &inv_x_pow, &inv_x);
|
||||
}
|
||||
|
||||
// [x^n]_2
|
||||
blst_fr_eucl_inverse(&x_pow, &inv_x_pow);
|
||||
p2_mul(&xn2, blst_p2_generator(), &x_pow);
|
||||
|
||||
// [s^n - x^n]_2
|
||||
p2_sub(&xn_minus_yn, &ks->secret_g2[n], &xn2);
|
||||
|
||||
// [interpolation_polynomial(s)]_1
|
||||
commit_to_poly(&is1, ks, &interp);
|
||||
|
||||
// [commitment - interpolation_polynomial(s)]_1 = [commit]_1 - [interpolation_polynomial(s)]_1
|
||||
p1_sub(&commit_minus_interp, commitment, &is1);
|
||||
|
||||
return pairings_verify(&commit_minus_interp, blst_p2_generator(), proof, &xn_minus_yn);
|
||||
}
|
|
@ -15,9 +15,20 @@
|
|||
*/
|
||||
|
||||
#include "c_kzg.h"
|
||||
#include "kzg_common.h"
|
||||
#include "fft_fr.h"
|
||||
#include "poly.h"
|
||||
|
||||
typedef struct {
|
||||
FFTSettings *fs;
|
||||
blst_p1 *secret_g1;
|
||||
blst_p1 *extended_secret_g1;
|
||||
blst_p2 *secret_g2;
|
||||
uint64_t length;
|
||||
} KZGSettings;
|
||||
|
||||
C_KZG_RET new_kzg_settings(KZGSettings *ks, FFTSettings *fs, blst_p1 *secret_g1, blst_p2 *secret_g2, uint64_t length);
|
||||
void commit_to_poly(blst_p1 *out, const KZGSettings *ks, const poly *p);
|
||||
C_KZG_RET compute_proof_single(blst_p1 *out, const KZGSettings *ks, poly *p, const uint64_t x0);
|
||||
C_KZG_RET compute_proof_single(blst_p1 *out, const KZGSettings *ks, poly *p, const blst_fr *x0);
|
||||
bool check_proof_single(const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof, const blst_fr *x, blst_fr *y);
|
||||
C_KZG_RET compute_proof_multi(blst_p1 *out, const KZGSettings *ks, poly *p, const blst_fr *x0, uint64_t n);
|
||||
bool check_proof_multi(const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof, const blst_fr *x, const blst_fr *ys, uint64_t n);
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright 2021 Benjamin Edgington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "../inc/acutest.h"
|
||||
#include "debug_util.h"
|
||||
#include "kzg_proofs.h"
|
||||
|
||||
// The generator for our "trusted" setup
|
||||
blst_scalar secret =
|
||||
{
|
||||
0xa4, 0x73, 0x31, 0x95, 0x28, 0xc8, 0xb6, 0xea,
|
||||
0x4d, 0x08, 0xcc, 0x53, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
}; // Little-endian?
|
||||
|
||||
void generate_setup(blst_p1 *s1, blst_p2 *s2, const blst_scalar *secret, const uint64_t n) {
|
||||
blst_fr s_pow, s;
|
||||
blst_fr_from_scalar(&s, secret);
|
||||
s_pow = fr_one;
|
||||
for (uint64_t i = 0; i < n; i++) {
|
||||
p1_mul(&s1[i], blst_p1_generator(), &s_pow);
|
||||
p2_mul(&s2[i], blst_p2_generator(), &s_pow);
|
||||
blst_fr_mul(&s_pow, &s_pow, &s);
|
||||
}
|
||||
}
|
||||
|
||||
void title(void) {;}
|
||||
|
||||
void proof_single(void) {
|
||||
// Our polynomial: degree 15, 16 coefficients
|
||||
uint64_t coeffs[] = {1, 2, 3, 4, 7, 7, 7, 7, 13, 13, 13, 13, 13, 13, 13, 13};
|
||||
int poly_len = sizeof coeffs / sizeof coeffs[0];
|
||||
uint64_t secrets_len = poly_len + 1;
|
||||
|
||||
FFTSettings fs;
|
||||
KZGSettings ks;
|
||||
poly p;
|
||||
blst_p1 commitment, proof;
|
||||
blst_p1 *s1 = malloc(secrets_len * sizeof(blst_p1));
|
||||
blst_p2 *s2 = malloc(secrets_len * sizeof(blst_p2));
|
||||
blst_fr x, value;
|
||||
|
||||
// Create the polynomial
|
||||
init_poly(&p, poly_len);
|
||||
for (int i = 0; i < poly_len; i++) {
|
||||
fr_from_uint64(&p.coeffs[i], coeffs[i]);
|
||||
}
|
||||
|
||||
// Initialise the secrets and data structures
|
||||
generate_setup(s1, s2, &secret, secrets_len);
|
||||
TEST_CHECK(C_KZG_OK == new_fft_settings(&fs, 4)); // ln_2 of poly_len
|
||||
TEST_CHECK(C_KZG_OK == new_kzg_settings(&ks, &fs, s1, s2, secrets_len));
|
||||
|
||||
// Compute the proof for x = 25
|
||||
fr_from_uint64(&x, 25);
|
||||
commit_to_poly(&commitment, &ks, &p);
|
||||
TEST_CHECK(C_KZG_OK == compute_proof_single(&proof, &ks, &p, &x));
|
||||
|
||||
// Verify the proof for x = 25
|
||||
eval_poly(&value, &p, &x);
|
||||
TEST_CHECK(true == check_proof_single(&ks, &commitment, &proof, &x, &value));
|
||||
|
||||
free_fft_settings(&fs);
|
||||
free_poly(p);
|
||||
free(s1);
|
||||
free(s2);
|
||||
}
|
||||
|
||||
void proof_multi(void) {
|
||||
// Our polynomial: degree 15, 16 coefficients
|
||||
uint64_t coeffs[] = {1, 2, 3, 4, 7, 7, 7, 7, 13, 13, 13, 13, 13, 13, 13, 13};
|
||||
int poly_len = sizeof coeffs / sizeof coeffs[0];
|
||||
uint64_t secrets_len = poly_len + 1;
|
||||
|
||||
FFTSettings fs1, fs2;
|
||||
KZGSettings ks1, ks2;
|
||||
poly p;
|
||||
blst_p1 commitment, proof;
|
||||
blst_p1 *s1 = malloc(secrets_len * sizeof(blst_p1));
|
||||
blst_p2 *s2 = malloc(secrets_len * sizeof(blst_p2));
|
||||
blst_fr x, tmp;
|
||||
int coset_scale = 3, coset_len = (1 << coset_scale); // Where do these come from?
|
||||
blst_fr ys[coset_len];
|
||||
|
||||
// Create the polynomial
|
||||
init_poly(&p, poly_len);
|
||||
for (int i = 0; i < poly_len; i++) {
|
||||
fr_from_uint64(&p.coeffs[i], coeffs[i]);
|
||||
}
|
||||
|
||||
// Initialise the secrets and data structures
|
||||
generate_setup(s1, s2, &secret, secrets_len);
|
||||
TEST_CHECK(C_KZG_OK == new_fft_settings(&fs1, 4)); // ln_2 of poly_len
|
||||
TEST_CHECK(C_KZG_OK == new_kzg_settings(&ks1, &fs1, s1, s2, secrets_len));
|
||||
|
||||
// Commit to the polynomial
|
||||
commit_to_poly(&commitment, &ks1, &p);
|
||||
|
||||
TEST_CHECK(C_KZG_OK == new_fft_settings(&fs2, coset_scale));
|
||||
TEST_CHECK(C_KZG_OK == new_kzg_settings(&ks2, &fs2, s1, s2, secrets_len));
|
||||
|
||||
// Compute proof at the points [x * root_i] 0 <= i < coset_len
|
||||
fr_from_uint64(&x, 5431);
|
||||
TEST_CHECK(C_KZG_OK == compute_proof_multi(&proof, &ks2, &p, &x, coset_len));
|
||||
|
||||
// The ys are the values of the polynomial at the points above
|
||||
for (int i = 0; i < coset_len; i++) {
|
||||
blst_fr_mul(&tmp, &x, &ks2.fs->expanded_roots_of_unity[i]);
|
||||
eval_poly(&ys[i], &p, &tmp);
|
||||
}
|
||||
|
||||
// Verify the proof
|
||||
TEST_CHECK(check_proof_multi(&ks2, &commitment, &proof, &x, ys, coset_len));
|
||||
|
||||
free_fft_settings(&fs1);
|
||||
free_fft_settings(&fs2);
|
||||
free_poly(p);
|
||||
free(s1);
|
||||
free(s2);
|
||||
}
|
||||
|
||||
void proof_single_error(void) {
|
||||
poly p;
|
||||
blst_p1 proof;
|
||||
KZGSettings ks;
|
||||
blst_fr x;
|
||||
|
||||
// Check it barfs on a constant polynomial
|
||||
init_poly(&p, 1);
|
||||
|
||||
fr_from_uint64(&x, 1234);
|
||||
TEST_CHECK(C_KZG_BADARGS == compute_proof_single(&proof, &ks, &p, &x));
|
||||
|
||||
free_poly(p);
|
||||
}
|
||||
|
||||
TEST_LIST =
|
||||
{
|
||||
{"KZG_PROOFS_TEST", title},
|
||||
{"proof_single", proof_single},
|
||||
{"proof_multi", proof_multi},
|
||||
{"proof_single_error", proof_single},
|
||||
{ NULL, NULL } /* zero record marks the end of the list */
|
||||
};
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 Benjamin Edgington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "kzg_single_proofs.h"
|
||||
|
||||
void commit_to_poly(blst_p1 *out, const KZGSettings *ks, const poly *p) {
|
||||
linear_combination_g1(out, ks->secret_g1, p->coeffs, p->length);
|
||||
}
|
||||
|
||||
// Compute KZG proof for polynomial at position x0
|
||||
C_KZG_RET compute_proof_single(blst_p1 *out, const KZGSettings *ks, poly *p, const uint64_t x0) {
|
||||
poly divisor, q;
|
||||
blst_fr tmp;
|
||||
uint64_t len;
|
||||
|
||||
ASSERT(p->length >= 2, C_KZG_BADARGS);
|
||||
|
||||
// The divisor is x - x0
|
||||
poly_init(&divisor, 2);
|
||||
fr_from_uint64(&tmp, x0);
|
||||
fr_negate(&divisor.coeffs[0],&tmp);
|
||||
divisor.coeffs[1] = fr_one;
|
||||
|
||||
// Calculate q = p / (x - x0)
|
||||
// Discard the return codes since we already checked above that all should be fine.
|
||||
(void) poly_quotient_length(&len, p, &divisor);
|
||||
poly_init(&q, len);
|
||||
(void) poly_long_div(&q, p, &divisor);
|
||||
|
||||
linear_combination_g1(out, ks->secret_g1, q.coeffs, q.length);
|
||||
|
||||
poly_free(q);
|
||||
poly_free(divisor);
|
||||
|
||||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
bool check_proof_single(const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof, const blst_fr *x, blst_fr *y) {
|
||||
blst_p2 x_g2, s_minus_x;
|
||||
blst_p1 y_g1, commitment_minus_y;
|
||||
p2_mul(&x_g2, blst_p2_generator(), x);
|
||||
p2_sub(&s_minus_x, &ks->secret_g2[1], &x_g2);
|
||||
p1_mul(&y_g1, blst_p1_generator(), y);
|
||||
p1_sub(&commitment_minus_y, commitment, &y_g1);
|
||||
|
||||
return pairings_verify(&commitment_minus_y, blst_p2_generator(), proof, &s_minus_x);
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 Benjamin Edgington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "../inc/acutest.h"
|
||||
#include "debug_util.h"
|
||||
#include "kzg_single_proofs.h"
|
||||
|
||||
void generate_setup(blst_p1 *s1, blst_p2 *s2, const blst_scalar *secret, const uint64_t n) {
|
||||
blst_fr s_pow, s;
|
||||
blst_fr_from_scalar(&s, secret);
|
||||
s_pow = fr_one;
|
||||
for (uint64_t i = 0; i < n; i++) {
|
||||
p1_mul(&s1[i], blst_p1_generator(), &s_pow);
|
||||
p2_mul(&s2[i], blst_p2_generator(), &s_pow);
|
||||
blst_fr_mul(&s_pow, &s_pow, &s);
|
||||
}
|
||||
}
|
||||
|
||||
void title(void) {;}
|
||||
|
||||
void proof_single(void) {
|
||||
FFTSettings fs;
|
||||
KZGSettings ks;
|
||||
poly p;
|
||||
blst_p1 commitment, proof;
|
||||
blst_p1 *s1 = malloc(17 * sizeof(blst_p1));
|
||||
blst_p2 *s2 = malloc(17 * sizeof(blst_p2));
|
||||
blst_scalar secret =
|
||||
{
|
||||
0xa4, 0x73, 0x31, 0x95, 0x28, 0xc8, 0xb6, 0xea,
|
||||
0x4d, 0x08,0xcc, 0x53, 0x18, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
}; // Little-endian?
|
||||
uint64_t coeffs_u[16] = {1, 2, 3, 4, 7, 7, 7, 7, 13, 13, 13, 13, 13, 13, 13, 13};
|
||||
blst_fr x, value;
|
||||
|
||||
poly_init(&p, 16);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
fr_from_uint64(&p.coeffs[i], coeffs_u[i]);
|
||||
}
|
||||
|
||||
generate_setup(s1, s2, &secret, 17);
|
||||
new_fft_settings(&fs, 4);
|
||||
new_kzg_settings(&ks, &fs, s1, s2, 17);
|
||||
|
||||
commit_to_poly(&commitment, &ks, &p);
|
||||
TEST_CHECK(C_KZG_OK == compute_proof_single(&proof, &ks, &p, 17));
|
||||
|
||||
fr_from_uint64(&x, 17);
|
||||
poly_eval(&value, &p, &x);
|
||||
|
||||
TEST_CHECK(true == check_proof_single(&ks, &commitment, &proof, &x, &value));
|
||||
|
||||
free(s1);
|
||||
free(s2);
|
||||
}
|
||||
|
||||
void proof_single_error(void) {
|
||||
poly p;
|
||||
blst_p1 proof;
|
||||
KZGSettings ks;
|
||||
|
||||
// Check it barfs on a constant polynomial
|
||||
poly_init(&p, 1);
|
||||
|
||||
TEST_CHECK(C_KZG_BADARGS == compute_proof_single(&proof, &ks, &p, 17));
|
||||
|
||||
poly_free(p);
|
||||
}
|
||||
|
||||
TEST_LIST =
|
||||
{
|
||||
{"KZG_SINGLE_PRROFS_TEST", title},
|
||||
{"proof_single", proof_single},
|
||||
{"proof_single_error", proof_single},
|
||||
{ NULL, NULL } /* zero record marks the end of the list */
|
||||
};
|
|
@ -21,16 +21,16 @@ static void poly_factor_div(blst_fr *out, const blst_fr *a, const blst_fr *b) {
|
|||
blst_fr_mul(out, out, a);
|
||||
}
|
||||
|
||||
void poly_init(poly *out, const uint64_t length) {
|
||||
void init_poly(poly *out, const uint64_t length) {
|
||||
out->length = length;
|
||||
out->coeffs = malloc(length * sizeof(blst_fr));
|
||||
}
|
||||
|
||||
void poly_free(poly p) {
|
||||
void free_poly(poly p) {
|
||||
free(p.coeffs);
|
||||
}
|
||||
|
||||
void poly_eval(blst_fr *out, const poly *p, const blst_fr *x) {
|
||||
void eval_poly(blst_fr *out, const poly *p, const blst_fr *x) {
|
||||
blst_fr tmp;
|
||||
uint64_t i;
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@ typedef struct {
|
|||
uint64_t length; // one more than the polynomial's degree
|
||||
} poly;
|
||||
|
||||
void poly_init(poly *out, const uint64_t length);
|
||||
void poly_free(poly p);
|
||||
void poly_eval(blst_fr *out, const poly *p, const blst_fr *x);
|
||||
void init_poly(poly *out, const uint64_t length);
|
||||
void free_poly(poly p);
|
||||
void eval_poly(blst_fr *out, const poly *p, const blst_fr *x);
|
||||
C_KZG_RET poly_quotient_length(uint64_t *out, const poly *dividend, const poly *divisor);
|
||||
C_KZG_RET poly_long_div(poly *out, const poly *dividend, const poly *divisor);
|
||||
|
|
|
@ -23,8 +23,8 @@ void title(void) {;}
|
|||
void poly_div_length(void) {
|
||||
poly a, b;
|
||||
uint64_t len;
|
||||
poly_init(&a, 17);
|
||||
poly_init(&b, 5);
|
||||
init_poly(&a, 17);
|
||||
init_poly(&b, 5);
|
||||
TEST_CHECK(C_KZG_OK == poly_quotient_length(&len, &a, &b));
|
||||
TEST_CHECK(13 == len);
|
||||
}
|
||||
|
@ -32,8 +32,8 @@ void poly_div_length(void) {
|
|||
void poly_div_length_bad(void) {
|
||||
poly a, b;
|
||||
uint64_t len;
|
||||
poly_init(&a, 5);
|
||||
poly_init(&b, 17);
|
||||
init_poly(&a, 5);
|
||||
init_poly(&b, 17);
|
||||
TEST_CHECK(C_KZG_BADARGS == poly_quotient_length(&len, &a, &b));
|
||||
}
|
||||
|
||||
|
@ -115,13 +115,13 @@ void poly_eval_check(void) {
|
|||
uint64_t n = 10;
|
||||
blst_fr res, expected;
|
||||
poly p;
|
||||
poly_init(&p, n);
|
||||
init_poly(&p, n);
|
||||
for (uint64_t i = 0; i < n; i++) {
|
||||
fr_from_uint64(&p.coeffs[i], i + 1);
|
||||
}
|
||||
fr_from_uint64(&expected, n * (n + 1) / 2);
|
||||
|
||||
poly_eval(&res, &p, &fr_one);
|
||||
eval_poly(&res, &p, &fr_one);
|
||||
|
||||
TEST_CHECK(fr_equal(&expected, &res));
|
||||
}
|
||||
|
@ -130,13 +130,13 @@ void poly_eval_0_check(void) {
|
|||
uint64_t n = 7, a = 597;
|
||||
blst_fr res, expected;
|
||||
poly p;
|
||||
poly_init(&p, n);
|
||||
init_poly(&p, n);
|
||||
for (uint64_t i = 0; i < n; i++) {
|
||||
fr_from_uint64(&p.coeffs[i], i + a);
|
||||
}
|
||||
fr_from_uint64(&expected, a);
|
||||
|
||||
poly_eval(&res, &p, &fr_zero);
|
||||
eval_poly(&res, &p, &fr_zero);
|
||||
|
||||
TEST_CHECK(fr_equal(&expected, &res));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue