Skip to content

Commit

Permalink
Pre-compute root of unity in fr-form (#491)
Browse files Browse the repository at this point in the history
* Pre-compute root of unity in fr-form

* Remove NUM_ELEMENTS macro

* Reformat shift factors

* Regenerate Rust bindings

* Add back a test

* Fix comment

* Delete double space

* Delete unnecessary max_scale computation

* Add back tests + a new one

* Fix comment
  • Loading branch information
jtraglia authored Aug 16, 2024
1 parent 344188f commit 87bb61e
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 100 deletions.
2 changes: 0 additions & 2 deletions bindings/rust/src/bindings/generated.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 2 additions & 8 deletions src/eip7594/fft.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,7 @@
* printf("%#018llxL,\n", a.l[i]);
*/
static const fr_t RECOVERY_SHIFT_FACTOR = {
0x0000000efffffff1L,
0x17e363d300189c0fL,
0xff9c57876f8457b0L,
0x351332208fc5a8c4L,
0x0000000efffffff1L, 0x17e363d300189c0fL, 0xff9c57876f8457b0L, 0x351332208fc5a8c4L
};

/**
Expand All @@ -51,10 +48,7 @@ static const fr_t RECOVERY_SHIFT_FACTOR = {
* printf("%#018llxL,\n", a.l[i]);
*/
static const fr_t INV_RECOVERY_SHIFT_FACTOR = {
0xdb6db6dadb6db6dcL,
0xe6b5824adb6cc6daL,
0xf8b356e005810db9L,
0x66d0f1e660ec4796L,
0xdb6db6dadb6db6dcL, 0xe6b5824adb6cc6daL, 0xf8b356e005810db9L, 0x66d0f1e660ec4796L
};

////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
60 changes: 38 additions & 22 deletions src/setup/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,42 @@
/** The number of g2 points in a trusted setup. */
#define NUM_G2_POINTS 65

/** Returns number of elements in a statically defined array. */
#define NUM_ELEMENTS(a) (sizeof(a) / sizeof(a[0]))
////////////////////////////////////////////////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////////////////////////////////////////////////

/**
* This is the root of unity associated with FIELD_ELEMENTS_PER_EXT_BLOB.
*
* Compute this constant with the scripts below:
*
* @code{.py}
* import math
*
* FIELD_ELEMENTS_PER_EXT_BLOB = 8192
* PRIMITIVE_ROOT_OF_UNITY = 7
* BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513
*
* order = int(math.log2(FIELD_ELEMENTS_PER_EXT_BLOB))
* root_of_unity = pow(PRIMITIVE_ROOT_OF_UNITY, (BLS_MODULUS - 1) // (2**order), BLS_MODULUS)
* uint64s = [(root_of_unity >> (64 * i)) & 0xFFFFFFFFFFFFFFFF for i in range(4)]
* values = [f"0x{uint64:016x}L" for uint64 in uint64s]
* print(f"{{{', '.join(values)}}}")
* @endcode
*
* Then paste the output into the following:
*
* @code{.c}
* fr_t root_of_unity;
* uint64_t values[4] = <output-from-python>;
* blst_fr_from_uint64(&root_of_unity, values);
* for (size_t i = 0; i < 4; i++)
* printf("%#018llxL,\n", root_of_unity.l[i]);
* @endcode
*/
static const fr_t ROOT_OF_UNITY = {
0xa33d279ff0ccffc9L, 0x41fac79f59e91972L, 0x065d227fead1139bL, 0x71db41abda03e055L
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Trusted Setup Functions
Expand Down Expand Up @@ -92,22 +126,9 @@ static C_KZG_RET expand_root_of_unity(fr_t *out, const fr_t *root, size_t width)
*/
static C_KZG_RET compute_roots_of_unity(KZGSettings *s) {
C_KZG_RET ret;
fr_t root_of_unity;

size_t max_scale = 0;
while ((1ULL << max_scale) < FIELD_ELEMENTS_PER_EXT_BLOB)
max_scale++;

/* Ensure this element will exist */
if (max_scale >= NUM_ELEMENTS(SCALE2_ROOT_OF_UNITY)) {
return C_KZG_BADARGS;
}

/* 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->roots_of_unity, &root_of_unity, FIELD_ELEMENTS_PER_EXT_BLOB);
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 */
Expand Down Expand Up @@ -146,7 +167,7 @@ void free_trusted_setup(KZGSettings *s) {

/*
* If for whatever reason we accidentally call free_trusted_setup() on an uninitialized
* structure, we don't want to deference these 2d arrays. Without these NULL checks, it's
* structure, we don't want to deference these 2d arrays. Without these NULL checks, it's
* possible for there to be a segmentation fault via null pointer dereference.
*/
if (s->x_ext_fft_columns != NULL) {
Expand Down Expand Up @@ -381,11 +402,6 @@ C_KZG_RET load_trusted_setup(
goto out_error;
}

/* 1<<max_scale is the smallest power of 2 >= n1 */
size_t max_scale = 0;
while ((1ULL << max_scale) < NUM_G1_POINTS)
max_scale++;

/* Allocate all of our arrays */
ret = new_fr_array(&out->brp_roots_of_unity, FIELD_ELEMENTS_PER_EXT_BLOB);
if (ret != C_KZG_OK) goto out_error;
Expand Down
62 changes: 0 additions & 62 deletions src/setup/setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,68 +20,6 @@

#include <stdio.h> /* For FILE */

////////////////////////////////////////////////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////////////////////////////////////////////////

/**
* The first 32 roots of unity in the finite field F_r. SCALE2_ROOT_OF_UNITY[i] is a 2^i'th root of
* unity.
*
* For element `{A, B, C, D}`, the field element value is `A + B * 2^64 + C * 2^128 + D * 2^192`.
* This format may be converted to an `fr_t` type via the blst_fr_from_uint64() function.
*
* The decimal values may be calculated with the following Python code:
* @code{.py}
* MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513
* PRIMITIVE_ROOT = 7
* [pow(PRIMITIVE_ROOT, (MODULUS - 1) // (2**i), MODULUS) for i in range(32)]
* @endcode
*
* Note: Being a "primitive root" in this context means that `r^k != 1` for any `k < q-1` where q is
* the modulus. So powers of r generate the field. This is also known as being a "primitive
* element".
*
* In the formula above, the restriction can be slightly relaxed to `r` being a non-square. This is
* easy to check: We just require that r^((q-1)/2) == -1. Instead of 7, we could use 10, 13, 14, 15,
* 20... to create the 2^i'th roots of unity below. Generally, there are a lot of primitive roots:
* https://crypto.stanford.edu/pbc/notes/numbertheory/gen.html
*/
static const uint64_t SCALE2_ROOT_OF_UNITY[][4] = {
{0x0000000000000001L, 0x0000000000000000L, 0x0000000000000000L, 0x0000000000000000L},
{0xffffffff00000000L, 0x53bda402fffe5bfeL, 0x3339d80809a1d805L, 0x73eda753299d7d48L},
{0x0001000000000000L, 0xec03000276030000L, 0x8d51ccce760304d0L, 0x0000000000000000L},
{0x7228fd3397743f7aL, 0xb38b21c28713b700L, 0x8c0625cd70d77ce2L, 0x345766f603fa66e7L},
{0x53ea61d87742bcceL, 0x17beb312f20b6f76L, 0xdd1c0af834cec32cL, 0x20b1ce9140267af9L},
{0x360c60997369df4eL, 0xbf6e88fb4c38fb8aL, 0xb4bcd40e22f55448L, 0x50e0903a157988baL},
{0x8140d032f0a9ee53L, 0x2d967f4be2f95155L, 0x14a1e27164d8fdbdL, 0x45af6345ec055e4dL},
{0x5130c2c1660125beL, 0x98d0caac87f5713cL, 0xb7c68b4d7fdd60d0L, 0x6898111413588742L},
{0x4935bd2f817f694bL, 0x0a0865a899e8deffL, 0x6b368121ac0cf4adL, 0x4f9b4098e2e9f12eL},
{0x4541b8ff2ee0434eL, 0xd697168a3a6000feL, 0x39feec240d80689fL, 0x095166525526a654L},
{0x3c28d666a5c2d854L, 0xea437f9626fc085eL, 0x8f4de02c0f776af3L, 0x325db5c3debf77a1L},
{0x4a838b5d59cd79e5L, 0x55ea6811be9c622dL, 0x09f1ca610a08f166L, 0x6d031f1b5c49c834L},
{0xe206da11a5d36306L, 0x0ad1347b378fbf96L, 0xfc3e8acfe0f8245fL, 0x564c0a11a0f704f4L},
{0x6fdd00bfc78c8967L, 0x146b58bc434906acL, 0x2ccddea2972e89edL, 0x485d512737b1da3dL},
{0x034d2ff22a5ad9e1L, 0xae4622f6a9152435L, 0xdc86b01c0d477fa6L, 0x56624634b500a166L},
{0xfbd047e11279bb6eL, 0xc8d5f51db3f32699L, 0x483405417a0cbe39L, 0x3291357ee558b50dL},
{0xd7118f85cd96b8adL, 0x67a665ae1fcadc91L, 0x88f39a78f1aeb578L, 0x2155379d12180caaL},
{0x08692405f3b70f10L, 0xcd7f2bd6d0711b7dL, 0x473a2eef772c33d6L, 0x224262332d8acbf4L},
{0x6f421a7d8ef674fbL, 0xbb97a3bf30ce40fdL, 0x652f717ae1c34bb0L, 0x2d3056a530794f01L},
{0x194e8c62ecb38d9dL, 0xad8e16e84419c750L, 0xdf625e80d0adef90L, 0x520e587a724a6955L},
{0xfece7e0e39898d4bL, 0x2f69e02d265e09d9L, 0xa57a6e07cb98de4aL, 0x03e1c54bcb947035L},
{0xcd3979122d3ea03aL, 0x46b3105f04db5844L, 0xc70d0874b0691d4eL, 0x47c8b5817018af4fL},
{0xc6e7a6ffb08e3363L, 0xe08fec7c86389beeL, 0xf2d38f10fbb8d1bbL, 0x0abe6a5e5abcaa32L},
{0x5616c57de0ec9eaeL, 0xc631ffb2585a72dbL, 0x5121af06a3b51e3cL, 0x73560252aa0655b2L},
{0x92cf4deb77bd779cL, 0x72cf6a8029b7d7bcL, 0x6e0bcd91ee762730L, 0x291cf6d68823e687L},
{0xce32ef844e11a51eL, 0xc0ba12bb3da64ca5L, 0x0454dc1edc61a1a3L, 0x019fe632fd328739L},
{0x531a11a0d2d75182L, 0x02c8118402867ddcL, 0x116168bffbedc11dL, 0x0a0a77a3b1980c0dL},
{0xe2d0a7869f0319edL, 0xb94f1101b1d7a628L, 0xece8ea224f31d25dL, 0x23397a9300f8f98bL},
{0xd7b688830a4f2089L, 0x6558e9e3f6ac7b41L, 0x99e276b571905a7dL, 0x52dd465e2f094256L},
{0x474650359d8e211bL, 0x84d37b826214abc6L, 0x8da40c1ef2bb4598L, 0x0c83ea7744bf1beeL},
{0x694341f608c9dd56L, 0xed3a181fabb30adcL, 0x1339a815da8b398fL, 0x2c6d4e4511657e1eL},
{0x63e7cb4906ffc93fL, 0xf070bb00e28a193dL, 0xad1715b02e5713b5L, 0x4b5371495990693fL}
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Public Functions
////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
46 changes: 40 additions & 6 deletions src/test/tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,11 +261,10 @@ static void test_fr_pow__test_power_of_two(void) {
}

static void test_fr_pow__test_inverse_on_root_of_unity(void) {
fr_t a, r;
fr_t r;

blst_fr_from_uint64(&a, SCALE2_ROOT_OF_UNITY[31]);

fr_pow(&r, &a, 1ULL << 31);
size_t order = log2_pow2(FIELD_ELEMENTS_PER_EXT_BLOB);
fr_pow(&r, &ROOT_OF_UNITY, 1ULL << order);

bool ok = fr_equal(&r, &FR_ONE);
ASSERT_EQUALS(ok, true);
Expand Down Expand Up @@ -1612,12 +1611,44 @@ static void test_verify_kzg_proof_batch__fails_invalid_blob(void) {
// Tests for expand_root_of_unity
////////////////////////////////////////////////////////////////////////////////////////////////////

/** The 2**7th (128th) root of unity. */
static uint64_t root_of_unity_parts_7[] = {
0x5130c2c1660125beL, 0x98d0caac87f5713cL, 0xb7c68b4d7fdd60d0L, 0x6898111413588742L
};

/** The 2**8th (256th) root of unity. */
static uint64_t root_of_unity_parts_8[] = {
0x4935bd2f817f694bL, 0x0a0865a899e8deffL, 0x6b368121ac0cf4adL, 0x4f9b4098e2e9f12eL
};

/**
* The 2**13th (8192th) root of unity.
*
* @note We are removing the SCALE2_ROOT_OF_UNITY array and only exposing the root of unity we need,
* but in fr_t form directly. For posterity, we have added this test to ensure the new value
* matches. For EIP-7594, we need the 8192th root of unity, order of log2(8192)=13. Please confirm
* that this value matches SCALE2_ROOT_OF_UNITY[13] as defined here:
* https://github.com/ethereum/c-kzg-4844/blob/e3ef368c67c7877636c66d6c66beb1bcbf883493/src/setup/setup.h#L64
*/
static uint64_t root_of_unity_parts_13[] = {
0x6fdd00bfc78c8967L, 0x146b58bc434906acL, 0x2ccddea2972e89edL, 0x485d512737b1da3dL
};

static void test_expand_root_of_unity__global_matches_expected(void) {
fr_t root_of_unity;

/* The global value*/
blst_fr_from_uint64(&root_of_unity, root_of_unity_parts_13);
ASSERT_EQUALS(fr_equal(&ROOT_OF_UNITY, &root_of_unity), true);
}

static void test_expand_root_of_unity__succeeds_with_root(void) {
C_KZG_RET ret;
fr_t roots[257], root_of_unity;

blst_fr_from_uint64(&root_of_unity, SCALE2_ROOT_OF_UNITY[8]);
blst_fr_from_uint64(&root_of_unity, root_of_unity_parts_8);

/* We gave it the correct root of unity, so this should succeed */
ret = expand_root_of_unity(roots, &root_of_unity, 256);
ASSERT_EQUALS(ret, C_KZG_OK);
}
Expand All @@ -1628,6 +1659,7 @@ static void test_expand_root_of_unity__fails_not_root_of_unity(void) {

fr_from_uint64(&root_of_unity, 3);

/* We gave it a bogus root of unity, so this should fail */
ret = expand_root_of_unity(roots, &root_of_unity, 256);
ASSERT_EQUALS(ret, C_KZG_BADARGS);
}
Expand All @@ -1636,8 +1668,9 @@ static void test_expand_root_of_unity__fails_wrong_root_of_unity(void) {
C_KZG_RET ret;
fr_t roots[257], root_of_unity;

blst_fr_from_uint64(&root_of_unity, SCALE2_ROOT_OF_UNITY[7]);
blst_fr_from_uint64(&root_of_unity, root_of_unity_parts_7);

/* We expected the 2**8th root of unity, so this should fail */
ret = expand_root_of_unity(roots, &root_of_unity, 256);
ASSERT_EQUALS(ret, C_KZG_BADARGS);
}
Expand Down Expand Up @@ -2268,6 +2301,7 @@ int main(void) {
RUN(test_verify_kzg_proof_batch__fails_proof_not_in_g1);
RUN(test_verify_kzg_proof_batch__fails_commitment_not_in_g1);
RUN(test_verify_kzg_proof_batch__fails_invalid_blob);
RUN(test_expand_root_of_unity__global_matches_expected);
RUN(test_expand_root_of_unity__succeeds_with_root);
RUN(test_expand_root_of_unity__fails_not_root_of_unity);
RUN(test_expand_root_of_unity__fails_wrong_root_of_unity);
Expand Down

0 comments on commit 87bb61e

Please sign in to comment.