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

Cleanup/moving primitive roots to consts #38

Merged
merged 53 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
55a5bf0
adding bare changes for batch verification
Jan 4, 2025
259f6b0
adding some comments
anupsv Jan 4, 2025
4c4bdd0
adding more comments
anupsv Jan 4, 2025
4ecd566
moving back to sha2
Jan 6, 2025
cb75b3b
removing a test which is no longer needed. Removing methods no longer…
Jan 6, 2025
42bc913
updates to method visibility, updating tests
Jan 7, 2025
f3dd7f4
merging main
Jan 7, 2025
02fa7ca
fmt fixes
anupsv Jan 7, 2025
0807ce0
clean up
anupsv Jan 7, 2025
da5e5ad
cleanup, optimization, inline docs
anupsv Jan 7, 2025
b58174b
removing unwanted const
anupsv Jan 7, 2025
c1c2f70
more docs and cleanup
anupsv Jan 7, 2025
fa02398
formatting
anupsv Jan 7, 2025
914e059
removing unwanted comments
anupsv Jan 7, 2025
c74accf
merging main
anupsv Jan 8, 2025
f054c19
cargo fmt and clippy
anupsv Jan 8, 2025
90b3d13
adding test for point at infinity
anupsv Jan 8, 2025
486f7da
cleaner errors, cleanup
anupsv Jan 8, 2025
32716fe
adding another test case
anupsv Jan 8, 2025
73bc809
removing unwanted errors
anupsv Jan 8, 2025
618e098
adding fixes per comments
anupsv Jan 8, 2025
f7eb705
adding 4844 spec references
anupsv Jan 8, 2025
61e1744
comment fixes
anupsv Jan 9, 2025
1c2a79d
formatting, adding index out of bound check, removing print statement
anupsv Jan 10, 2025
baf5a44
removing unwanted test, adding test for evaluate_polynomial_in_evalua…
anupsv Jan 10, 2025
aa1ded9
moving test to bottom section
anupsv Jan 10, 2025
86ceab3
Update src/polynomial.rs
anupsv Jan 10, 2025
d67adec
Update src/kzg.rs
anupsv Jan 10, 2025
02194ba
Update src/kzg.rs
anupsv Jan 10, 2025
bfd2fac
Update src/kzg.rs
anupsv Jan 10, 2025
1c9bcac
Update src/helpers.rs
anupsv Jan 10, 2025
f6c07eb
updating deps, and toolchain to 1.84
anupsv Jan 10, 2025
7531098
removing errors test, no longer useful
anupsv Jan 10, 2025
f9bb219
adding to_byte_array arg explanation
anupsv Jan 10, 2025
5f9fa77
fmt fixes
anupsv Jan 10, 2025
cdeae7c
fmt and clippy fixes
anupsv Jan 10, 2025
0624dc6
fixing function names and fmt
anupsv Jan 10, 2025
c6f0bdd
clippy fixes
anupsv Jan 10, 2025
42c328b
moving primitive root to consts, adding helper function and changing …
anupsv Jan 10, 2025
3633bc5
merge main and cleanup
anupsv Jan 12, 2025
61d719a
Merge branch 'master' into cleanup/moving-primitive-roots-to-consts
anupsv Jan 14, 2025
7122430
removing function
anupsv Jan 14, 2025
ab22fa2
wrong branch updated
anupsv Jan 14, 2025
955dea8
removing is_zero
anupsv Jan 14, 2025
d1621a0
comment updates
anupsv Jan 14, 2025
e40ec08
using macro for roots consts
anupsv Jan 14, 2025
3d644d3
merge master
anupsv Jan 15, 2025
b3d7c1e
adding explanation to PRIMITIVE_ROOTS_OF_UNITY
anupsv Jan 15, 2025
641e7b0
Update src/kzg.rs
anupsv Jan 16, 2025
a327933
Update src/helpers.rs
anupsv Jan 16, 2025
a3d7767
comment change, renames and doc fixes
anupsv Jan 16, 2025
d43d004
merge master
anupsv Jan 23, 2025
f4b224f
cargo fmt
anupsv Jan 23, 2025
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
44 changes: 44 additions & 0 deletions src/consts.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use ark_bn254::Fr;
use ark_ff::MontFp;

pub const BYTES_PER_FIELD_ELEMENT: usize = 32;
pub const SIZE_OF_G1_AFFINE_COMPRESSED: usize = 32; // in bytes
pub const SIZE_OF_G2_AFFINE_COMPRESSED: usize = 64; // in bytes
Expand All @@ -7,3 +10,44 @@ pub const FIAT_SHAMIR_PROTOCOL_DOMAIN: &[u8] = b"EIGENDA_FSBLOBVERIFY_V1_"; // A

/// Ref: https://github.com/ethereum/consensus-specs/blob/master/specs/deneb/polynomial-commitments.md#blob
pub const RANDOM_CHALLENGE_KZG_BATCH_DOMAIN: &[u8] = b"EIGENDA_RCKZGBATCH___V1_"; // Adapted from 4844

/// These are the primitive 2^nth roots of unity. `2^28`
/// is the largest power of two that divides `r - 1`, therefore there are no primitive
/// roots of unity for higher powers of 2 in Fr.). Given a blob
/// length, we calculate the number of field elements needed and then get the
/// value of the actual power of 2 which is less than or equal to 28. We then use
/// this value to get the primitive root of unity from the array below to expand
/// to the roots of unity needed. The number of expanded roots elements will be the
/// same as the power of 2 i.e if `8th` power of 2 was calculated then we get `2^8 = 256`
/// expanded roots of unity.
pub const PRIMITIVE_ROOTS_OF_UNITY: [Fr; 29] = [
MontFp!("1"),
MontFp!("21888242871839275222246405745257275088548364400416034343698204186575808495616"),
MontFp!("21888242871839275217838484774961031246007050428528088939761107053157389710902"),
MontFp!("19540430494807482326159819597004422086093766032135589407132600596362845576832"),
MontFp!("14940766826517323942636479241147756311199852622225275649687664389641784935947"),
MontFp!("4419234939496763621076330863786513495701855246241724391626358375488475697872"),
MontFp!("9088801421649573101014283686030284801466796108869023335878462724291607593530"),
MontFp!("10359452186428527605436343203440067497552205259388878191021578220384701716497"),
MontFp!("3478517300119284901893091970156912948790432420133812234316178878452092729974"),
MontFp!("6837567842312086091520287814181175430087169027974246751610506942214842701774"),
MontFp!("3161067157621608152362653341354432744960400845131437947728257924963983317266"),
MontFp!("1120550406532664055539694724667294622065367841900378087843176726913374367458"),
MontFp!("4158865282786404163413953114870269622875596290766033564087307867933865333818"),
MontFp!("197302210312744933010843010704445784068657690384188106020011018676818793232"),
MontFp!("20619701001583904760601357484951574588621083236087856586626117568842480512645"),
MontFp!("20402931748843538985151001264530049874871572933694634836567070693966133783803"),
MontFp!("421743594562400382753388642386256516545992082196004333756405989743524594615"),
MontFp!("12650941915662020058015862023665998998969191525479888727406889100124684769509"),
MontFp!("11699596668367776675346610687704220591435078791727316319397053191800576917728"),
MontFp!("15549849457946371566896172786938980432421851627449396898353380550861104573629"),
MontFp!("17220337697351015657950521176323262483320249231368149235373741788599650842711"),
MontFp!("13536764371732269273912573961853310557438878140379554347802702086337840854307"),
MontFp!("12143866164239048021030917283424216263377309185099704096317235600302831912062"),
MontFp!("934650972362265999028062457054462628285482693704334323590406443310927365533"),
MontFp!("5709868443893258075976348696661355716898495876243883251619397131511003808859"),
MontFp!("19200870435978225707111062059747084165650991997241425080699860725083300967194"),
MontFp!("7419588552507395652481651088034484897579724952953562618697845598160172257810"),
MontFp!("2082940218526944230311718225077035922214683169814847712455127909555749686340"),
MontFp!("19103219067921713944291392827692070036145651957329286315305642004821462161904"),
];
38 changes: 37 additions & 1 deletion src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use std::cmp;

use crate::{
arith,
consts::{BYTES_PER_FIELD_ELEMENT, SIZE_OF_G1_AFFINE_COMPRESSED, SIZE_OF_G2_AFFINE_COMPRESSED},
consts::{
BYTES_PER_FIELD_ELEMENT, PRIMITIVE_ROOTS_OF_UNITY, SIZE_OF_G1_AFFINE_COMPRESSED,
SIZE_OF_G2_AFFINE_COMPRESSED,
},
errors::KzgError,
traits::ReadPointFromBytes,
};
Expand Down Expand Up @@ -502,3 +505,36 @@ pub fn g1_lincomb(points: &[G1Affine], scalars: &[Fr]) -> Result<G1Affine, KzgEr
// This is typically needed as most protocols expect points in affine form
Ok(lincomb.into_affine())
}

/// Retrieves and converts a primitive root of unity to a field element
///
/// # Arguments
/// * `index` - Index of the primitive root to retrieve from PRIMITIVE_ROOTS_OF_UNITY array
///
/// # Returns
/// * `Result<Fr, KzgError>` - Field element representation of the primitive root if successful,
/// or KzgError if index is invalid or conversion fails
///
/// # Errors
/// - Returns KzgError::GenericError if:
/// - Index is out of bounds for PRIMITIVE_ROOTS_OF_UNITY array
/// - BigInt conversion to field element fails
///
/// # Details
/// - Looks up a primitive root of unity from a predefined array using the given index
/// - Converts the BigInt representation to an Fr field element
/// - Commonly used in FFT and polynomial operations requiring roots of unity
///
/// # Example
/// ```
/// use rust_kzg_bn254::helpers::get_primitive_root_of_unity;
/// let root = get_primitive_root_of_unity(0); // Gets first primitive root
/// ```
/// Gets the primitive root of unity of order 2^power.
/// For example, power=3 returns a primitive 8th root of unity.
pub fn get_primitive_root_of_unity(power: usize) -> Result<Fr, KzgError> {
PRIMITIVE_ROOTS_OF_UNITY
.get(power)
.ok_or_else(|| KzgError::GenericError("power must be <= 28".to_string()))
.copied()
}
53 changes: 3 additions & 50 deletions src/kzg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup, VariableBaseMSM};
use ark_ff::{BigInteger, Field, PrimeField};
use ark_poly::{EvaluationDomain, GeneralEvaluationDomain};
use ark_serialize::{CanonicalSerialize, Read};
use ark_std::{iterable::Iterable, ops::Div, str::FromStr, One, Zero};
use ark_std::{iterable::Iterable, ops::Div, One, Zero};
use crossbeam_channel::{bounded, Sender};
use num_traits::ToPrimitive;
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
Expand Down Expand Up @@ -155,16 +155,11 @@ impl KZG {
));
}

// Get the primitive roots of unity
let primitive_roots_of_unity = Self::get_primitive_roots_of_unity()?;

// Find the root of unity corresponding to the calculated log2 value
let found_root_of_unity = primitive_roots_of_unity
.get(log2_of_evals as usize)
.ok_or_else(|| KzgError::GenericError("Root of unity not found".to_string()))?;
let root_of_unity = helpers::get_primitive_root_of_unity(log2_of_evals.into())?;

// Expand the root to get all the roots of unity
let mut expanded_roots_of_unity = Self::expand_root_of_unity(found_root_of_unity);
let mut expanded_roots_of_unity = Self::expand_root_of_unity(&root_of_unity);

// Remove the last element to avoid duplication
expanded_roots_of_unity.truncate(expanded_roots_of_unity.len() - 1);
Expand Down Expand Up @@ -237,48 +232,6 @@ impl KZG {
roots
}

/// Precompute the primitive roots of unity for binary powers that divide r - 1
/// TODO(anupsv): Move this to the constants file. Ref: https://github.com/Layr-Labs/rust-kzg-bn254/issues/31
fn get_primitive_roots_of_unity() -> Result<Vec<Fr>, KzgError> {
let data: [&str; 29] = [
"1",
"21888242871839275222246405745257275088548364400416034343698204186575808495616",
"21888242871839275217838484774961031246007050428528088939761107053157389710902",
"19540430494807482326159819597004422086093766032135589407132600596362845576832",
"14940766826517323942636479241147756311199852622225275649687664389641784935947",
"4419234939496763621076330863786513495701855246241724391626358375488475697872",
"9088801421649573101014283686030284801466796108869023335878462724291607593530",
"10359452186428527605436343203440067497552205259388878191021578220384701716497",
"3478517300119284901893091970156912948790432420133812234316178878452092729974",
"6837567842312086091520287814181175430087169027974246751610506942214842701774",
"3161067157621608152362653341354432744960400845131437947728257924963983317266",
"1120550406532664055539694724667294622065367841900378087843176726913374367458",
"4158865282786404163413953114870269622875596290766033564087307867933865333818",
"197302210312744933010843010704445784068657690384188106020011018676818793232",
"20619701001583904760601357484951574588621083236087856586626117568842480512645",
"20402931748843538985151001264530049874871572933694634836567070693966133783803",
"421743594562400382753388642386256516545992082196004333756405989743524594615",
"12650941915662020058015862023665998998969191525479888727406889100124684769509",
"11699596668367776675346610687704220591435078791727316319397053191800576917728",
"15549849457946371566896172786938980432421851627449396898353380550861104573629",
"17220337697351015657950521176323262483320249231368149235373741788599650842711",
"13536764371732269273912573961853310557438878140379554347802702086337840854307",
"12143866164239048021030917283424216263377309185099704096317235600302831912062",
"934650972362265999028062457054462628285482693704334323590406443310927365533",
"5709868443893258075976348696661355716898495876243883251619397131511003808859",
"19200870435978225707111062059747084165650991997241425080699860725083300967194",
"7419588552507395652481651088034484897579724952953562618697845598160172257810",
"2082940218526944230311718225077035922214683169814847712455127909555749686340",
"19103219067921713944291392827692070036145651957329286315305642004821462161904",
];
data.iter()
.map(Fr::from_str)
.collect::<Result<Vec<_>, _>>()
.map_err(|_| {
KzgError::GenericError("Failed to parse primitive roots of unity".to_string())
})
}

/// helper function to get g1 points
pub fn get_g1_points(&self) -> Vec<G1Affine> {
self.g1.to_vec()
Expand Down
49 changes: 48 additions & 1 deletion tests/kzg_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ mod tests {
use ark_ff::UniformRand;
use lazy_static::lazy_static;
use rand::Rng;
use rust_kzg_bn254::{blob::Blob, errors::KzgError, kzg::KZG, polynomial::PolynomialCoeffForm};
use rust_kzg_bn254::{
blob::Blob, consts::PRIMITIVE_ROOTS_OF_UNITY, errors::KzgError, kzg::KZG,
polynomial::PolynomialCoeffForm,
};
use std::{env, fs::File, io::BufReader};
const GETTYSBURG_ADDRESS_BYTES: &[u8] = "Fourscore and seven years ago our fathers brought forth, on this continent, a new nation, conceived in liberty, and dedicated to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived, and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting-place for those who here gave their lives, that that nation might live. It is altogether fitting and proper that we should do this. But, in a larger sense, we cannot dedicate, we cannot consecrate—we cannot hallow—this ground. The brave men, living and dead, who struggled here, have consecrated it far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us—that from these honored dead we take increased devotion to that cause for which they here gave the last full measure of devotion—that we here highly resolve that these dead shall not have died in vain—that this nation, under God, shall have a new birth of freedom, and that government of the people, by the people, for the people, shall not perish from the earth.".as_bytes();
use ark_std::{str::FromStr, One};
Expand Down Expand Up @@ -566,6 +569,50 @@ mod tests {
}
}

#[test]
fn test_primitive_roots_from_bigint_to_fr() {
let data: [&str; 29] = [
"1",
"21888242871839275222246405745257275088548364400416034343698204186575808495616",
"21888242871839275217838484774961031246007050428528088939761107053157389710902",
"19540430494807482326159819597004422086093766032135589407132600596362845576832",
anupsv marked this conversation as resolved.
Show resolved Hide resolved
"14940766826517323942636479241147756311199852622225275649687664389641784935947",
"4419234939496763621076330863786513495701855246241724391626358375488475697872",
"9088801421649573101014283686030284801466796108869023335878462724291607593530",
"10359452186428527605436343203440067497552205259388878191021578220384701716497",
"3478517300119284901893091970156912948790432420133812234316178878452092729974",
"6837567842312086091520287814181175430087169027974246751610506942214842701774",
"3161067157621608152362653341354432744960400845131437947728257924963983317266",
"1120550406532664055539694724667294622065367841900378087843176726913374367458",
"4158865282786404163413953114870269622875596290766033564087307867933865333818",
"197302210312744933010843010704445784068657690384188106020011018676818793232",
"20619701001583904760601357484951574588621083236087856586626117568842480512645",
"20402931748843538985151001264530049874871572933694634836567070693966133783803",
"421743594562400382753388642386256516545992082196004333756405989743524594615",
"12650941915662020058015862023665998998969191525479888727406889100124684769509",
"11699596668367776675346610687704220591435078791727316319397053191800576917728",
"15549849457946371566896172786938980432421851627449396898353380550861104573629",
"17220337697351015657950521176323262483320249231368149235373741788599650842711",
"13536764371732269273912573961853310557438878140379554347802702086337840854307",
"12143866164239048021030917283424216263377309185099704096317235600302831912062",
"934650972362265999028062457054462628285482693704334323590406443310927365533",
"5709868443893258075976348696661355716898495876243883251619397131511003808859",
"19200870435978225707111062059747084165650991997241425080699860725083300967194",
"7419588552507395652481651088034484897579724952953562618697845598160172257810",
"2082940218526944230311718225077035922214683169814847712455127909555749686340",
"19103219067921713944291392827692070036145651957329286315305642004821462161904",
];
let fr_s = data
.iter()
.map(|s: &&str| Fr::from_str(*s).unwrap())
.collect::<Vec<_>>();

for i in 0..PRIMITIVE_ROOTS_OF_UNITY.len() {
let root_of_unity_at_index = PRIMITIVE_ROOTS_OF_UNITY[i];
assert_eq!(root_of_unity_at_index, fr_s[i]);
}
}

// Helper function to generate a point in the wrong subgroup
fn generate_point_wrong_subgroup() -> G1Affine {
let x = Fq::from_str(
Expand Down
Loading