diff --git a/bindings/rust/README.md b/bindings/rust/README.md index 85d89f39..5a6c098b 100644 --- a/bindings/rust/README.md +++ b/bindings/rust/README.md @@ -19,3 +19,9 @@ cargo test --release ``` cargo bench ``` + +## Update `generated.rs` + +``` +cargo build --features generate-bindings +``` diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs index 484627ee..984f4fa1 100644 --- a/bindings/rust/build.rs +++ b/bindings/rust/build.rs @@ -82,6 +82,7 @@ fn make_bindings(header_path: &str, blst_headers_dir: &str, bindings_out_path: & .allowlist_type("C_KZG_RET") .allowlist_var("BYTES_PER_.*") .allowlist_var("FIELD_ELEMENTS_PER_BLOB") + .allowlist_var("FIELD_ELEMENTS_PER_EXT_BLOB") .allowlist_file(".*eip.*.h") .allowlist_file(".*setup.h") /* diff --git a/bindings/rust/src/bindings/generated.rs b/bindings/rust/src/bindings/generated.rs index 9c698120..82f11096 100644 --- a/bindings/rust/src/bindings/generated.rs +++ b/bindings/rust/src/bindings/generated.rs @@ -6,8 +6,8 @@ pub const BYTES_PER_COMMITMENT: usize = 48; pub const BYTES_PER_PROOF: usize = 48; pub const BYTES_PER_FIELD_ELEMENT: usize = 32; pub const FIELD_ELEMENTS_PER_BLOB: usize = 4096; -pub const BYTES_PER_BLOB: usize = 131072; pub const FIELD_ELEMENTS_PER_EXT_BLOB: usize = 8192; +pub const BYTES_PER_BLOB: usize = 131072; pub const FIELD_ELEMENTS_PER_CELL: usize = 64; pub const CELLS_PER_EXT_BLOB: usize = 128; pub const BYTES_PER_CELL: usize = 2048; @@ -85,13 +85,11 @@ pub struct Blob { #[repr(C)] #[derive(Debug, Hash, PartialEq, Eq)] pub struct KZGSettings { - #[doc = " The length of `roots_of_unity`, a power of 2."] - max_width: u64, - #[doc = " Powers of the primitive root of unity determined by `SCALE2_ROOT_OF_UNITY` in bit-reversal\n permutation order, length `max_width`."] + #[doc = " Roots of unity for the subgroup of size `domain_size`.\n\n The array contains `domain_size + 1` elements, it starts and ends with Fr::one()."] roots_of_unity: *mut fr_t, - #[doc = " The expanded roots of unity."] - expanded_roots_of_unity: *mut fr_t, - #[doc = " The bit-reversal permuted roots of unity."] + #[doc = " Roots of unity for the subgroup of size `domain_size` in bit-reversed order.\n\n This array is derived by applying a bit-reversal permutation to `roots_of_unity`\n excluding the last element. Essentially:\n `brp_roots_of_unity = bit_reversal_permutation(roots_of_unity[:-1])`\n\n The array contains `domain_size` elements."] + brp_roots_of_unity: *mut fr_t, + #[doc = " Roots of unity for the subgroup of size `domain_size` in reversed order.\n\n It is the reversed version of `roots_of_unity`. Essentially:\n `reverse_roots_of_unity = reverse(roots_of_unity)`\n\n This array is primarily used in FFTs.\n The array contains `domain_size + 1` elements, it starts and ends with Fr::one()."] reverse_roots_of_unity: *mut fr_t, #[doc = " G1 group elements from the trusted setup in monomial form."] g1_values_monomial: *mut g1_t, diff --git a/src/Makefile b/src/Makefile index 468916b0..c587443a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -39,15 +39,21 @@ BLST_BUILDSCRIPT_FLAGS = -D__BLST_PORTABLE__ # Libraries to build with. LIBS = $(BLST_LIBRARY) -# List of individual implementation files. -IMPL_FILES = common.c debug.c eip4844.c eip7594.c fft.c setup.c -HEADER_FILES = $(patsubst %.c, %.h, $(IMPL_FILES)) +# Create file lists. +SOURCE_FILES := $(shell find . -name '*.c' | sed 's|^\./||' | sort) +HEADER_FILES := $(patsubst %.c, %.h, $(SOURCE_FILES)) +OBJECT_FILES := $(patsubst %.c, %.o, $(SOURCE_FILES)) + +# There is no tests header file. +HEADER_FILES := $(filter-out tests.h, $(HEADER_FILES)) +# We don't want to format this and it is not expected to change. +HEADER_FILES := $(filter-out tinytest.h, $(HEADER_FILES)) ############################################################################### # Core ############################################################################### -all: ckzg.o test +all: $(OBJECT_FILES) test $(BLST_BUILDSCRIPT): @git submodule update --init @@ -62,8 +68,8 @@ $(BLST_LIBRARY): $(BLST_BUILDSCRIPT) blst: $(BLST_LIBRARY) tests: CFLAGS += -O0 -tests: tests.c $(BLST_LIBRARY) - @$(CC) $(CFLAGS) -o $@ $< $(LIBS) +tests: $(SOURCE_FILES) $(HEADER_FILES) $(BLST_LIBRARY) + @$(CC) $(CFLAGS) -o $@ tests.c $(LIBS) .PHONY: test test: tests @@ -74,17 +80,17 @@ test: tests ############################################################################### tests_cov: CFLAGS += -O0 -fprofile-instr-generate -fcoverage-mapping -tests_cov: tests.c ckzg.c - @$(CC) $(CFLAGS) -o $@ $< $(LIBS) +tests_cov: $(SOURCE_FILES) $(HEADER_FILES) $(BLST_LIBRARY) + @$(CC) $(CFLAGS) -o $@ tests.c $(LIBS) .PHONY: coverage coverage: tests_cov @LLVM_PROFILE_FILE="ckzg.profraw" ./$< @$(XCRUN) llvm-profdata merge --sparse ckzg.profraw -o ckzg.profdata @$(XCRUN) llvm-cov show --instr-profile=ckzg.profdata --format=html \ - $< $(IMPL_FILES) > coverage.html + $< $(SOURCE_FILES) > coverage.html @$(XCRUN) llvm-cov report --instr-profile=ckzg.profdata \ - --show-functions $< $(IMPL_FILES) + --show-functions $< $(SOURCE_FILES) ############################################################################### # Profile @@ -96,8 +102,8 @@ ifeq ($(PLATFORM),Darwin) tests_prof: CFLAGS += -L$(shell brew --prefix gperftools)/lib tests_prof: CFLAGS += -I$(shell brew --prefix gperftools)/include endif -tests_prof: tests.c - @$(CC) $(CFLAGS) -o $@ $< $(LIBS) +tests_prof: $(SOURCE_FILES) $(HEADER_FILES) $(BLST_LIBRARY) + @$(CC) $(CFLAGS) -o $@ tests.c $(LIBS) .PHONY: run_profiler run_profiler: tests_prof @@ -127,9 +133,9 @@ profile: \ .PHONY: sanitize_% sanitize_%: CFLAGS += -O0 -fsanitize=$* -sanitize_%: tests.c +sanitize_%: $(SOURCE_FILES) $(HEADER_FILES) $(BLST_LIBRARY) @echo Running sanitize=$*... - @$(CC) $(CFLAGS) -o $@ $< $(LIBS) + @$(CC) $(CFLAGS) -o $@ tests.c $(LIBS) @ASAN_OPTIONS=allocator_may_return_null=1 \ LSAN_OPTIONS=allocator_may_return_null=1 \ ./$@; rm $@ @@ -152,7 +158,7 @@ endif ############################################################################### .PHONY: analyze -analyze: $(IMPL_FILES) +analyze: $(SOURCE_FILES) $(HEADER_FILES) @$(CC) --analyze -Xanalyzer -analyzer-output=html \ -o analysis-report $(CFLAGS) -c $< @[ -d analysis-report ] && exit 1 || exit 0 @@ -163,7 +169,7 @@ analyze: $(IMPL_FILES) .PHONY: format format: - @clang-format -i --sort-includes $(IMPL_FILES) $(HEADER_FILES) tests.c + @clang-format -i --sort-includes $(SOURCE_FILES) $(HEADER_FILES) .PHONY: clean clean: diff --git a/src/common.h b/src/common.h index 5c98822a..8cd938fc 100644 --- a/src/common.h +++ b/src/common.h @@ -17,6 +17,7 @@ #pragma once #include "blst.h" + #include #ifdef __cplusplus @@ -39,6 +40,9 @@ extern "C" { /** The number of field elements in a blob. */ #define FIELD_ELEMENTS_PER_BLOB 4096 +/** The number of field elements in an extended blob */ +#define FIELD_ELEMENTS_PER_EXT_BLOB (FIELD_ELEMENTS_PER_BLOB * 2) + /** The number of bytes in a blob. */ #define BYTES_PER_BLOB (FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT) @@ -100,14 +104,31 @@ typedef Bytes48 KZGProof; /** Stores the setup and parameters needed for computing KZG proofs. */ typedef struct { - /** The length of `roots_of_unity`, a power of 2. */ - uint64_t max_width; - /** Powers of the primitive root of unity determined by `SCALE2_ROOT_OF_UNITY` in bit-reversal - * permutation order, length `max_width`. */ + /** + * Roots of unity for the subgroup of size `domain_size`. + * + * The array contains `domain_size + 1` elements, it starts and ends with Fr::one(). + */ fr_t *roots_of_unity; - /** The expanded roots of unity. */ - fr_t *expanded_roots_of_unity; - /** The bit-reversal permuted roots of unity. */ + /** + * Roots of unity for the subgroup of size `domain_size` in bit-reversed order. + * + * This array is derived by applying a bit-reversal permutation to `roots_of_unity` + * excluding the last element. Essentially: + * `brp_roots_of_unity = bit_reversal_permutation(roots_of_unity[:-1])` + * + * The array contains `domain_size` elements. + */ + fr_t *brp_roots_of_unity; + /** + * Roots of unity for the subgroup of size `domain_size` in reversed order. + * + * It is the reversed version of `roots_of_unity`. Essentially: + * `reverse_roots_of_unity = reverse(roots_of_unity)` + * + * This array is primarily used in FFTs. + * The array contains `domain_size + 1` elements, it starts and ends with Fr::one(). + */ fr_t *reverse_roots_of_unity; /** G1 group elements from the trusted setup in monomial form. */ g1_t *g1_values_monomial; diff --git a/src/debug.c b/src/debug.c index 8d9e54ef..a478acbb 100644 --- a/src/debug.c +++ b/src/debug.c @@ -16,6 +16,8 @@ #include "debug.h" +#include + void print_bytes32(const Bytes32 *bytes) { for (size_t i = 0; i < 32; i++) { printf("%02x", bytes->bytes[i]); diff --git a/src/eip4844.c b/src/eip4844.c index 4fae1e5d..3b6d5b06 100644 --- a/src/eip4844.c +++ b/src/eip4844.c @@ -19,7 +19,9 @@ #include "blst.h" -#include +#include /* For assert */ +#include /* For NULL */ +#include /* For memcpy */ //////////////////////////////////////////////////////////////////////////////////////////////////// // Macros @@ -197,7 +199,7 @@ static C_KZG_RET evaluate_polynomial_in_evaluation_form( fr_t *inverses_in = NULL; fr_t *inverses = NULL; uint64_t i; - const fr_t *roots_of_unity = s->roots_of_unity; + const fr_t *brp_roots_of_unity = s->brp_roots_of_unity; ret = new_fr_array(&inverses_in, FIELD_ELEMENTS_PER_BLOB); if (ret != C_KZG_OK) goto out; @@ -210,12 +212,12 @@ static C_KZG_RET evaluate_polynomial_in_evaluation_form( * given, we can just return the result directly. Note that special-casing this is * necessary, as the formula below would divide by zero otherwise. */ - if (fr_equal(x, &roots_of_unity[i])) { + if (fr_equal(x, &brp_roots_of_unity[i])) { *out = p->evals[i]; ret = C_KZG_OK; goto out; } - blst_fr_sub(&inverses_in[i], x, &roots_of_unity[i]); + blst_fr_sub(&inverses_in[i], x, &brp_roots_of_unity[i]); } ret = fr_batch_inv(inverses, inverses_in, FIELD_ELEMENTS_PER_BLOB); @@ -223,7 +225,7 @@ static C_KZG_RET evaluate_polynomial_in_evaluation_form( *out = FR_ZERO; for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) { - blst_fr_mul(&tmp, &inverses[i], &roots_of_unity[i]); + blst_fr_mul(&tmp, &inverses[i], &brp_roots_of_unity[i]); blst_fr_mul(&tmp, &tmp, &p->evals[i]); blst_fr_add(out, out, &tmp); } @@ -428,7 +430,7 @@ static C_KZG_RET compute_kzg_proof_impl( fr_t tmp; Polynomial q; - const fr_t *roots_of_unity = s->roots_of_unity; + const fr_t *brp_roots_of_unity = s->brp_roots_of_unity; uint64_t i; /* m != 0 indicates that the evaluation point z equals root_of_unity[m-1] */ uint64_t m = 0; @@ -439,7 +441,7 @@ static C_KZG_RET compute_kzg_proof_impl( if (ret != C_KZG_OK) goto out; for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) { - if (fr_equal(z, &roots_of_unity[i])) { + if (fr_equal(z, &brp_roots_of_unity[i])) { /* We are asked to compute a KZG proof inside the domain */ m = i + 1; inverses_in[i] = FR_ONE; @@ -447,7 +449,7 @@ static C_KZG_RET compute_kzg_proof_impl( } // (p_i - y) / (ω_i - z) blst_fr_sub(&q.evals[i], &polynomial->evals[i], y_out); - blst_fr_sub(&inverses_in[i], &roots_of_unity[i], z); + blst_fr_sub(&inverses_in[i], &brp_roots_of_unity[i], z); } ret = fr_batch_inv(inverses, inverses_in, FIELD_ELEMENTS_PER_BLOB); @@ -462,7 +464,7 @@ static C_KZG_RET compute_kzg_proof_impl( for (i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) { if (i == m) continue; /* Build denominator: z * (z - ω_i) */ - blst_fr_sub(&tmp, z, &roots_of_unity[i]); + blst_fr_sub(&tmp, z, &brp_roots_of_unity[i]); blst_fr_mul(&inverses_in[i], &tmp, z); } @@ -473,7 +475,7 @@ static C_KZG_RET compute_kzg_proof_impl( if (i == m) continue; /* Build numerator: ω_i * (p_i - y) */ blst_fr_sub(&tmp, &polynomial->evals[i], y_out); - blst_fr_mul(&tmp, &tmp, &roots_of_unity[i]); + blst_fr_mul(&tmp, &tmp, &brp_roots_of_unity[i]); /* Do the division: (p_i - y) * ω_i / (z * (z - ω_i)) */ blst_fr_mul(&tmp, &tmp, &inverses[i]); blst_fr_add(&q.evals[m], &q.evals[m], &tmp); diff --git a/src/eip7594.c b/src/eip7594.c index 694b9bd4..e827d383 100644 --- a/src/eip7594.c +++ b/src/eip7594.c @@ -20,8 +20,9 @@ #include "common.h" #include "fft.h" -#include -#include +#include /* For assert */ +#include /* For NULL */ +#include /* For memcpy */ //////////////////////////////////////////////////////////////////////////////////////////////////// // Constants @@ -163,7 +164,7 @@ static C_KZG_RET compute_vanishing_polynomial_from_roots( * the domain of size `FIELD_ELEMENTS_PER_BLOB`. * * The roots of unity are chosen based on the missing cell indices. If the i'th cell is missing, - * then the i'th root of unity from `expanded_roots_of_unity` will be zero on the polynomial + * then the i'th root of unity from `roots_of_unity` will be zero on the polynomial * computed, along with every `CELLS_PER_EXT_BLOB` spaced root of unity in the domain. * * @param[in,out] vanishing_poly The vanishing polynomial @@ -200,9 +201,6 @@ static C_KZG_RET vanishing_polynomial_for_missing_cells( ret = new_fr_array(&short_vanishing_poly, (len_missing_cells + 1)); if (ret != C_KZG_OK) goto out; - /* Check if max_width is divisible by CELLS_PER_EXT_BLOB */ - assert(s->max_width % CELLS_PER_EXT_BLOB == 0); - /* * For each missing cell index, choose the corresponding root of unity from the subgroup of * size `CELLS_PER_EXT_BLOB`. @@ -210,9 +208,9 @@ static C_KZG_RET vanishing_polynomial_for_missing_cells( * In other words, if the missing index is `i`, then we add \omega^i to the roots array, where * \omega is a primitive `CELLS_PER_EXT_BLOB` root of unity. */ - size_t stride = s->max_width / CELLS_PER_EXT_BLOB; + size_t stride = FIELD_ELEMENTS_PER_EXT_BLOB / CELLS_PER_EXT_BLOB; for (size_t i = 0; i < len_missing_cells; i++) { - roots[i] = s->expanded_roots_of_unity[missing_cell_indices[i] * stride]; + roots[i] = s->roots_of_unity[missing_cell_indices[i] * stride]; } /* Compute the polynomial that evaluates to zero on the roots */ @@ -372,28 +370,30 @@ static C_KZG_RET recover_cells_impl( fr_t *cells_brp = NULL; /* Allocate space for arrays */ - ret = c_kzg_calloc((void **)&missing_cell_indices, s->max_width, sizeof(uint64_t)); + ret = c_kzg_calloc( + (void **)&missing_cell_indices, FIELD_ELEMENTS_PER_EXT_BLOB, sizeof(uint64_t) + ); if (ret != C_KZG_OK) goto out; - ret = new_fr_array(&vanishing_poly_eval, s->max_width); + ret = new_fr_array(&vanishing_poly_eval, FIELD_ELEMENTS_PER_EXT_BLOB); if (ret != C_KZG_OK) goto out; - ret = new_fr_array(&vanishing_poly_coeff, s->max_width); + ret = new_fr_array(&vanishing_poly_coeff, FIELD_ELEMENTS_PER_EXT_BLOB); if (ret != C_KZG_OK) goto out; - ret = new_fr_array(&extended_evaluation_times_zero, s->max_width); + ret = new_fr_array(&extended_evaluation_times_zero, FIELD_ELEMENTS_PER_EXT_BLOB); if (ret != C_KZG_OK) goto out; - ret = new_fr_array(&extended_evaluation_times_zero_coeffs, s->max_width); + ret = new_fr_array(&extended_evaluation_times_zero_coeffs, FIELD_ELEMENTS_PER_EXT_BLOB); if (ret != C_KZG_OK) goto out; - ret = new_fr_array(&extended_evaluations_over_coset, s->max_width); + ret = new_fr_array(&extended_evaluations_over_coset, FIELD_ELEMENTS_PER_EXT_BLOB); if (ret != C_KZG_OK) goto out; - ret = new_fr_array(&vanishing_poly_over_coset, s->max_width); + ret = new_fr_array(&vanishing_poly_over_coset, FIELD_ELEMENTS_PER_EXT_BLOB); if (ret != C_KZG_OK) goto out; - ret = new_fr_array(&reconstructed_poly_coeff, s->max_width); + ret = new_fr_array(&reconstructed_poly_coeff, FIELD_ELEMENTS_PER_EXT_BLOB); if (ret != C_KZG_OK) goto out; - ret = new_fr_array(&cells_brp, s->max_width); + ret = new_fr_array(&cells_brp, FIELD_ELEMENTS_PER_EXT_BLOB); if (ret != C_KZG_OK) goto out; /* Bit-reverse the data points, stored in new array */ - memcpy(cells_brp, cells, s->max_width * sizeof(fr_t)); - ret = bit_reversal_permutation(cells_brp, sizeof(fr_t), s->max_width); + memcpy(cells_brp, cells, FIELD_ELEMENTS_PER_EXT_BLOB * sizeof(fr_t)); + ret = bit_reversal_permutation(cells_brp, sizeof(fr_t), FIELD_ELEMENTS_PER_EXT_BLOB); if (ret != C_KZG_OK) goto out; /* Identify missing cells */ @@ -420,11 +420,11 @@ static C_KZG_RET recover_cells_impl( if (ret != C_KZG_OK) goto out; /* Convert Z(x) to evaluation form */ - ret = fr_fft(vanishing_poly_eval, vanishing_poly_coeff, s->max_width, s); + ret = fr_fft(vanishing_poly_eval, vanishing_poly_coeff, FIELD_ELEMENTS_PER_EXT_BLOB, s); if (ret != C_KZG_OK) goto out; /* Compute (E*Z)(x) = E(x) * Z(x) in evaluation form over the FFT domain */ - for (size_t i = 0; i < s->max_width; i++) { + for (size_t i = 0; i < FIELD_ELEMENTS_PER_EXT_BLOB; i++) { if (fr_is_null(&cells_brp[i])) { extended_evaluation_times_zero[i] = FR_ZERO; } else { @@ -434,7 +434,10 @@ static C_KZG_RET recover_cells_impl( /* Convert (E*Z)(x) to monomial form */ ret = fr_ifft( - extended_evaluation_times_zero_coeffs, extended_evaluation_times_zero, s->max_width, s + extended_evaluation_times_zero_coeffs, + extended_evaluation_times_zero, + FIELD_ELEMENTS_PER_EXT_BLOB, + s ); if (ret != C_KZG_OK) goto out; @@ -445,15 +448,20 @@ static C_KZG_RET recover_cells_impl( * Q3 = D(k * x) */ ret = coset_fft( - extended_evaluations_over_coset, extended_evaluation_times_zero_coeffs, s->max_width, s + extended_evaluations_over_coset, + extended_evaluation_times_zero_coeffs, + FIELD_ELEMENTS_PER_EXT_BLOB, + s ); if (ret != C_KZG_OK) goto out; - ret = coset_fft(vanishing_poly_over_coset, vanishing_poly_coeff, s->max_width, s); + ret = coset_fft( + vanishing_poly_over_coset, vanishing_poly_coeff, FIELD_ELEMENTS_PER_EXT_BLOB, s + ); if (ret != C_KZG_OK) goto out; /* The result of the division is Q3 */ - for (size_t i = 0; i < s->max_width; i++) { + for (size_t i = 0; i < FIELD_ELEMENTS_PER_EXT_BLOB; i++) { fr_div( &extended_evaluations_over_coset[i], &extended_evaluations_over_coset[i], @@ -467,18 +475,22 @@ static C_KZG_RET recover_cells_impl( */ /* Convert the evaluations back to coefficents */ - ret = coset_ifft(reconstructed_poly_coeff, extended_evaluations_over_coset, s->max_width, s); + ret = coset_ifft( + reconstructed_poly_coeff, extended_evaluations_over_coset, FIELD_ELEMENTS_PER_EXT_BLOB, s + ); if (ret != C_KZG_OK) goto out; /* * After unscaling the reconstructed polynomial, we have D(x) which evaluates to our original * data at the roots of unity. Next, we evaluate the polynomial to get the original data. */ - ret = fr_fft(reconstructed_data_out, reconstructed_poly_coeff, s->max_width, s); + ret = fr_fft(reconstructed_data_out, reconstructed_poly_coeff, FIELD_ELEMENTS_PER_EXT_BLOB, s); if (ret != C_KZG_OK) goto out; /* Bit-reverse the recovered data points */ - ret = bit_reversal_permutation(reconstructed_data_out, sizeof(fr_t), s->max_width); + ret = bit_reversal_permutation( + reconstructed_data_out, sizeof(fr_t), FIELD_ELEMENTS_PER_EXT_BLOB + ); if (ret != C_KZG_OK) goto out; out: @@ -1012,7 +1024,7 @@ C_KZG_RET recover_cells_and_kzg_proofs( } /* Do allocations */ - ret = new_fr_array(&recovered_cells_fr, s->max_width); + ret = new_fr_array(&recovered_cells_fr, FIELD_ELEMENTS_PER_EXT_BLOB); if (ret != C_KZG_OK) goto out; ret = new_g1_array(&recovered_proofs_g1, CELLS_PER_EXT_BLOB); if (ret != C_KZG_OK) goto out; @@ -1020,7 +1032,7 @@ C_KZG_RET recover_cells_and_kzg_proofs( if (ret != C_KZG_OK) goto out; /* Initialize all cells as missing */ - for (size_t i = 0; i < s->max_width; i++) { + for (size_t i = 0; i < FIELD_ELEMENTS_PER_EXT_BLOB; i++) { recovered_cells_fr[i] = FR_NULL; } @@ -1330,7 +1342,7 @@ C_KZG_RET verify_cell_kzg_proof_batch( */ uint32_t pos = reverse_bits_limited(CELLS_PER_EXT_BLOB, i); fr_t inv_coset_factor; - blst_fr_eucl_inverse(&inv_coset_factor, &s->expanded_roots_of_unity[pos]); + blst_fr_eucl_inverse(&inv_coset_factor, &s->roots_of_unity[pos]); shift_poly(column_interpolation_poly, FIELD_ELEMENTS_PER_CELL, &inv_coset_factor); /* Update the aggregated poly */ @@ -1358,7 +1370,7 @@ C_KZG_RET verify_cell_kzg_proof_batch( for (size_t i = 0; i < num_cells; i++) { uint32_t pos = reverse_bits_limited(CELLS_PER_EXT_BLOB, cell_indices[i]); - fr_t coset_factor = s->expanded_roots_of_unity[pos]; + fr_t coset_factor = s->roots_of_unity[pos]; fr_pow(&weights[i], &coset_factor, FIELD_ELEMENTS_PER_CELL); blst_fr_mul(&weighted_powers_of_r[i], &r_powers[i], &weights[i]); } diff --git a/src/eip7594.h b/src/eip7594.h index 9a246b02..b04287b9 100644 --- a/src/eip7594.h +++ b/src/eip7594.h @@ -16,10 +16,10 @@ #pragma once -#include - #include "common.h" +#include + #ifdef __cplusplus extern "C" { #endif @@ -28,9 +28,6 @@ extern "C" { // Macros //////////////////////////////////////////////////////////////////////////////////////////////////// -/** The number of field elements in an extended blob */ -#define FIELD_ELEMENTS_PER_EXT_BLOB (FIELD_ELEMENTS_PER_BLOB * 2) - /** The number of field elements in a cell. */ #define FIELD_ELEMENTS_PER_CELL 64 diff --git a/src/fft.c b/src/fft.c index d2a1b0a2..f0e3d914 100644 --- a/src/fft.c +++ b/src/fft.c @@ -63,12 +63,12 @@ static void fr_fft_fast( */ C_KZG_RET fr_fft(fr_t *out, const fr_t *in, size_t n, const KZGSettings *s) { /* Ensure the length is valid */ - if (n > s->max_width || !is_power_of_two(n)) { + if (n > FIELD_ELEMENTS_PER_EXT_BLOB || !is_power_of_two(n)) { return C_KZG_BADARGS; } - size_t stride = s->max_width / n; - fr_fft_fast(out, in, 1, s->expanded_roots_of_unity, stride, n); + size_t stride = FIELD_ELEMENTS_PER_EXT_BLOB / n; + fr_fft_fast(out, in, 1, s->roots_of_unity, stride, n); return C_KZG_OK; } @@ -86,11 +86,11 @@ C_KZG_RET fr_fft(fr_t *out, const fr_t *in, size_t n, const KZGSettings *s) { */ C_KZG_RET fr_ifft(fr_t *out, const fr_t *in, size_t n, const KZGSettings *s) { /* Ensure the length is valid */ - if (n > s->max_width || !is_power_of_two(n)) { + if (n > FIELD_ELEMENTS_PER_EXT_BLOB || !is_power_of_two(n)) { return C_KZG_BADARGS; } - size_t stride = s->max_width / n; + size_t stride = FIELD_ELEMENTS_PER_EXT_BLOB / n; fr_fft_fast(out, in, 1, s->reverse_roots_of_unity, stride, n); fr_t inv_len; @@ -159,12 +159,12 @@ static void g1_fft_fast( */ C_KZG_RET g1_fft(g1_t *out, const g1_t *in, size_t n, const KZGSettings *s) { /* Ensure the length is valid */ - if (n > s->max_width || !is_power_of_two(n)) { + if (n > FIELD_ELEMENTS_PER_EXT_BLOB || !is_power_of_two(n)) { return C_KZG_BADARGS; } - uint64_t stride = s->max_width / n; - g1_fft_fast(out, in, 1, s->expanded_roots_of_unity, stride, n); + uint64_t stride = FIELD_ELEMENTS_PER_EXT_BLOB / n; + g1_fft_fast(out, in, 1, s->roots_of_unity, stride, n); return C_KZG_OK; } @@ -182,11 +182,11 @@ C_KZG_RET g1_fft(g1_t *out, const g1_t *in, size_t n, const KZGSettings *s) { */ C_KZG_RET g1_ifft(g1_t *out, const g1_t *in, size_t n, const KZGSettings *s) { /* Ensure the length is valid */ - if (n > s->max_width || !is_power_of_two(n)) { + if (n > FIELD_ELEMENTS_PER_EXT_BLOB || !is_power_of_two(n)) { return C_KZG_BADARGS; } - uint64_t stride = s->max_width / n; + uint64_t stride = FIELD_ELEMENTS_PER_EXT_BLOB / n; g1_fft_fast(out, in, 1, s->reverse_roots_of_unity, stride, n); fr_t inv_len; diff --git a/src/setup.c b/src/setup.c index 7bb25518..fee3f72a 100644 --- a/src/setup.c +++ b/src/setup.c @@ -15,9 +15,15 @@ */ #include "setup.h" +#include "common.h" #include "eip7594.h" +#include "fft.h" +#include /* For assert */ #include /* For SCNu64 */ +#include /* For FILE */ +#include /* For NULL */ +#include /* For memcpy */ //////////////////////////////////////////////////////////////////////////////////////////////////// // Macros @@ -85,7 +91,7 @@ static C_KZG_RET compute_roots_of_unity(KZGSettings *s) { fr_t root_of_unity; uint32_t max_scale = 0; - while ((1ULL << max_scale) < s->max_width) + while ((1ULL << max_scale) < FIELD_ELEMENTS_PER_EXT_BLOB) max_scale++; /* Ensure this element will exist */ @@ -93,23 +99,25 @@ static C_KZG_RET compute_roots_of_unity(KZGSettings *s) { return C_KZG_BADARGS; } - /* Get the root of unity */ + /* Get the right subgroup generator */ blst_fr_from_uint64(&root_of_unity, SCALE2_ROOT_OF_UNITY[max_scale]); /* Populate the roots of unity */ - ret = expand_root_of_unity(s->expanded_roots_of_unity, &root_of_unity, s->max_width); + ret = expand_root_of_unity(s->roots_of_unity, &root_of_unity, FIELD_ELEMENTS_PER_EXT_BLOB); if (ret != C_KZG_OK) goto out; /* Copy all but the last root to the roots of unity */ - memcpy(s->roots_of_unity, s->expanded_roots_of_unity, sizeof(fr_t) * s->max_width); + memcpy(s->brp_roots_of_unity, s->roots_of_unity, sizeof(fr_t) * FIELD_ELEMENTS_PER_EXT_BLOB); - /* Permute the roots of unity */ - ret = bit_reversal_permutation(s->roots_of_unity, sizeof(fr_t), s->max_width); + /* Apply the bit reversal permutation to the roots of unity */ + ret = bit_reversal_permutation( + s->brp_roots_of_unity, sizeof(fr_t), FIELD_ELEMENTS_PER_EXT_BLOB + ); if (ret != C_KZG_OK) goto out; /* Populate reverse roots of unity */ - for (uint64_t i = 0; i <= s->max_width; i++) { - s->reverse_roots_of_unity[i] = s->expanded_roots_of_unity[s->max_width - i]; + for (uint64_t i = 0; i <= FIELD_ELEMENTS_PER_EXT_BLOB; i++) { + s->reverse_roots_of_unity[i] = s->roots_of_unity[FIELD_ELEMENTS_PER_EXT_BLOB - i]; } out: @@ -125,9 +133,8 @@ static C_KZG_RET compute_roots_of_unity(KZGSettings *s) { */ void free_trusted_setup(KZGSettings *s) { if (s == NULL) return; - s->max_width = 0; + c_kzg_free(s->brp_roots_of_unity); c_kzg_free(s->roots_of_unity); - c_kzg_free(s->expanded_roots_of_unity); c_kzg_free(s->reverse_roots_of_unity); c_kzg_free(s->g1_values_monomial); c_kzg_free(s->g1_values_lagrange_brp); @@ -202,7 +209,7 @@ static C_KZG_RET init_fk20_multi_settings(KZGSettings *s) { blst_p1_affine *p_affine = NULL; bool precompute = s->wbits != 0; - n = s->max_width / 2; + n = FIELD_ELEMENTS_PER_EXT_BLOB / 2; k = n / FIELD_ELEMENTS_PER_CELL; k2 = 2 * k; @@ -339,9 +346,8 @@ C_KZG_RET load_trusted_setup( ) { C_KZG_RET ret; - out->max_width = 0; + out->brp_roots_of_unity = NULL; out->roots_of_unity = NULL; - out->expanded_roots_of_unity = NULL; out->reverse_roots_of_unity = NULL; out->g1_values_monomial = NULL; out->g1_values_lagrange_brp = NULL; @@ -376,18 +382,12 @@ C_KZG_RET load_trusted_setup( while ((1ULL << max_scale) < NUM_G1_POINTS) max_scale++; - /* Set the max_width */ - out->max_width = 1ULL << max_scale; - - /* For DAS reconstruction */ - out->max_width *= 2; - /* Allocate all of our arrays */ - ret = new_fr_array(&out->roots_of_unity, out->max_width); + ret = new_fr_array(&out->brp_roots_of_unity, FIELD_ELEMENTS_PER_EXT_BLOB); if (ret != C_KZG_OK) goto out_error; - ret = new_fr_array(&out->expanded_roots_of_unity, out->max_width + 1); + ret = new_fr_array(&out->roots_of_unity, FIELD_ELEMENTS_PER_EXT_BLOB + 1); if (ret != C_KZG_OK) goto out_error; - ret = new_fr_array(&out->reverse_roots_of_unity, out->max_width + 1); + ret = new_fr_array(&out->reverse_roots_of_unity, FIELD_ELEMENTS_PER_EXT_BLOB + 1); if (ret != C_KZG_OK) goto out_error; ret = new_g1_array(&out->g1_values_monomial, NUM_G1_POINTS); if (ret != C_KZG_OK) goto out_error; diff --git a/src/setup.h b/src/setup.h index 4eab1f94..2a2f1ee4 100644 --- a/src/setup.h +++ b/src/setup.h @@ -15,6 +15,8 @@ */ #pragma once +#include "common.h" + #include #ifdef __cplusplus diff --git a/src/tests.c b/src/tests.c index 1d00ca2a..c4128d96 100644 --- a/src/tests.c +++ b/src/tests.c @@ -982,7 +982,7 @@ static void test_evaluate_polynomial_in_evaluation_form__constant_polynomial_in_ fr_t x, y, c; get_rand_fr(&c); - x = s.roots_of_unity[123]; + x = s.brp_roots_of_unity[123]; for (size_t i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) { p.evals[i] = c; @@ -1005,7 +1005,7 @@ static void test_evaluate_polynomial_in_evaluation_form__random_polynomial(void) } for (size_t i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) { - eval_poly(&p.evals[i], poly_coefficients, &s.roots_of_unity[i]); + eval_poly(&p.evals[i], poly_coefficients, &s.brp_roots_of_unity[i]); } get_rand_fr(&x); @@ -1016,7 +1016,7 @@ static void test_evaluate_polynomial_in_evaluation_form__random_polynomial(void) ASSERT("evaluation methods match", fr_equal(&y, &check)); - x = s.roots_of_unity[123]; + x = s.brp_roots_of_unity[123]; eval_poly(&check, poly_coefficients, &x); @@ -1186,7 +1186,7 @@ static void test_compute_and_verify_kzg_proof__succeeds_within_domain(void) { ret = blob_to_polynomial(poly.evals, &blob); ASSERT_EQUALS(ret, C_KZG_OK); - z_fr = s.roots_of_unity[i]; + z_fr = s.brp_roots_of_unity[i]; bytes_from_bls_field(&z, &z_fr); /* Compute the proof */ @@ -1680,7 +1680,7 @@ static void test_fft(void) { for (size_t i = 0; i < N; i++) { fr_t individual_evaluation; - eval_extended_poly(&individual_evaluation, poly_coeff, &s.expanded_roots_of_unity[i]); + eval_extended_poly(&individual_evaluation, poly_coeff, &s.roots_of_unity[i]); bool ok = fr_equal(&individual_evaluation, &poly_eval[i]); ASSERT_EQUALS(ok, true); @@ -1717,7 +1717,7 @@ static void test_coset_fft(void) { fr_t shifted_w; fr_t individual_evaluation; - blst_fr_mul(&shifted_w, &s.expanded_roots_of_unity[i], &RECOVERY_SHIFT_FACTOR); + blst_fr_mul(&shifted_w, &s.roots_of_unity[i], &RECOVERY_SHIFT_FACTOR); eval_extended_poly(&individual_evaluation, poly_coeff, &shifted_w); @@ -1900,11 +1900,11 @@ static void test_compute_vanishing_polynomial_from_roots(void) { static void test_vanishing_polynomial_for_missing_cells(void) { fr_t *vanishing_poly = NULL; - C_KZG_RET ret = new_fr_array(&vanishing_poly, s.max_width); + C_KZG_RET ret = new_fr_array(&vanishing_poly, FIELD_ELEMENTS_PER_EXT_BLOB); ASSERT("vanishing poly alloc", ret == C_KZG_OK); fr_t *fft_result = NULL; - ret = new_fr_array(&fft_result, s.max_width); + ret = new_fr_array(&fft_result, FIELD_ELEMENTS_PER_EXT_BLOB); ASSERT("fft_result alloc", ret == C_KZG_OK); /* Test case: the 0th and 1st cell are missing */ @@ -1919,7 +1919,7 @@ static void test_vanishing_polynomial_for_missing_cells(void) { ASSERT("compute vanishing poly from cells", ret == C_KZG_OK); /* Compute FFT of vanishing_poly */ - fr_fft(fft_result, vanishing_poly, s.max_width, &s); + fr_fft(fft_result, vanishing_poly, FIELD_ELEMENTS_PER_EXT_BLOB, &s); /* * Check FFT results @@ -1930,34 +1930,34 @@ static void test_vanishing_polynomial_for_missing_cells(void) { * We expect that the following roots will evaluate to zero on the vanishing polynomial we * computed: * - * s->expanded_roots_of_unity[0] - * s->expanded_roots_of_unity[128] - * s->expanded_roots_of_unity[256] + * s->roots_of_unity[0] + * s->roots_of_unity[128] + * s->roots_of_unity[256] * ... - * s->expanded_roots_of_unity[8064] + * s->roots_of_unity[8064] * * For every cell index, we should have `FIELD_ELEMENTS_PER_CELL` number of these roots. ie each - * cell index corresponds to 64 roots taken from `expanded_roots_of_unity` in the vanishing + * cell index corresponds to 64 roots taken from `roots_of_unity` in the vanishing * polynomial. * - * In general, the formula is expanded_roots_of_unity[cell_index + CELLS_PER_EXT_BLOB * k] where + * In general, the formula is roots_of_unity[cell_index + CELLS_PER_EXT_BLOB * k] where * `k` goes from 0 to FIELD_ELEMENTS_PER_CELL-1. * * For cell index 1, we would therefore expect the polynomial to vanish at points: * - * s->expanded_roots_of_unity[1] - * s->expanded_roots_of_unity[129] - * s->expanded_roots_of_unity[257] + * s->roots_of_unity[1] + * s->roots_of_unity[129] + * s->roots_of_unity[257] * ... - * s->expanded_roots_of_unity[8065] + * s->roots_of_unity[8065] * * Sanity check: * The largest cell index we can have is 127 since there are 128 cells. * * The last element for that cell index would have array index `127 + 128*63 = 8191`. This is - * correct since `expanded_roots_of_unity` has 8192 elements. + * correct since `roots_of_unity` has 8192 elements. */ - for (size_t i = 0; i < s.max_width; i++) { + for (size_t i = 0; i < FIELD_ELEMENTS_PER_EXT_BLOB; i++) { if (i % CELLS_PER_EXT_BLOB == 1 || i % CELLS_PER_EXT_BLOB == 0) { /* Every CELLS_PER_EXT_BLOB-th evaluation should be zero */ ASSERT("evaluation is zero", fr_is_zero(&fft_result[i]));