Implement single polynomial commitment

This commit is contained in:
Ben Edgington 2021-02-04 21:23:34 +00:00
parent c68056638a
commit 686d1c5ca7
16 changed files with 266 additions and 8 deletions

View File

@ -7,6 +7,7 @@ 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
## Installation

View File

@ -1,5 +1,7 @@
TESTS = blst_util_test fft_common_test fft_fr_test fft_g1_test poly_test
LIB_SRC = poly.c blst_util.c fft_common.c fft_fr.c fft_g1.c
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
LIB_OBJ = $(LIB_SRC:.c=.o)
CFLAGS =

View File

@ -14,7 +14,9 @@
* limitations under the License.
*/
#include <stdlib.h>
#include "fft_common.h"
#include "blst_util.h"
bool is_power_of_two(const uint64_t n) {
return (n & (n - 1)) == 0;

View File

@ -14,9 +14,7 @@
* limitations under the License.
*/
#include <stdlib.h>
#include "c_kzg.h"
#include "blst_util.h"
// MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513
// PRIMITIVE_ROOT = 5

View File

@ -17,6 +17,7 @@
#include "../inc/acutest.h"
#include "debug_util.h"
#include "fft_common.h"
#include "blst_util.h"
#define NUM_ROOTS 32

View File

@ -15,6 +15,7 @@
*/
#include "fft_fr.h"
#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) {

View File

@ -17,6 +17,7 @@
#include "../inc/acutest.h"
#include "debug_util.h"
#include "fft_fr.h"
#include "blst_util.h"
const uint64_t inv_fft_expected[][4] =
{

View File

@ -15,6 +15,7 @@
*/
#include "fft_g1.h"
#include "blst_util.h"
// Slow Fourier Transform (simple, good for small sizes)
void fft_g1_slow(blst_p1 *out, blst_p1 *in, uint64_t stride, blst_fr *roots, uint64_t roots_stride, uint64_t l) {

28
src/kzg_common.c Normal file
View File

@ -0,0 +1,28 @@
/*
* 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_SUCCESS;
}

28
src/kzg_common.h Normal file
View File

@ -0,0 +1,28 @@
/*
* 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);

53
src/kzg_single_proofs.c Normal file
View File

@ -0,0 +1,53 @@
/*
* 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
void compute_proof_single(blst_p1 *out, const KZGSettings *ks, poly *p, const uint64_t x0) {
poly divisor, q;
blst_fr tmp;
// The divisor is x - x0
init_poly(&divisor, 2);
fr_from_uint64(&tmp, x0);
fr_negate(&divisor.coeffs[0],&tmp);
divisor.coeffs[1] = one;
// Calculate q = p / (x - x0)
init_poly(&q, poly_long_div_length(p->length, 2));
poly_long_div(&q, p, &divisor);
linear_combination_g1(out, ks->secret_g1, q.coeffs, q.length);
free_poly(q);
free_poly(divisor);
}
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);
}

23
src/kzg_single_proofs.h Normal file
View File

@ -0,0 +1,23 @@
/*
* 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 "kzg_common.h"
#include "poly.h"
void commit_to_poly(blst_p1 *out, const KZGSettings *ks, const poly *p);
void compute_proof_single(blst_p1 *out, const KZGSettings *ks, poly *p, const uint64_t x0);
bool check_proof_single(const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof, const blst_fr *x, blst_fr *y);

View File

@ -0,0 +1,74 @@
/*
* 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 = 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 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;
init_poly(&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);
compute_proof_single(&proof, &ks, &p, 17);
fr_from_uint64(&x, 17);
eval_poly_at(&value, &p, &x);
TEST_CHECK(true == check_proof_single(&ks, &commitment, &proof, &x, &value));
free(s1);
free(s2);
}
TEST_LIST =
{
{"proof_single", proof_single},
{ NULL, NULL } /* zero record marks the end of the list */
};

View File

@ -21,6 +21,31 @@ static void poly_factor_div(blst_fr *out, const blst_fr *a, const blst_fr *b) {
blst_fr_mul(out, out, a);
}
void init_poly(poly *out, const uint64_t length) {
out->length = length;
out->coeffs = malloc(length * sizeof(blst_fr));
}
void free_poly(poly p) {
free(p.coeffs);
}
void eval_poly_at(blst_fr *out, const poly *p, const blst_fr *x) {
blst_fr tmp;
if (p->length == 0) {
fr_from_uint64(out, 0);
}
// TODO x = 0 case
// Horner's method
*out = p->coeffs[p->length - 1];
for (int i = p->length - 2; i >= 0; i--) { // needs to be uint64_t?
blst_fr_mul(&tmp, out, x);
blst_fr_add(out, &tmp, &p->coeffs[i]);
}
}
// Call this to find out how much space to allocate for the result
uint64_t poly_long_div_length(const uint64_t len_dividend, const uint64_t len_divisor) {
return len_dividend - len_divisor + 1;

View File

@ -14,12 +14,17 @@
* limitations under the License.
*/
#include <stdlib.h> // malloc, free
#include "c_kzg.h"
#include "blst_util.h"
typedef struct {
blst_fr *coeffs; // coeffs[i] is the x^i term
uint64_t length; // one more than the polynomial's degree
} poly;
void init_poly(poly *out, const uint64_t length);
void free_poly(poly p);
void eval_poly_at(blst_fr *out, const poly *p, const blst_fr *x);
uint64_t poly_long_div_length(const uint64_t len_dividend, const uint64_t len_divisor);
C_KZG_RET poly_long_div(poly *out, const poly *dividend, const poly *divisor);

View File

@ -16,14 +16,13 @@
#include "../inc/acutest.h"
#include "debug_util.h"
#include "blst_util.h"
#include "poly.h"
void poly_div_length() {
void poly_div_length(void) {
TEST_CHECK(3 == poly_long_div_length(4, 2));
}
void poly_div_0() {
void poly_div_0(void) {
blst_fr a[3], b[2], c[2], expected[2];
poly dividend, divisor, actual;
@ -56,7 +55,7 @@ void poly_div_0() {
TEST_CHECK(fr_equal(&expected[1], &actual.coeffs[1]));
}
void poly_div_1() {
void poly_div_1(void) {
blst_fr a[4], b[2], c[3], expected[3];
poly dividend, divisor, actual;
@ -97,11 +96,27 @@ void poly_wrong_size(void) {
TEST_CHECK(poly_long_div(&result, &dividend, &divisor) == C_KZG_BADARGS);
}
void eval_poly(void) {
uint64_t n = 10;
blst_fr res, expected;
poly p;
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);
eval_poly_at(&res, &p, &one);
TEST_CHECK(fr_equal(&expected, &res));
}
TEST_LIST =
{
{"poly_div_length", poly_div_length},
{"poly_div_0", poly_div_0},
{"poly_div_1", poly_div_1},
{"poly_wrong_size", poly_wrong_size},
{"eval_poly", eval_poly},
{ NULL, NULL } /* zero record marks the end of the list */
};