Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pre-compute root of unity in fr-form #491

Merged
merged 10 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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, uint64_t widt
*/
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
Loading