Implement single polynomial commitment
This commit is contained in:
parent
c68056638a
commit
686d1c5ca7
|
@ -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
|
||||
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -14,9 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "c_kzg.h"
|
||||
#include "blst_util.h"
|
||||
|
||||
// MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513
|
||||
// PRIMITIVE_ROOT = 5
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "../inc/acutest.h"
|
||||
#include "debug_util.h"
|
||||
#include "fft_common.h"
|
||||
#include "blst_util.h"
|
||||
|
||||
#define NUM_ROOTS 32
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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] =
|
||||
{
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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 */
|
||||
};
|
25
src/poly.c
25
src/poly.c
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, ÷nd, &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 */
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue