Add FK20 single proofs
This commit is contained in:
parent
8986f1cde3
commit
f476a0f6ce
|
@ -2,6 +2,7 @@
|
||||||
*.a
|
*.a
|
||||||
*_test
|
*_test
|
||||||
*_bench
|
*_bench
|
||||||
|
*_debug
|
||||||
*.prof
|
*.prof
|
||||||
*.out
|
*.out
|
||||||
*.log
|
*.log
|
||||||
|
|
13
README.md
13
README.md
|
@ -9,6 +9,7 @@ Done so far:
|
||||||
- FFTs over the G1 group
|
- FFTs over the G1 group
|
||||||
- Polynomial single commitment and verification
|
- Polynomial single commitment and verification
|
||||||
- Polynomial multi commitment and verification
|
- Polynomial multi commitment and verification
|
||||||
|
- [FK20](https://github.com/khovratovich/Kate/blob/master/Kate_amortized.pdf) single proof method (needs a tidy up)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
@ -69,8 +70,20 @@ make fft_fr_bench
|
||||||
|
|
||||||
Doing `make clean` should resolve any weird build issues.
|
Doing `make clean` should resolve any weird build issues.
|
||||||
|
|
||||||
|
## Make debug builds of the tests
|
||||||
|
|
||||||
|
The default build is designed not to exit on errors, and will (should) return fairly coarse error codes for any issue. This is good for a utility library, but unhelpful for debugging. The `-DDEBUG` compiler flag builds a version such that any assertion failure aborts the run and outputs file and line info. This is much more useful for tracking down deeply buried errors.
|
||||||
|
|
||||||
|
Each test suite can be compiled into its debug version. For example, as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
make fk20_proofs_test_debug
|
||||||
|
./fk20_proofs_test_debug fk_single_strided
|
||||||
|
```
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Blst library (see above)
|
- Blst library (see above)
|
||||||
- `clang` compiler. I'm using Clang 10.0.0. I'll likely add `gcc` options in future.
|
- `clang` compiler. I'm using Clang 10.0.0. I'll likely add `gcc` options in future.
|
||||||
|
- The Makefile is GNU make compatible.
|
||||||
- I'm developing on Ubuntu 20.04. Will check portability later.
|
- I'm developing on Ubuntu 20.04. Will check portability later.
|
||||||
|
|
25
src/Makefile
25
src/Makefile
|
@ -1,10 +1,10 @@
|
||||||
TESTS = blst_util_test c_kzg_util_test fft_common_test fft_fr_test fft_g1_test \
|
TESTS = blst_util_test c_kzg_util_test fft_common_test fft_fr_test fft_g1_test \
|
||||||
kzg_proofs_test poly_test
|
fk20_proofs_test kzg_proofs_test poly_test
|
||||||
BENCH = fft_fr_bench fft_g1_bench
|
BENCH = fft_fr_bench fft_g1_bench
|
||||||
LIB_SRC = blst_util.c c_kzg_util.c fft_common.c fft_fr.c fft_g1.c kzg_proofs.c poly.c
|
LIB_SRC = blst_util.c c_kzg_util.c fft_common.c fft_fr.c fft_g1.c fk20_proofs.c kzg_proofs.c poly.c
|
||||||
LIB_OBJ = $(LIB_SRC:.c=.o)
|
LIB_OBJ = $(LIB_SRC:.c=.o)
|
||||||
|
|
||||||
CFLAGS = -g
|
CFLAGS =
|
||||||
|
|
||||||
.PRECIOUS: %.o
|
.PRECIOUS: %.o
|
||||||
|
|
||||||
|
@ -14,22 +14,24 @@ CFLAGS = -g
|
||||||
libckzg.a: $(LIB_OBJ) Makefile
|
libckzg.a: $(LIB_OBJ) Makefile
|
||||||
ar rc libckzg.a $(LIB_OBJ)
|
ar rc libckzg.a $(LIB_OBJ)
|
||||||
|
|
||||||
%_test: %_test.c debug_util.o libckzg.a Makefile
|
%_test: %_test.c debug_util.o test_util.o libckzg.a Makefile
|
||||||
clang -Wall $(CFLAGS) -o $@ $@.c debug_util.o libckzg.a -L../lib -lblst
|
clang -Wall $(CFLAGS) -o $@ $@.c debug_util.o test_util.o libckzg.a -L../lib -lblst
|
||||||
./$@
|
./$@
|
||||||
|
|
||||||
|
# This version will abort on error and print the file and line number
|
||||||
|
%_test_debug: CFLAGS += -g -O0 -DDEBUG
|
||||||
|
%_test_debug: %_test.c debug_util.o test_util.o libckzg.a Makefile
|
||||||
|
clang -Wall $(CFLAGS) -o $@ $*_test.c debug_util.o test_util.o libckzg.a -L../lib -lblst
|
||||||
|
|
||||||
|
# Benchmarks
|
||||||
|
%_bench: CFLAGS += -O3
|
||||||
%_bench: %_bench.c bench_util.o $(LIB_OBJ) Makefile
|
%_bench: %_bench.c bench_util.o $(LIB_OBJ) Makefile
|
||||||
clang -Wall $(CFLAGS) -o $@ $@.c bench_util.o $(LIB_OBJ) -L../lib -lblst
|
clang -Wall $(CFLAGS) -o $@ $@.c bench_util.o $(LIB_OBJ) -L../lib -lblst
|
||||||
./$@
|
./$@
|
||||||
|
|
||||||
|
lib: CFLAGS += -O3
|
||||||
lib: clean libckzg.a
|
lib: clean libckzg.a
|
||||||
|
|
||||||
debuglib: CFLAGS += -O1 -DDEBUG
|
|
||||||
debuglib: clean libckzg.a
|
|
||||||
|
|
||||||
optlib: CFLAGS += -O2
|
|
||||||
optlib: clean libckzg.a
|
|
||||||
|
|
||||||
profilelib: CFLAGS += -fprofile-instr-generate -fcoverage-mapping
|
profilelib: CFLAGS += -fprofile-instr-generate -fcoverage-mapping
|
||||||
profilelib: clean libckzg.a
|
profilelib: clean libckzg.a
|
||||||
|
|
||||||
|
@ -42,4 +44,5 @@ clean:
|
||||||
rm -f libckzg.a
|
rm -f libckzg.a
|
||||||
rm -f $(TESTS)
|
rm -f $(TESTS)
|
||||||
rm -f $(BENCH)
|
rm -f $(BENCH)
|
||||||
|
rm -f *_debug
|
||||||
rm -f a.out
|
rm -f a.out
|
||||||
|
|
|
@ -16,13 +16,12 @@
|
||||||
|
|
||||||
#include "../inc/acutest.h"
|
#include "../inc/acutest.h"
|
||||||
#include "debug_util.h"
|
#include "debug_util.h"
|
||||||
|
#include "test_util.h"
|
||||||
#include "blst_util.h"
|
#include "blst_util.h"
|
||||||
|
|
||||||
// This is -1 (the second root of unity)
|
// This is -1 (the second root of unity)
|
||||||
uint64_t m1[] = {0xffffffff00000000L, 0x53bda402fffe5bfeL, 0x3339d80809a1d805L, 0x73eda753299d7d48L};
|
uint64_t m1[] = {0xffffffff00000000L, 0x53bda402fffe5bfeL, 0x3339d80809a1d805L, 0x73eda753299d7d48L};
|
||||||
|
|
||||||
void title(void) {}
|
|
||||||
|
|
||||||
void fr_is_zero_works(void) {
|
void fr_is_zero_works(void) {
|
||||||
blst_fr zero;
|
blst_fr zero;
|
||||||
fr_from_uint64(&zero, 0);
|
fr_from_uint64(&zero, 0);
|
||||||
|
|
|
@ -16,10 +16,9 @@
|
||||||
|
|
||||||
#include "../inc/acutest.h"
|
#include "../inc/acutest.h"
|
||||||
#include "debug_util.h"
|
#include "debug_util.h"
|
||||||
|
#include "test_util.h"
|
||||||
#include "c_kzg_util.h"
|
#include "c_kzg_util.h"
|
||||||
|
|
||||||
void title(void) {}
|
|
||||||
|
|
||||||
void malloc_works(void) {
|
void malloc_works(void) {
|
||||||
int *p;
|
int *p;
|
||||||
TEST_CHECK(C_KZG_OK == c_kzg_malloc((void **)&p, 4));
|
TEST_CHECK(C_KZG_OK == c_kzg_malloc((void **)&p, 4));
|
||||||
|
|
|
@ -49,19 +49,20 @@ C_KZG_RET reverse(blst_fr *out, const blst_fr *roots, const uint64_t width) {
|
||||||
}
|
}
|
||||||
|
|
||||||
C_KZG_RET new_fft_settings(FFTSettings *fs, const unsigned int max_scale) {
|
C_KZG_RET new_fft_settings(FFTSettings *fs, const unsigned int max_scale) {
|
||||||
C_KZG_RET ret;
|
|
||||||
fs->max_width = (uint64_t)1 << max_scale;
|
fs->max_width = (uint64_t)1 << max_scale;
|
||||||
blst_fr_from_uint64(&fs->root_of_unity, scale2_root_of_unity[max_scale]);
|
blst_fr_from_uint64(&fs->root_of_unity, scale2_root_of_unity[max_scale]);
|
||||||
|
|
||||||
ASSERT(c_kzg_malloc((void **)&fs->expanded_roots_of_unity, (fs->max_width + 1) * sizeof(blst_fr)) == C_KZG_OK,
|
ASSERT(c_kzg_malloc((void **)&fs->expanded_roots_of_unity,
|
||||||
|
(fs->max_width + 1) * sizeof *fs->expanded_roots_of_unity) == C_KZG_OK,
|
||||||
C_KZG_MALLOC);
|
C_KZG_MALLOC);
|
||||||
ASSERT(c_kzg_malloc((void **)&fs->reverse_roots_of_unity, (fs->max_width + 1) * sizeof(blst_fr)) == C_KZG_OK,
|
ASSERT(c_kzg_malloc((void **)&fs->reverse_roots_of_unity,
|
||||||
|
(fs->max_width + 1) * sizeof *fs->reverse_roots_of_unity) == C_KZG_OK,
|
||||||
C_KZG_MALLOC);
|
C_KZG_MALLOC);
|
||||||
|
|
||||||
ret = expand_root_of_unity(fs->expanded_roots_of_unity, &fs->root_of_unity, fs->max_width);
|
ASSERT(expand_root_of_unity(fs->expanded_roots_of_unity, &fs->root_of_unity, fs->max_width) == C_KZG_OK,
|
||||||
if (ret != C_KZG_OK) return ret;
|
C_KZG_ERROR);
|
||||||
ret = reverse(fs->reverse_roots_of_unity, fs->expanded_roots_of_unity, fs->max_width);
|
ASSERT(reverse(fs->reverse_roots_of_unity, fs->expanded_roots_of_unity, fs->max_width) == C_KZG_OK, C_KZG_ERROR);
|
||||||
return ret;
|
return C_KZG_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_fft_settings(FFTSettings *fs) {
|
void free_fft_settings(FFTSettings *fs) {
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef FFT_COMMON
|
||||||
|
#define FFT_COMMON
|
||||||
|
|
||||||
#include "c_kzg.h"
|
#include "c_kzg.h"
|
||||||
|
|
||||||
// MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513
|
// MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513
|
||||||
|
@ -67,3 +70,5 @@ C_KZG_RET expand_root_of_unity(blst_fr *roots, const blst_fr *root_of_unity, con
|
||||||
C_KZG_RET reverse(blst_fr *out, const blst_fr *roots, const uint64_t width);
|
C_KZG_RET reverse(blst_fr *out, const blst_fr *roots, const uint64_t width);
|
||||||
C_KZG_RET new_fft_settings(FFTSettings *s, const unsigned int max_scale);
|
C_KZG_RET new_fft_settings(FFTSettings *s, const unsigned int max_scale);
|
||||||
void free_fft_settings(FFTSettings *s);
|
void free_fft_settings(FFTSettings *s);
|
||||||
|
|
||||||
|
#endif
|
|
@ -16,13 +16,12 @@
|
||||||
|
|
||||||
#include "../inc/acutest.h"
|
#include "../inc/acutest.h"
|
||||||
#include "debug_util.h"
|
#include "debug_util.h"
|
||||||
|
#include "test_util.h"
|
||||||
#include "fft_common.h"
|
#include "fft_common.h"
|
||||||
#include "blst_util.h"
|
#include "blst_util.h"
|
||||||
|
|
||||||
#define NUM_ROOTS 32
|
#define NUM_ROOTS 32
|
||||||
|
|
||||||
void title(void) {}
|
|
||||||
|
|
||||||
void roots_of_unity_is_the_expected_size(void) {
|
void roots_of_unity_is_the_expected_size(void) {
|
||||||
TEST_CHECK(NUM_ROOTS == sizeof(scale2_root_of_unity) / sizeof(scale2_root_of_unity[0]));
|
TEST_CHECK(NUM_ROOTS == sizeof(scale2_root_of_unity) / sizeof(scale2_root_of_unity[0]));
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "../inc/acutest.h"
|
#include "../inc/acutest.h"
|
||||||
#include "debug_util.h"
|
#include "debug_util.h"
|
||||||
|
#include "test_util.h"
|
||||||
#include "fft_fr.h"
|
#include "fft_fr.h"
|
||||||
#include "blst_util.h"
|
#include "blst_util.h"
|
||||||
|
|
||||||
|
@ -37,8 +38,6 @@ const uint64_t inv_fft_expected[][4] = {
|
||||||
{0xe92ffdda2306c7d4L, 0x54dd2afcd2dfb16bL, 0xf6554603677e87beL, 0x5dbc603bc53c7a39L},
|
{0xe92ffdda2306c7d4L, 0x54dd2afcd2dfb16bL, 0xf6554603677e87beL, 0x5dbc603bc53c7a39L},
|
||||||
{0xd8cda22e753b3117L, 0x880454ec72238f55L, 0xcaf6199fc14a5353L, 0x197df7c2f05866d4L}};
|
{0xd8cda22e753b3117L, 0x880454ec72238f55L, 0xcaf6199fc14a5353L, 0x197df7c2f05866d4L}};
|
||||||
|
|
||||||
void title(void) {}
|
|
||||||
|
|
||||||
void compare_sft_fft(void) {
|
void compare_sft_fft(void) {
|
||||||
// Initialise: ascending values of i (could be anything), and arbitrary size
|
// Initialise: ascending values of i (could be anything), and arbitrary size
|
||||||
unsigned int size = 12;
|
unsigned int size = 12;
|
||||||
|
@ -126,6 +125,9 @@ void stride_fft(void) {
|
||||||
for (int i = 0; i < width; i++) {
|
for (int i = 0; i < width; i++) {
|
||||||
TEST_CHECK(fr_equal(coeffs1 + i, coeffs2 + i));
|
TEST_CHECK(fr_equal(coeffs1 + i, coeffs2 + i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free_fft_settings(&fs1);
|
||||||
|
free_fft_settings(&fs2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_LIST = {
|
TEST_LIST = {
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
#include "blst_util.h"
|
#include "blst_util.h"
|
||||||
|
|
||||||
// Slow Fourier Transform (simple, good for small sizes)
|
// 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) {
|
void fft_g1_slow(blst_p1 *out, const blst_p1 *in, uint64_t stride, const blst_fr *roots, uint64_t roots_stride,
|
||||||
|
uint64_t l) {
|
||||||
blst_p1 v, last, jv;
|
blst_p1 v, last, jv;
|
||||||
blst_fr r;
|
blst_fr r;
|
||||||
for (uint64_t i = 0; i < l; i++) {
|
for (uint64_t i = 0; i < l; i++) {
|
||||||
|
@ -34,7 +35,8 @@ void fft_g1_slow(blst_p1 *out, blst_p1 *in, uint64_t stride, blst_fr *roots, uin
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fast Fourier Transform
|
// Fast Fourier Transform
|
||||||
void fft_g1_fast(blst_p1 *out, blst_p1 *in, uint64_t stride, blst_fr *roots, uint64_t roots_stride, uint64_t l) {
|
void fft_g1_fast(blst_p1 *out, const blst_p1 *in, uint64_t stride, const blst_fr *roots, uint64_t roots_stride,
|
||||||
|
uint64_t l) {
|
||||||
uint64_t half = l / 2;
|
uint64_t half = l / 2;
|
||||||
if (half > 0) { // Tunable parameter
|
if (half > 0) { // Tunable parameter
|
||||||
fft_g1_fast(out, in, stride * 2, roots, roots_stride * 2, half);
|
fft_g1_fast(out, in, stride * 2, roots, roots_stride * 2, half);
|
||||||
|
@ -51,7 +53,7 @@ void fft_g1_fast(blst_p1 *out, blst_p1 *in, uint64_t stride, blst_fr *roots, uin
|
||||||
}
|
}
|
||||||
|
|
||||||
// The main entry point for forward and reverse FFTs
|
// The main entry point for forward and reverse FFTs
|
||||||
C_KZG_RET fft_g1(blst_p1 *out, blst_p1 *in, FFTSettings *fs, bool inv, uint64_t n) {
|
C_KZG_RET fft_g1(blst_p1 *out, const blst_p1 *in, const FFTSettings *fs, bool inv, uint64_t n) {
|
||||||
uint64_t stride = fs->max_width / n;
|
uint64_t stride = fs->max_width / n;
|
||||||
ASSERT(n <= fs->max_width, C_KZG_BADARGS);
|
ASSERT(n <= fs->max_width, C_KZG_BADARGS);
|
||||||
ASSERT(is_power_of_two(n), C_KZG_BADARGS);
|
ASSERT(is_power_of_two(n), C_KZG_BADARGS);
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#include "c_kzg.h"
|
#include "c_kzg.h"
|
||||||
#include "fft_common.h"
|
#include "fft_common.h"
|
||||||
|
|
||||||
void fft_g1_slow(blst_p1 *out, blst_p1 *in, uint64_t stride, blst_fr *roots, uint64_t roots_stride, uint64_t l);
|
void fft_g1_slow(blst_p1 *out, const blst_p1 *in, uint64_t stride, const blst_fr *roots, uint64_t roots_stride,
|
||||||
void fft_g1_fast(blst_p1 *out, blst_p1 *in, uint64_t stride, blst_fr *roots, uint64_t roots_stride, uint64_t l);
|
uint64_t l);
|
||||||
C_KZG_RET fft_g1(blst_p1 *out, blst_p1 *in, FFTSettings *fs, bool inv, uint64_t n);
|
void fft_g1_fast(blst_p1 *out, const blst_p1 *in, uint64_t stride, const blst_fr *roots, uint64_t roots_stride,
|
||||||
|
uint64_t l);
|
||||||
|
C_KZG_RET fft_g1(blst_p1 *out, const blst_p1 *in, const FFTSettings *fs, bool inv, uint64_t n);
|
||||||
|
|
|
@ -16,10 +16,9 @@
|
||||||
|
|
||||||
#include "../inc/acutest.h"
|
#include "../inc/acutest.h"
|
||||||
#include "debug_util.h"
|
#include "debug_util.h"
|
||||||
|
#include "test_util.h"
|
||||||
#include "fft_g1.h"
|
#include "fft_g1.h"
|
||||||
|
|
||||||
void title(void) {}
|
|
||||||
|
|
||||||
void make_data(blst_p1 *out, uint64_t n) {
|
void make_data(blst_p1 *out, uint64_t n) {
|
||||||
// Multiples of g1_gen
|
// Multiples of g1_gen
|
||||||
if (n == 0) return;
|
if (n == 0) return;
|
||||||
|
@ -85,6 +84,9 @@ void stride_fft(void) {
|
||||||
for (int i = 0; i < width; i++) {
|
for (int i = 0; i < width; i++) {
|
||||||
TEST_CHECK(blst_p1_is_equal(coeffs1 + i, coeffs2 + i));
|
TEST_CHECK(blst_p1_is_equal(coeffs1 + i, coeffs2 + i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free_fft_settings(&fs1);
|
||||||
|
free_fft_settings(&fs2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_LIST = {
|
TEST_LIST = {
|
||||||
|
|
|
@ -0,0 +1,222 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// FK20 refers to this technique: https://github.com/khovratovich/Kate/blob/master/Kate_amortized.pdf
|
||||||
|
|
||||||
|
#include <stdlib.h> // free()
|
||||||
|
#include <string.h> // memcpy()
|
||||||
|
#include "fk20_proofs.h"
|
||||||
|
#include "fft_g1.h"
|
||||||
|
#include "c_kzg_util.h"
|
||||||
|
|
||||||
|
// Log base 2 - only works for n a power of two
|
||||||
|
int log2_pow2(uint32_t n) {
|
||||||
|
const uint32_t b[] = {0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000};
|
||||||
|
register uint32_t r;
|
||||||
|
r = (n & b[0]) != 0;
|
||||||
|
r |= ((n & b[1]) != 0) << 1;
|
||||||
|
r |= ((n & b[2]) != 0) << 2;
|
||||||
|
r |= ((n & b[3]) != 0) << 3;
|
||||||
|
r |= ((n & b[4]) != 0) << 4;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This simply wraps the macro to enforce the type check
|
||||||
|
uint32_t reverse_bits(uint32_t a) {
|
||||||
|
return rev_4byte(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t reverse_bits_limited(uint32_t length, uint32_t value) {
|
||||||
|
int unused_bit_len = 32 - log2_pow2(length);
|
||||||
|
return reverse_bits(value) >> unused_bit_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In-place re-ordering of an array by the bit-reversal of the indices
|
||||||
|
// Can handle arrays of any type: provide the element size in `size`
|
||||||
|
C_KZG_RET reverse_bit_order(void *values, size_t size, uint64_t n) {
|
||||||
|
ASSERT(n >> 32 == 0, C_KZG_BADARGS);
|
||||||
|
ASSERT(is_power_of_two(n), C_KZG_BADARGS);
|
||||||
|
|
||||||
|
byte tmp[size];
|
||||||
|
int unused_bit_len = 32 - log2_pow2(n);
|
||||||
|
for (uint32_t i = 0; i < n; i++) {
|
||||||
|
uint32_t r = reverse_bits(i) >> unused_bit_len;
|
||||||
|
if (r > i) {
|
||||||
|
// Swap the two elements
|
||||||
|
memcpy(tmp, values + (i * size), size);
|
||||||
|
memcpy(values + (i * size), values + (r * size), size);
|
||||||
|
memcpy(values + (r * size), tmp, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return C_KZG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Performs the first part of the Toeplitz matrix multiplication algorithm, which is a Fourier
|
||||||
|
// transform of the vector x extended
|
||||||
|
C_KZG_RET toeplitz_part_1(blst_p1 *out, const blst_p1 *x, uint64_t n, KZGSettings *ks) {
|
||||||
|
uint64_t n2 = n * 2;
|
||||||
|
blst_p1 identity_g1, *x_ext;
|
||||||
|
|
||||||
|
ASSERT(c_kzg_malloc((void **)&x_ext, n2 * sizeof *x_ext) == C_KZG_OK, C_KZG_MALLOC);
|
||||||
|
|
||||||
|
blst_p1_from_affine(&identity_g1, &identity_g1_affine);
|
||||||
|
for (uint64_t i = 0; i < n; i++) {
|
||||||
|
x_ext[i] = x[i];
|
||||||
|
}
|
||||||
|
for (uint64_t i = n; i < n2; i++) {
|
||||||
|
x_ext[i] = identity_g1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(fft_g1(out, x_ext, ks->fs, false, n2) == C_KZG_OK, C_KZG_ERROR);
|
||||||
|
|
||||||
|
free(x_ext);
|
||||||
|
return C_KZG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Performs the second part of the Toeplitz matrix multiplication algorithm
|
||||||
|
C_KZG_RET toeplitz_part_2(blst_p1 *out, const poly *toeplitz_coeffs, const FK20SingleSettings *fk) {
|
||||||
|
blst_fr *toeplitz_coeffs_fft;
|
||||||
|
|
||||||
|
ASSERT(toeplitz_coeffs->length == fk->x_ext_fft_len, C_KZG_BADARGS);
|
||||||
|
ASSERT(c_kzg_malloc((void **)&toeplitz_coeffs_fft, toeplitz_coeffs->length * sizeof *toeplitz_coeffs_fft) ==
|
||||||
|
C_KZG_OK,
|
||||||
|
C_KZG_MALLOC);
|
||||||
|
|
||||||
|
ASSERT(fft_fr(toeplitz_coeffs_fft, toeplitz_coeffs->coeffs, fk->ks->fs, false, toeplitz_coeffs->length) == C_KZG_OK,
|
||||||
|
C_KZG_ERROR);
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < toeplitz_coeffs->length; i++) {
|
||||||
|
p1_mul(&out[i], &fk->x_ext_fft[i], &toeplitz_coeffs_fft[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(toeplitz_coeffs_fft);
|
||||||
|
return C_KZG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform back and return the first half of the vector
|
||||||
|
C_KZG_RET toeplitz_part_3(blst_p1 *out, const blst_p1 *h_ext_fft, uint64_t length, const FK20SingleSettings *fk) {
|
||||||
|
ASSERT(fft_g1(out, h_ext_fft, fk->ks->fs, true, length) == C_KZG_OK, C_KZG_ERROR);
|
||||||
|
|
||||||
|
return C_KZG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toeplitz_coeffs_step(poly *out, const poly *in) {
|
||||||
|
uint64_t n = in->length, n2 = n * 2;
|
||||||
|
|
||||||
|
out->coeffs[0] = in->coeffs[n - 1];
|
||||||
|
for (uint64_t i = 1; i <= n + 1; i++) {
|
||||||
|
out->coeffs[i] = fr_zero;
|
||||||
|
}
|
||||||
|
for (uint64_t i = n + 2; i < n2; i++) {
|
||||||
|
out->coeffs[i] = in->coeffs[i - (n + 1)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special version of the FK20 for the situation of data availability checks:
|
||||||
|
// The upper half of the polynomial coefficients is always 0, so we do not need to extend to twice the size
|
||||||
|
// for Toeplitz matrix multiplication
|
||||||
|
C_KZG_RET fk20_single_da_opt(blst_p1 *out, const poly *p, FK20SingleSettings *fk) {
|
||||||
|
uint64_t n2 = p->length, n = n2 / 2;
|
||||||
|
blst_p1 *h, *h_ext_fft, identity_g1;
|
||||||
|
poly reduced_poly, toeplitz_coeffs;
|
||||||
|
C_KZG_RET ret;
|
||||||
|
|
||||||
|
ASSERT(n2 <= fk->ks->fs->max_width, C_KZG_BADARGS);
|
||||||
|
ASSERT(is_power_of_two(n2), C_KZG_BADARGS);
|
||||||
|
|
||||||
|
for (uint64_t i = n; i < n2; i++) {
|
||||||
|
ASSERT(fr_is_zero(&p->coeffs[i]), C_KZG_BADARGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The first half of the input polynomial
|
||||||
|
reduced_poly.coeffs = p->coeffs;
|
||||||
|
reduced_poly.length = n;
|
||||||
|
|
||||||
|
ASSERT(init_poly(&toeplitz_coeffs, n2) == C_KZG_OK, C_KZG_MALLOC);
|
||||||
|
toeplitz_coeffs_step(&toeplitz_coeffs, &reduced_poly);
|
||||||
|
|
||||||
|
ASSERT(c_kzg_malloc((void **)&h_ext_fft, toeplitz_coeffs.length * sizeof *h_ext_fft) == C_KZG_OK, C_KZG_MALLOC);
|
||||||
|
ASSERT((ret = toeplitz_part_2(h_ext_fft, &toeplitz_coeffs, fk)) == C_KZG_OK,
|
||||||
|
ret == C_KZG_MALLOC ? ret : C_KZG_ERROR);
|
||||||
|
ASSERT(c_kzg_malloc((void **)&h, toeplitz_coeffs.length * sizeof *h) == C_KZG_OK, C_KZG_MALLOC);
|
||||||
|
ASSERT(toeplitz_part_3(h, h_ext_fft, n2, fk) == C_KZG_OK, C_KZG_ERROR);
|
||||||
|
|
||||||
|
blst_p1_from_affine(&identity_g1, &identity_g1_affine);
|
||||||
|
for (uint64_t i = n; i < n2; i++) {
|
||||||
|
h[i] = identity_g1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(fft_g1(out, h, fk->ks->fs, false, n2) == C_KZG_OK, C_KZG_ERROR);
|
||||||
|
|
||||||
|
free(h);
|
||||||
|
free(h_ext_fft);
|
||||||
|
free_poly(&toeplitz_coeffs);
|
||||||
|
return C_KZG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
C_KZG_RET da_using_fk20_single(blst_p1 *out, const poly *p, FK20SingleSettings *fk) {
|
||||||
|
uint64_t n = p->length, n2 = n * 2;
|
||||||
|
poly extended_poly;
|
||||||
|
|
||||||
|
ASSERT(n2 <= fk->ks->fs->max_width, C_KZG_BADARGS);
|
||||||
|
ASSERT(is_power_of_two(n), C_KZG_BADARGS);
|
||||||
|
|
||||||
|
ASSERT(init_poly(&extended_poly, n2) == C_KZG_OK, C_KZG_MALLOC);
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < n; i++) {
|
||||||
|
extended_poly.coeffs[i] = p->coeffs[i];
|
||||||
|
}
|
||||||
|
for (uint64_t i = n; i < n2; i++) {
|
||||||
|
extended_poly.coeffs[i] = fr_zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(fk20_single_da_opt(out, &extended_poly, fk) == C_KZG_OK, C_KZG_ERROR);
|
||||||
|
|
||||||
|
ASSERT(reverse_bit_order(out, sizeof out[0], n2) == C_KZG_OK, C_KZG_ERROR);
|
||||||
|
|
||||||
|
free_poly(&extended_poly);
|
||||||
|
return C_KZG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
C_KZG_RET new_fk20_single_settings(FK20SingleSettings *fk, uint64_t n2, KZGSettings *ks) {
|
||||||
|
int n = n2 / 2;
|
||||||
|
blst_p1 *x;
|
||||||
|
|
||||||
|
ASSERT(n2 <= ks->fs->max_width, C_KZG_BADARGS);
|
||||||
|
ASSERT(is_power_of_two(n2), C_KZG_BADARGS);
|
||||||
|
ASSERT(n2 >= 2, C_KZG_BADARGS);
|
||||||
|
|
||||||
|
fk->ks = ks;
|
||||||
|
fk->x_ext_fft_len = n2;
|
||||||
|
|
||||||
|
ASSERT(c_kzg_malloc((void **)&x, n * sizeof *x) == C_KZG_OK, C_KZG_MALLOC);
|
||||||
|
ASSERT(c_kzg_malloc((void **)&fk->x_ext_fft, n2 * sizeof *fk->x_ext_fft) == C_KZG_OK, C_KZG_MALLOC);
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < n - 1; i++) {
|
||||||
|
x[i] = ks->secret_g1[n - 2 - i];
|
||||||
|
}
|
||||||
|
blst_p1_from_affine(&x[n - 1], &identity_g1_affine);
|
||||||
|
|
||||||
|
ASSERT(toeplitz_part_1(fk->x_ext_fft, x, n, ks) == C_KZG_OK, C_KZG_ERROR);
|
||||||
|
|
||||||
|
free(x);
|
||||||
|
return C_KZG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_fk20_single_settings(FK20SingleSettings *fk) {
|
||||||
|
free(fk->x_ext_fft);
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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_proofs.h"
|
||||||
|
|
||||||
|
// TODO: Benchmark some of the other options at https://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable
|
||||||
|
#define rev_byte(a) ((((a)&0xff) * 0x0202020202ULL & 0x010884422010ULL) % 1023)
|
||||||
|
#define rev_4byte(a) (rev_byte(a) << 24 | rev_byte((a) >> 8) << 16 | rev_byte((a) >> 16) << 8 | rev_byte((a) >> 24))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
KZGSettings *ks;
|
||||||
|
blst_p1 *x_ext_fft;
|
||||||
|
uint64_t x_ext_fft_len;
|
||||||
|
} FK20SingleSettings;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
KZGSettings *ks;
|
||||||
|
uint64_t chunk_len;
|
||||||
|
blst_p1 **x_ext_fft_files;
|
||||||
|
uint64_t length;
|
||||||
|
} FK20MultiSettings;
|
||||||
|
|
||||||
|
int log2_pow2(uint32_t n);
|
||||||
|
uint32_t reverse_bits(uint32_t a);
|
||||||
|
uint32_t reverse_bits_limited(uint32_t length, uint32_t value);
|
||||||
|
C_KZG_RET reverse_bit_order(void *values, size_t size, uint64_t n);
|
||||||
|
C_KZG_RET toeplitz_part_1(blst_p1 *out, const blst_p1 *x, uint64_t n, KZGSettings *ks);
|
||||||
|
C_KZG_RET toeplitz_part_2(blst_p1 *out, const poly *toeplitz_coeffs, const FK20SingleSettings *fk);
|
||||||
|
C_KZG_RET toeplitz_part_3(blst_p1 *out, const blst_p1 *h_ext_fft, uint64_t length, const FK20SingleSettings *fk);
|
||||||
|
C_KZG_RET fk20_single_da_opt(blst_p1 *out, const poly *p, FK20SingleSettings *fk);
|
||||||
|
C_KZG_RET da_using_fk20_single(blst_p1 *out, const poly *p, FK20SingleSettings *fk);
|
||||||
|
C_KZG_RET new_fk20_single_settings(FK20SingleSettings *fk, uint64_t n2, KZGSettings *ks);
|
||||||
|
void free_fk20_single_settings(FK20SingleSettings *fk);
|
|
@ -0,0 +1,208 @@
|
||||||
|
/*
|
||||||
|
* 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 "test_util.h"
|
||||||
|
#include "fk20_proofs.h"
|
||||||
|
|
||||||
|
void test_reverse_bits_macros(void) {
|
||||||
|
TEST_CHECK(128 == rev_byte(1));
|
||||||
|
TEST_CHECK(128 == rev_byte(257));
|
||||||
|
TEST_CHECK((uint32_t)1 << 31 == rev_4byte(1));
|
||||||
|
TEST_CHECK(0x1e6a2c48 == rev_4byte(0x12345678));
|
||||||
|
TEST_CHECK(0x00000000 == rev_4byte(0x00000000));
|
||||||
|
TEST_CHECK(0xffffffff == rev_4byte(0xffffffff));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_reverse_bits_0(void) {
|
||||||
|
uint32_t actual, expected;
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
expected = (uint32_t)1 << (31 - i);
|
||||||
|
actual = reverse_bits((uint32_t)1 << i);
|
||||||
|
TEST_CHECK(expected == actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_reverse_bits_1(void) {
|
||||||
|
TEST_CHECK(0x84c2a6e1 == reverse_bits(0x87654321));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_log2_pow2(void) {
|
||||||
|
int actual, expected;
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
expected = i;
|
||||||
|
actual = log2_pow2((uint32_t)1 << i);
|
||||||
|
TEST_CHECK(expected == actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_reverse_bit_order_g1(void) {
|
||||||
|
int size = 10, n = 1 << size;
|
||||||
|
blst_p1 a[n], b[n];
|
||||||
|
blst_fr tmp;
|
||||||
|
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
fr_from_uint64(&tmp, i);
|
||||||
|
p1_mul(&a[i], blst_p1_generator(), &tmp);
|
||||||
|
b[i] = a[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CHECK(C_KZG_OK == reverse_bit_order(a, sizeof(blst_p1), n));
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
TEST_CHECK(true == blst_p1_is_equal(&b[reverse_bits(i) >> (32 - size)], &a[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hand check a few select values
|
||||||
|
TEST_CHECK(true == blst_p1_is_equal(&b[0], &a[0]));
|
||||||
|
TEST_CHECK(false == blst_p1_is_equal(&b[1], &a[1]));
|
||||||
|
TEST_CHECK(true == blst_p1_is_equal(&b[n - 1], &a[n - 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_reverse_bit_order_fr(void) {
|
||||||
|
int size = 12, n = 1 << size;
|
||||||
|
blst_fr a[n], b[n];
|
||||||
|
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
fr_from_uint64(&a[i], i);
|
||||||
|
b[i] = a[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CHECK(C_KZG_OK == reverse_bit_order(a, sizeof(blst_fr), n));
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
TEST_CHECK(true == fr_equal(&b[reverse_bits(i) >> (32 - size)], &a[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hand check a few select values
|
||||||
|
TEST_CHECK(true == fr_equal(&b[0], &a[0]));
|
||||||
|
TEST_CHECK(false == fr_equal(&b[1], &a[1]));
|
||||||
|
TEST_CHECK(true == fr_equal(&b[n - 1], &a[n - 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
void fk_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];
|
||||||
|
|
||||||
|
// The FFT settings size
|
||||||
|
uint64_t n = 5, n_len = (uint64_t)1 << n;
|
||||||
|
|
||||||
|
FFTSettings fs;
|
||||||
|
KZGSettings ks;
|
||||||
|
FK20SingleSettings fk;
|
||||||
|
uint64_t secrets_len = n_len + 1;
|
||||||
|
blst_p1 *s1;
|
||||||
|
blst_p2 *s2;
|
||||||
|
poly p;
|
||||||
|
blst_p1 commitment, all_proofs[2 * poly_len], proof;
|
||||||
|
blst_fr x, y;
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
TEST_CHECK(n_len >= 2 * poly_len);
|
||||||
|
TEST_CHECK(init_poly_with_coeffs(&p, coeffs, poly_len) == C_KZG_OK);
|
||||||
|
|
||||||
|
// Initialise the secrets and data structures
|
||||||
|
generate_trusted_setup(&s1, &s2, &secret, secrets_len);
|
||||||
|
TEST_CHECK(C_KZG_OK == new_fft_settings(&fs, n));
|
||||||
|
TEST_CHECK(C_KZG_OK == new_kzg_settings(&ks, &fs, s1, s2, secrets_len));
|
||||||
|
TEST_CHECK(C_KZG_OK == new_fk20_single_settings(&fk, 2 * poly_len, &ks));
|
||||||
|
|
||||||
|
// Generate the proofs
|
||||||
|
commit_to_poly(&commitment, &p, &ks);
|
||||||
|
TEST_CHECK(da_using_fk20_single(all_proofs, &p, &fk) == C_KZG_OK);
|
||||||
|
|
||||||
|
// Verify the proof at each position
|
||||||
|
for (uint64_t i = 0; i < 2 * poly_len; i++) {
|
||||||
|
x = fs.expanded_roots_of_unity[i];
|
||||||
|
eval_poly(&y, &p, &x);
|
||||||
|
proof = all_proofs[reverse_bits_limited(2 * poly_len, i)];
|
||||||
|
|
||||||
|
TEST_CHECK(C_KZG_OK == check_proof_single(&result, &ks, &commitment, &proof, &x, &y));
|
||||||
|
TEST_CHECK(true == result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
free_poly(&p);
|
||||||
|
free_fft_settings(&fs);
|
||||||
|
free_kzg_settings(&ks);
|
||||||
|
free_fk20_single_settings(&fk);
|
||||||
|
free_trusted_setup(s1, s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fk_single_strided(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];
|
||||||
|
|
||||||
|
// We can set up the FFTs for bigger widths if we wish.
|
||||||
|
// This is a useful canary for issues elsewhere in the code.
|
||||||
|
uint64_t n = 8, n_len = (uint64_t)1 << n;
|
||||||
|
uint64_t stride = n_len / (2 * poly_len);
|
||||||
|
|
||||||
|
FFTSettings fs;
|
||||||
|
KZGSettings ks;
|
||||||
|
FK20SingleSettings fk;
|
||||||
|
uint64_t secrets_len = n_len + 1;
|
||||||
|
blst_p1 *s1;
|
||||||
|
blst_p2 *s2;
|
||||||
|
poly p;
|
||||||
|
blst_p1 commitment, all_proofs[2 * poly_len], proof;
|
||||||
|
blst_fr x, y;
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
TEST_CHECK(n_len >= 2 * poly_len);
|
||||||
|
TEST_CHECK(init_poly_with_coeffs(&p, coeffs, poly_len) == C_KZG_OK);
|
||||||
|
|
||||||
|
// Initialise the secrets and data structures
|
||||||
|
generate_trusted_setup(&s1, &s2, &secret, secrets_len);
|
||||||
|
TEST_CHECK(C_KZG_OK == new_fft_settings(&fs, n));
|
||||||
|
TEST_CHECK(C_KZG_OK == new_kzg_settings(&ks, &fs, s1, s2, secrets_len));
|
||||||
|
TEST_CHECK(C_KZG_OK == new_fk20_single_settings(&fk, 2 * poly_len, &ks));
|
||||||
|
|
||||||
|
// Generate the proofs
|
||||||
|
commit_to_poly(&commitment, &p, &ks);
|
||||||
|
TEST_CHECK(da_using_fk20_single(all_proofs, &p, &fk) == C_KZG_OK);
|
||||||
|
|
||||||
|
// Verify the proof at each position
|
||||||
|
for (uint64_t i = 0; i < 2 * poly_len; i++) {
|
||||||
|
x = fs.expanded_roots_of_unity[i * stride];
|
||||||
|
eval_poly(&y, &p, &x);
|
||||||
|
proof = all_proofs[reverse_bits_limited(2 * poly_len, i)];
|
||||||
|
|
||||||
|
TEST_CHECK(C_KZG_OK == check_proof_single(&result, &ks, &commitment, &proof, &x, &y));
|
||||||
|
TEST_CHECK(true == result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
free_poly(&p);
|
||||||
|
free_fft_settings(&fs);
|
||||||
|
free_kzg_settings(&ks);
|
||||||
|
free_fk20_single_settings(&fk);
|
||||||
|
free_trusted_setup(s1, s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_LIST = {
|
||||||
|
{"FK20_PROOFS_TEST", title},
|
||||||
|
{"test_reverse_bits_macros", test_reverse_bits_macros},
|
||||||
|
{"test_reverse_bits_0", test_reverse_bits_0},
|
||||||
|
{"test_reverse_bits_1", test_reverse_bits_1},
|
||||||
|
{"test_log2_pow2", test_log2_pow2},
|
||||||
|
{"test_reverse_bit_order_g1", test_reverse_bit_order_g1},
|
||||||
|
{"test_reverse_bit_order_fr", test_reverse_bit_order_fr},
|
||||||
|
{"fk_single", fk_single},
|
||||||
|
{"fk_single_strided", fk_single_strided},
|
||||||
|
{NULL, NULL} /* zero record marks the end of the list */
|
||||||
|
};
|
|
@ -17,17 +17,7 @@
|
||||||
#include <stddef.h> // NULL
|
#include <stddef.h> // NULL
|
||||||
#include "kzg_proofs.h"
|
#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) {
|
void commit_to_poly(blst_p1 *out, const poly *p, const KZGSettings *ks) {
|
||||||
ASSERT(length >= fs->max_width, C_KZG_BADARGS);
|
|
||||||
ks->fs = fs;
|
|
||||||
ks->secret_g1 = secret_g1;
|
|
||||||
ks->extended_secret_g1 = NULL; // What's this for?
|
|
||||||
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);
|
linear_combination_g1(out, ks->secret_g1, p->coeffs, p->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +65,7 @@ C_KZG_RET compute_proof_multi(blst_p1 *out, const KZGSettings *ks, poly *p, cons
|
||||||
// Calculate q = p / (x^n - x0^n)
|
// Calculate q = p / (x^n - x0^n)
|
||||||
ASSERT(poly_long_div(&q, p, &divisor) == C_KZG_OK, C_KZG_ERROR);
|
ASSERT(poly_long_div(&q, p, &divisor) == C_KZG_OK, C_KZG_ERROR);
|
||||||
|
|
||||||
commit_to_poly(out, ks, &q);
|
commit_to_poly(out, &q, ks);
|
||||||
|
|
||||||
free_poly(&q);
|
free_poly(&q);
|
||||||
free_poly(&divisor);
|
free_poly(&divisor);
|
||||||
|
@ -112,7 +102,7 @@ C_KZG_RET check_proof_multi(bool *out, const KZGSettings *ks, const blst_p1 *com
|
||||||
p2_sub(&xn_minus_yn, &ks->secret_g2[n], &xn2);
|
p2_sub(&xn_minus_yn, &ks->secret_g2[n], &xn2);
|
||||||
|
|
||||||
// [interpolation_polynomial(s)]_1
|
// [interpolation_polynomial(s)]_1
|
||||||
commit_to_poly(&is1, ks, &interp);
|
commit_to_poly(&is1, &interp, ks);
|
||||||
|
|
||||||
// [commitment - interpolation_polynomial(s)]_1 = [commit]_1 - [interpolation_polynomial(s)]_1
|
// [commitment - interpolation_polynomial(s)]_1 = [commit]_1 - [interpolation_polynomial(s)]_1
|
||||||
p1_sub(&commit_minus_interp, commitment, &is1);
|
p1_sub(&commit_minus_interp, commitment, &is1);
|
||||||
|
@ -122,3 +112,18 @@ C_KZG_RET check_proof_multi(bool *out, const KZGSettings *ks, const blst_p1 *com
|
||||||
free_poly(&interp);
|
free_poly(&interp);
|
||||||
return C_KZG_OK;
|
return C_KZG_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We don't allocate space for the secrets s1 and s2 here as they are assumed to be pre-generated
|
||||||
|
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; // What's this for?
|
||||||
|
ks->secret_g2 = secret_g2;
|
||||||
|
ks->length = length;
|
||||||
|
return C_KZG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a no-op since s1 and s2 are assumed to have been provided externally
|
||||||
|
void free_kzg_settings(KZGSettings *ks) {}
|
|
@ -26,11 +26,12 @@ typedef struct {
|
||||||
uint64_t length;
|
uint64_t length;
|
||||||
} KZGSettings;
|
} 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 poly *p, const KZGSettings *ks);
|
||||||
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 blst_fr *x0);
|
C_KZG_RET compute_proof_single(blst_p1 *out, const KZGSettings *ks, poly *p, const blst_fr *x0);
|
||||||
C_KZG_RET check_proof_single(bool *out, const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof,
|
C_KZG_RET check_proof_single(bool *out, const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof,
|
||||||
const blst_fr *x, blst_fr *y);
|
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);
|
C_KZG_RET compute_proof_multi(blst_p1 *out, const KZGSettings *ks, poly *p, const blst_fr *x0, uint64_t n);
|
||||||
C_KZG_RET check_proof_multi(bool *out, const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof,
|
C_KZG_RET check_proof_multi(bool *out, const KZGSettings *ks, const blst_p1 *commitment, const blst_p1 *proof,
|
||||||
const blst_fr *x, const blst_fr *ys, uint64_t n);
|
const blst_fr *x, const blst_fr *ys, uint64_t n);
|
||||||
|
C_KZG_RET new_kzg_settings(KZGSettings *ks, FFTSettings *fs, blst_p1 *secret_g1, blst_p2 *secret_g2, uint64_t length);
|
||||||
|
void free_kzg_settings(KZGSettings *ks);
|
||||||
|
|
|
@ -16,28 +16,9 @@
|
||||||
|
|
||||||
#include "../inc/acutest.h"
|
#include "../inc/acutest.h"
|
||||||
#include "debug_util.h"
|
#include "debug_util.h"
|
||||||
|
#include "test_util.h"
|
||||||
#include "kzg_proofs.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) {
|
void proof_single(void) {
|
||||||
// Our polynomial: degree 15, 16 coefficients
|
// 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};
|
uint64_t coeffs[] = {1, 2, 3, 4, 7, 7, 7, 7, 13, 13, 13, 13, 13, 13, 13, 13};
|
||||||
|
@ -46,10 +27,10 @@ void proof_single(void) {
|
||||||
|
|
||||||
FFTSettings fs;
|
FFTSettings fs;
|
||||||
KZGSettings ks;
|
KZGSettings ks;
|
||||||
|
blst_p1 *s1;
|
||||||
|
blst_p2 *s2;
|
||||||
poly p;
|
poly p;
|
||||||
blst_p1 commitment, proof;
|
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;
|
blst_fr x, value;
|
||||||
bool result;
|
bool result;
|
||||||
|
|
||||||
|
@ -60,13 +41,13 @@ void proof_single(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise the secrets and data structures
|
// Initialise the secrets and data structures
|
||||||
generate_setup(s1, s2, &secret, secrets_len);
|
generate_trusted_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_fft_settings(&fs, 4)); // ln_2 of poly_len
|
||||||
TEST_CHECK(C_KZG_OK == new_kzg_settings(&ks, &fs, s1, s2, secrets_len));
|
TEST_CHECK(C_KZG_OK == new_kzg_settings(&ks, &fs, s1, s2, secrets_len));
|
||||||
|
|
||||||
// Compute the proof for x = 25
|
// Compute the proof for x = 25
|
||||||
fr_from_uint64(&x, 25);
|
fr_from_uint64(&x, 25);
|
||||||
commit_to_poly(&commitment, &ks, &p);
|
commit_to_poly(&commitment, &p, &ks);
|
||||||
TEST_CHECK(C_KZG_OK == compute_proof_single(&proof, &ks, &p, &x));
|
TEST_CHECK(C_KZG_OK == compute_proof_single(&proof, &ks, &p, &x));
|
||||||
|
|
||||||
eval_poly(&value, &p, &x);
|
eval_poly(&value, &p, &x);
|
||||||
|
@ -81,6 +62,7 @@ void proof_single(void) {
|
||||||
TEST_CHECK(false == result);
|
TEST_CHECK(false == result);
|
||||||
|
|
||||||
free_fft_settings(&fs);
|
free_fft_settings(&fs);
|
||||||
|
free_kzg_settings(&ks);
|
||||||
free_poly(&p);
|
free_poly(&p);
|
||||||
free(s1);
|
free(s1);
|
||||||
free(s2);
|
free(s2);
|
||||||
|
@ -93,6 +75,8 @@ void proof_multi(void) {
|
||||||
|
|
||||||
FFTSettings fs1, fs2;
|
FFTSettings fs1, fs2;
|
||||||
KZGSettings ks1, ks2;
|
KZGSettings ks1, ks2;
|
||||||
|
blst_p1 *s1;
|
||||||
|
blst_p2 *s2;
|
||||||
poly p;
|
poly p;
|
||||||
blst_p1 commitment, proof;
|
blst_p1 commitment, proof;
|
||||||
blst_fr x, tmp;
|
blst_fr x, tmp;
|
||||||
|
@ -103,8 +87,6 @@ void proof_multi(void) {
|
||||||
blst_fr y[coset_len];
|
blst_fr y[coset_len];
|
||||||
|
|
||||||
uint64_t secrets_len = poly_len > coset_len ? poly_len + 1 : coset_len + 1;
|
uint64_t secrets_len = poly_len > coset_len ? poly_len + 1 : coset_len + 1;
|
||||||
blst_p1 *s1 = malloc(secrets_len * sizeof(blst_p1));
|
|
||||||
blst_p2 *s2 = malloc(secrets_len * sizeof(blst_p2));
|
|
||||||
|
|
||||||
// Create the polynomial
|
// Create the polynomial
|
||||||
init_poly(&p, poly_len);
|
init_poly(&p, poly_len);
|
||||||
|
@ -113,12 +95,12 @@ void proof_multi(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise the secrets and data structures
|
// Initialise the secrets and data structures
|
||||||
generate_setup(s1, s2, &secret, secrets_len);
|
generate_trusted_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_fft_settings(&fs1, 4)); // ln_2 of poly_len
|
||||||
TEST_CHECK(C_KZG_OK == new_kzg_settings(&ks1, &fs1, s1, s2, secrets_len));
|
TEST_CHECK(C_KZG_OK == new_kzg_settings(&ks1, &fs1, s1, s2, secrets_len));
|
||||||
|
|
||||||
// Commit to the polynomial
|
// Commit to the polynomial
|
||||||
commit_to_poly(&commitment, &ks1, &p);
|
commit_to_poly(&commitment, &p, &ks1);
|
||||||
|
|
||||||
TEST_CHECK(C_KZG_OK == new_fft_settings(&fs2, coset_scale));
|
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));
|
TEST_CHECK(C_KZG_OK == new_kzg_settings(&ks2, &fs2, s1, s2, secrets_len));
|
||||||
|
@ -144,6 +126,8 @@ void proof_multi(void) {
|
||||||
|
|
||||||
free_fft_settings(&fs1);
|
free_fft_settings(&fs1);
|
||||||
free_fft_settings(&fs2);
|
free_fft_settings(&fs2);
|
||||||
|
free_kzg_settings(&ks1);
|
||||||
|
free_kzg_settings(&ks2);
|
||||||
free_poly(&p);
|
free_poly(&p);
|
||||||
free(s1);
|
free(s1);
|
||||||
free(s2);
|
free(s2);
|
||||||
|
@ -154,20 +138,25 @@ void commit_to_nil_poly(void) {
|
||||||
FFTSettings fs;
|
FFTSettings fs;
|
||||||
KZGSettings ks;
|
KZGSettings ks;
|
||||||
uint64_t secrets_len = 16;
|
uint64_t secrets_len = 16;
|
||||||
blst_p1 *s1 = malloc(secrets_len * sizeof(blst_p1));
|
blst_p1 *s1;
|
||||||
blst_p2 *s2 = malloc(secrets_len * sizeof(blst_p2));
|
blst_p2 *s2;
|
||||||
blst_p1 result;
|
blst_p1 result;
|
||||||
blst_p1_affine result_affine;
|
blst_p1_affine result_affine;
|
||||||
|
|
||||||
// Initialise the (arbitrary) secrets and data structures
|
// Initialise the (arbitrary) secrets and data structures
|
||||||
generate_setup(s1, s2, &secret, secrets_len);
|
generate_trusted_setup(&s1, &s2, &secret, secrets_len);
|
||||||
TEST_CHECK(C_KZG_OK == new_fft_settings(&fs, 4));
|
TEST_CHECK(C_KZG_OK == new_fft_settings(&fs, 4));
|
||||||
TEST_CHECK(C_KZG_OK == new_kzg_settings(&ks, &fs, s1, s2, secrets_len));
|
TEST_CHECK(C_KZG_OK == new_kzg_settings(&ks, &fs, s1, s2, secrets_len));
|
||||||
|
|
||||||
init_poly(&a, 0);
|
init_poly(&a, 0);
|
||||||
commit_to_poly(&result, &ks, &a);
|
commit_to_poly(&result, &a, &ks);
|
||||||
blst_p1_to_affine(&result_affine, &result);
|
blst_p1_to_affine(&result_affine, &result);
|
||||||
TEST_CHECK(blst_p1_affine_is_equal(&identity_g1_affine, &result_affine));
|
TEST_CHECK(blst_p1_affine_is_equal(&identity_g1_affine, &result_affine));
|
||||||
|
|
||||||
|
free_fft_settings(&fs);
|
||||||
|
free_kzg_settings(&ks);
|
||||||
|
free(s1);
|
||||||
|
free(s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_LIST = {
|
TEST_LIST = {
|
||||||
|
|
10
src/poly.c
10
src/poly.c
|
@ -25,7 +25,15 @@ static void poly_factor_div(blst_fr *out, const blst_fr *a, const blst_fr *b) {
|
||||||
|
|
||||||
C_KZG_RET init_poly(poly *out, const uint64_t length) {
|
C_KZG_RET init_poly(poly *out, const uint64_t length) {
|
||||||
out->length = length;
|
out->length = length;
|
||||||
return c_kzg_malloc((void **)&out->coeffs, length * sizeof(blst_fr));
|
return c_kzg_malloc((void **)&out->coeffs, length * sizeof *out->coeffs);
|
||||||
|
}
|
||||||
|
|
||||||
|
C_KZG_RET init_poly_with_coeffs(poly *out, const uint64_t *coeffs, const uint64_t length) {
|
||||||
|
ASSERT(init_poly(out, length) == C_KZG_OK, C_KZG_MALLOC);
|
||||||
|
for (uint64_t i = 0; i < length; i++) {
|
||||||
|
fr_from_uint64(&out->coeffs[i], coeffs[i]);
|
||||||
|
}
|
||||||
|
return C_KZG_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_poly(poly *p) {
|
void free_poly(poly *p) {
|
||||||
|
|
|
@ -23,6 +23,7 @@ typedef struct {
|
||||||
} poly;
|
} poly;
|
||||||
|
|
||||||
C_KZG_RET init_poly(poly *out, const uint64_t length);
|
C_KZG_RET init_poly(poly *out, const uint64_t length);
|
||||||
|
C_KZG_RET init_poly_with_coeffs(poly *out, const uint64_t *coeffs, const uint64_t length);
|
||||||
void free_poly(poly *p);
|
void free_poly(poly *p);
|
||||||
void eval_poly(blst_fr *out, const poly *p, const blst_fr *x);
|
void eval_poly(blst_fr *out, const poly *p, const blst_fr *x);
|
||||||
uint64_t poly_quotient_length(const poly *dividend, const poly *divisor);
|
uint64_t poly_quotient_length(const poly *dividend, const poly *divisor);
|
||||||
|
|
|
@ -16,12 +16,9 @@
|
||||||
|
|
||||||
#include "../inc/acutest.h"
|
#include "../inc/acutest.h"
|
||||||
#include "debug_util.h"
|
#include "debug_util.h"
|
||||||
|
#include "test_util.h"
|
||||||
#include "poly.h"
|
#include "poly.h"
|
||||||
|
|
||||||
void title(void) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void poly_div_length(void) {
|
void poly_div_length(void) {
|
||||||
poly a, b;
|
poly a, b;
|
||||||
init_poly(&a, 17);
|
init_poly(&a, 17);
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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> // malloc()
|
||||||
|
#include "test_util.h"
|
||||||
|
#include "blst_util.h"
|
||||||
|
|
||||||
|
void generate_trusted_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;
|
||||||
|
|
||||||
|
*s1 = malloc(n * sizeof(blst_p1));
|
||||||
|
*s2 = malloc(n * sizeof(blst_p2));
|
||||||
|
|
||||||
|
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 free_trusted_setup(blst_p1 *s1, blst_p2 *s2) {
|
||||||
|
free(s1);
|
||||||
|
free(s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dummy function used to get the test-suite to print a title
|
||||||
|
void title(void) {}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
// The generator for our "trusted" setup
|
||||||
|
static const 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_trusted_setup(blst_p1 **s1, blst_p2 **s2, const blst_scalar *secret, const uint64_t n);
|
||||||
|
void free_trusted_setup(blst_p1 *s1, blst_p2 *s2);
|
||||||
|
void title(void);
|
Loading…
Reference in New Issue