From c6067144c5928e4910ca87d0eb786bd97c3732b2 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:35:59 -0300 Subject: [PATCH 01/18] Stark: Make batch commit of trace columns compatible with SHARP (#581) * add test * make trace commitment SHARP compatible * wip * use powers of a single challenge for the boundary and transition coefficients * add permutation to match sharp compatible commitments on the trace * change trait bound from ByteConversion to Serializable * minor refactor * fmt, clippy * move std feature to inner trait function in Serializable --- .../src/merkle_tree/backends/field_element.rs | 6 +- .../backends/field_element_vector.rs | 6 +- .../fields/montgomery_backed_prime_fields.rs | 12 +- math/src/traits.rs | 2 +- provers/stark/src/constraints/evaluator.rs | 4 +- provers/stark/src/domain.rs | 4 +- provers/stark/src/fri/fri_commitment.rs | 6 +- provers/stark/src/fri/mod.rs | 6 +- provers/stark/src/prover.rs | 196 +++++++++++++++--- provers/stark/src/transcript.rs | 12 +- provers/stark/src/verifier.rs | 117 +++++++++-- 11 files changed, 300 insertions(+), 71 deletions(-) diff --git a/crypto/src/merkle_tree/backends/field_element.rs b/crypto/src/merkle_tree/backends/field_element.rs index c6d00245a0..f5c034b979 100644 --- a/crypto/src/merkle_tree/backends/field_element.rs +++ b/crypto/src/merkle_tree/backends/field_element.rs @@ -1,7 +1,7 @@ use crate::merkle_tree::traits::IsMerkleTreeBackend; use lambdaworks_math::{ field::{element::FieldElement, traits::IsField}, - traits::ByteConversion, + traits::Serializable, }; use sha3::{ digest::{generic_array::GenericArray, OutputSizeUser}, @@ -28,7 +28,7 @@ impl IsMerkleTreeBackend for FieldElementBackend where F: IsField, - FieldElement: ByteConversion, + FieldElement: Serializable, [u8; NUM_BYTES]: From::OutputSize>>, { type Node = [u8; NUM_BYTES]; @@ -36,7 +36,7 @@ where fn hash_data(&self, input: &FieldElement) -> [u8; NUM_BYTES] { let mut hasher = D::new(); - hasher.update(input.to_bytes_be()); + hasher.update(input.serialize()); hasher.finalize().into() } diff --git a/crypto/src/merkle_tree/backends/field_element_vector.rs b/crypto/src/merkle_tree/backends/field_element_vector.rs index c22ce63181..7d748f9453 100644 --- a/crypto/src/merkle_tree/backends/field_element_vector.rs +++ b/crypto/src/merkle_tree/backends/field_element_vector.rs @@ -3,7 +3,7 @@ use std::marker::PhantomData; use crate::merkle_tree::traits::IsMerkleTreeBackend; use lambdaworks_math::{ field::{element::FieldElement, traits::IsField}, - traits::ByteConversion, + traits::Serializable, }; use sha3::{ digest::{generic_array::GenericArray, OutputSizeUser}, @@ -29,7 +29,7 @@ impl IsMerkleTreeBackend for FieldElementVectorBackend where F: IsField, - FieldElement: ByteConversion, + FieldElement: Serializable, [u8; NUM_BYTES]: From::OutputSize>>, { type Node = [u8; NUM_BYTES]; @@ -38,7 +38,7 @@ where fn hash_data(&self, input: &Vec>) -> [u8; NUM_BYTES] { let mut hasher = D::new(); for element in input.iter() { - hasher.update(element.to_bytes_be()); + hasher.update(element.serialize()); } let mut result_hash = [0_u8; NUM_BYTES]; result_hash.copy_from_slice(&hasher.finalize()); diff --git a/math/src/field/fields/montgomery_backed_prime_fields.rs b/math/src/field/fields/montgomery_backed_prime_fields.rs index 674914991d..91d5600e67 100644 --- a/math/src/field/fields/montgomery_backed_prime_fields.rs +++ b/math/src/field/fields/montgomery_backed_prime_fields.rs @@ -1,7 +1,7 @@ use crate::field::element::FieldElement; use crate::field::errors::FieldError; use crate::field::traits::IsPrimeField; -use crate::traits::ByteConversion; +use crate::traits::{ByteConversion, Serializable}; use crate::{ field::traits::IsField, unsigned_integer::element::UnsignedInteger, unsigned_integer::montgomery::MontgomeryAlgorithms, @@ -350,6 +350,16 @@ where } } +impl Serializable + for FieldElement> +where + M: IsModulus> + Clone + Debug, +{ + #[cfg(feature = "std")] + fn serialize(&self) -> Vec { + self.value().to_bytes_be() + } +} #[cfg(test)] mod tests_u384_prime_fields { use crate::field::element::FieldElement; diff --git a/math/src/traits.rs b/math/src/traits.rs index e97704f5a7..b5ece2d195 100644 --- a/math/src/traits.rs +++ b/math/src/traits.rs @@ -29,9 +29,9 @@ pub trait ByteConversion { /// Serialize function without args /// Used for serialization when formatting options are not relevant -#[cfg(feature = "std")] pub trait Serializable { /// Default serialize without args + #[cfg(feature = "std")] fn serialize(&self) -> Vec; } diff --git a/provers/stark/src/constraints/evaluator.rs b/provers/stark/src/constraints/evaluator.rs index 18c0fc6f4f..9c07823cc9 100644 --- a/provers/stark/src/constraints/evaluator.rs +++ b/provers/stark/src/constraints/evaluator.rs @@ -3,7 +3,7 @@ use lambdaworks_math::{ fft::cpu::roots_of_unity::get_powers_of_primitive_root_coset, field::{element::FieldElement, traits::IsFFTField}, polynomial::Polynomial, - traits::ByteConversion, + traits::Serializable, }; #[cfg(feature = "parallel")] @@ -44,7 +44,7 @@ impl> ConstraintEvaluator { rap_challenges: &A::RAPChallenges, ) -> ConstraintEvaluationTable where - FieldElement: ByteConversion + Send + Sync, + FieldElement: Serializable + Send + Sync, A: Send + Sync, A::RAPChallenges: Send + Sync, { diff --git a/provers/stark/src/domain.rs b/provers/stark/src/domain.rs index d35b2f60e9..a287d9ad1c 100644 --- a/provers/stark/src/domain.rs +++ b/provers/stark/src/domain.rs @@ -23,7 +23,7 @@ impl Domain { { // Initial definitions let blowup_factor = air.options().blowup_factor as usize; - let coset_offset = FieldElement::::from(air.options().coset_offset); + let coset_offset = FieldElement::from(air.options().coset_offset); let interpolation_domain_size = air.trace_length(); let root_order = air.trace_length().trailing_zeros(); // * Generate Coset @@ -31,7 +31,7 @@ impl Domain { let trace_roots_of_unity = get_powers_of_primitive_root_coset( root_order as u64, interpolation_domain_size, - &FieldElement::::one(), + &FieldElement::one(), ) .unwrap(); diff --git a/provers/stark/src/fri/fri_commitment.rs b/provers/stark/src/fri/fri_commitment.rs index d6f9740048..60df1b6e52 100644 --- a/provers/stark/src/fri/fri_commitment.rs +++ b/provers/stark/src/fri/fri_commitment.rs @@ -5,7 +5,7 @@ use lambdaworks_math::{ traits::{IsFFTField, IsField}, }, polynomial::Polynomial, - traits::ByteConversion, + traits::Serializable, }; use crate::config::FriMerkleTree; @@ -14,7 +14,7 @@ use crate::config::FriMerkleTree; pub struct FriLayer where F: IsField, - FieldElement: ByteConversion, + FieldElement: Serializable, { pub evaluation: Vec>, pub merkle_tree: FriMerkleTree, @@ -25,7 +25,7 @@ where impl FriLayer where F: IsField + IsFFTField, - FieldElement: ByteConversion, + FieldElement: Serializable, { pub fn new( poly: &Polynomial>, diff --git a/provers/stark/src/fri/mod.rs b/provers/stark/src/fri/mod.rs index 2feb10b959..1ee9dde908 100644 --- a/provers/stark/src/fri/mod.rs +++ b/provers/stark/src/fri/mod.rs @@ -3,7 +3,7 @@ pub mod fri_decommit; mod fri_functions; use lambdaworks_math::field::traits::{IsFFTField, IsField}; -use lambdaworks_math::traits::ByteConversion; +use lambdaworks_math::traits::Serializable; pub use lambdaworks_math::{ field::{element::FieldElement, fields::u64_prime_field::U64PrimeField}, polynomial::Polynomial, @@ -25,7 +25,7 @@ pub fn fri_commit_phase( domain_size: usize, ) -> (FieldElement, Vec>) where - FieldElement: ByteConversion, + FieldElement: Serializable, { let mut domain_size = domain_size; @@ -80,7 +80,7 @@ pub fn fri_query_phase( where F: IsFFTField, A: AIR, - FieldElement: ByteConversion, + FieldElement: Serializable, { if !fri_layers.is_empty() { let number_of_queries = air.options().fri_number_of_queries; diff --git a/provers/stark/src/prover.rs b/provers/stark/src/prover.rs index 130a148521..d177621af4 100644 --- a/provers/stark/src/prover.rs +++ b/provers/stark/src/prover.rs @@ -1,11 +1,13 @@ #[cfg(feature = "instruments")] use std::time::Instant; +use lambdaworks_crypto::merkle_tree::proof::Proof; +use lambdaworks_math::fft::cpu::bit_reversing::in_place_bit_reverse_permute; use lambdaworks_math::fft::{errors::FFTError, polynomial::FFTPoly}; +use lambdaworks_math::traits::Serializable; use lambdaworks_math::{ field::{element::FieldElement, traits::IsFFTField}, polynomial::Polynomial, - traits::ByteConversion, }; use log::info; @@ -38,7 +40,7 @@ struct Round1 where F: IsFFTField, A: AIR, - FieldElement: ByteConversion, + FieldElement: Serializable, { trace_polys: Vec>>, lde_trace: TraceTable, @@ -50,7 +52,7 @@ where struct Round2 where F: IsFFTField, - FieldElement: ByteConversion, + FieldElement: Serializable, { composition_poly_even: Polynomial>, lde_composition_poly_even_evaluations: Vec>, @@ -77,7 +79,7 @@ struct Round4 { fn batch_commit(vectors: &[Vec>]) -> (BatchedMerkleTree, Commitment) where F: IsFFTField, - FieldElement: ByteConversion, + FieldElement: Serializable, { let tree = BatchedMerkleTree::::build(vectors); let commitment = tree.root; @@ -94,7 +96,6 @@ where F: IsFFTField, Polynomial>: FFTPoly, { - // Evaluate those polynomials t_j on the large domain D_LDE. let evaluations = p.evaluate_offset_fft(blowup_factor, Some(domain_size), offset)?; let step = evaluations.len() / (domain_size * blowup_factor); match step { @@ -103,6 +104,47 @@ where } } +fn apply_permutation(vector: &mut Vec>, permutation: &[usize]) { + assert_eq!( + vector.len(), + permutation.len(), + "Vector and permutation must have the same length" + ); + + let mut temp = Vec::with_capacity(vector.len()); + for &index in permutation { + temp.push(vector[index].clone()); + } + + vector.clear(); + vector.extend(temp); +} + +/// This function returns the permutation that converts lambdaworks ordering of rows to the one used in the stone prover +pub fn get_stone_prover_domain_permutation(domain_size: usize, blowup_factor: usize) -> Vec { + let mut permutation = Vec::new(); + let n = domain_size; + + let mut indices: Vec = (0..blowup_factor).collect(); + in_place_bit_reverse_permute(&mut indices); + + for i in indices.iter() { + for j in 0..n { + permutation.push(i + j * blowup_factor) + } + } + + for coset_indices in permutation.chunks_mut(n) { + let mut temp = coset_indices.to_owned(); + in_place_bit_reverse_permute(&mut temp); + for (j, elem) in coset_indices.iter_mut().enumerate() { + *elem = temp[j]; + } + } + + permutation.to_vec() +} + #[allow(clippy::type_complexity)] fn interpolate_and_commit( trace: &TraceTable, @@ -116,15 +158,24 @@ fn interpolate_and_commit( ) where F: IsFFTField, - FieldElement: ByteConversion + Send + Sync, + FieldElement: Serializable + Send + Sync, { let trace_polys = trace.compute_trace_polys(); // Evaluate those polynomials t_j on the large domain D_LDE. let lde_trace_evaluations = compute_lde_trace_evaluations(&trace_polys, domain); + let permutation = + get_stone_prover_domain_permutation(domain.interpolation_domain_size, domain.blowup_factor); + + let mut lde_trace_permuted = lde_trace_evaluations.clone(); + + for col in lde_trace_permuted.iter_mut() { + apply_permutation(col, &permutation); + } + // Compute commitments [t_j]. - let lde_trace = TraceTable::new_from_cols(&lde_trace_evaluations); + let lde_trace = TraceTable::new_from_cols(&lde_trace_permuted); let (lde_trace_merkle_tree, lde_trace_merkle_root) = batch_commit(&lde_trace.rows()); // >>>> Send commitments: [tβ±Ό] @@ -171,7 +222,7 @@ fn round_1_randomized_air_with_preprocessing>( transcript: &mut impl IsStarkTranscript, ) -> Result, ProvingError> where - FieldElement: ByteConversion + Send + Sync, + FieldElement: Serializable + Send + Sync, { let (mut trace_polys, mut evaluations, main_merkle_tree, main_merkle_root) = interpolate_and_commit(main_trace, domain, transcript); @@ -214,7 +265,7 @@ where F: IsFFTField, A: AIR + Send + Sync, A::RAPChallenges: Send + Sync, - FieldElement: ByteConversion + Send + Sync, + FieldElement: Serializable + Send + Sync, { // Create evaluation table let evaluator = ConstraintEvaluator::new(air, &round_1_result.rap_challenges); @@ -273,7 +324,7 @@ fn round_3_evaluate_polynomials_in_out_of_domain_element, ) -> Round3 where - FieldElement: ByteConversion, + FieldElement: Serializable, { let z_squared = z.square(); @@ -317,7 +368,7 @@ fn round_4_compute_and_run_fri_on_the_deep_composition_polynomial< transcript: &mut impl IsStarkTranscript, ) -> Round4 where - FieldElement: ByteConversion + Send + Sync, + FieldElement: Serializable + Send + Sync, { let coset_offset_u64 = air.context().proof_options.coset_offset; let coset_offset = FieldElement::::from(coset_offset_u64); @@ -399,7 +450,7 @@ fn compute_deep_composition_poly( where A: AIR, F: IsFFTField, - FieldElement: ByteConversion + Send + Sync, + FieldElement: Serializable + Send + Sync, { // Compute composition polynomial terms of the deep composition polynomial. let h_1 = &round_2_result.composition_poly_even; @@ -480,7 +531,7 @@ fn compute_trace_term( ) -> Polynomial> where F: IsFFTField, - FieldElement: ByteConversion + Send + Sync, + FieldElement: Serializable + Send + Sync, { let i_times_trace_frame_evaluation = i * trace_frame_length; let iter_trace_gammas = trace_terms_gammas @@ -513,8 +564,10 @@ fn open_deep_composition_poly>( indexes_to_open: &[usize], // list of iotas ) -> Vec> where - FieldElement: ByteConversion, + FieldElement: Serializable, { + let permutation = + get_stone_prover_domain_permutation(domain.interpolation_domain_size, domain.blowup_factor); indexes_to_open .iter() .map(|index_to_open| { @@ -533,18 +586,19 @@ where let lde_composition_poly_odd_evaluation = round_2_result.lde_composition_poly_odd_evaluations[index].clone(); + let lde_trace_evaluations = round_1_result.lde_trace.get_row(index).to_vec(); + + let index = permutation[index]; // Trace polynomials openings #[cfg(feature = "parallel")] let merkle_trees_iter = round_1_result.lde_trace_merkle_trees.par_iter(); #[cfg(not(feature = "parallel"))] let merkle_trees_iter = round_1_result.lde_trace_merkle_trees.iter(); - let lde_trace_merkle_proofs = merkle_trees_iter + let lde_trace_merkle_proofs: Vec> = merkle_trees_iter .map(|tree| tree.get_proof_by_pos(index).unwrap()) .collect(); - let lde_trace_evaluations = round_1_result.lde_trace.get_row(index).to_vec(); - DeepPolynomialOpenings { lde_composition_poly_proof, lde_composition_poly_even_evaluation, @@ -567,7 +621,7 @@ where F: IsFFTField, A: AIR + Send + Sync, A::RAPChallenges: Send + Sync, - FieldElement: ByteConversion + Send + Sync, + FieldElement: Serializable + Send + Sync, { info!("Started proof generation..."); #[cfg(feature = "instruments")] @@ -621,16 +675,22 @@ where #[cfg(feature = "instruments")] let timer2 = Instant::now(); - // <<<< Receive challenges: 𝛽_j^B - let boundary_coefficients = batch_sample_challenges( - air.boundary_constraints(&round_1_result.rap_challenges) - .constraints - .len(), - &mut transcript, - ); - // <<<< Receive challenges: 𝛽_j^T - let transition_coefficients = - batch_sample_challenges(air.context().num_transition_constraints, &mut transcript); + // <<<< Receive challenge: 𝛽 + let beta = transcript.sample_field_element(); + let num_boundary_constraints = air + .boundary_constraints(&round_1_result.rap_challenges) + .constraints + .len(); + + let num_transition_constraints = air.context().num_transition_constraints; + + let mut coefficients: Vec<_> = (1..num_boundary_constraints + num_transition_constraints + 1) + .map(|i| beta.pow(i)) + .collect(); + + let transition_coefficients: Vec<_> = + coefficients.drain(..num_transition_constraints).collect(); + let boundary_coefficients = coefficients; let round_2_result = round_2_compute_composition_polynomial( &air, @@ -767,9 +827,15 @@ where #[cfg(test)] mod tests { + use std::num::ParseIntError; + use crate::{ - examples::simple_fibonacci::{self, FibonacciPublicInputs}, + examples::{ + fibonacci_2_cols_shifted::{self, Fibonacci2ColsShifted}, + simple_fibonacci::{self, FibonacciPublicInputs}, + }, proof::options::ProofOptions, + transcript::StoneProverTranscript, Felt252, }; @@ -878,4 +944,76 @@ mod tests { assert_eq!(*eval, poly.evaluate(&(offset * primitive_root.pow(i)))); } } + + pub fn decode_hex(s: &str) -> Result, ParseIntError> { + (0..s.len()) + .step_by(2) + .map(|i| u8::from_str_radix(&s[i..i + 2], 16)) + .collect() + } + + #[test] + fn test_trace_commitment_is_compatible_with_stone_prover_1() { + let trace = fibonacci_2_cols_shifted::compute_trace(FieldElement::one(), 4); + + let claimed_index = 3; + let claimed_value = trace.get_row(claimed_index)[0]; + let mut proof_options = ProofOptions::default_test_options(); + proof_options.blowup_factor = 4; + proof_options.coset_offset = 3; + + let pub_inputs = fibonacci_2_cols_shifted::PublicInputs { + claimed_value, + claimed_index, + }; + + let transcript_init_seed = [0xca, 0xfe, 0xca, 0xfe]; + + let air = Fibonacci2ColsShifted::new(trace.n_rows(), &pub_inputs, &proof_options); + let domain = Domain::new(&air); + + let (_, _, _, trace_commitment) = interpolate_and_commit( + &trace, + &domain, + &mut StoneProverTranscript::new(&transcript_init_seed), + ); + + assert_eq!( + &trace_commitment.to_vec(), + &decode_hex("0eb9dcc0fb1854572a01236753ce05139d392aa3aeafe72abff150fe21175594") + .unwrap() + ); + } + #[test] + fn test_trace_commitment_is_compatible_with_stone_prover_2() { + let trace = fibonacci_2_cols_shifted::compute_trace(FieldElement::one(), 4); + + let claimed_index = 3; + let claimed_value = trace.get_row(claimed_index)[0]; + let mut proof_options = ProofOptions::default_test_options(); + proof_options.blowup_factor = 64; + proof_options.coset_offset = 3; + + let pub_inputs = fibonacci_2_cols_shifted::PublicInputs { + claimed_value, + claimed_index, + }; + + let transcript_init_seed = [0xfa, 0xfa, 0xfa, 0xee]; + + let air = Fibonacci2ColsShifted::new(trace.n_rows(), &pub_inputs, &proof_options); + let domain = Domain::new(&air); + + let (_, _, _, trace_commitment) = interpolate_and_commit( + &trace, + &domain, + &mut StoneProverTranscript::new(&transcript_init_seed), + ); + + assert_eq!( + &trace_commitment.to_vec(), + &decode_hex("99d8d4342895c4e35a084f8ea993036be06f51e7fa965734ed9c7d41104f0848") + .unwrap() + ); + } } diff --git a/provers/stark/src/transcript.rs b/provers/stark/src/transcript.rs index bd7d81dca9..b6952b70bb 100644 --- a/provers/stark/src/transcript.rs +++ b/provers/stark/src/transcript.rs @@ -4,7 +4,7 @@ use lambdaworks_math::{ fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, traits::{IsFFTField, IsField}, }, - traits::ByteConversion, + traits::{ByteConversion, Serializable}, unsigned_integer::element::U256, }; use sha3::{Digest, Keccak256}; @@ -21,7 +21,7 @@ pub trait IsStarkTranscript { trace_roots_of_unity: &[FieldElement], ) -> FieldElement where - FieldElement: ByteConversion, + FieldElement: Serializable, { loop { let value: FieldElement = self.sample_field_element(); @@ -155,7 +155,7 @@ pub fn batch_sample_challenges( transcript: &mut impl IsStarkTranscript, ) -> Vec> where - FieldElement: ByteConversion, + FieldElement: Serializable, { (0..size) .map(|_| transcript.sample_field_element()) @@ -289,7 +289,7 @@ mod tests { // This corresponds to the following run. // Air: `Fibonacci2ColsShifted` // `trace_length`: 4 - // `blowup_factor`: 2 + // `blowup_factor`: 4 // `fri_number_of_queries`: 1 let mut transcript = StoneProverTranscript::new(&[0xca, 0xfe, 0xca, 0xfe]); // Send hash of trace commitment @@ -304,7 +304,7 @@ mod tests { "86105fff7b04ed4068ecccb8dbf1ed223bd45cd26c3532d6c80a818dbd4fa7" ) ); - // Send hash of composition poly commitment H(z) + // Send hash of composition poly commitment H transcript.append_bytes( &decode_hex("7cdd8d5fe3bd62254a417e2e260e0fed4fccdb6c9005e828446f645879394f38") .unwrap(), @@ -374,7 +374,7 @@ mod tests { // This corresponds to the following run. // Air: `Fibonacci2ColsShifted` // `trace_length`: 4 - // `blowup_factor`: 6 + // `blowup_factor`: 64 // `fri_number_of_queries`: 2 let mut transcript = StoneProverTranscript::new(&[0xfa, 0xfa, 0xfa, 0xee]); // Send hash of trace commitment diff --git a/provers/stark/src/verifier.rs b/provers/stark/src/verifier.rs index fe7afd687f..38a505602a 100644 --- a/provers/stark/src/verifier.rs +++ b/provers/stark/src/verifier.rs @@ -10,10 +10,10 @@ use lambdaworks_math::{ element::FieldElement, traits::{IsFFTField, IsField}, }, - traits::ByteConversion, + traits::Serializable, }; -use crate::transcript::IsStarkTranscript; +use crate::{prover::get_stone_prover_domain_permutation, transcript::IsStarkTranscript}; use super::{ config::{BatchedMerkleTreeBackend, FriMerkleTreeBackend}, @@ -22,7 +22,6 @@ use super::{ grinding::hash_transcript_with_int_and_get_leading_zeros, proof::{options::ProofOptions, stark::StarkProof}, traits::AIR, - transcript::batch_sample_challenges, }; struct Challenges @@ -50,7 +49,7 @@ fn step_1_replay_rounds_and_recover_challenges( ) -> Challenges where F: IsFFTField, - FieldElement: ByteConversion, + FieldElement: Serializable, A: AIR, { // =================================== @@ -72,15 +71,18 @@ where // ==========| Round 2 |========== // =================================== - // These are the challenges alpha^B_j and beta^B_j - // >>>> Send challenges: 𝛽_j^B - let boundary_coeffs = batch_sample_challenges( - air.boundary_constraints(&rap_challenges).constraints.len(), - transcript, - ); - // >>>> Send challenges: 𝛽_j^T - let transition_coeffs = - batch_sample_challenges(air.context().num_transition_constraints, transcript); + // <<<< Receive challenge: 𝛽 + let beta = transcript.sample_field_element(); + let num_boundary_constraints = air.boundary_constraints(&rap_challenges).constraints.len(); + + let num_transition_constraints = air.context().num_transition_constraints; + + let mut coefficients: Vec<_> = (1..num_boundary_constraints + num_transition_constraints + 1) + .map(|i| beta.pow(i)) + .collect(); + + let transition_coeffs: Vec<_> = coefficients.drain(..num_transition_constraints).collect(); + let boundary_coeffs = coefficients; // <<<< Receive commitments: [H₁], [Hβ‚‚] transcript.append_bytes(&proof.composition_poly_root); @@ -270,7 +272,7 @@ fn step_3_verify_fri( ) -> bool where F: IsFFTField, - FieldElement: ByteConversion, + FieldElement: Serializable, A: AIR, { // verify FRI @@ -309,8 +311,10 @@ fn step_4_verify_deep_composition_polynomial>( challenges: &Challenges, ) -> bool where - FieldElement: ByteConversion, + FieldElement: Serializable, { + let permutation = + get_stone_prover_domain_permutation(domain.interpolation_domain_size, domain.blowup_factor); let primitive_root = &F::get_primitive_root_of_unity(domain.root_order as u64).unwrap(); let z_squared = &challenges.z.square(); let mut denom_inv = challenges @@ -363,7 +367,7 @@ where .fold(result, |acc, ((merkle_root, merkle_proof), evaluation)| { acc & merkle_proof.verify::>( merkle_root, - *iota_n, + permutation[*iota_n], &evaluation, ) }); @@ -397,7 +401,7 @@ fn verify_query_and_sym_openings( two_inv: &FieldElement, ) -> bool where - FieldElement: ByteConversion, + FieldElement: Serializable, { let fri_layers_merkle_roots = &proof.fri_layers_merkle_roots; let evaluation_point_vec: Vec> = @@ -512,7 +516,7 @@ pub fn verify( where F: IsFFTField, A: AIR, - FieldElement: ByteConversion, + FieldElement: Serializable, { // Verify there are enough queries if proof.query_list.len() < proof_options.fri_number_of_queries { @@ -602,3 +606,80 @@ where true } + +#[cfg(test)] +pub mod tests { + use std::num::ParseIntError; + + use lambdaworks_math::field::{ + element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, + }; + + use crate::{ + domain::Domain, + examples::fibonacci_2_cols_shifted::{self, Fibonacci2ColsShifted}, + proof::options::ProofOptions, + prover::prove, + traits::AIR, + transcript::StoneProverTranscript, + verifier::step_1_replay_rounds_and_recover_challenges, + }; + + pub fn decode_hex(s: &str) -> Result, ParseIntError> { + (0..s.len()) + .step_by(2) + .map(|i| u8::from_str_radix(&s[i..i + 2], 16)) + .collect() + } + + #[test] + fn test_sharp_compatibility() { + let trace = fibonacci_2_cols_shifted::compute_trace(FieldElement::one(), 4); + + let claimed_index = 3; + let claimed_value = trace.get_row(claimed_index)[0]; + let mut proof_options = ProofOptions::default_test_options(); + proof_options.blowup_factor = 4; + proof_options.coset_offset = 3; + + let pub_inputs = fibonacci_2_cols_shifted::PublicInputs { + claimed_value, + claimed_index, + }; + + let transcript_init_seed = [0xca, 0xfe, 0xca, 0xfe]; + + let proof = prove::>( + &trace, + &pub_inputs, + &proof_options, + StoneProverTranscript::new(&transcript_init_seed), + ) + .unwrap(); + + let air = Fibonacci2ColsShifted::new(proof.trace_length, &pub_inputs, &proof_options); + let domain = Domain::new(&air); + let challenges = step_1_replay_rounds_and_recover_challenges( + &air, + &proof, + &domain, + &mut StoneProverTranscript::new(&transcript_init_seed), + ); + + assert_eq!( + proof.lde_trace_merkle_roots[0].to_vec(), + decode_hex("0eb9dcc0fb1854572a01236753ce05139d392aa3aeafe72abff150fe21175594").unwrap() + ); + + let beta = challenges.transition_coeffs[0]; + assert_eq!( + beta, + FieldElement::from_hex_unchecked( + "86105fff7b04ed4068ecccb8dbf1ed223bd45cd26c3532d6c80a818dbd4fa7" + ), + ); + assert_eq!(challenges.transition_coeffs[1], beta.pow(2u64)); + assert_eq!(challenges.boundary_coeffs[0], beta.pow(3u64)); + assert_eq!(challenges.boundary_coeffs[1], beta.pow(4u64)); + } +} From 64053db4df9d47bc8bea49fe6937ab7f8ba16dbe Mon Sep 17 00:00:00 2001 From: Diego K <43053772+diegokingston@users.noreply.github.com> Date: Thu, 5 Oct 2023 17:15:29 -0300 Subject: [PATCH 02/18] Update README.md (#594) --- README.md | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/README.md b/README.md index ae71fa8061..bc0f2f5f5d 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,67 @@ From the heights of these towers of fields, forty centuries of mathematics look +## List of features + +Disclaimer: This list contains cryptographic primitives and mathematical structures that we want to support in Lambdaworks. It can be expanded later to include new primitives. If you find there is a mistake or there has been an update in another library, please let us know. + +List of symbols: +- :heavy_check_mark: means the feature is currently supported. +- :hammer: means that the feature is partially implemented or is under active construction. +- :x: means that the feature is not currently supported. + +| Finite Fields | Lambdaworks | Arkworks | Constantine | GNARK | +| -------------- | ------------------ | ------------------ | ----------- | ----- | +| StarkField 252 | :heavy_check_mark: | :heavy_check_mark: | | | +| Mersenne 31 | :hammer: | | | | +| Baby Bear | :hammer: | | | | +| MiniGoldilocks | :hammer: | | | | + +| ZK friendly Hash function | Lambdaworks | Arkworks | Constantine | GNARK | +| ------------------------- | ----------- | ------------------ | ----------- | ----- | +| Poseidon | :hammer: | :heavy_check_mark: | | | +| Pedersen | :hammer: | :heavy_check_mark: | | | +| Rescue Prime XLIX | :x: | | | | + +| Elliptic Curves | Lambdaworks | Arkworks | Constantine | GNARK | +| --------------- | ------------------ | ------------------ | ----------- | ------------------ | +| BLS12-381 | :heavy_check_mark: | :heavy_check_mark: | | | +| BLS12-377 | :hammer: | :heavy_check_mark: | | :heavy_check_mark: | +| BN-254 | :x: | :heavy_check_mark: | | | +| Pallas | :x: | :heavy_check_mark: | | | +| Vesta | :x: | :heavy_check_mark: | | | +| Bandersnatch | :hammer: | :heavy_check_mark: | | | + +| STARKs | Lambdaworks | Arkworks | Constantine | GNARK | +| -------------- | ------------------ | -------- | ----------- | ----- | +| STARK Prover | :heavy_check_mark: | :x: | | :x: | +| CAIRO Prover | :hammer: | :x: | | :x: | + +We are currently working to make the CAIRO prover compatible with the Stone Prover + +| SNARKs | Lambdaworks | Arkworks | Constantine | GNARK | +| ------- | ----------- | ------------------ | ----------- | ------------------ | +| Groth16 | :x: | :heavy_check_mark: | | :heavy_check_mark: | +| Plonk | :hammer: | :x: | | :heavy_check_mark: | +| Spartan | :x: | :heavy_check_mark: | | | +| Marlin | :x: | :heavy_check_mark: | | | +| GKR | :x: | :heavy_check_mark: | | :heavy_check_mark: | + + +| Polynomial Commitment Schemes | Lambdaworks | Arkworks | Constantine | GNARK | +| ----------------------------- | ------------------ | ------------------ | ----------- | ------------------ | +| FRI | :hammer: | :x: | | :heavy_check_mark: | +| IPA | :x: | :heavy_check_mark: | | | +| Hyrax | :x: | :x: | | | +| KZG10 | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark: | + +| Folding Schemes | Lambdaworks | Arkworks | Constantine | GNARK | +| --------------- | ----------- | -------- | ----------- | ----- | +| Nova | :x: | | | | +| Supernova | :x: | | | | +| Protostar | :x: | | | | +| Protogalaxy | :x: | | | | + ## [Documentation](https://lambdaclass.github.io/lambdaworks) Zero-Knowledge and Validity Proofs have gained a lot of attention over the last few years. We strongly believe in this potential and that is why we decided to start working in this challenging ecosystem, where math, cryptography and distributed systems meet. The main barrier in the beginning was not the cryptography or math but the lack of good libraries which are performant and developer friendly. There are some exceptions, though, like gnark or halo2. Some have nice APIs and are easy to work with, but they are not written in Rust, and some are written in Rust but have poor programming and engineering practices. Most of them don't have support for CUDA, Metal and WebGPU or distributed FFT calculation using schedulers like Dask. From f050c5cc435052a54cd4e6b432f8518a5ec284f9 Mon Sep 17 00:00:00 2001 From: Mauro Toscano <12560266+MauroToscano@users.noreply.github.com> Date: Thu, 5 Oct 2023 17:28:25 -0300 Subject: [PATCH 03/18] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bc0f2f5f5d..65dbf8bd8f 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ From the heights of these towers of fields, forty centuries of mathematics look +## [Documentation](https://lambdaclass.github.io/lambdaworks) + ## List of features Disclaimer: This list contains cryptographic primitives and mathematical structures that we want to support in Lambdaworks. It can be expanded later to include new primitives. If you find there is a mistake or there has been an update in another library, please let us know. @@ -72,8 +74,6 @@ We are currently working to make the CAIRO prover compatible with the Stone Prov | Protostar | :x: | | | | | Protogalaxy | :x: | | | | -## [Documentation](https://lambdaclass.github.io/lambdaworks) - Zero-Knowledge and Validity Proofs have gained a lot of attention over the last few years. We strongly believe in this potential and that is why we decided to start working in this challenging ecosystem, where math, cryptography and distributed systems meet. The main barrier in the beginning was not the cryptography or math but the lack of good libraries which are performant and developer friendly. There are some exceptions, though, like gnark or halo2. Some have nice APIs and are easy to work with, but they are not written in Rust, and some are written in Rust but have poor programming and engineering practices. Most of them don't have support for CUDA, Metal and WebGPU or distributed FFT calculation using schedulers like Dask. So, we decided to build our library, focusing on performance, with clear documentation and developer-focused. Our core team is a group of passionate people from different backgrounds and different strengths; we think that the whole is greater than just the addition of the parts. We don't want to be a compilation of every research result in the ZK space. We want this to be a library that can be used in production, not just in academic research. We want to offer developers the main building blocks and proof systems so that they can build their applications on top of this library. From bea1b8d6fe02e955084d82d6cf4a7f5ee1ce84c3 Mon Sep 17 00:00:00 2001 From: Mauro Toscano <12560266+MauroToscano@users.noreply.github.com> Date: Thu, 5 Oct 2023 17:11:55 -0300 Subject: [PATCH 04/18] Fix clippy, remove partial ord from babybear (#591) --- math/src/field/fields/fft_friendly/babybear.rs | 12 ------------ .../fields/fft_friendly/stark_252_prime_field.rs | 1 + math/src/unsigned_integer/element.rs | 1 + 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/math/src/field/fields/fft_friendly/babybear.rs b/math/src/field/fields/fft_friendly/babybear.rs index 1dcefc28d6..68da03f91a 100644 --- a/math/src/field/fields/fft_friendly/babybear.rs +++ b/math/src/field/fields/fft_friendly/babybear.rs @@ -30,18 +30,6 @@ impl FieldElement { } } -impl PartialOrd for FieldElement { - fn partial_cmp(&self, other: &Self) -> Option { - self.representative().partial_cmp(&other.representative()) - } -} - -impl Ord for FieldElement { - fn cmp(&self, other: &Self) -> core::cmp::Ordering { - self.representative().cmp(&other.representative()) - } -} - #[cfg(test)] mod test_babybear_31_bytes_ops { use super::Babybear31PrimeField; diff --git a/math/src/field/fields/fft_friendly/stark_252_prime_field.rs b/math/src/field/fields/fft_friendly/stark_252_prime_field.rs index abea28907b..0703a97f6c 100644 --- a/math/src/field/fields/fft_friendly/stark_252_prime_field.rs +++ b/math/src/field/fields/fft_friendly/stark_252_prime_field.rs @@ -63,6 +63,7 @@ impl FieldElement { } } +#[allow(clippy::incorrect_partial_ord_impl_on_ord_type)] impl PartialOrd for FieldElement { fn partial_cmp(&self, other: &Self) -> Option { self.representative().partial_cmp(&other.representative()) diff --git a/math/src/unsigned_integer/element.rs b/math/src/unsigned_integer/element.rs index d76e54ec75..fab80ce6fd 100644 --- a/math/src/unsigned_integer/element.rs +++ b/math/src/unsigned_integer/element.rs @@ -36,6 +36,7 @@ pub struct UnsignedInteger { // NOTE: manually implementing `PartialOrd` may seem unorthodox, but the // derived implementation had terrible performance. +#[allow(clippy::incorrect_partial_ord_impl_on_ord_type)] impl PartialOrd for UnsignedInteger { fn partial_cmp(&self, other: &Self) -> Option { let mut i = 0; From ea9d5cc2a4cfb7b895cb8c0fbec152cf86e21441 Mon Sep 17 00:00:00 2001 From: Mauro Toscano <12560266+MauroToscano@users.noreply.github.com> Date: Thu, 5 Oct 2023 19:01:46 -0300 Subject: [PATCH 05/18] Update README.md --- README.md | 100 +++++++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 65dbf8bd8f..ccf3d3e1c1 100644 --- a/README.md +++ b/README.md @@ -14,65 +14,65 @@ From the heights of these towers of fields, forty centuries of mathematics look ## [Documentation](https://lambdaclass.github.io/lambdaworks) ## List of features - Disclaimer: This list contains cryptographic primitives and mathematical structures that we want to support in Lambdaworks. It can be expanded later to include new primitives. If you find there is a mistake or there has been an update in another library, please let us know. List of symbols: - :heavy_check_mark: means the feature is currently supported. -- :hammer: means that the feature is partially implemented or is under active construction. +- πŸ—οΈ means that the feature is partially implemented or is under active construction. - :x: means that the feature is not currently supported. -| Finite Fields | Lambdaworks | Arkworks | Constantine | GNARK | -| -------------- | ------------------ | ------------------ | ----------- | ----- | -| StarkField 252 | :heavy_check_mark: | :heavy_check_mark: | | | -| Mersenne 31 | :hammer: | | | | -| Baby Bear | :hammer: | | | | -| MiniGoldilocks | :hammer: | | | | - -| ZK friendly Hash function | Lambdaworks | Arkworks | Constantine | GNARK | -| ------------------------- | ----------- | ------------------ | ----------- | ----- | -| Poseidon | :hammer: | :heavy_check_mark: | | | -| Pedersen | :hammer: | :heavy_check_mark: | | | -| Rescue Prime XLIX | :x: | | | | - -| Elliptic Curves | Lambdaworks | Arkworks | Constantine | GNARK | -| --------------- | ------------------ | ------------------ | ----------- | ------------------ | -| BLS12-381 | :heavy_check_mark: | :heavy_check_mark: | | | -| BLS12-377 | :hammer: | :heavy_check_mark: | | :heavy_check_mark: | -| BN-254 | :x: | :heavy_check_mark: | | | -| Pallas | :x: | :heavy_check_mark: | | | -| Vesta | :x: | :heavy_check_mark: | | | -| Bandersnatch | :hammer: | :heavy_check_mark: | | | - -| STARKs | Lambdaworks | Arkworks | Constantine | GNARK | -| -------------- | ------------------ | -------- | ----------- | ----- | -| STARK Prover | :heavy_check_mark: | :x: | | :x: | -| CAIRO Prover | :hammer: | :x: | | :x: | +| Finite Fields | Lambdaworks | Arkworks | Halo2 | GNARK | Constantine | +| -------------- | ------------------ | ------------------ | --- | ----- | ----------- | +| StarkField 252 | :heavy_check_mark: | :heavy_check_mark: | | | | +| Mersenne 31 | πŸ—οΈ | | | | | +| Baby Bear | πŸ—οΈ | | | | | +| MiniGoldilocks | πŸ—οΈ | | | | | + +| ZK friendly Hash function | Lambdaworks | Arkworks | Halo2 | GNARK | Constantine | +| ------------------------- | ----------- | ------------------ | --- | ----- | ----------- | +| Poseidon | πŸ—οΈ | :heavy_check_mark: | | | | +| Pedersen | πŸ—οΈ | :heavy_check_mark: | | | | +| Rescue Prime XLIX | :x: | | | | | + +| Elliptic Curves | Lambdaworks | Arkworks | Halo2 | GNARK | Constantine | +| --------------- | ------------------ | ------------------ | --- | ------------------ | ----------- | +| BLS12-381 | :heavy_check_mark: | :heavy_check_mark: | | | | +| BLS12-377 | πŸ—οΈ | :heavy_check_mark: | | :heavy_check_mark: | | +| BN-254 | :x: | :heavy_check_mark: | | | | +| Pallas | :x: | :heavy_check_mark: | | | | +| Vesta | :x: | :heavy_check_mark: | | | | +| Bandersnatch | πŸ—οΈ | :heavy_check_mark: | | | | + +| STARKs | Lambdaworks | Arkworks | Halo2 | GNARK | Constantine | +| ------------ | ------------------ | -------- | --- | ----- | ----------- | +| STARK Prover | :heavy_check_mark: | :x: | | :x: | | +| CAIRO Prover | πŸ—οΈ | :x: | | :x: | | We are currently working to make the CAIRO prover compatible with the Stone Prover -| SNARKs | Lambdaworks | Arkworks | Constantine | GNARK | -| ------- | ----------- | ------------------ | ----------- | ------------------ | -| Groth16 | :x: | :heavy_check_mark: | | :heavy_check_mark: | -| Plonk | :hammer: | :x: | | :heavy_check_mark: | -| Spartan | :x: | :heavy_check_mark: | | | -| Marlin | :x: | :heavy_check_mark: | | | -| GKR | :x: | :heavy_check_mark: | | :heavy_check_mark: | - - -| Polynomial Commitment Schemes | Lambdaworks | Arkworks | Constantine | GNARK | -| ----------------------------- | ------------------ | ------------------ | ----------- | ------------------ | -| FRI | :hammer: | :x: | | :heavy_check_mark: | -| IPA | :x: | :heavy_check_mark: | | | -| Hyrax | :x: | :x: | | | -| KZG10 | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark: | - -| Folding Schemes | Lambdaworks | Arkworks | Constantine | GNARK | -| --------------- | ----------- | -------- | ----------- | ----- | -| Nova | :x: | | | | -| Supernova | :x: | | | | -| Protostar | :x: | | | | -| Protogalaxy | :x: | | | | +| SNARKs | Lambdaworks | Arkworks | Halo2 | GNARK | Constantine | +| ------- | ----------- | ------------------ | --- | ------------------ | ----------- | +| Groth16 | :x: | :heavy_check_mark: | | :heavy_check_mark: | | +| Plonk | πŸ—οΈ | :x: | | :heavy_check_mark: | | +| Spartan | :x: | :heavy_check_mark: | | | | +| Marlin | :x: | :heavy_check_mark: | | | | +| GKR | :x: | :heavy_check_mark: | | :heavy_check_mark: | | + + +| Polynomial Commitment Schemes | Lambdaworks | Halo2 | Arkworks | GNARK | Constantine | +| ----------------------------- | ------------------ | --- | ------------------ | ------------------ | ----------- | +| FRI | πŸ—οΈ | | :x: | :heavy_check_mark: | | +| IPA | :x: | | :heavy_check_mark: | | | +| Hyrax | :x: | | :x: | | | +| KZG10 | :heavy_check_mark: | | :heavy_check_mark: | :heavy_check_mark: | | + +| Folding Schemes | Lambdaworks | Arkworks | Halo2 | GNARK | Constantine | +| --------------- | ----------- | -------- | --- | ----- | ----------- | +| Nova | :x: | | | | | +| Supernova | :x: | | | | | +| Protostar | :x: | | | | | +| Protogalaxy | :x: | | | | | + Zero-Knowledge and Validity Proofs have gained a lot of attention over the last few years. We strongly believe in this potential and that is why we decided to start working in this challenging ecosystem, where math, cryptography and distributed systems meet. The main barrier in the beginning was not the cryptography or math but the lack of good libraries which are performant and developer friendly. There are some exceptions, though, like gnark or halo2. Some have nice APIs and are easy to work with, but they are not written in Rust, and some are written in Rust but have poor programming and engineering practices. Most of them don't have support for CUDA, Metal and WebGPU or distributed FFT calculation using schedulers like Dask. From 2c2e0f754dc989f2049f65c4fd4a7e1a57a502f6 Mon Sep 17 00:00:00 2001 From: Priyansh Rathi Date: Fri, 6 Oct 2023 13:12:17 -0700 Subject: [PATCH 06/18] Add Ed448-Goldilocks elliptic curve (#557) * Fix equality testing in P448-Goldilocks prime field * Implement IsPrimeField for P448GoldilocksPrimeField * Add Ed448-Goldilocks elliptic curve --- .../edwards/curves/ed448_goldilocks.rs | 99 +++++++++++ math/src/elliptic_curve/edwards/curves/mod.rs | 1 + .../fields/p448_goldilocks_prime_field.rs | 160 ++++++++++++++---- 3 files changed, 229 insertions(+), 31 deletions(-) create mode 100644 math/src/elliptic_curve/edwards/curves/ed448_goldilocks.rs diff --git a/math/src/elliptic_curve/edwards/curves/ed448_goldilocks.rs b/math/src/elliptic_curve/edwards/curves/ed448_goldilocks.rs new file mode 100644 index 0000000000..e9fe3d32eb --- /dev/null +++ b/math/src/elliptic_curve/edwards/curves/ed448_goldilocks.rs @@ -0,0 +1,99 @@ +use crate::{ + elliptic_curve::{ + edwards::{point::EdwardsProjectivePoint, traits::IsEdwards}, + traits::IsEllipticCurve, + }, + field::{element::FieldElement, fields::p448_goldilocks_prime_field::P448GoldilocksPrimeField}, +}; + +#[derive(Debug, Clone)] +pub struct Ed448Goldilocks; + +impl IsEllipticCurve for Ed448Goldilocks { + type BaseField = P448GoldilocksPrimeField; + type PointRepresentation = EdwardsProjectivePoint; + + /// Taken from https://www.rfc-editor.org/rfc/rfc7748#page-6 + fn generator() -> Self::PointRepresentation { + Self::PointRepresentation::new([ + FieldElement::::from_hex("4f1970c66bed0ded221d15a622bf36da9e146570470f1767ea6de324a3d3a46412ae1af72ab66511433b80e18b00938e2626a82bc70cc05e").unwrap(), + FieldElement::::from_hex("693f46716eb6bc248876203756c9c7624bea73736ca3984087789c1e05a0c2d73ad3ff1ce67c39c4fdbd132c4ed7c8ad9808795bf230fa14").unwrap(), + FieldElement::one(), + ]) + } +} + +impl IsEdwards for Ed448Goldilocks { + fn a() -> FieldElement { + FieldElement::one() + } + + fn d() -> FieldElement { + -FieldElement::from(39081) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + cyclic_group::IsGroup, elliptic_curve::traits::EllipticCurveError, + field::element::FieldElement, + }; + + #[allow(clippy::upper_case_acronyms)] + type FE = FieldElement; + + fn generator_times_5() -> EdwardsProjectivePoint { + let x = FE::from_hex("7a9f9335a48dcb0e2ba7601eedb50def80cbcf728562ada756d761e8958812808bc0d57a920c3c96f07b2d8cefc6f950d0a99d1092030034").unwrap(); + let y = FE::from_hex("adfd751a2517edd3b9109ce4fd580ade260ca1823ab18fced86551f7b698017127d7a4ee59d2b33c58405512881f225443b4731472f435eb").unwrap(); + Ed448Goldilocks::create_point_from_affine(x, y).unwrap() + } + + fn point_1() -> EdwardsProjectivePoint { + let x = FE::from_hex("c591e0987244569fbb80a8edda5f9c5b30d9e7862acbb19ac0f24b766fe29c5e5782efc0e7a169f0c55c5524f8a9f9333ca985ec56404926").unwrap(); + let y = FE::from_hex("f969573bf05f19ac5824718d7483d3b83a3ece5847e25487ae2a176290ad2b1cb9c7f4dd55f6ca6c50209556d7fc16e0683c3177356ac9bc").unwrap(); + Ed448Goldilocks::create_point_from_affine(x, y).unwrap() + } + + fn point_1_times_7() -> EdwardsProjectivePoint { + let x = FE::from_hex("63c9cd1d79f027458015c2013fc819dd0f46f71c21a11fee0c32998acd17bac5b06d0f2f1e1539cfc33223a6e989b2b119dae9bbb16c3743").unwrap(); + let y = FE::from_hex("654de66ab8be9fbeec6e72798a0ba2bb39c1888b99104de6cb0acf4516ea5e018bd292a1855f0fea673a5d8e8724d1b19ca52817db624f06").unwrap(); + Ed448Goldilocks::create_point_from_affine(x, y).unwrap() + } + + #[test] + fn generator_satisfies_defining_equation() { + let g = Ed448Goldilocks::generator().to_affine(); + assert_eq!(Ed448Goldilocks::defining_equation(g.x(), g.y()), FE::zero()); + } + + #[test] + fn adding_generator_five_times_works() { + let g_times_5 = Ed448Goldilocks::generator().operate_with_self(5_u16); + assert_eq!(g_times_5, generator_times_5()); + } + + #[test] + fn adding_point_1_seven_times_works() { + let point_1 = point_1(); + let point_1_times_7 = point_1_times_7(); + assert_eq!(point_1.operate_with_self(7_u16), point_1_times_7); + } + + #[test] + fn create_valid_point_works() { + let p = point_1(); + assert_eq!(*p.x(), FE::from_hex("c591e0987244569fbb80a8edda5f9c5b30d9e7862acbb19ac0f24b766fe29c5e5782efc0e7a169f0c55c5524f8a9f9333ca985ec56404926").unwrap()); + assert_eq!(*p.y(), FE::from_hex("f969573bf05f19ac5824718d7483d3b83a3ece5847e25487ae2a176290ad2b1cb9c7f4dd55f6ca6c50209556d7fc16e0683c3177356ac9bc").unwrap()); + assert_eq!(*p.z(), FE::one()); + } + + #[test] + fn create_invalid_points_panics() { + assert_eq!( + Ed448Goldilocks::create_point_from_affine(FE::from(1), FE::from(1)).unwrap_err(), + EllipticCurveError::InvalidPoint + ) + } +} diff --git a/math/src/elliptic_curve/edwards/curves/mod.rs b/math/src/elliptic_curve/edwards/curves/mod.rs index 34aec6d603..f0fc03b7a5 100644 --- a/math/src/elliptic_curve/edwards/curves/mod.rs +++ b/math/src/elliptic_curve/edwards/curves/mod.rs @@ -1,2 +1,3 @@ pub mod bandersnatch; +pub mod ed448_goldilocks; pub mod tiny_jub_jub; diff --git a/math/src/field/fields/p448_goldilocks_prime_field.rs b/math/src/field/fields/p448_goldilocks_prime_field.rs index 1d161df1f9..55eb2e2f7d 100644 --- a/math/src/field/fields/p448_goldilocks_prime_field.rs +++ b/math/src/field/fields/p448_goldilocks_prime_field.rs @@ -1,5 +1,6 @@ +use crate::errors::CreationError; use crate::field::errors::FieldError; -use crate::field::traits::IsField; +use crate::field::traits::{IsField, IsPrimeField}; use crate::unsigned_integer::element::UnsignedInteger; #[derive(Debug, Clone, PartialEq, Eq)] @@ -133,8 +134,15 @@ impl IsField for P448GoldilocksPrimeField { Self::mul(a, &b_inv) } + /// Taken from https://sourceforge.net/p/ed448goldilocks/code/ci/master/tree/src/per_field/f_generic.tmpl.c fn eq(a: &U56x8, b: &U56x8) -> bool { - a.limbs == b.limbs + let mut c = Self::sub(a, b); + Self::strong_reduce(&mut c); + let mut ret = 0u64; + for limb in c.limbs.iter() { + ret |= limb; + } + ret == 0 } fn zero() -> U56x8 { @@ -156,12 +164,38 @@ impl IsField for P448GoldilocksPrimeField { fn from_base_type(x: U56x8) -> U56x8 { let mut x = x; - Self::weak_reduce(&mut x); + Self::strong_reduce(&mut x); x } } +impl IsPrimeField for P448GoldilocksPrimeField { + type RepresentativeType = U448; + + fn representative(a: &U56x8) -> U448 { + let mut a = *a; + Self::strong_reduce(&mut a); + + let mut r = U448::from_u64(0); + for i in (0..7).rev() { + r = r << 56; + r = r + U448::from_u64(a.limbs[i]); + } + r + } + + fn from_hex(hex_string: &str) -> Result { + U56x8::from_hex(hex_string) + } + + fn field_bit_size() -> usize { + 448 + } +} + impl P448GoldilocksPrimeField { + /// Reduces the value in each limb to less than 2^57 (2^56 + 2^8 - 2 is the largest possible value in a limb after this reduction) + /// Taken from https://sourceforge.net/p/ed448goldilocks/code/ci/master/tree/src/p448/arch_ref64/f_impl.h fn weak_reduce(a: &mut U56x8) { let a = &mut a.limbs; @@ -175,15 +209,55 @@ impl P448GoldilocksPrimeField { a[0] = (a[0] & mask) + tmp; } + + /// Reduces the number to its canonical form + /// Taken from https://sourceforge.net/p/ed448goldilocks/code/ci/master/tree/src/per_field/f_generic.tmpl.c + fn strong_reduce(a: &mut U56x8) { + P448GoldilocksPrimeField::weak_reduce(a); + + const MODULUS: U56x8 = U56x8 { + limbs: [ + 0xffffffffffffff, + 0xffffffffffffff, + 0xffffffffffffff, + 0xffffffffffffff, + 0xfffffffffffffe, + 0xffffffffffffff, + 0xffffffffffffff, + 0xffffffffffffff, + ], + }; + let mask = (1u128 << 56) - 1; + + let mut scarry = 0i128; + for i in 0..8 { + scarry = scarry + (a.limbs[i] as i128) - (MODULUS.limbs[i] as i128); + a.limbs[i] = ((scarry as u128) & mask) as u64; + scarry >>= 56; + } + + assert!((scarry as u64) == 0 || (scarry as u64).wrapping_add(1) == 0); + + let scarry_0 = scarry as u64; + let mut carry = 0u128; + + for i in 0..8 { + carry = carry + (a.limbs[i] as u128) + ((scarry_0 & MODULUS.limbs[i]) as u128); + a.limbs[i] = (carry & mask) as u64; + carry >>= 56; + } + + assert!((carry as u64).wrapping_add(scarry_0) == 0); + } } impl U56x8 { - pub const fn from(value: &str) -> Self { + pub const fn from_hex(hex_string: &str) -> Result { let mut result = [0u64; 8]; let mut limb = 0; let mut limb_index = 0; let mut shift = 0; - let value = value.as_bytes(); + let value = hex_string.as_bytes(); let mut i: usize = value.len(); while i > 0 { i -= 1; @@ -192,7 +266,7 @@ impl U56x8 { c @ b'a'..=b'f' => (c as u64 - 'a' as u64 + 10) << shift, c @ b'A'..=b'F' => (c as u64 - 'A' as u64 + 10) << shift, _ => { - panic!("Malformed hex expression.") + return Err(CreationError::InvalidHexString); } }; shift += 4; @@ -205,7 +279,7 @@ impl U56x8 { } result[limb_index] = limb; - U56x8 { limbs: result } + Ok(U56x8 { limbs: result }) } } @@ -214,16 +288,16 @@ mod tests { use super::*; #[test] - fn construc_u56x8_from_hex_string_1() { + fn construct_u56x8_from_hex_string_1() { let hex_str = "1"; - let num = U56x8::from(hex_str); + let num = U56x8::from_hex(hex_str).unwrap(); assert_eq!(num.limbs, [1, 0, 0, 0, 0, 0, 0, 0]); } #[test] fn construct_u56x8_from_hex_string_2() { let hex_str = "49bbeeaa7102b38a0cfba4634f64a288bcb9b1366599f7afcb5453567ef7c34cce0f7139c6dea4841497172f637c7bbbf3ca1990ad88381e"; - let num = U56x8::from(hex_str); + let num = U56x8::from_hex(hex_str).unwrap(); assert_eq!( num.limbs, [ @@ -239,64 +313,85 @@ mod tests { ); } + #[test] + fn strong_reduce_test1() { + let mut num = U56x8::from_hex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(); + P448GoldilocksPrimeField::strong_reduce(&mut num); + assert_eq!(num.limbs, [0, 0, 0, 0, 0, 0, 0, 0]); + } + + #[test] + fn strong_reduce_test2() { + let mut num = U56x8::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000").unwrap(); + P448GoldilocksPrimeField::strong_reduce(&mut num); + assert_eq!(num.limbs, [1, 0, 0, 0, 0, 0, 0, 0]); + } + + #[test] + fn representative_test() { + let num = U56x8::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000029").unwrap(); + let r = P448GoldilocksPrimeField::representative(&num); + assert_eq!(r, U448::from_u64(42)); + } + #[test] fn p448_add_test_1() { - let num1 = U56x8::from("73c7941e36ee1e12b2105fb96634848d62def10bc1782576cfa7f54486820202847bbfb2e8f89ff7707f9913b8cf9b9efaf2029cfd6d3fa9"); - let num2 = U56x8::from("f3ef02193a11b6ea80be4bd2944d32c4674456a888b470b14e0cf223bed114bb28146d967f0d220cf20be2016dc84f51e5d5e29a71751f06"); + let num1 = U56x8::from_hex("73c7941e36ee1e12b2105fb96634848d62def10bc1782576cfa7f54486820202847bbfb2e8f89ff7707f9913b8cf9b9efaf2029cfd6d3fa9").unwrap(); + let num2 = U56x8::from_hex("f3ef02193a11b6ea80be4bd2944d32c4674456a888b470b14e0cf223bed114bb28146d967f0d220cf20be2016dc84f51e5d5e29a71751f06").unwrap(); let num3 = P448GoldilocksPrimeField::add(&num1, &num2); - assert_eq!(num3, U56x8::from("67b6963770ffd4fd32ceab8bfa81b751ca2347b44a2c96281db4e769455316bdac902d496805c204628b7b152697eaf0e0c7e5376ee25eb0")); + assert_eq!(num3, U56x8::from_hex("67b6963770ffd4fd32ceab8bfa81b751ca2347b44a2c96281db4e769455316bdac902d496805c204628b7b152697eaf0e0c7e5376ee25eb0").unwrap()); } #[test] fn p448_sub_test_1() { - let num1 = U56x8::from("22264a9d5272984a996cc5eef6bd165e63bc70f2050bbd5bc24343df9cc25f826cef7bff7466963a82cd59f36671c724c53b8b27330ea076"); - let num2 = U56x8::from("7a0063b5cd729df62c0e77071727639e06d0892eacb505569e8b47a99175d1d09a4bd7c22a2168c1fb9f3de31d9633d92341f84d000633b1"); + let num1 = U56x8::from_hex("22264a9d5272984a996cc5eef6bd165e63bc70f2050bbd5bc24343df9cc25f826cef7bff7466963a82cd59f36671c724c53b8b27330ea076").unwrap(); + let num2 = U56x8::from_hex("7a0063b5cd729df62c0e77071727639e06d0892eacb505569e8b47a99175d1d09a4bd7c22a2168c1fb9f3de31d9633d92341f84d000633b1").unwrap(); let num3 = P448GoldilocksPrimeField::sub(&num1, &num2); - assert_eq!(num3, U56x8::from("a825e6e784fffa546d5e4ee7df95b2c05cebe7c35856b80523b7fc350b4c8db1d2a3a43d4a452d78872e1c1048db934ba1f992da33086cc4")); + assert_eq!(num3, U56x8::from_hex("a825e6e784fffa546d5e4ee7df95b2c05cebe7c35856b80523b7fc350b4c8db1d2a3a43d4a452d78872e1c1048db934ba1f992da33086cc4").unwrap()); } #[test] fn p448_neg_test_1() { - let num1 = U56x8::from("21183d1faa857cd3f08d54871837b06d70af4e6b85173c0ff02685147f38e8b9af3141baad0067f3514a527bd3e7405a953c3a8fa9a15bb3"); + let num1 = U56x8::from_hex("21183d1faa857cd3f08d54871837b06d70af4e6b85173c0ff02685147f38e8b9af3141baad0067f3514a527bd3e7405a953c3a8fa9a15bb3").unwrap(); let num2 = P448GoldilocksPrimeField::neg(&num1); - assert_eq!(num2, U56x8::from("dee7c2e0557a832c0f72ab78e7c84f928f50b1947ae8c3f00fd97aea80c7174650cebe4552ff980caeb5ad842c18bfa56ac3c570565ea44c")); + assert_eq!(num2, U56x8::from_hex("dee7c2e0557a832c0f72ab78e7c84f928f50b1947ae8c3f00fd97aea80c7174650cebe4552ff980caeb5ad842c18bfa56ac3c570565ea44c").unwrap()); } #[test] fn p448_mul_test_1() { - let num1 = U56x8::from("a"); - let num2 = U56x8::from("b"); + let num1 = U56x8::from_hex("a").unwrap(); + let num2 = U56x8::from_hex("b").unwrap(); let num3 = P448GoldilocksPrimeField::mul(&num1, &num2); - assert_eq!(num3, U56x8::from("6e")); + assert_eq!(num3, U56x8::from_hex("6e").unwrap()); } #[test] fn p448_mul_test_2() { - let num1 = U56x8::from("b7aa542ac8824fbf654ee0ab4ea5eb3b0ad65b48bfef5e4d8b84ab5737e9283c06ecbadd799688cdf73cd7d077d53b5e6f738b264086d034"); - let num2 = U56x8::from("89a36d8b491f5a9af136a35061a59aa2c65353a3c99bb205a53c7ae2f37e6ae492f24248fc549344ba2f203c6d5b2b5dab216fdd1a7dcf87"); + let num1 = U56x8::from_hex("b7aa542ac8824fbf654ee0ab4ea5eb3b0ad65b48bfef5e4d8b84ab5737e9283c06ecbadd799688cdf73cd7d077d53b5e6f738b264086d034").unwrap(); + let num2 = U56x8::from_hex("89a36d8b491f5a9af136a35061a59aa2c65353a3c99bb205a53c7ae2f37e6ae492f24248fc549344ba2f203c6d5b2b5dab216fdd1a7dcf87").unwrap(); let num3 = P448GoldilocksPrimeField::mul(&num1, &num2); - assert_eq!(num3, U56x8::from("f61c57f70d8a1eaf261907d08eb1086c2289f7bbb6ff6a0dfd016f91ac9eda658879b52a654a10b2ce123717fad3ab15b1e77ce643683886")); + assert_eq!(num3, U56x8::from_hex("f61c57f70d8a1eaf261907d08eb1086c2289f7bbb6ff6a0dfd016f91ac9eda658879b52a654a10b2ce123717fad3ab15b1e77ce643683886").unwrap()); } #[test] fn p448_pow_test_1() { - let num1 = U56x8::from("6b1b1d952930ee34fb6ed3521f7653293fd7e01de2027673d3d5a0bf3dc0688530bec50b3dfca4df28cc432bec1198e17fde3e1cc79e5732"); + let num1 = U56x8::from_hex("6b1b1d952930ee34fb6ed3521f7653293fd7e01de2027673d3d5a0bf3dc0688530bec50b3dfca4df28cc432bec1198e17fde3e1cc79e5732").unwrap(); let num2 = P448GoldilocksPrimeField::pow(&num1, 65537u64); - assert_eq!(num2, U56x8::from("ec48eda1579a0879c01e8853e4a718ede9cd6bcf88d6696b47dc4dce7d2acdd1a37674aa455d84126800893975c95bb47c40b098a9e30836")); + assert_eq!(num2, U56x8::from_hex("ec48eda1579a0879c01e8853e4a718ede9cd6bcf88d6696b47dc4dce7d2acdd1a37674aa455d84126800893975c95bb47c40b098a9e30836").unwrap()); } #[test] fn p448_inv_test_1() { - let num1 = U56x8::from("b86e226f5ac29af28c74e272fc129ab167798f70dedd2ce76aa76204a23beb74c8ddba2a643196c62ee35a18472d6de7d82b6af4b2fc5e58"); - let num2 = U56x8::from("bb2bd89a1297c7a6052b41be503aa7de2cd6e6775396e76bf995f27f1dccf69131067824ded693bdd6e58fe7c2276fa92ec1d9a0048b9be6"); + let num1 = U56x8::from_hex("b86e226f5ac29af28c74e272fc129ab167798f70dedd2ce76aa76204a23beb74c8ddba2a643196c62ee35a18472d6de7d82b6af4b2fc5e58").unwrap(); + let num2 = U56x8::from_hex("bb2bd89a1297c7a6052b41be503aa7de2cd6e6775396e76bf995f27f1dccf69131067824ded693bdd6e58fe7c2276fa92ec1d9a0048b9be6").unwrap(); let num3 = P448GoldilocksPrimeField::div(&num1, &num2); - assert_eq!(num3, U56x8::from("707b5cc75967b58ebd28d14d4ed7ed9eaae1187d0b359c7733cf61b1a5c87fc88228ca532c50f19d1ba57146ca2e38417922033f647c8d9")); + assert_eq!(num3, U56x8::from_hex("707b5cc75967b58ebd28d14d4ed7ed9eaae1187d0b359c7733cf61b1a5c87fc88228ca532c50f19d1ba57146ca2e38417922033f647c8d9").unwrap()); } #[test] fn p448_from_u64_test_1() { let num = P448GoldilocksPrimeField::from_u64(2012613457133209520u64); - assert_eq!(num, U56x8::from("1bee3d46a69887b0")); + assert_eq!(num, U56x8::from_hex("1bee3d46a69887b0").unwrap()); } #[test] @@ -306,6 +401,9 @@ mod tests { limbs[1] = 6217911673150459564u64; let num1 = U56x8 { limbs }; let num2 = P448GoldilocksPrimeField::from_base_type(num1); - assert_eq!(num2, U56x8::from("564a75b90ae34f8155d5821d7e9484")); + assert_eq!( + num2, + U56x8::from_hex("564a75b90ae34f8155d5821d7e9484").unwrap() + ); } } From bc43d72a5b182947fdaed4f35c2f8838278139ba Mon Sep 17 00:00:00 2001 From: Federico Carrone Date: Sat, 7 Oct 2023 10:57:21 -0300 Subject: [PATCH 07/18] Update README.md --- README.md | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index ccf3d3e1c1..a8b667f9df 100644 --- a/README.md +++ b/README.md @@ -21,53 +21,38 @@ List of symbols: - πŸ—οΈ means that the feature is partially implemented or is under active construction. - :x: means that the feature is not currently supported. -| Finite Fields | Lambdaworks | Arkworks | Halo2 | GNARK | Constantine | +| Finite Fields | Lambdaworks | Arkworks | Halo2 | gnark | Constantine | | -------------- | ------------------ | ------------------ | --- | ----- | ----------- | | StarkField 252 | :heavy_check_mark: | :heavy_check_mark: | | | | | Mersenne 31 | πŸ—οΈ | | | | | | Baby Bear | πŸ—οΈ | | | | | | MiniGoldilocks | πŸ—οΈ | | | | | - -| ZK friendly Hash function | Lambdaworks | Arkworks | Halo2 | GNARK | Constantine | -| ------------------------- | ----------- | ------------------ | --- | ----- | ----------- | +| **ZK friendly Hash function** | **Lambdaworks** | **Arkworks** | **Halo2** | **gnark** | **Constantine** | | Poseidon | πŸ—οΈ | :heavy_check_mark: | | | | | Pedersen | πŸ—οΈ | :heavy_check_mark: | | | | | Rescue Prime XLIX | :x: | | | | | - -| Elliptic Curves | Lambdaworks | Arkworks | Halo2 | GNARK | Constantine | -| --------------- | ------------------ | ------------------ | --- | ------------------ | ----------- | +| **Elliptic Curves** | **Lambdaworks** | **Arkworks** | **Halo2** | **gnark** | **Constantine** | | BLS12-381 | :heavy_check_mark: | :heavy_check_mark: | | | | | BLS12-377 | πŸ—οΈ | :heavy_check_mark: | | :heavy_check_mark: | | | BN-254 | :x: | :heavy_check_mark: | | | | | Pallas | :x: | :heavy_check_mark: | | | | | Vesta | :x: | :heavy_check_mark: | | | | | Bandersnatch | πŸ—οΈ | :heavy_check_mark: | | | | - -| STARKs | Lambdaworks | Arkworks | Halo2 | GNARK | Constantine | -| ------------ | ------------------ | -------- | --- | ----- | ----------- | +| **STARKs** | **Lambdaworks** | **Arkworks** | **Halo2** | **gnark** | **Constantine** | | STARK Prover | :heavy_check_mark: | :x: | | :x: | | | CAIRO Prover | πŸ—οΈ | :x: | | :x: | | - -We are currently working to make the CAIRO prover compatible with the Stone Prover - -| SNARKs | Lambdaworks | Arkworks | Halo2 | GNARK | Constantine | -| ------- | ----------- | ------------------ | --- | ------------------ | ----------- | +| **SNARKs** |**Lambdaworks** | **Arkworks** | **Halo2** | **gnark** | **Constantine** | | Groth16 | :x: | :heavy_check_mark: | | :heavy_check_mark: | | | Plonk | πŸ—οΈ | :x: | | :heavy_check_mark: | | | Spartan | :x: | :heavy_check_mark: | | | | | Marlin | :x: | :heavy_check_mark: | | | | | GKR | :x: | :heavy_check_mark: | | :heavy_check_mark: | | - - -| Polynomial Commitment Schemes | Lambdaworks | Halo2 | Arkworks | GNARK | Constantine | -| ----------------------------- | ------------------ | --- | ------------------ | ------------------ | ----------- | +| **Polynomial Commitment Schemes** | **Lambdaworks** | **Arkworks** | **Halo2** | **gnark** | **Constantine** | | FRI | πŸ—οΈ | | :x: | :heavy_check_mark: | | | IPA | :x: | | :heavy_check_mark: | | | | Hyrax | :x: | | :x: | | | | KZG10 | :heavy_check_mark: | | :heavy_check_mark: | :heavy_check_mark: | | - -| Folding Schemes | Lambdaworks | Arkworks | Halo2 | GNARK | Constantine | -| --------------- | ----------- | -------- | --- | ----- | ----------- | +| **Folding Schemes** | **Lambdaworks** | **Arkworks** | **Halo2** | **gnark** | **Constantine** | | Nova | :x: | | | | | | Supernova | :x: | | | | | | Protostar | :x: | | | | | From c0314d8ba2ca283e1975056e2ea90dbdd520124f Mon Sep 17 00:00:00 2001 From: "Mariano A. Nicolini" Date: Tue, 10 Oct 2023 13:36:36 -0300 Subject: [PATCH 08/18] Fix some CLI errors related to Makefile (#586) * Fix CLI error * Add simple comment explaining variable definition in Makefile --------- Co-authored-by: Mauro Toscano <12560266+MauroToscano@users.noreply.github.com> --- provers/cairo/Makefile | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/provers/cairo/Makefile b/provers/cairo/Makefile index 37bcb44846..add3e58f7a 100644 --- a/provers/cairo/Makefile +++ b/provers/cairo/Makefile @@ -6,6 +6,10 @@ CAIRO0_PROGRAMS_DIR=cairo_programs/cairo0 CAIRO0_PROGRAMS:=$(wildcard $(CAIRO0_PROGRAMS_DIR)/*.cairo) COMPILED_CAIRO0_PROGRAMS:=$(patsubst $(CAIRO0_PROGRAMS_DIR)/%.cairo, $(CAIRO0_PROGRAMS_DIR)/%.json, $(CAIRO0_PROGRAMS)) +# Variable to give compiled Cairo programas a proper name. It extracts the file extension and adds +# the .json extension to it. +COMPILED_PROGRAM=$(basename $(PROGRAM)).json + # Rule to compile Cairo programs for testing purposes. # If the `cairo-lang` toolchain is installed, programs will be compiled with it. # Otherwise, the cairo_compile docker image will be used @@ -53,38 +57,38 @@ docker_build_cairo_compiler: docker build -f cairo_compile.Dockerfile -t cairo . docker_compile_cairo: - docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM) > $(OUTPUT) + docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM) > $(COMPILED_PROGRAM) target/release/cairo-platinum-prover: cargo build --bin cairo-platinum-prover --release --features instruments docker_compile_and_run_all: target/release/cairo-platinum-prover @echo "Compiling program with docker" - @docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM) > $(PROGRAM).json + docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM) > $(COMPILED_PROGRAM) @echo "Compiling done \n" - @cargo run --bin cairo-platinum-prover --features instruments --quiet --release prove_and_verify $(PROGRAM).json - @rm $(PROGRAM).json + @cargo run --bin cairo-platinum-prover --features instruments --quiet --release prove_and_verify $(COMPILED_PROGRAM) + @rm $(COMPILED_PROGRAM) docker_compile_and_prove: target/release/cairo-platinum-prover @echo "Compiling program with docker" - @docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM) > $(PROGRAM).json + @docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM) > $(COMPILED_PROGRAM) @echo "Compiling done \n" - @cargo run --bin cairo-platinum-prover --features instruments --quiet --release prove $(PROGRAM).json $(PROOF_PATH) - @rm $(PROGRAM).json + @cargo run --bin cairo-platinum-prover --features instruments --quiet --release prove $(COMPILED_PROGRAM) $(PROOF_PATH) + @rm $(COMPILED_PROGRAM) compile_and_run_all: target/release/cairo-platinum-prover @echo "Compiling program with cairo-compile" - @cairo-compile --proof_mode $(PROGRAM) > $(PROGRAM).json + @cairo-compile --proof_mode $(PROGRAM) > $(COMPILED_PROGRAM) @echo "Compiling done \n" - @cargo run --bin cairo-platinum-prover --features instruments --quiet --release prove_and_verify $(PROGRAM).json - @rm $(PROGRAM).json + @cargo run --bin cairo-platinum-prover --features instruments --quiet --release prove_and_verify $(COMPILED_PROGRAM) + @rm $(COMPILED_PROGRAM) compile_and_prove: target/release/cairo-platinum-prover @echo "Compiling program with cairo-compile" - @cairo-compile --proof_mode $(PROGRAM) > $(PROGRAM).json + @cairo-compile --proof_mode $(PROGRAM) --output $(COMPILED_PROGRAM) @echo "Compiling done \n" - @cargo run --bin cairo-platinum-prover --features instruments --quiet --release prove $(PROGRAM).json $(PROOF_PATH) - @rm $(PROGRAM).json + @cargo run --bin cairo-platinum-prover --features instruments --quiet --release prove $(COMPILED_PROGRAM) $(PROOF_PATH) + @rm $(COMPILED_PROGRAM) clean: rm -f $(CAIRO0_PROGRAMS_DIR)/*.json From 5a938e7d12305e0a7b05e7f7131c1dc8c39f2e0c Mon Sep 17 00:00:00 2001 From: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Date: Wed, 11 Oct 2023 10:10:44 -0300 Subject: [PATCH 09/18] Fix CIOS overflow check (#602) * fix cios overflow check * rename test --- .../fields/montgomery_backed_prime_fields.rs | 25 ++++++++++++++++++- math/src/unsigned_integer/montgomery.rs | 2 +- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/math/src/field/fields/montgomery_backed_prime_fields.rs b/math/src/field/fields/montgomery_backed_prime_fields.rs index 91d5600e67..309e4b6912 100644 --- a/math/src/field/fields/montgomery_backed_prime_fields.rs +++ b/math/src/field/fields/montgomery_backed_prime_fields.rs @@ -12,6 +12,7 @@ use core::marker::PhantomData; pub type U384PrimeField = MontgomeryBackendPrimeField; pub type U256PrimeField = MontgomeryBackendPrimeField; +pub type U64PrimeField = MontgomeryBackendPrimeField; /// This trait is necessary for us to be able to use unsigned integer types bigger than /// `u128` (the biggest native `unit`) as constant generics. @@ -759,8 +760,10 @@ mod tests_u256_prime_fields { use crate::field::traits::IsPrimeField; #[cfg(feature = "std")] use crate::traits::ByteConversion; - use crate::unsigned_integer::element::UnsignedInteger; use crate::unsigned_integer::element::U256; + use crate::unsigned_integer::element::{UnsignedInteger, U64}; + + use super::U64PrimeField; #[derive(Clone, Debug)] struct U256Modulus29; @@ -1122,4 +1125,24 @@ mod tests_u256_prime_fields { let b = U256F29Element::zero(); assert_eq!(a, b); } + + // Goldilocks + #[derive(Clone, Debug)] + struct GoldilocksModulus; + impl IsModulus for GoldilocksModulus { + const MODULUS: U64 = UnsignedInteger { + limbs: [18446744069414584321], + }; + } + + type GoldilocksField = U64PrimeField; + type GoldilocksElement = FieldElement; + + #[test] + fn test_cios_overflow_case() { + let a = GoldilocksElement::from(732582227915286439); + let b = GoldilocksElement::from(3906369333256140342); + let expected_sum = GoldilocksElement::from(4638951561171426781); + assert_eq!(a + b, expected_sum); + } } diff --git a/math/src/unsigned_integer/montgomery.rs b/math/src/unsigned_integer/montgomery.rs index 3b64c822dc..65222d2697 100644 --- a/math/src/unsigned_integer/montgomery.rs +++ b/math/src/unsigned_integer/montgomery.rs @@ -67,7 +67,7 @@ impl MontgomeryAlgorithms { } let mut result = UnsignedInteger { limbs: t }; - let overflow = t_extra[0] > 0; + let overflow = t_extra[1] > 0; if overflow || UnsignedInteger::const_le(q, &result) { (result, _) = UnsignedInteger::sub(&result, q); From 50b9fbd31481423e6f070139cc626cfd238aa116 Mon Sep 17 00:00:00 2001 From: juan518munoz <62400508+juan518munoz@users.noreply.github.com> Date: Thu, 12 Oct 2023 12:09:24 -0300 Subject: [PATCH 10/18] migrate cli to extern crate (#598) * migrate cli to extern crate * add clap4 for cli handling * cargo fmt * readme changes * Add disclaimer readme * Remove bit security text from cairo prover crate * add compile option to makefile * add compile and run all to makefile * add example to readme * cargo fmt * add compile and prove to makefile * better readme * add quiet flag to makefile binaries * reorganized readme --------- Co-authored-by: Jmunoz Co-authored-by: Mariano A. Nicolini Co-authored-by: MauroFab --- Cargo.toml | 3 +- README.md | 13 +-- provers/cairo-prover-cli/Cargo.toml | 16 +++ provers/cairo-prover-cli/Makefile | 43 +++++++ provers/cairo-prover-cli/README.md | 107 ++++++++++++++++++ .../cairo-prover-cli/cairo_compile.Dockerfile | 11 ++ provers/cairo-prover-cli/requirements.txt | 6 + .../{cairo => cairo-prover-cli}/src/main.rs | 105 +++++++++-------- provers/cairo/Cargo.toml | 4 - provers/cairo/Makefile | 9 -- provers/cairo/README.md | 47 +------- 11 files changed, 246 insertions(+), 118 deletions(-) create mode 100644 provers/cairo-prover-cli/Cargo.toml create mode 100644 provers/cairo-prover-cli/Makefile create mode 100644 provers/cairo-prover-cli/README.md create mode 100644 provers/cairo-prover-cli/cairo_compile.Dockerfile create mode 100644 provers/cairo-prover-cli/requirements.txt rename provers/{cairo => cairo-prover-cli}/src/main.rs (63%) diff --git a/Cargo.toml b/Cargo.toml index c88c5cff06..59fc41ff65 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["math", "crypto", "gpu", "benches", "provers/plonk", "provers/stark", "provers/cairo"] +members = ["math", "crypto", "gpu", "benches", "provers/plonk", "provers/stark", "provers/cairo", "provers/cairo-prover-cli"] exclude = ["ensure-no_std"] resolver = "2" @@ -15,6 +15,7 @@ lambdaworks-crypto = { path = "./crypto", version = "0.2.0" } lambdaworks-gpu = { path = "./gpu", version = "0.2.0" } lambdaworks-math = { path = "./math", version = "0.2.0" } stark-platinum-prover = { path = "./provers/stark", version = "0.2.0" } +cairo-platinum-prover = { path = "./provers/cairo", version = "0.2.0" } [profile.bench] lto = true diff --git a/README.md b/README.md index a8b667f9df..1f2255c2eb 100644 --- a/README.md +++ b/README.md @@ -63,21 +63,16 @@ Zero-Knowledge and Validity Proofs have gained a lot of attention over the last So, we decided to build our library, focusing on performance, with clear documentation and developer-focused. Our core team is a group of passionate people from different backgrounds and different strengths; we think that the whole is greater than just the addition of the parts. We don't want to be a compilation of every research result in the ZK space. We want this to be a library that can be used in production, not just in academic research. We want to offer developers the main building blocks and proof systems so that they can build their applications on top of this library. -## Provers and Polynomial Commitment Schemes using LambdaWorks - -All provers are being migrated to Lambdaworks library - -Right now Plonk prover is in this repo, you can find the others here: - -- [Cairo STARK LambdaWorks prover](https://github.com/lambdaclass/lambdaworks_cairo_prover/tree/main) -- [CairoVM Trace Generation using LambdaWorks](https://github.com/lambdaclass/cairo-rs/pull/1184) -- [ABI compatible KZG commitment scheme - EIP-4844](https://github.com/lambdaclass/lambdaworks_kzg) ## Main crates - [Math](https://github.com/lambdaclass/lambdaworks/tree/main/math) - [Crypto primitives](https://github.com/lambdaclass/lambdaworks/tree/main/crypto) - [Plonk Prover](https://github.com/lambdaclass/lambdaworks/tree/main/provers/plonk) +- [Cairo Prover](https://github.com/lambdaclass/lambdaworks/tree/main/provers/cairo) +- [Cairo Prover CLI](https://github.com/lambdaclass/lambdaworks/tree/main/provers/cairo-prover-cli) + +If you are interested in proving Cairo programs, use the Cairo Prover CLI. ### Crypto - [Elliptic curves](https://github.com/lambdaclass/lambdaworks/tree/main/math/src/elliptic_curve) diff --git a/provers/cairo-prover-cli/Cargo.toml b/provers/cairo-prover-cli/Cargo.toml new file mode 100644 index 0000000000..f1f391e2e1 --- /dev/null +++ b/provers/cairo-prover-cli/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "cairo-platinum-prover-cli" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[[bin]] +name = "cairo-platinum-prover-cli" +path = "src/main.rs" + +[dependencies] +lambdaworks-math = { workspace = true , features = ["lambdaworks-serde"] } +stark-platinum-prover = { workspace = true, features = ["wasm"] } +cairo-platinum-prover = { workspace = true} +clap = { version = "4.4.6", features = ["derive"] } diff --git a/provers/cairo-prover-cli/Makefile b/provers/cairo-prover-cli/Makefile new file mode 100644 index 0000000000..39a94d79ba --- /dev/null +++ b/provers/cairo-prover-cli/Makefile @@ -0,0 +1,43 @@ +.PHONY: test coverage clippy clean + +ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) + +# Variable to give compiled Cairo programas a proper name. It extracts the file extension and adds +# the .json extension to it. +COMPILED_PROGRAM=$(basename $(PROGRAM_PATH)).json + +build: + cargo build --release + +docker_build_cairo_compiler: + docker build -f cairo_compile.Dockerfile -t cairo . + +compile: + cairo-compile --proof_mode $(PROGRAM_PATH) > $(COMPILED_PROGRAM) 2>/dev/null || \ + docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM_PATH) > $(COMPILED_PROGRAM) + +prove: + cargo run --quiet --release prove $(PROGRAM_PATH) $(PROOF_PATH) + +verify: + cargo run --quiet --release verify $(PROOF_PATH) + +run_all: + cargo run --quiet --release prove-and-verify $(PROGRAM_PATH) + +compile_and_prove: + @cairo-compile --proof_mode $(PROGRAM_PATH) > $(COMPILED_PROGRAM) 2>/dev/null || \ + docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM_PATH) > $(COMPILED_PROGRAM) + @echo "Compiling done \n" + @cargo run --quiet --release prove $(COMPILED_PROGRAM) $(PROOF_PATH) + @rm $(COMPILED_PROGRAM) + +compile_and_run_all: + @cairo-compile --proof_mode $(PROGRAM_PATH) > $(COMPILED_PROGRAM) 2>/dev/null || \ + docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM_PATH) > $(COMPILED_PROGRAM) + @echo "Compiling done \n" + @cargo run --quiet --release prove-and-verify $(COMPILED_PROGRAM) $(PROOF_PATH) + @rm $(COMPILED_PROGRAM) + +clippy: + cargo clippy --workspace --all-targets -- -D warnings diff --git a/provers/cairo-prover-cli/README.md b/provers/cairo-prover-cli/README.md new file mode 100644 index 0000000000..b6155e5ed1 --- /dev/null +++ b/provers/cairo-prover-cli/README.md @@ -0,0 +1,107 @@ +
+ +# Lambdaworks Cairo Platinum Prover CLI + +
+ +## ⚠️ Disclaimer + +This prover is still in development and may contain bugs. It is not intended to be used in production yet. + +Please check issues under security label, and wait for them to be resolved if they are relevant your project. + +Output builtin is finished, and range check is supported but it's not sound yet. + +CLI currently runs with 100 bits of conjecturable security + +## [Cairo Platinum Prover Docs](<[lambdaclass.github.io/lambdaworks/](https://github.com/lambdaclass/lambdaworks/blob/main/provers/cairo/README.md)>) + +### Usage: + +To prove programs Cairo has to be compiled. For compilation you need to have `cairo-lang` or `docker` installed. + +When using Docker, start by creating the container image with: + +```**bash** + make docker_build_cairo_compiler +``` + +Examples of Cairo 0 programs can be found [here](https://github.com/lambdaclass/lambdaworks/tree/main/provers/cairo/cairo_programs/cairo0) + + +**To compile and generate a proof you can use:** + +```bash +make compile_and_prove PROGRAM_PATH= PROOF_PATH= +``` + +For example: + +```bash +make compile_and_prove PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.cairo PROOF_PATH=cairo_programs/cairo0/fibonacci_5.proof +``` + + +**To verify a proof you can use:** + +```bash +make verify PROOF_PATH= +``` + +For example: + +```bash +make verify PROOF_PATH=fibonacci_5.proof +``` + +**To compile Cairo:** + +```bash +make compile PROGRAM_PATH= +``` + +For example: + +```bash +make compile PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.cairo +``` + +**To prove a compiled program:** + +```bash +make prove PROGRAM_PATH= PROOF_PATH= +``` + +For example: + +```bash +make prove PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.json PROOF_PATH=program_proof.proof +``` + + + +**To prove and verify with a single command you can use:** + +```bash +make run_all PROGRAM_PATH= +``` + +For example: + +```bash +make run_all PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.json +``` + + + +**To compile, proof, prove and verify at the same time you can use:** + +```bash +make compile_and_run_all PROGRAM_PATH= +``` + +For example: + +```bash +make compile_and_run_all PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.cairo +``` \ No newline at end of file diff --git a/provers/cairo-prover-cli/cairo_compile.Dockerfile b/provers/cairo-prover-cli/cairo_compile.Dockerfile new file mode 100644 index 0000000000..369f6db844 --- /dev/null +++ b/provers/cairo-prover-cli/cairo_compile.Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.9-slim + +WORKDIR /app + +RUN apt-get update && apt-get install -y --no-install-recommends g++ libgmp3-dev + +COPY requirements.txt / + +RUN pip install -r /requirements.txt + +ENTRYPOINT ["cairo-compile"] diff --git a/provers/cairo-prover-cli/requirements.txt b/provers/cairo-prover-cli/requirements.txt new file mode 100644 index 0000000000..6e0951b922 --- /dev/null +++ b/provers/cairo-prover-cli/requirements.txt @@ -0,0 +1,6 @@ +ecdsa==0.18.0 +bitarray==2.7.3 +fastecdsa==2.2.3 +sympy==1.11.1 +typeguard==2.13.3 +cairo-lang==0.11.0 diff --git a/provers/cairo/src/main.rs b/provers/cairo-prover-cli/src/main.rs similarity index 63% rename from provers/cairo/src/main.rs rename to provers/cairo-prover-cli/src/main.rs index 6d6584265c..35ab08794e 100644 --- a/provers/cairo/src/main.rs +++ b/provers/cairo-prover-cli/src/main.rs @@ -6,9 +6,43 @@ use lambdaworks_math::traits::{Deserializable, Serializable}; use stark_platinum_prover::proof::options::{ProofOptions, SecurityLevel}; use stark_platinum_prover::proof::stark::StarkProof; -use std::env; use std::time::Instant; +use clap::{Args, Parser, Subcommand}; + +#[derive(Parser, Debug)] +#[command(author = "Lambdaworks", version, about)] +struct ProverArgs { + #[clap(subcommand)] + entity: ProverEntity, +} + +#[derive(Subcommand, Debug)] +enum ProverEntity { + #[clap(about = "Generate a proof for a given compiled cairo program")] + Prove(ProveArgs), + #[clap(about = "Verify a proof for a given compiled cairo program")] + Verify(VerifyArgs), + #[clap(about = "Generate and verify a proof for a given compiled cairo program")] + ProveAndVerify(ProveAndVerifyArgs), +} + +#[derive(Args, Debug)] +struct ProveArgs { + program_path: String, + proof_path: String, +} + +#[derive(Args, Debug)] +struct VerifyArgs { + proof_path: String, +} + +#[derive(Args, Debug)] +struct ProveAndVerifyArgs { + program_path: String, +} + fn generate_proof( input_path: &String, proof_options: &ProofOptions, @@ -68,31 +102,17 @@ fn verify_proof( fn main() { let proof_options = ProofOptions::new_secure(SecurityLevel::Conjecturable100Bits, 3); - let args: Vec = env::args().collect(); - - if args.len() < 2 { - println!("Usage: cargo run [arguments]"); - return; - } - - let command = &args[1]; - - match command.as_str() { - "prove" => { - if args.len() < 4 { - println!("Usage: cargo run prove "); - return; - } - - let input_path = &args[2]; - let output_path = &args[3]; - - if input_path.contains(".cairo") { + let args: ProverArgs = ProverArgs::parse(); + match args.entity { + ProverEntity::Prove(args) => { + // verify input file is .cairo + if args.program_path.contains(".cairo") { println!("\nYou are trying to prove a non compiled Cairo program. Please compile it before sending it to the prover.\n"); return; } - let Some((proof, pub_inputs)) = generate_proof(input_path, &proof_options) else { + let Some((proof, pub_inputs)) = generate_proof(&args.program_path, &proof_options) + else { return; }; @@ -102,62 +122,49 @@ fn main() { bytes.extend(proof_bytes); bytes.extend(pub_inputs.serialize()); - let Ok(()) = std::fs::write(output_path, bytes) else { - println!("Error writing proof to file: {output_path}"); + let Ok(()) = std::fs::write(&args.proof_path, bytes) else { + println!("Error writing proof to file: {}", args.proof_path); return; }; - println!("Proof written to {output_path}"); + println!("Proof written to {}", args.proof_path); } - "verify" => { - if args.len() < 3 { - println!("Usage: cargo run verify "); - return; - } - - let input_path = &args[2]; - let Ok(program_content) = std::fs::read(input_path) else { - println!("Error opening {input_path} file"); + ProverEntity::Verify(args) => { + let Ok(program_content) = std::fs::read(&args.proof_path) else { + println!("Error opening {} file", args.proof_path); return; }; let mut bytes = program_content.as_slice(); if bytes.len() < 8 { - println!("Error reading proof from file: {input_path}"); + println!("Error reading proof from file: {}", args.proof_path); return; } + let proof_len = usize::from_be_bytes(bytes[0..8].try_into().unwrap()); bytes = &bytes[8..]; if bytes.len() < proof_len { - println!("Error reading proof from file: {input_path}"); + println!("Error reading proof from file: {}", args.proof_path); return; } let Ok(proof) = StarkProof::::deserialize(&bytes[0..proof_len]) else { - println!("Error reading proof from file: {input_path}"); + println!("Error reading proof from file: {}", args.proof_path); return; }; bytes = &bytes[proof_len..]; let Ok(pub_inputs) = PublicInputs::deserialize(bytes) else { - println!("Error reading proof from file: {input_path}"); + println!("Error reading proof from file: {}", args.proof_path); return; }; verify_proof(proof, pub_inputs, &proof_options); } - "prove_and_verify" => { - if args.len() < 3 { - println!("Usage: cargo run prove_and_verify "); - return; - } - - let input_path = &args[2]; - let Some((proof, pub_inputs)) = generate_proof(input_path, &proof_options) else { + ProverEntity::ProveAndVerify(args) => { + let Some((proof, pub_inputs)) = generate_proof(&args.program_path, &proof_options) + else { return; }; verify_proof(proof, pub_inputs, &proof_options); } - _ => { - println!("Unknown command: {}", command); - } } } diff --git a/provers/cairo/Cargo.toml b/provers/cairo/Cargo.toml index b0518ca9a3..8b16793007 100644 --- a/provers/cairo/Cargo.toml +++ b/provers/cairo/Cargo.toml @@ -6,10 +6,6 @@ version.workspace = true edition.workspace = true license.workspace = true -[[bin]] -name = "cairo-platinum-prover" -path = "src/main.rs" - [lib] crate-type = ["cdylib", "rlib"] diff --git a/provers/cairo/Makefile b/provers/cairo/Makefile index add3e58f7a..3a22a15e8f 100644 --- a/provers/cairo/Makefile +++ b/provers/cairo/Makefile @@ -22,15 +22,6 @@ $(CAIRO0_PROGRAMS_DIR)/%.json: $(CAIRO0_PROGRAMS_DIR)/%.cairo build: cargo build --release -prove: build - cargo run --release prove $(PROGRAM_PATH) $(PROOF_PATH) - -verify: build - cargo run --release verify $(PROOF_PATH) - -run_all: build - cargo run --release prove_and_verify $(PROGRAM_PATH) - test: $(COMPILED_CAIRO0_PROGRAMS) cargo test diff --git a/provers/cairo/README.md b/provers/cairo/README.md index 3d4a3fc0c0..2700f463b4 100644 --- a/provers/cairo/README.md +++ b/provers/cairo/README.md @@ -24,8 +24,6 @@ Output builtin is finished, and range check is supported but it's not sound yet. We expect to have something working in a good state by mid August 2023. -CLI currently runs with 100 bits of conjecturable security - ## [Documentation]([lambdaclass.github.io/lambdaworks/](https://lambdaclass.github.io/lambdaworks/starks/cairo.html)) ## Table of Contents @@ -71,50 +69,7 @@ To be added: ### πŸš€ Prove and verify -To compile and prove Cairo 0 programs without arguments you can use: - -```bash - make compile_and_prove PROGRAM= PROOF_PATH= -``` - -For example: - -```bash - make prove PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.json PROOF_PATH=fibonacci_5.proof -``` - -Notice for compilation either `cairo-lang` or `docker` is required - -If the program is already compiled you can use: - -```bash -make prove PROGRAM_PATH= PROOF_PATH= -``` - -For example: - -```bash -make prove PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.json PROOF_PATH=program_proof.proof -``` - -To verify a proof you can use: - -```bash -make verify PROOF_PATH= -``` - -For example: - -```bash -make verify PROOF_PATH=fibonacci_5.proof -``` - -To prove and verify with a single command you can use: - -```bash -make run_all PROGRAM_PATH= -``` - +To prove and verify a program through the CLI, refer to the [CLI documentation](https://lambdaclass.github.io/lambdaworks/tree/main/provers/cairo-prover-cli/README.md). ### Using WASM verifier To use the verifier in WASM, generate a npm package using `wasm-pack` From 5e952544a2b5f506f2c0afa72896c08abccc82c8 Mon Sep 17 00:00:00 2001 From: irfan Date: Tue, 17 Oct 2023 16:22:10 +0300 Subject: [PATCH 11/18] stark curve, pedersen hash, precalculated points (#597) * stark curve, pedersen hash, precalculated points * lint * lint + array index fixes * cargo fmt * clippy * fmt * ref to starknet-rs * reviews * constant points moved to another file * move 'from_affine_hex_string' to starkcurve * make add_points a private fn * docs for pedersen * rename add_points -> lookup_and_accumulate --------- Co-authored-by: Mariano A. Nicolini --- README.md | 1 + crypto/src/hash/mod.rs | 1 + crypto/src/hash/pedersen/constants.rs | 7590 +++++++++++++++++ crypto/src/hash/pedersen/mod.rs | 114 + crypto/src/hash/pedersen/parameters.rs | 36 + math/src/elliptic_curve/point.rs | 2 +- .../short_weierstrass/curves/mod.rs | 1 + .../short_weierstrass/curves/stark_curve.rs | 54 + .../elliptic_curve/short_weierstrass/point.rs | 2 +- .../fft_friendly/stark_252_prime_field.rs | 20 + 10 files changed, 7819 insertions(+), 2 deletions(-) create mode 100644 crypto/src/hash/pedersen/constants.rs create mode 100644 crypto/src/hash/pedersen/mod.rs create mode 100644 crypto/src/hash/pedersen/parameters.rs create mode 100644 math/src/elliptic_curve/short_weierstrass/curves/stark_curve.rs diff --git a/README.md b/README.md index 1f2255c2eb..f6f0ceb120 100644 --- a/README.md +++ b/README.md @@ -189,6 +189,7 @@ The following links, repos and projects have been important in the development o - [Ministark](https://github.com/andrewmilson/ministark) - [Sandstorm](https://github.com/andrewmilson/sandstorm) - [STARK-101](https://starkware.co/stark-101/) +- [starknet-rs](https://github.com/xJonathanLEI/starknet-rs/) - [Risc0](https://github.com/risc0/risc0) - [Neptune](https://github.com/Neptune-Crypto) - [Summary on FRI low degree test](https://eprint.iacr.org/2022/1216) diff --git a/crypto/src/hash/mod.rs b/crypto/src/hash/mod.rs index 697dfb5dac..c11e1ab166 100644 --- a/crypto/src/hash/mod.rs +++ b/crypto/src/hash/mod.rs @@ -1,3 +1,4 @@ pub mod hash_to_field; +pub mod pedersen; pub mod poseidon; pub mod sha3; diff --git a/crypto/src/hash/pedersen/constants.rs b/crypto/src/hash/pedersen/constants.rs new file mode 100644 index 0000000000..8ba601af56 --- /dev/null +++ b/crypto/src/hash/pedersen/constants.rs @@ -0,0 +1,7590 @@ +use lambdaworks_math::elliptic_curve::short_weierstrass::{ + curves::stark_curve::StarkCurve, point::ShortWeierstrassProjectivePoint, +}; + +pub const fn shift_point() -> ShortWeierstrassProjectivePoint { + StarkCurve::from_affine_hex_string( + "0x049ee3eba8c1600700ee1b87eb599f16716b0b1022947733551fde4050ca6804", + "0x03ca0cfe4b3bc6ddf346d49d06ea0ed34e621062c0e056c1d0405d266e10268a", + ) +} + +pub const fn points_p1() -> [ShortWeierstrassProjectivePoint; 930] { + [ + StarkCurve::from_affine_hex_string( + "0x0234287dcbaffe7f969c748655fca9e58fa8120b6d56eb0c1080d17957ebe47b", + "0x03b056f100f96fb21e889527d41f4e39940135dd7a6c94cc6ed0268ee89e5615", + ), + StarkCurve::from_affine_hex_string( + "0x003909690e1123c80678a7ba0fde0e8447f6f02b3f6b960034d1e93524f8b476", + "0x07122e9063d239d89d4e336753845b76f2b33ca0d7f0c1acd4b9fe974994cc19", + ), + StarkCurve::from_affine_hex_string( + "0x07229b12e8428f710abf28f83336c210d35cce1fce0c3fb83f5bbbd1033f68c9", + "0x023425e83f32f3677ce1e46d004c13898d5170248300fd0f3ee42b6013a2a2fa", + ), + StarkCurve::from_affine_hex_string( + "0x040fd002e38ea01a01b2702eb7c643e9decc2894cbf31765922e281939ab542c", + "0x0109f720a79e2a41471f054ca885efd90c8cfbbec37991d1b6343991e0a3e740", + ), + StarkCurve::from_affine_hex_string( + "0x00df45299e7e1d2231116da91797315f672deabd6fdd83b139a782c6a3328df4", + "0x058d8082c3852c613f18759e1bce170c8225a2202456c638660aef996f4907cb", + ), + StarkCurve::from_affine_hex_string( + "0x0340f018dac64edcc62482a77357ffa46cb5560a935be398dc1f2d9072728e32", + "0x029d2c3fee3257c4af71536cb2c1a8b5eb960bb874444a956b92f1dab9c23495", + ), + StarkCurve::from_affine_hex_string( + "0x0550eaa3b906d70f681f279029342cb6ca7a18eeaf41f40460dcac94a33558bd", + "0x03290266ae4666f375765ff418ce895ec04e6849bf6c79fd1fdfa55a0d6dbc36", + ), + StarkCurve::from_affine_hex_string( + "0x02f52066635c139fc2f64eb0bd5e3fd7a705f576854ec4f00aa60361fddb981b", + "0x06d78a24d8a5f97fc600318ce16b3c840315979c3273078ec1a285f217ee6a26", + ), + StarkCurve::from_affine_hex_string( + "0x0406a4903dff511fd555465a62c879070daff3f97d5dfcbc25a89b912b0f245d", + "0x02ac3ad5e021f342459f3e23535a1b76b546b7ce8922e8cb4b42272dee8c15d2", + ), + StarkCurve::from_affine_hex_string( + "0x048ee5faafb8626a51f20bc4d9d7171ba796193bcfc4dc15efe2f01842c159d6", + "0x0436a82462639f945fe0cc7807bf3df035bf74aee299e0317efe51c3b7b29e5a", + ), + StarkCurve::from_affine_hex_string( + "0x05e8906095605da0ce8bbcf4f1faa885239d46cffd0ec58ebd80d85d2ff17f5f", + "0x07363c43c0f6f1756a27bd9b67960f31f26a71777d150af9d9e9d5f397a13184", + ), + StarkCurve::from_affine_hex_string( + "0x04e724e82fe08a75b06bf4601435f0dd7146b07f2ce99915f2fbb3e8d2739391", + "0x00a1aafde6e3ad64e28d30f25ce2ba34bb978fa70c374c37a1a506dd065252f1", + ), + StarkCurve::from_affine_hex_string( + "0x07ed3443a478173dfc6e695e46866cdf09a1eccc24bac49f457bbc2c4a16893e", + "0x016376037b759d6b042da47d35003a7b926c66c4009a07188bf42317ddd0a397", + ), + StarkCurve::from_affine_hex_string( + "0x00184e6a77137f5981ba3104f641272d4315dbf17942aa72306f5039ef44face", + "0x0383342a72aae69729343a8363d3d674c0c2fecba1be4bdb7c54e11548a1b08f", + ), + StarkCurve::from_affine_hex_string( + "0x014b98c2eee31d8cce3ada97504f033be6f447d4b4b6e9374b5d0826ca1e1154", + "0x071178c2f4ca2c6fd7fcdfa6ae6b87f7c5cc5e46e3b577896f8afb376dc10008", + ), + StarkCurve::from_affine_hex_string( + "0x06a0767a1fd60d5b9027a35af1b68e57a1c366ebcde2006cdd07af27043ef674", + "0x0606b72c0ca0498b8c1817ed7922d550894c324f5efdfc85a19a1ae382411ca2", + ), + StarkCurve::from_affine_hex_string( + "0x07fa463ee2a2d6a585d5c3358918270f6c28c66df1f86803374d1edf3819cc62", + "0x00a996edf01598832e644e1cae9a37288865ad80e2787f9bf958aceccc99afae", + ), + StarkCurve::from_affine_hex_string( + "0x00433ca5a9740fd5444c82d3a031842be7fc64c52c24731a68aaebc4b3fad126", + "0x0182d522a91b3605ddfc2b1a0fd2a7ccb705c6e6d1bc6b35bc75933748d2512c", + ), + StarkCurve::from_affine_hex_string( + "0x03d4da70d1540da597dbae1651d28487604a4e66a4a1823b97e8e9639393dbec", + "0x045cdef70c35d3b6f0a2273a9886ccb6306d813e8204bdfd30b4efee63c8a3f9", + ), + StarkCurve::from_affine_hex_string( + "0x05132ef198cb729635749974739d4096f25142db97af3fde079089cfc8fff003", + "0x03946837958b4b03428a4ae47c197a0de9e13d372282705f1959770b47ce25ae", + ), + StarkCurve::from_affine_hex_string( + "0x01b5fd788e27a712d739d6b86cfc2907bf230a56762550ab90885d0d5d0711d8", + "0x0365ec932cb2e4cfdc9169d832101f16e4a9fcb17f9073ee96d9ed7eb779cd66", + ), + StarkCurve::from_affine_hex_string( + "0x00f8e5df3d74ea43638d46640e3d7ec79590ec4fef664bb48a521a88005ff510", + "0x047003dcbef6a4dda6c5a6d22dd974134ac1aedc2b01730bfff81c5ad0f9e3c4", + ), + StarkCurve::from_affine_hex_string( + "0x01e448fdbcd9896c6fbf5f36cb7e7fcb77a751ff2d942593cae023363cc7750e", + "0x030c81da0f3a8cb64468eaa491c7ae7b4842b62cb4148820da211afc4caffb3a", + ), + StarkCurve::from_affine_hex_string( + "0x05473730c8a3fc843fcc70d2e20533f07a45689c7381857191137af36bd6a743", + "0x05d96a94e1ccf4c60b95b1a6d4482c2451c1bfb12d899e6d967df63dfe6d315e", + ), + StarkCurve::from_affine_hex_string( + "0x007fac20fe7b0c59c67987b3a7e42aff5b857ee532b73d10a5a689e34280325b", + "0x03b20d3e307ed631871a9074e800448d807d2d6586edd3953cbdfd6876d5c3a5", + ), + StarkCurve::from_affine_hex_string( + "0x049299aa96ce9e57b9ea9d4737351f5ad20bd02f618d3af294227e552ad3fccf", + "0x01b2c2c73c4839c94e9b62f8430f0f88da1336173a471a1af14e9d04b91575eb", + ), + StarkCurve::from_affine_hex_string( + "0x015908bd905fc4b1ab61802421d99acad007eec07f9cc5a7f51a7c8166f42a7c", + "0x074532c685718fd5eb89b8a84fd5ea112953ecaeddf3310705a4ec694c27b369", + ), + StarkCurve::from_affine_hex_string( + "0x00893e0cde416f8a61d58c8cacf2314af9eb331d6cfce6d36a210486b76c9048", + "0x0405879e7817d8dfac211f9d051463e8b8ffe47f911e8404557554faef193cd5", + ), + StarkCurve::from_affine_hex_string( + "0x021fb8a6378be3dfb0af4a899e5c51b6e3f53c677a6fe34244b846fc065d95b3", + "0x00a8e9f5cc41dbd7e43bc24caddeaa2f6526d03b1acbc0c9780d2df18e57d29d", + ), + StarkCurve::from_affine_hex_string( + "0x00abbb0ca4aa2018feca36fed8ffd2779ce1c444de7cf1e6f4336317239a229b", + "0x03a5f5f1372ed9a8811eb74154001c7b2d491d590c97e67e9fc3f4a881eb1fd6", + ), + StarkCurve::from_affine_hex_string( + "0x06531acf1a7cb90a4eb27de0b7f915e387a3b0fd063ba6e1289b91f48411be26", + "0x031330f5daa091889981a3ea782ae997f5f171336ed0487a03f051551a2cafa2", + ), + StarkCurve::from_affine_hex_string( + "0x054be016394d5662d67d7e82f5e889ed2f97ccf95d911f57dd2362c4040ed4f4", + "0x00c6cb184053f054d6a59c1bf0986d17090d25089b3fdcdaf185edc87ef113e5", + ), + StarkCurve::from_affine_hex_string( + "0x06f4f4793df4469b4a89da52f3ff45832564fe7ee67a07c7aeb7bd849a359c48", + "0x02c47fb246409be043ccb20932fa308094142e0c1fdcedd0b279e74f00abec0b", + ), + StarkCurve::from_affine_hex_string( + "0x035b9ecd0499ca1d5d42dcbb0c6b4042b3733c64b607ca711e706e786ef2afc6", + "0x05624b476a5b21c3a544f0712d4817b06ad380a5a6529d323bf64da8ef862d8d", + ), + StarkCurve::from_affine_hex_string( + "0x03396de1b8034959c41bc44b32feaead8c07f54b2456c06403687dd45e92a01a", + "0x00c2ef4cd3a067d95dceb741b0e194b8b43c86964fe54337ee3a71e2d8ff215a", + ), + StarkCurve::from_affine_hex_string( + "0x07f5af55179620a0e291bf2e4975d4e4fd17f695228b57b6ef30ec4b64f5229f", + "0x0103e752c691f2ceab9d17fd391ac5aa69596225ca9015817c421174024c7f11", + ), + StarkCurve::from_affine_hex_string( + "0x007db0af269635778b2cdb98d49413e03419439c1db00891bf8cc23e17de0638", + "0x04aab69d21e8912e05b9ae1227baddcaf888a3945b71b1f0f676563112a94eb9", + ), + StarkCurve::from_affine_hex_string( + "0x04ce0378e3ee8f77ed58f2ddbd8bb7676c8a38bfb1d3694c275254bd8ca38e23", + "0x05a16fcbff0769c9cf2b02c31621878ec819fff4b8231bff82c6183db2746820", + ), + StarkCurve::from_affine_hex_string( + "0x058ee31b121e0d2343b525b8070124596d0f341e98b07afedadff9a74ec678b0", + "0x0649ebd69a4d612ac98f5cb10a3a59fb5080083488eba7ab6549d3133e936cec", + ), + StarkCurve::from_affine_hex_string( + "0x02e9a8c9adfd58e886ff5e8835be0304c5b921fd9b7e0d9ba246633d1f9b5cb6", + "0x02cf5c605a67acd85f01780fcfaa36de39ad964555d670b5c1e594652311c8f4", + ), + StarkCurve::from_affine_hex_string( + "0x0114f01fdad91af9a43da1079c51dfb76f1c6b47d24811b7a161f548d1ce94d4", + "0x000ceabf891c2a439f28e3f70797ba51026253492d614576c431d4aa9e319939", + ), + StarkCurve::from_affine_hex_string( + "0x03906297bfbe91c274b3439b2d358dd753500988cf4ab33b4699cb92852a8351", + "0x0628e4f1c3b085f71f276a0857e7aa033dc64cdaee9af2fee88055b53738e62a", + ), + StarkCurve::from_affine_hex_string( + "0x0372d1ef3230d499d5ddd8475e5b878a4d01785da806ba92226a7ca9ad379de7", + "0x073ab138117f1b679c11fa81e572187d94eec710164c3bc3523d0094dfceba37", + ), + StarkCurve::from_affine_hex_string( + "0x07675b925eb1860917ecffde0db01d51770fbe7108460b808c56b3e354f70d97", + "0x06627121085781697f62c43c0d29833c3fdc257a8e6375429e620be7c63632ac", + ), + StarkCurve::from_affine_hex_string( + "0x03804a310c3d332ae426a892e125dd13bf0a0cc9849a8e7b2a67be7334a1fb86", + "0x0700ff46ee391b0ef5d86438734ae3b4c1043c9c488a78a16bc552c516aeb75b", + ), + StarkCurve::from_affine_hex_string( + "0x0648d5c6f98680a1b926bfeb01c00224c56fdcf751b251c4449c8a94f425cfcf", + "0x072c05ac793cd1620a833fbe2214d36900ebe446e095c62fcb740937f98cca8c", + ), + StarkCurve::from_affine_hex_string( + "0x00bd09be3e4e1af8a14189977e334f097c18e4a8bf42577ef5aafa0f807bd89b", + "0x06e0e72ed7eb65c86cee29c411fb4761122558ee81013344ba8509c49de9f9b6", + ), + StarkCurve::from_affine_hex_string( + "0x0060e98611c70049ba42e68adab8db06fa3deb24e542481cb50e998c1c444c17", + "0x0783ccedeb3bee6376f0c02f2b5cb54e115d36c71038be64b4798b1dd9e20886", + ), + StarkCurve::from_affine_hex_string( + "0x035ea4e339b44ae7724419bdfbe07022253137a4afb7cbaffad341ea61249357", + "0x03665d676a026a174f367bb4417780e53a7803cb02d0db32eb4545c267c42f14", + ), + StarkCurve::from_affine_hex_string( + "0x05fb52838d0a4e255cd59f9df0810b1f511ded5ef26f95eb20a589bd3ded9899", + "0x039460e30ec6a68c1eaa2b27a512bbf5097ccae98153eedb82a851adaa554e6e", + ), + StarkCurve::from_affine_hex_string( + "0x029d553857527a9fb753b218628f7fa22d0b035e134acba9fe7bb603ae11a4b5", + "0x00abf9b2689831b7f8bfc5d3e8db2af3f5feb26645e0ec08bf5ecb7d4a806877", + ), + StarkCurve::from_affine_hex_string( + "0x04cae397bcab2196aebb6152f2aa6c0ed9d4243c7f52cb930c5cd602f784cff4", + "0x07c84f8966daf03473e05e53439ada76452a4fd5bb485865732ba8bfe122fd40", + ), + StarkCurve::from_affine_hex_string( + "0x036457bc744f42e697b825c2d1afd8f4029d696a4514710f81da52d88e178643", + "0x07c93715896735492a68c7969a024b3a8fd538bffc1521538107de1a5f13ce9c", + ), + StarkCurve::from_affine_hex_string( + "0x026f3bdef66b4befcff1076c8733db1e24cd4e25640db0d722055ca05e03499d", + "0x05f2ac048f88ab6ee28dab048d6b0e6b7edb38ef93433a05b033b59a5aaf5b07", + ), + StarkCurve::from_affine_hex_string( + "0x043daf55d25dd9b7b0048d14762d1798bb88c6a74a10b6379b17c3fe3ab662ae", + "0x0644593b6956b8c0f62c1a8eeeac8a2d44bed6a7b932d66337dd55a7821f047b", + ), + StarkCurve::from_affine_hex_string( + "0x001db2e250ef3c59382857425e99183f2c512a90c8c02677cea5ce5a503bc829", + "0x06dc4e058d69707948cbbac387bedec2be560d4e0bcc3ec1ce82808def25fae9", + ), + StarkCurve::from_affine_hex_string( + "0x078e58bc2fa1c4a6feeb772c23f80e4fc3d9c9a06475213e88e7e05dbeed8bec", + "0x009b6a3f676231e9af5b51e9348952996ca1854d3dbd339f78ad344b0abc53dc", + ), + StarkCurve::from_affine_hex_string( + "0x013424b850382824f7b451f1542e06ba56a945f20494848cb33d731f947f7a21", + "0x0374e341c5cc8126591881817cd671d72d48f50cfb2fefb4b5e7500453072f82", + ), + StarkCurve::from_affine_hex_string( + "0x02425cce7159478cbd8efd4134f8d91c422292bac4deee60e301057ec5359f08", + "0x0097301e86fbe625c711aba4a954c15c226ca2736c1fa621cc279cea3ac32443", + ), + StarkCurve::from_affine_hex_string( + "0x06151a3c5bccd2285771488d6bf61ae5339450824597674e8f7251354c913892", + "0x02fa5b62063fe9db9bb29cd0b707aa0f5de65a48a4c78c17beb4574d171cbc3f", + ), + StarkCurve::from_affine_hex_string( + "0x05b3a08ebcf9c109cc9082f70d9df2b9c11b5428ee23917b4e790c4c10f6e661", + "0x0009d7b42ab0c20f5510df7ea5e196eec99342739077e9a168198c89da859753", + ), + StarkCurve::from_affine_hex_string( + "0x021883ef8580fc06e59481955d52ece3aca6e82c8c9fc58e216dcf46f96990c6", + "0x051a6423543e6e8a43e71da34cd90f5b520b8d33b67c4bf857573ab9e301aa4c", + ), + StarkCurve::from_affine_hex_string( + "0x00efbdfb8d391b3857a053d0526ac1d92a3c855e82db9fa5744f0512b06df3fe", + "0x03655a1e71a701d2c9495c20035a6a80711fb6b1978e156677d0356a323c434a", + ), + StarkCurve::from_affine_hex_string( + "0x019e86b77f9b581e81092b305c852faf53940a8f15f0a6990c414f04c0fa7ef9", + "0x00515630e35d4398c9c79fc4ee08e1023fa47d8e03c6e7819c6d2ccef45398fa", + ), + StarkCurve::from_affine_hex_string( + "0x052cbca763f535966ba8be2b32f8ae9284ee1591f37a8958d7595c884ca57031", + "0x0762e9c04bfe85fa231f59afba1a1c52f1994aedc3853c89e7e98964b8ff6b57", + ), + StarkCurve::from_affine_hex_string( + "0x078f1e6fbd1395703c932a3921efafabee829c1983221513337e3368b076cb75", + "0x034e5af4b2634492bf595b5ed70975b548660ee658d81b74dae90d90717602c0", + ), + StarkCurve::from_affine_hex_string( + "0x048410d09bf47d33426af0af7934427a6d86325b3d7be2954ce996f19ec42a62", + "0x0022532d2cf20f61e1b63778626d3871658178a49002bd0f1e5fabaafec2c462", + ), + StarkCurve::from_affine_hex_string( + "0x00888ab8eb4c31bb2ac5b54aa320dbe1a69c96b864e8a5f54d89c1d1a6b86c24", + "0x0730e148467f6a55ce22c5296f5380df88f38de76ef0b2de844cd3094aaaf3ea", + ), + StarkCurve::from_affine_hex_string( + "0x042c95d04e4af3f0b485e7dc19d031c82ecd9dc8210ddcbedf651534e217d5f6", + "0x055cd9cab9d502856e5420c4684cf1561472f05b0f97788bc755c80c59dba7dd", + ), + StarkCurve::from_affine_hex_string( + "0x03be1c8c0747b35b64f024328ce45f71b99df5c8ffa09a8fb79c326ee0a67fbd", + "0x05e4e474c847ebf98e3209d504f81cdbf58c993322ef2e08b802468ed719fe24", + ), + StarkCurve::from_affine_hex_string( + "0x008b0d7f0ff79cd042af4b42bc5d384d9f8cb200216f9824e25d3b0a9fe429aa", + "0x0025d6198e37257433b6728a7d6f3a6b60f6ee3b8d462168422e06c79da2298e", + ), + StarkCurve::from_affine_hex_string( + "0x0509606f39d2df35826bad011f25a6850e017b32deef00e1974f2ed0934666e4", + "0x03d6ca71df802ca910b8e8afa8213e2fcb9740701e326e21c61e58bec33262ab", + ), + StarkCurve::from_affine_hex_string( + "0x01e337495b39b3bad6bc211f6dbca74335a5c12da286cf0451df207734a07d59", + "0x02272c3b13aaa4533bed1a4485abf771a5ea0b96ddfa14fb3beebb0db767ef8f", + ), + StarkCurve::from_affine_hex_string( + "0x03fe9f774fe0b6485d33f7bdf6efd1c12d31c70b2df9411515cd283a1bdc70b6", + "0x02fd7de11035a8dda9b2906f7511460fabeaedbac515810f6583731356e39a59", + ), + StarkCurve::from_affine_hex_string( + "0x012716a93cf48c54fd93617650cbece5335eeb039f214a6a97a3ca0f3aa80df0", + "0x0271b36528eb2717442d3500177ed6c1811ae38e53003d8defff5a07fb4505f3", + ), + StarkCurve::from_affine_hex_string( + "0x075e79ff13a894e7120dac17b7429c0c32ce7828f726c9973728c0977a5f5977", + "0x04960526e59c1c736561a201bc56f7d762641b39f609d273cc996f5d9197cfb8", + ), + StarkCurve::from_affine_hex_string( + "0x0640fe009249115d7254f72ecafb3006139e4bed7e9041af51458c737282d1d5", + "0x003cc6c978a575246e2ce4f7ef1fcc7f63085db9ff98a1b1f3fe374087c0332c", + ), + StarkCurve::from_affine_hex_string( + "0x03830e694ae144b0a73d050a57a06e15b7d5c9a16998abcac3afcaf4f225dd7c", + "0x0270f5368cc52b0fd67dc3686652f2c08570abd38975ee210e27e7afac934de4", + ), + StarkCurve::from_affine_hex_string( + "0x06d6fd09ccab7c26de9b3906191235deb5c34685580c488275356a05e209ca96", + "0x07157f81a34213dd8f91dea4f6df1bcfabc4ee091a3049eeeb3b7923d39b8645", + ), + StarkCurve::from_affine_hex_string( + "0x07c6a612a9c2a86a3d96a0d0800b4cddb4662e204e5185f0a3c158b721130ead", + "0x0721caed7f45fe1ac7858cb9155058d886419d2c19a5a72cc5f0b8902c6871a4", + ), + StarkCurve::from_affine_hex_string( + "0x0478a2342289c28dc0846655731ee2468c89b57ce721298cc0200e27a7cf6cbc", + "0x007f689580e05c555a40803badb2177fc00aa4e0b7fe99323c03b7b5854c1cdb", + ), + StarkCurve::from_affine_hex_string( + "0x02926bb76680ae6a841dfca3c3dc4baadb18ee48c8e2fd495b3a17627b073e5c", + "0x03ecc73926c07a0e4d2ede2ec610037993fdb626526bd5c5ff522fe28a2a6353", + ), + StarkCurve::from_affine_hex_string( + "0x05531ca1d00f151d71da820918f74caf2985b24dca20e124721fff507b5a5876", + "0x0518529643d3f25e47f72c322223ba60a63d6bfe78cf3f612215d9c19bf29200", + ), + StarkCurve::from_affine_hex_string( + "0x03e2edd1d2f6d2f8309263d45d4e3c5f53a08aa7018a73d15162d8501ea05d23", + "0x04753d9733655e9b4b9c0af76101be6dbfb9457e8b4440d8fc2d9da058bead4c", + ), + StarkCurve::from_affine_hex_string( + "0x07f136709ac0667cf209936843d95b2b80e491e01180d1bfddab7c82f872b7c3", + "0x0412f28bdf5f186382c48b9159799ab4db8194d7bfcd7a6adc186729b655dc67", + ), + StarkCurve::from_affine_hex_string( + "0x0419df0b81d159286588f4ae84b5b5d5ed36017eb9c4ac46e76f664798fd0129", + "0x00f793ea32bc98aa47576cecc807c136192a8add62e1ab4df81e805fbf47f8af", + ), + StarkCurve::from_affine_hex_string( + "0x057ad67b9a20c16c80f1b584a96ffec61b513dcec44c8b5bb37074753aa4123d", + "0x00b6bd4fdd04d4b386d11dbfa6443f0bac3288889e7f6ca950d420c1c4497e56", + ), + StarkCurve::from_affine_hex_string( + "0x0122e7fd3f587a9c678cb36d2d86a92ff6d360dfc5910eb435e7388f39cbdbd2", + "0x073675b1f1d80cbb437e6bc21b88ba6b1bc1e191f7cd70ae7f495ea13e63307f", + ), + StarkCurve::from_affine_hex_string( + "0x06e433daad3a1cd8d35a2982818e0f8210ab82834f2d093b8969c42949813009", + "0x07b1fd0bbb89675604da04b1313625f3762ee723bc66a9999bf713bab185a7d8", + ), + StarkCurve::from_affine_hex_string( + "0x00ec75fb16f84d66aa46b1d8398fa0293c9fa124aea4c8d8f23d5a8155af7d6e", + "0x065dee206316554f51e8f892645baed6dbe56bac1660ff84441e76a7cb4cf584", + ), + StarkCurve::from_affine_hex_string( + "0x06192d454e4f8fe212bdfccd5b15dd5056d7622ffe456c6c67e5a7265aea49c4", + "0x02377a45dc630017ae863cb968ddb38333a70c7946d8684e6d7a6213f634b7bc", + ), + StarkCurve::from_affine_hex_string( + "0x0542fb44b4ef3640a64fdb22a2560fb26668065c069cf31d1df424819a39ff18", + "0x05dbae9b0948e0361aea443503840341c322aa1a1366ce5390e71bf161f78f8c", + ), + StarkCurve::from_affine_hex_string( + "0x03c5133d3856680586e284eec9bd4c056eb8c1204d5e9a5303023bf902d3e8c2", + "0x05ce549f398e6267cd2974be878d8af04b1238b65aa4c3bd7809df5311b11b31", + ), + StarkCurve::from_affine_hex_string( + "0x0299ff3e3412a7eb4cb4a3051b07b1be2e7b1c4b789f39ffb52cba3d048b71de", + "0x01951d3175c02761b291d86b6c0a08387ad5e2a2130ccc33c852530572cb3958", + ), + StarkCurve::from_affine_hex_string( + "0x05f856bb94f77c71e220e2a6b8402efd6129b334bdb7a8711c6fb00ef1b78fdc", + "0x058ba8d0578bb9fa33e15a3ee2d45ece949c9f6259eb05337087d56b920de8b1", + ), + StarkCurve::from_affine_hex_string( + "0x050edcce31d3b563adbc1624987cf8c7b72b2743b1b50483b7d0cd64635e6b6e", + "0x05a6d296d418426c6524b4eee788ce56dad6fb5108ad8802409e133d2e68f1e0", + ), + StarkCurve::from_affine_hex_string( + "0x0351165fa9ec8c06e7746b92e952e0fe48d27ec73ad8cd78c1290e8e1c9e25ad", + "0x0682356c7a3ab57b9eda27076ff63971e7af69a9ca4c9233888dbd06a5679f5a", + ), + StarkCurve::from_affine_hex_string( + "0x0628ce3f5367dadc1411133e55eb25e2e3c2880d6e28754a5cb1c5d109627e73", + "0x00ae3e9b7d50964e28bd15380400b7659b87affdef5d2586cbefcd9be7d67c0d", + ), + StarkCurve::from_affine_hex_string( + "0x050e9c67b03b31c31a558148ae9a9664afceb3f5cdaa8b9a00bd4e30631ae01b", + "0x05897e56d78ddde8d0add98a1e30dafd21593f8de223f9889cc239b2391a1bd4", + ), + StarkCurve::from_affine_hex_string( + "0x05854498bfd63718edae41d9dc2d3a2b219f639d74785e866a34cb78acd3f968", + "0x05f68d1e30764b34862247d27e19556fbf35d5cc5d413f8ea2d91b3da878e1fb", + ), + StarkCurve::from_affine_hex_string( + "0x02b7221dcd584907e4726834836f878093f49e83aa5d75e280cc13a8d24ccdd5", + "0x00be79753a6b45ef082f465ba6e0cf12230ac0b7f270cab3a4a5b25457b55fda", + ), + StarkCurve::from_affine_hex_string( + "0x02c520c3ec539142f046b83dcbe511dc85a484e6597025adcb41a3d78f914c92", + "0x072c6abede13fb05f7bdfaa5a12d795141cda7249f049ccb70847d10ac2d738c", + ), + StarkCurve::from_affine_hex_string( + "0x05133871c2159d5542c66c2c2d5040ae934c80a16c56bef96268abd876a6ee93", + "0x04f415510268fcc33be7a721b7ea6e7fd06cc61aeb87b18a2a18d49752754920", + ), + StarkCurve::from_affine_hex_string( + "0x00d3c599e0e2585f4e527c19dc2784641da8b8f056d6b20d7f83130bc7ea4020", + "0x06f592771da9b47d4ac6ec283c75d4d3f7fbe7470553ecea6357c92f747eb12b", + ), + StarkCurve::from_affine_hex_string( + "0x03abaa62706e3a1f0d1bc732695a5a9247fbcc9d470b31a0e24c0f2a97967eca", + "0x06696bf44d9f4e91c4eb2cc011100e039be6ddf5f571424e0c9ebbdf499788cd", + ), + StarkCurve::from_affine_hex_string( + "0x06ea54aff064895eccf9db2283225d62044ae67621192b3346338948382f5933", + "0x06431507e51aadacfaf39f102a8ff387756e9b5e1bc8323d44acae55130d93db", + ), + StarkCurve::from_affine_hex_string( + "0x028097d50d175a6235320fe8cfe138dd9e46895d189582e472c38ad7a67d923a", + "0x07f9eab4133d7d09a7ff63368d6135c26262b62336eca1b5ca33f2096ce388ba", + ), + StarkCurve::from_affine_hex_string( + "0x056f27b3d3213f0f8e0f4eef2728932d1df85acf21088a390d7732ed6d7d623d", + "0x06be64a2e18be2f9e537f0371979a7bf76f27eb3ae07e1ad3dd8f00622edee57", + ), + StarkCurve::from_affine_hex_string( + "0x0619fd09cdd6ff4323973f256c2cbdcb224f7f25b8aef623af2d4a0105e62e02", + "0x02c95f0ae11d47eeae1bc7f1350f75f9185c5bc840382ceb38a797cae9c40308", + ), + StarkCurve::from_affine_hex_string( + "0x056e37c9108a1d2fda8184f6fc34abbdde3dd0ce0b8be9cde7830a0746abbd57", + "0x023937e0878524b2ec775a75fe19b0cb66abef6470550ff575b1aa456c50c7b2", + ), + StarkCurve::from_affine_hex_string( + "0x04743a9d13b8d93ca9be5837206aa3898c21ae857fc78c08a1b8005bfa339274", + "0x006876b5abacde7286c583e3bc26e8b3a52f900d8e4bd61ced78fd099f54f177", + ), + StarkCurve::from_affine_hex_string( + "0x000257fcf60b12428f4f0f367bb0d30bad503e8077d9b170f39fef16cdf53bac", + "0x02a74981aee312c9abd84c496453263c15dcac33c5bade7d77dffe680c3ca811", + ), + StarkCurve::from_affine_hex_string( + "0x0641c18982ced304512a3f2395942a38add0d6a7156229c2a7c8b8dfbe9beb96", + "0x06f6288c9c659b6af5ac975f4180deffe53d516399b2cc62f31732e9d4ba9837", + ), + StarkCurve::from_affine_hex_string( + "0x00e58fcb9fad01845eb1aab852c1e52e36adf03e4d261f15db8299cb01e655fc", + "0x016c88b6f8f08359d38396bba1f4fe9c891fa96489cbda34b4588cc2ac249072", + ), + StarkCurve::from_affine_hex_string( + "0x01b40ff525d25d7f3183d7dcebccdb77a744881d4ea55f3e7d9f46abfb16cbb7", + "0x03901f0a3862c75c8d6ddd73fc1b3d5385b387b18a0796cafbaad4654ec4dd94", + ), + StarkCurve::from_affine_hex_string( + "0x0481eae9b66e9d36d64c6eccc93c19d58894663c3ef14fa2b381933c34db3d1f", + "0x0436b2ec7b91cd6759bb3c0da90eb57533c7a2aa540708b114b187b8b399d88e", + ), + StarkCurve::from_affine_hex_string( + "0x05e00043d6d6bf4da4b217db351260f44708ac82f3271e66122f83af2bded486", + "0x00870b6f17d317dfa3bf74a9baeee8b4958d0fc6ad3c9ba0b5b5046cd064d1ef", + ), + StarkCurve::from_affine_hex_string( + "0x0214386164c5401f527177e159ad5aac65c011fac5a6b6bc099435c886e4a7cd", + "0x011e32e1b14c3e41b6a97459942ca4e876ac65581974a13466ef41928d8aed0a", + ), + StarkCurve::from_affine_hex_string( + "0x02c7b7f80095baad8e823dff5264e2755dc30f65ceaa1aff244f264049c59a94", + "0x07dc1ca9a72eff96bcb83df039e955c8ab477bf573be1321c7ba831a3f786e4f", + ), + StarkCurve::from_affine_hex_string( + "0x077348f0f64c22a974103026e3dd14504af0467ff0d3cf264f72d5885b4d1b56", + "0x029be64c099813861bebb51866af87e865f9c3f4c1bc111e59a88d6bdf0e97fc", + ), + StarkCurve::from_affine_hex_string( + "0x058ab546e51fe49fc5a382e4064a2bd6cfc268904412f86c26de14f28a71d0f2", + "0x0124b7217943e7e328408e8afdfa7da00dcbc94a2bb85fd8e01fb162d2c2c0a9", + ), + StarkCurve::from_affine_hex_string( + "0x00a82c2fdedbb26c3c762a12f7e86b0e01e65320e0a25a8399d665f6e266bf74", + "0x01a1de28e253f3e10f44d0111e8074f882d7f42e5900780ccbdc31da372d3fd8", + ), + StarkCurve::from_affine_hex_string( + "0x013fe2361b752ff86102093c99e7a1e62c402c379b05976d9ff8d9a96d1c26cb", + "0x067d67a12ad6636829119b38de0d58244168d4888b151d3aebb6273e1018c870", + ), + StarkCurve::from_affine_hex_string( + "0x0744c725a7455a992e3cf5bd007bc234dd4668dba285f553f38350ad94c1615b", + "0x007f721a87f48798bdc4a9c0eb88559e2ad7a74112fd901e70ea159e67a9c33f", + ), + StarkCurve::from_affine_hex_string( + "0x0367132c7537dab3c343203c0ec263ae1cefa2b31b30783d624d748ee25e3ce7", + "0x026483d7d266b97556d1487ba741c7acdf024bace065cef0541dd6d79254abcb", + ), + StarkCurve::from_affine_hex_string( + "0x04a5c65b81bc26c33368701f6ad8cfc5280724f24a987ef29c53eab4f2968139", + "0x030bf1ecd36032d842d4092c5141f19240634caf76c7547bece1750aaa1f6683", + ), + StarkCurve::from_affine_hex_string( + "0x0546bb08bed63f6f52361c14d757102e6e32621c68af1d0d3002d577d3fa7d1e", + "0x0544e48665da6f36379c5734cd2947c5c1f9e9604b3630c42e39cd9dc4b19dd5", + ), + StarkCurve::from_affine_hex_string( + "0x0434df142ddaa60f7881b6348d91687de40457de7ccfb07f0304b9e820705d0c", + "0x07fae425e3b53f97dd1f5b20e49ed9fe24ff1efc341ba5e017ac89cf8df0cc39", + ), + StarkCurve::from_affine_hex_string( + "0x057de1d7ecf6257014f41031b7de385c7456d269fb5f13fd17e554c89722bba8", + "0x037502052d7da135a35d230b4165485a6e2d454f67c400b8a1a42524be1cd63e", + ), + StarkCurve::from_affine_hex_string( + "0x071f2a596947104aa3b412f6aa553233bbef109d822908a70daeb4a9c7cf5771", + "0x00dc285aca4f3198411ab11a016ef79aa1d8ff625c106772b33308d5b66abc79", + ), + StarkCurve::from_affine_hex_string( + "0x05e5209f472b8df53e8013f4ac455cb7e4dfe87e814c50d4e8186b4bad9a2112", + "0x06771696bd86be587c2215410cdeb302db6728272258430167238c26f38ef22e", + ), + StarkCurve::from_affine_hex_string( + "0x00f49d2cbab24aa7f9718fce314274fe81720b9934b2115b1cdeafc8ef1b57a6", + "0x02053b559490b125437c64d6f6083f45e4d6a1df9a40465542d92487bc3e4df5", + ), + StarkCurve::from_affine_hex_string( + "0x06045932e1a10c8b3bd9b5a6c0fa6e3df67d5aad8d990ed9c38edcd5490f8b06", + "0x02d98d4be121ebf85fb76e86c5248deb73aea7531cedaf560863886a4a92bd71", + ), + StarkCurve::from_affine_hex_string( + "0x0770cca3cb044b99c9d93344e663a4cbdfb9593aec5d03d558d870414cf1f480", + "0x02dd22cc6f8383122e80b80eda1071ad440f1898013e57974898df8c6e29a684", + ), + StarkCurve::from_affine_hex_string( + "0x04b510386dc302ff3b605eb3c06d8e333d1b09c84139534c26b776a7f2458b1d", + "0x06d84a0c04de8517f28bc6b7ba10f12f520ec11016ffa9133906b34ff2f2e0fd", + ), + StarkCurve::from_affine_hex_string( + "0x07a1e2b809dff46277021cbc376f79c37e1b683bbd6bca5317014f0dc0e1ae73", + "0x056790278a231912c334eff05281e08af1558e85516b4411ef64647c13bea431", + ), + StarkCurve::from_affine_hex_string( + "0x04931b7990348d41cf8907be79f45bb7991fd18f8a57868351c92fa7a34cbcd7", + "0x00ca35091815cdf0837d396e25aad6052ad32d497a33b123256cffdc008bc50e", + ), + StarkCurve::from_affine_hex_string( + "0x01d7e6ee48280a0c3f107b8a0ecacd04b9e1c4db62de8e136b40c238d5cc2b57", + "0x033057135b2a8364c61b5ca96638f651ade34ae5f23285adae5b7c0c8a6f0513", + ), + StarkCurve::from_affine_hex_string( + "0x0250b815d352fd89f8210b624b147ea7d0a4f47bcac49f3ac9b777840da93ebe", + "0x01173f10e9691948b7da7632f328520455aadcba46e017f891e0a1d7da2bef04", + ), + StarkCurve::from_affine_hex_string( + "0x02f6203142dbbc95fb523363f51b4bf13baa257aee5b83a7f49d83f05bd2ad9c", + "0x011bb55422518f09d7e7778125cbaf5b49a74c5820d17dc85621bf2f8f19d292", + ), + StarkCurve::from_affine_hex_string( + "0x0281d21dfe1d27eda730a2488e79067e5b1c53c40ef8861c1d32aac141450074", + "0x02efd08f6011d0eb872a5650cb95cfa540e0c81b91552884283f141f6091e846", + ), + StarkCurve::from_affine_hex_string( + "0x00582cb34a054000bedd3a91d515c9eca50187f7366a0a33b75396330e398faf", + "0x05d4e4f9789ed10ba497c69a932dec90ccae75defe67c7221b1871cd2e8b4e7c", + ), + StarkCurve::from_affine_hex_string( + "0x02223b85032fa67292f6e1f822628e6756e5c3cc08fc252ab88d63d624e4dfb2", + "0x055619ba96a7dcec77832fcb22cd5c21c7dcebc0280d730cba0002b67e0a8c63", + ), + StarkCurve::from_affine_hex_string( + "0x0278bba40eabef3a5a90acbdedc5a6ba4ae7673a8548d754a91bb4651971fd99", + "0x06ea582bca1b0e0c1a71f47f263ba8471b63ce9906eea7278cdc0dc9b31e66ad", + ), + StarkCurve::from_affine_hex_string( + "0x05efa75044ab99e653b10373bf2e11c050101d60182e5af9ccecdc40973b371e", + "0x02e48ec5dc905140e1b07badddab17c6e46745688b14d25c3d2520c3feca473b", + ), + StarkCurve::from_affine_hex_string( + "0x066ace6d06507c12bd6072fed3e9069349cbd965ad3a797713368fbaff16fe8e", + "0x06853c4dbf2739b33a3479f789ed511c00f7865abee02efab4bce52659211e1f", + ), + StarkCurve::from_affine_hex_string( + "0x00cf54045847e20eaf005f0ec2be53e9ac8836f73de68d07d8c064349c58443e", + "0x06754bb13c7ebca6603639a51daf38ab90b188e931008bb4fd3708354ed80b76", + ), + StarkCurve::from_affine_hex_string( + "0x06ea7cdf0463d267f2f4f2d00a84d2f512378c6df89a346c54e7b58d7cb883ec", + "0x03cfa940ccb6f6f35f909251a54db168deff502373803115c8a8ced55bec0b5a", + ), + StarkCurve::from_affine_hex_string( + "0x074562ab94b86dfa3f863469e2a4a2f609bb669551370854c19ab0de8b2b2c13", + "0x02700611fa6b7ca567c908488e2320b23346bacdd63d465db01063c5eec0a847", + ), + StarkCurve::from_affine_hex_string( + "0x032a857deaab815f1a6ffd3f4d8716b01a5516c35625389d2a41d39ae125f796", + "0x055dce8162dced3648178e2468e2f73a60ae1094674a8bca96f960b48ba69495", + ), + StarkCurve::from_affine_hex_string( + "0x0249b131e04de73af9820d3e22492d9ec51bdc0c4c4f34d95352fa44dd61f245", + "0x07576d3b5d136368ff01170a77d8286d0d1c7c40688862fb40813b4af3c6065e", + ), + StarkCurve::from_affine_hex_string( + "0x06777915d9b4769027eb7e04733f8a2d669c84fe06080f55e8a55674dfbf9efb", + "0x0640d0ff384c9635e1af364760f104e058e3c86209fa9d2320aeac887b2e02d8", + ), + StarkCurve::from_affine_hex_string( + "0x06f81282734648ff7e5e82d23f1994f927af1c6d195c03c5b1b741a54e2ddbc4", + "0x023ff8b7e243ef2b4b2d00a55c856e2e413a73e3d5c5598e2c56d71d4964c9d8", + ), + StarkCurve::from_affine_hex_string( + "0x02abe3f237681052f002414399111cf07f8421535af41251edc427a36b5b19c9", + "0x0636ce4deaf468a503ab20ccb2f7e5bdc98551656ebf53e9c7786b11dd9090be", + ), + StarkCurve::from_affine_hex_string( + "0x06447231367bb8d3467f904e1d3ad78e010117353048132968b232cc057b4fd6", + "0x01cb766be58ea36e7789de7c2041a48b4b0bb334758dd21828eb53908764c14c", + ), + StarkCurve::from_affine_hex_string( + "0x04b2cb0e9e019546afe025cb3d1e3953b79562b442aba1f1057f7e2cec5b9a4e", + "0x03035d83893a5713fd2988d9bfaa28f08d07d085c095b65c3c4fbc9c36e473f8", + ), + StarkCurve::from_affine_hex_string( + "0x05f78309f8ea28a2c5294bde2d423698157d73ebace06cd4f43eb319c4173e6b", + "0x06a7e61f89cb41194648ba19c9762c3e7264f9d6cebda77a40b097c902f3d3bb", + ), + StarkCurve::from_affine_hex_string( + "0x04d5cc5414758ea1be55be779bd7da296c7e11f1564d9e8797ceea347c16f8ea", + "0x01a680c4c410cf5ddc74e95ff2897c193edaaecce5b2cde4e96bbae5c0054eff", + ), + StarkCurve::from_affine_hex_string( + "0x04538e6f7c4156453eac50f114a0b361ebae3d035d15f313574cc25ddb2dba3f", + "0x03aa95bdb9e21b0649579bd0ff3ed6fe77959e7af23e50aa3c60c5ac4fc9d936", + ), + StarkCurve::from_affine_hex_string( + "0x06758a120cd5fe2dbb67a3f8d9bdab962f61164383e3036920a0773afae43b7e", + "0x0234ed0ec5dc97bbf5ef6c0ce8f497791471b562199c88d16b9699d53f67420d", + ), + StarkCurve::from_affine_hex_string( + "0x047e79174afc9f3350519ad3d53301c3009cd5c671eb938195ee6ced6b04a2f8", + "0x02883c9c71301e9d54a5e0c2a5b1e20bb3d356f5f45cc4f3005492beb2ea7f99", + ), + StarkCurve::from_affine_hex_string( + "0x00bb28aa289167e93b346ff0498f7920d447be3f53798d339c099f4ea6597990", + "0x056fa84b0d103472e21ad6a40b4708d361e4165e5ae2a7d8efad72032e005c5a", + ), + StarkCurve::from_affine_hex_string( + "0x029ab53a29de90eb1ef751b6ea917e5a10874f022cfd575136988a58f05c8787", + "0x028ec1aef03b9ec7813c4ee50c4c1cb7a883f13c4cd2d065c96cdf2a564f63a1", + ), + StarkCurve::from_affine_hex_string( + "0x06fa2f57cdb134c1dd5edc62476693f1e05c09301ce7b4d66a1e883dee04c28c", + "0x041b107d45024203bde56ce87f4b194ff607955a6cf43b28d38106d4dc51f507", + ), + StarkCurve::from_affine_hex_string( + "0x0768b03d0928644290b7d1b219daa677a8d5ecdba0f13776a9c137f3321723c0", + "0x01619d22350ed54c968bf733a549266affb5bc2f3aa1bc74f74f26473d5fa24d", + ), + StarkCurve::from_affine_hex_string( + "0x046c375c684b30adf4d51de81e92afee52b1a3847e177403372c82109373edca", + "0x01eaadc5783c90a0261306423d52009e991126b3f620e9cb6cffca41ca096f4f", + ), + StarkCurve::from_affine_hex_string( + "0x02ddfb71f51205888118cbabba8fd07d460a810289bfdeeb7118707e310cb152", + "0x01fd905d07b3933be886f2518246bdafa6f33259a174668808223cd7c28183c7", + ), + StarkCurve::from_affine_hex_string( + "0x003b31ad1cd77f77ba5c56becb4b136b2d8a14741cb004bdb599f158a1e37833", + "0x07c4ca72d1cfa29ebccf9f20f27001902b1684d442c229528e91134a8b4633a1", + ), + StarkCurve::from_affine_hex_string( + "0x0386f3879960713d41fdb3b1e41bbebf26b1c0e27a9a75bb1adcc1a0d3e8547b", + "0x02b21498c0f34ec6f17c720334dc0f36021c2f87afbbbc8847d0bd536eb265e5", + ), + StarkCurve::from_affine_hex_string( + "0x04c4b9ea052f688961c3c379a6cbc38c6c9ab5803b78b68ca2d8257855574170", + "0x023acc43c50950adfdc0e95fe717421a68c54d1226b0a4e527a0a698dc4c0b71", + ), + StarkCurve::from_affine_hex_string( + "0x00301bca1c8c68beb18de87861dc92ecaeb5bbc5722563289eed8c0b59f4c60e", + "0x016281c02661387ae85149686f6697617337850712ceea2e101b2264a6994d23", + ), + StarkCurve::from_affine_hex_string( + "0x00fabc1f9e72fd4dbd6211edbc3dc7b03cf3b958a9811ac60c566a38a2964698", + "0x06b2f7e58a0ee4ca917fe2e83a2f861c6dd68bd8a4c09643559e0fedd820b9bc", + ), + StarkCurve::from_affine_hex_string( + "0x0407eae62c6c4de3b942195afec3f45efec71ddb5e6edee3d427631bcdbf9b90", + "0x0436e7f2d78268ef62c4172d2ff1469028bad1f1d0f97ab007064418e61caa8f", + ), + StarkCurve::from_affine_hex_string( + "0x00b9d3092abf381cdd44c9027cf96c997fa5626915d348024b526b36a23d124d", + "0x0714e16dded4f9d2ac216528e8d192671a266363bafe02a0367e5c8ee59dba75", + ), + StarkCurve::from_affine_hex_string( + "0x017fe1cd41a05a31b0b68e402c0de14e65de3c39331526ae63853209d51c1295", + "0x05c928a5972db2423724e67f503c452450ed7fe2aaf375547b5ef485d97fd5f7", + ), + StarkCurve::from_affine_hex_string( + "0x06767ec2c42436d377daecc7ee1ecfc667fa381d27533ba675eed8fe55f0ab47", + "0x0134d2bb23030aa6366262732f9576ba8fd39dd4c25b1eda04bc12b303fc1233", + ), + StarkCurve::from_affine_hex_string( + "0x07b98e553566e2bc8fdd132346b69b9f8aacfdb0f742c4f0ca49525e3392133f", + "0x0208f4941b84d254c014170905b6c54c66dce9c37c99b031615e7d4e0729d214", + ), + StarkCurve::from_affine_hex_string( + "0x02127c55162f2641193ed8b7443f8297d34eed24c997eb046ff5b1a17430ddb5", + "0x03d3487f78c38cfdedd56cd01948f1a379230113b41edb5ba69356757155e045", + ), + StarkCurve::from_affine_hex_string( + "0x074a3f027b432d92d0c69c22088138b581d190cf4d9eddcf04616cb257936d15", + "0x020faf1a59b803c02c2f11ce58a7e6726c92b0d15d665a77e7e7b232c6e83cf7", + ), + StarkCurve::from_affine_hex_string( + "0x015ee18ca41ca3fc742f7a84b0764a0dae8e33ebcf6a20d2e055ab5f22b6aab8", + "0x0288807ac2ed330292a7c59ba06ab509e8a4f1f3e217e32db06602e4732f5102", + ), + StarkCurve::from_affine_hex_string( + "0x01b881175e21201d17e095e9b3966b354f47de8c1acee5177f5909e0fd72328f", + "0x069954b1a9b8bfccf8ec384d32924518a935758f3d3662ef754bcc88f1f6f3ec", + ), + StarkCurve::from_affine_hex_string( + "0x07d545a82bff003b8115be32a0c437f7c0a98f776bcf7fddb0392822844f3c5e", + "0x034b6e53a9565a7daa010711f5bf72254a4e61da3e6a562210a9abc9e8b66d69", + ), + StarkCurve::from_affine_hex_string( + "0x04d1c70bcbeaba9e818640fa41163dceefd51b263878a4ef74a3f3dded987a12", + "0x0001fa627351e1254784faf682544604cde313e86aebb73481a9ec4e637a490a", + ), + StarkCurve::from_affine_hex_string( + "0x0299b9fcd4fadfc4b6141457a3036aaa68501c23df579de26df69d4def89b913", + "0x00b95bf2c2bb303c38bb396382edc798ca6a4847e573ce19b7b08533d1912675", + ), + StarkCurve::from_affine_hex_string( + "0x006ead816a3f81aece567a9f0cdf99579bcfc97cf7db471c727523d6fe238569", + "0x018ce8deadb0ccd8bbcfaf4cc877ad57b4a68746fd1f48a090e934fb86044cfc", + ), + StarkCurve::from_affine_hex_string( + "0x0704982253eb1e57cbb5f4fcfded707f25eae70a7e1c61fcb0bcb9364181a5a4", + "0x051243d94f1f9e533da0f8eb82bd981086fbd80a25980bbdc6efca9ab7f0ae48", + ), + StarkCurve::from_affine_hex_string( + "0x04cd143414fd634368429d33a659a880326c652a58111a177e67ca7cc5931d82", + "0x01ef5a5eb84d0040e639f365b642151af708e8c32ae2f0e11e017b35b5738995", + ), + StarkCurve::from_affine_hex_string( + "0x0551f5a4dae4a341a3e20336a7d2f365ddd45849351ec6dd4fcbedfe4806d5d5", + "0x05865c977a0ecf13ce85ae14c5c316872080bd36f0f614f56b6dfc7ece83792e", + ), + StarkCurve::from_affine_hex_string( + "0x016a947ab797fb370353b4ea510f088c400733f32ff2eab29537548400fbddd8", + "0x0168ff79965be55ca10fb41fcc8c90591a6507e8aebfe125618f084e80f3f260", + ), + StarkCurve::from_affine_hex_string( + "0x0110f706235d35daa7c586b6be23cbec2d74cca91f1942777866ff132e9ae95d", + "0x04e9a3b34987ac6280f3326e752d433daccbbf7429e87eee3671b59067d0f889", + ), + StarkCurve::from_affine_hex_string( + "0x028c3edfcfdd88b3f57a58ca614346eb1473e93709c574ab961698e47e13b3d0", + "0x06d697633d1a49f8d8e2458eeb9787cdc72ffcc6c41e07898f261fb558180c88", + ), + StarkCurve::from_affine_hex_string( + "0x01bcb24af76973971e380b64754161cacda07bb0bc63ed0906ee06a90d7b3cf4", + "0x02b43aefcbe1197640cedf711febf20dafb9f0df070af6544a2f525844ef5c6a", + ), + StarkCurve::from_affine_hex_string( + "0x05176b4555b18f97318da67f6bc279600e9779259cef0a287f23da68165a769c", + "0x06dfc1596d53bf2a9b36892663eca3fcf701a977ea715ba2d4b3a05d91781a73", + ), + StarkCurve::from_affine_hex_string( + "0x035d98529f7c4be68dde9e7ded8bf1902429a8a1cab09122dd64c4854e609616", + "0x03677a5bbd9c04fa34e56d656d2341882a0f3ca9c812f66a380bd1084a691506", + ), + StarkCurve::from_affine_hex_string( + "0x01457a7bf6763c8bc8445322012e2037dbf43f00ab2d2760ae607d5f76136d04", + "0x00cc5fc5c98ea895c9c5f55b4bfa6a6fc488d37f5acf5e0c8aa1f36ac4781b1e", + ), + StarkCurve::from_affine_hex_string( + "0x07a1d69c08e68c80ad8b310736e6247a53bcba0183b9b8798833bc696a0fb6e2", + "0x03ce803a20ebb3b120d5eaf0ad64bed0522fad1a0f2ce39a5c5cbae98c4438f6", + ), + StarkCurve::from_affine_hex_string( + "0x028acacc0bc41d84e83663f02b36981a2c8272ecd72d3901164be2affb09c504", + "0x07a5aee0b160eaff5b5968ab1a0304ce58c3d5ae0148d9191c39e87668229e5b", + ), + StarkCurve::from_affine_hex_string( + "0x0791670163ec8ae6e52c1673806a05d3933d3f936f8282ca7424caf8a42c6932", + "0x0132c0c3e2bd499d74566a3c71122bece1c61c50266811a1288a99fdab86d3e0", + ), + StarkCurve::from_affine_hex_string( + "0x01f78cfdbcc767b68e69a224a077468cdfcb0afd6952b85bccbdb96d1fb8500b", + "0x04772ba173c6b583284eb001cfc2a124104833f464ff9df096443e10ef3e9dd4", + ), + StarkCurve::from_affine_hex_string( + "0x02cc9d19317a8e4d41e8b1878175cf76622c32d69b7c0163d7cf5d5c2a1714ba", + "0x063fa861f8ccef9d7277af4e206bc97f103083566add9d5374975290f232c5d3", + ), + StarkCurve::from_affine_hex_string( + "0x060b8808a0b4d26dc6a8469f289466a0340583ac0a42c11a8ac285481c9baf82", + "0x02ebdfb367d07bdd719e724692fa2746467185a09bb6ae2c60ee7f10ec7a359c", + ), + StarkCurve::from_affine_hex_string( + "0x0771eed999db52d032d808c947ce60cf98605f217905969d1413d0aa4c0f263b", + "0x049684fcaf0ef530d58c70cdb76137b51dcca9c2078d9119fd50578992daf4a9", + ), + StarkCurve::from_affine_hex_string( + "0x02774108962ca9897e7f22c064d2ccedac4fef5fc9569331c27cdc336c95774b", + "0x009e13d79b68e8dc8091c019618f5b07283a710ddf1733dc674a99fc32c12911", + ), + StarkCurve::from_affine_hex_string( + "0x00e47ec42e9659d96c44a25da2cf955e006c4284c1736e49627130e1d6ef83c7", + "0x07faa74393161e0fa276029865f7fe2e93be99ddf8a91ebd87cceab2f8778234", + ), + StarkCurve::from_affine_hex_string( + "0x015a86e35fb1dc4426f5856d1c3faeb126876bc75d34b03b37325559f0190686", + "0x052966463e31911fbc859370880a747f9af765db7937ae4585a7437c7b0cc90d", + ), + StarkCurve::from_affine_hex_string( + "0x0729ce3b24c4007e27c63d3ea7ff1b7a6bee2deb1c999249879476b5c8eb9c0b", + "0x05b3c4c99102f00ae20615f4873c1dc76cfeaac57ef652918c8d2c15d08e98fd", + ), + StarkCurve::from_affine_hex_string( + "0x05bd96eccc79ce49f3f74d22fa9d027f1b15ed3b4103cd043269857e3b61310d", + "0x02bc5db36b14e35c134cd907651a4110302139970a7055e683f3ae5616b1ae28", + ), + StarkCurve::from_affine_hex_string( + "0x055fc3fc54fd080b46e9022c5867a23cf94ec12cadd57d713ce591f454e8717a", + "0x039c17c15dde2c6b4e934c7f1a7b43d32a811fc1e666bb2f1e89c440ee479210", + ), + StarkCurve::from_affine_hex_string( + "0x05452a315bf5c79bd5adc042777d9cde7997dec81b15ae4d4224e4b638d1b660", + "0x036fd9b88ce52f2493f00b123664289e0fc9677a796716fe6ce781ccd6bae877", + ), + StarkCurve::from_affine_hex_string( + "0x0746abb611c99652227c9aabda92e91448a740d35a7cca71611e6a6e9cfd490d", + "0x07b82e74092feef8310a9f7fa1d04613ae6fd6f453564a138ebe1a41cd90e756", + ), + StarkCurve::from_affine_hex_string( + "0x0770d116415cd2c4ace0d8b721dd77e4a2ef766591f9ec9fa0b61304548994ed", + "0x042165d93c82f687635aa2b68492b3adffd516beb4baa94520efa11467a209fd", + ), + StarkCurve::from_affine_hex_string( + "0x05e6e4ece6621e2275415e1fda1e7c4f496de498b77c0b913073c6a6099394b9", + "0x03d92ce044fc77fa227adc31f6fc17ef8b4ec1c5aafc44630c0d9195075bf56d", + ), + StarkCurve::from_affine_hex_string( + "0x077c29753cae84788c0321eec01213b285795f3b86f9820b25144f2cd79bfa65", + "0x004a4cd6062dcf8796de9136585ceb4d16538bc2e0f915e311a24afd83dec3db", + ), + StarkCurve::from_affine_hex_string( + "0x06e69c717b5d98807ff1e404a5187a9ceaf0110b83aa15a84f930928b1171825", + "0x01ee7cfc3a9744d7fa380ba28604af9df33ac077724374c04588bd71fa16b177", + ), + StarkCurve::from_affine_hex_string( + "0x06524efaf1ef995c2fc022b07a92ad18aaff67ff1b58d26588756603fe4eb5b9", + "0x0433e654f7c7263ab56043059421a9aa8c0a2e93bae57cbf4ec33288b96a83cc", + ), + StarkCurve::from_affine_hex_string( + "0x04bf84f9ea7df23758cd894491e480d0a476ff631e9ad7ff718e0083b06e0f74", + "0x05b3d884d26b0f1a5f8ba62dab0feac7235a39cafacbc1e792ad27a23d409142", + ), + StarkCurve::from_affine_hex_string( + "0x079bb7d217a1ff047a278b13301a97a8c495a9ef6f499e55410fc60e98d323bd", + "0x03b55c720a835ae732a20039f0d994dc0a2f812947897a35c7ad72accb3ece94", + ), + StarkCurve::from_affine_hex_string( + "0x0404318f2d2ceb44f549c80f9d7de9879d8f7da4b81e7350c00e974ebf2daef1", + "0x03934831b5af70d17a3f1da9d2931bd757e6acf2893236264fc7e0d92ff1a1cb", + ), + StarkCurve::from_affine_hex_string( + "0x034f76980361989a9e712f25b56b0f3b50533f9efd10a2497a9a382bc7407121", + "0x02edf097fc9b674ac310a5b519f59a57ea6f37ee3115b7c799978c94a97913fa", + ), + StarkCurve::from_affine_hex_string( + "0x067abc6bb1f23ce52c19312b447d96ec01401436f27bdf4ed618852508100563", + "0x043ae7cd4a8999e2f0846ac6ca0e9b583e2abdfa093eb1d39ca2cc075f7dadc9", + ), + StarkCurve::from_affine_hex_string( + "0x012f583929f3e0de63f13fd9c1f0af5b11b284699d5dcad27380591fc8bff89c", + "0x0200564e5252fa89fd981d626b7fc56551c17bbd042e0f3ba836c7de1a31d767", + ), + StarkCurve::from_affine_hex_string( + "0x056f93fd763768ee8e3183be29faad3050682f325f71a9b7295ddd3a4ffb3df5", + "0x03d4d30d4ab48a9a30e9e1cde1a2fa265641cbfa109941d8397768cb05d68ef4", + ), + StarkCurve::from_affine_hex_string( + "0x07aec427b526806568b3661318e76c109304cc66e52b7d60f693677022debf55", + "0x07180910240525490405125aac39729e9fdd2318c823ca068350a7232262f627", + ), + StarkCurve::from_affine_hex_string( + "0x04c49cd4df5c6b8519131c6bb53633286c7b6e6eeeb0c4f8d4c4526be0f5090c", + "0x041a1abe17ff78b4c71ca1956b9d81f78786bde00657b4a0efd4d38298b47ea9", + ), + StarkCurve::from_affine_hex_string( + "0x041aa0e6b8bae1a7b37707abca58fd09ebdf61c6b2976c6eadf3618d5bad00ee", + "0x0550466e111fe2c8ba2a3598f512936e0c83b4d0cff5aa59f3e24d5a128d4848", + ), + StarkCurve::from_affine_hex_string( + "0x020dcb6f394fea6d549b2e75748f61b7ec03b6e52319cb14163373a9c22bb9dc", + "0x0106a8c96cfb95a331618b7416d1498554730499e194a58fbf63019890480fc7", + ), + StarkCurve::from_affine_hex_string( + "0x0119000f277ccee013e6bb121194ec1ab5460fb6a96eb702a14079865f4170aa", + "0x01737a32f5415e8720a5606ec1dd4756f02e7c6817e3723b453d091f2d192773", + ), + StarkCurve::from_affine_hex_string( + "0x024b7a9216a2ac531c2c318eee682180d394a7596e7219f64a4413206aa62108", + "0x078fd489922cb3c6e2d534d4e8000f475d3864b6383a7eaae2d88e3db5c960cc", + ), + StarkCurve::from_affine_hex_string( + "0x045d0fb5cd95db76d05dec3faa12e467a308eabaad363a062353db3cd2d9b749", + "0x00ae08691b5b0cdd19ec499132421638f470f493320e4003d123ab1da761b965", + ), + StarkCurve::from_affine_hex_string( + "0x014455bbe2a196d9320a6010f4a5ad6a0480f47a096cdd43b7524b13b19e187c", + "0x039f7df161a3cb28b249b666815853502548fc3d82c30cb87fd4b76e4a22a75b", + ), + StarkCurve::from_affine_hex_string( + "0x035645b557df8e66f0665354012e4e8b46ee19004547f4f0b1b9a2b9f4b7f27f", + "0x00ff38d481f14c324ab3995fa6f5686a60f0d41a6c73046da6f6eb75497b4dfa", + ), + StarkCurve::from_affine_hex_string( + "0x058816cfdd17d8f7e00c0e3b522d13adc6985831f84ffda523b5b15be049e712", + "0x037df06c43abbac34c74fe11a42dd2d08fc52b3123ce3a8184bf32341c7a9af6", + ), + StarkCurve::from_affine_hex_string( + "0x01257b3e65cdfb6367c6d0942327e799bc66eb221e70c6573a9862889eb51c38", + "0x0593309fd45755dd2cc4afd2b9316bc4638b0c5ddb3009694fcb7b250d0c8a2f", + ), + StarkCurve::from_affine_hex_string( + "0x070c55f523088ae4167872f9e0728817b8c8ee4d11ac69fac00935d2e9d278e5", + "0x02abc80ad7b1b2f026907138873052010ee5f30a853e135547e9c40f1f09b140", + ), + StarkCurve::from_affine_hex_string( + "0x0121be713b18775280c58ecaf99f3fafceba6a0a3ccd78bdaa0b039a01dca700", + "0x05f1a670cdcae1a793c509878b353de576044fbc774c4858ee066797ddadc241", + ), + StarkCurve::from_affine_hex_string( + "0x015274bbb7a6f089d769cb07bdaae45fbc82e3d7809845715fbe431f58508637", + "0x016ccaf74f364d3a84c87cde65ce9556f3ada0dd6d48a328fcae1feff5d68aba", + ), + StarkCurve::from_affine_hex_string( + "0x0689bdbbc1f6067756f775d2c80ac97dfe182686fa7f95b86d57f772c6859a3b", + "0x06843cefd0215f0dca692c37b1964e1481130705b2f7af487c3731b1a19cbcaa", + ), + StarkCurve::from_affine_hex_string( + "0x059f7aef17aea8fb52851a7d4f1cbda97a5df236488147c4f7a5d2149633dff9", + "0x05da3dd360110b43dbd06ff2c3b76f220b48c7c80a3b25f0dc1a1077177b0559", + ), + StarkCurve::from_affine_hex_string( + "0x0124c997ebcf7cfc0c4ec3e4d8ef8a1487f4c4bb18cd2fdfa55a2f33c3bc1955", + "0x0796eff8a3182604c60f8669b1a14bc61d23ed23ff977cb1ecb0359811d5b9bb", + ), + StarkCurve::from_affine_hex_string( + "0x01cfa692b4ea379c0a4a59212fa5afe459635081d8d65b73f659b5fce53d9959", + "0x001cb133c2d602c16f17860ef9255aad4b0f3c9fa5bc3f85f8777a82b5c2378b", + ), + StarkCurve::from_affine_hex_string( + "0x0186dcf9950f72e868014a8accf14aa36e82a7a2a29f86ba37f6632da4189db3", + "0x055684c9f7a043fc523ed78f756f834b4db823d5e4161bd79602c17d55a5cd8c", + ), + StarkCurve::from_affine_hex_string( + "0x058791d5569f282f5c3b01ecdc9388df7ba3ca223a2dc1eed5edaf2a1d302fb9", + "0x06298d7dd51561a045bb4089deda9f40b2865589ed433e56d54554f8b45e79f0", + ), + StarkCurve::from_affine_hex_string( + "0x049fcfd1f91de6367d15699c38f80b4253d4b38c3acb3a3ff7071f2344344949", + "0x05a2df8383e58f480df2ac020453a2638d25dddedfa599086ffb50cf2c726a63", + ), + StarkCurve::from_affine_hex_string( + "0x013fd87144aa5aa4b24d5a7bf907d8280d15937fed262d41084898cb688fc28b", + "0x03fa54367770cc4479a857411ddcabe86627b405ce1cd14ad3b2863bde13abe4", + ), + StarkCurve::from_affine_hex_string( + "0x03b795c36f08d24b5759983245b3f87bc0bb3a7bacd8ce469808cdd3dff756a0", + "0x054d1a63e20429b960320b732ee75c788cffe37d0af089af80a2bef759f2512e", + ), + StarkCurve::from_affine_hex_string( + "0x0493f307b898d0224d7abe27e8c3191e9c4bbb01252f2b58a85aa89d2202a2ca", + "0x05a938afdb84da82376707acdc8728bd7449e3873dad883cc864af9f1dbaaf60", + ), + StarkCurve::from_affine_hex_string( + "0x078c9fb111ffc902e5f4b4147306d461a5bb6a11d86a84fb10d2d0920d49a454", + "0x009b4364ca713d208f2a0acd560e778b1b6da7b896bb241f8851aa557495dc0e", + ), + StarkCurve::from_affine_hex_string( + "0x048118139445415f0c1879224e2dee744ed35280ff00537260402a1741ec3676", + "0x04dfa39dadaabecfc54ecb7a25319444f8e952782d863790e42a9887064fc0c1", + ), + StarkCurve::from_affine_hex_string( + "0x05bb002ce2f21ec59ffe50123b20ea7478c7095bded4b03b5c2b0c6e53addea9", + "0x065f10da81bf42af85f11a9da74d169fdd934a01eb42fe6ae9fccd6ac50615e2", + ), + StarkCurve::from_affine_hex_string( + "0x03b894f7e29397e50352e39ff99109a34329f6dc7b7b873dfb8f827a57a8e686", + "0x0431dc16e38ed4c1c8db6baf71d362f53923d925fc3f3413514b3d7386f1c197", + ), + StarkCurve::from_affine_hex_string( + "0x03d56abee17f1121d53fc762d5310a4b8b4fb0bbbe6084702de5ab72aaed74f0", + "0x07ba9284b8907e79fa3cd3af5bd5ac716b46be3d8e48fbcb93cf5b02013c9911", + ), + StarkCurve::from_affine_hex_string( + "0x02d16100e9e6fece514857e64cc1c3c54225d800167f7fd0c3a93bc8f55f0c79", + "0x045467e3b674303b6128258707d2767af5dbd7d46753597275b648b26653d1d2", + ), + StarkCurve::from_affine_hex_string( + "0x079ed57111b506958da71cc5905714b30fffd18f1178a4bf34b20600e10f9442", + "0x0314cb3044c8449d3507f7da2698cc4fec7f96ccc81cb6cf452657c2548b7f4f", + ), + StarkCurve::from_affine_hex_string( + "0x00fdf811b74879bf3f8b12d9bc32302452392372de0c45ca0e3bd0185b060ac6", + "0x03c6850f2d56034540f35910398e1cb375aa41497641493355e4f3c22640e7bf", + ), + StarkCurve::from_affine_hex_string( + "0x00a83defb97b3fa0f1dd7bd5cf8383cd9d8dd7a41089d8d4b2e2dee59c8eaf0c", + "0x04f917752be2065d7f0f1fb2450529046b2c752597a1932ed4488b1fe0d0dff0", + ), + StarkCurve::from_affine_hex_string( + "0x04ad031bb9eda84f2fe5d354c7948d41558ca657a04508654721810ee72ef158", + "0x0620ebd5d0086b92c6009a42777b946a351c2c7ba852b57d3c9905fc337459ef", + ), + StarkCurve::from_affine_hex_string( + "0x04a34abb016ad8cb4575ea5bd28385d2348e5bcc0cbba90059f90f9c71f86e8b", + "0x04f781829ad83f9ed1e1b6de0e5f4ac60dfdfe7f23cb4411e815817e705e52c8", + ), + StarkCurve::from_affine_hex_string( + "0x06dc7cb0b8fe8517f123122f101d89da7531947432e1a83ace06b661b107086d", + "0x0796fd2f8bca27b794a3fac0102213686c335a812fa9a4efdea35b7621630d7b", + ), + StarkCurve::from_affine_hex_string( + "0x07fc632d7512aab5356b7915dca854c8b12b369ab54f524fbce352f00eb9b9f9", + "0x02ce80b944fc9158005f630b34385d50c3ad84450a9e1e529925b3211dd2a1de", + ), + StarkCurve::from_affine_hex_string( + "0x0651848d45cab099b169e802527e4060e8df05b0219a69c4a5b5bc066a8dd6b0", + "0x03ccb493049854709b23ba862f92644256940b5ade5fe85c2102f2c2d1f35a82", + ), + StarkCurve::from_affine_hex_string( + "0x0520ec6007cd7ba1b5d6a83945931269d2d01c6d50d431ddeadd6903c242fa0e", + "0x038725464ae187f670443c0cd4b6261e67cf906fc02372626be86e5292214de4", + ), + StarkCurve::from_affine_hex_string( + "0x00e3f542a1c823c7f15fee11d64f0926a418c74ed74291b8cbd50c56f7ef0444", + "0x069aa4fcdf4905ee290355b41068753fe996463488c67301487959e42775884d", + ), + StarkCurve::from_affine_hex_string( + "0x065ed10347503cbc0216ca03f7536cca16b6abd18d332a9258685907f2e5c23f", + "0x03be1a18c6bfa6f2f4898ebefad5a8e844c74626d5baa04a820d407fe28bbca6", + ), + StarkCurve::from_affine_hex_string( + "0x037017d19d22b9af3c1c128bfc5a2145864d13d40c4c40a2ecbc341fce33aff8", + "0x02f375f28593711138cb277e7f6e7fbd02f288d3e1d0dca94a5ca9bf2ccce5f4", + ), + StarkCurve::from_affine_hex_string( + "0x078c2600f40a1b5c13922effbd632a2d937ad8d98cd19684ef71ada4d1178dbc", + "0x008f2cfb8f04abafb6cc4ca8b86836c03afcdf1cdc2a76635e033e42467b5d7e", + ), + StarkCurve::from_affine_hex_string( + "0x05a4bf8a155a3574e74b239ab778c451795db097f9ce2b654808db277239be57", + "0x03bda0a709a5a163640eb57b2825c3ac381af0c6542496e69f758342b73ced37", + ), + StarkCurve::from_affine_hex_string( + "0x00f731ace9f24a83c57eb3604e761bd77273ce89d8c13c421c02c3350dfac53e", + "0x0347d11e9c6113b2da709b4b0cda353b53607e03e2afed8905fd196a4b6fa6c1", + ), + StarkCurve::from_affine_hex_string( + "0x009a1b04db6a517f3ada896fc9a29104851614ff184e299673a276c072c9d9cd", + "0x02bebda66ce439885be6c1f94cff0ad63acd9e05388f5b394158f95ebf5805b1", + ), + StarkCurve::from_affine_hex_string( + "0x07fd4b320f0c1420b58b5f5d4680032a8584efbfcf8b4f32ee46ec962bc6250b", + "0x02a192f37e37affad5eb037961365be78cf2444de270925edfc93d5a2c3a100d", + ), + StarkCurve::from_affine_hex_string( + "0x079a4df1c28308725cfed2ea6fe4d67f02d2c80fb44e47c4e6a338bcf8cf6775", + "0x01d052c945d0dd6b44320bc98997e7c5682b680948a987fe23f3395ae0c25ed0", + ), + StarkCurve::from_affine_hex_string( + "0x01a8abba1be2e276cdd1f28c912280833a5ede1ec121738fcca47dc070dcc71d", + "0x021b724378bc029a5199799df005922590d4e59cae52976f8e437bf6693eec4a", + ), + StarkCurve::from_affine_hex_string( + "0x03a99c22dafcfe9004ebb674805736a26aeed7ed5d465ae37226dcbe270a972b", + "0x05bf67552af08e1e6e2a24bf562c23225e89869cab9bef8becb3669175a3c94f", + ), + StarkCurve::from_affine_hex_string( + "0x015d1e8b43ab3a789f64b02f034001f77ed2114448d424151a19618e1c763bc8", + "0x03ed8e0cd6836f4fed494c59daf090ad560e35371f6b6e0447224c0bec42cd25", + ), + StarkCurve::from_affine_hex_string( + "0x04a6a5e4b3501f2b7bbdd8da73ea81ffca347170bdfb6776a037cdd74c560fb4", + "0x05af167ebb259c2da88740ec559ee04052bb66480b836cadd0e2590c32d7111b", + ), + StarkCurve::from_affine_hex_string( + "0x031cd0f25ff0f756bad489d479905c9774ba0b6b2453d5d25ac59237ecc37935", + "0x02e9cff7d5d53a009bc77c12aa8dd60e6184ebd623cb2ddef07009e2ae8553b8", + ), + StarkCurve::from_affine_hex_string( + "0x01d8441c409d3c16b46a120d1e451faba47fb974bdd9b4474d4bd605034f34ca", + "0x059a9970eb948deb08bb15e69c6f1f33c5f73c827e0800467bc1f5d72bcb384d", + ), + StarkCurve::from_affine_hex_string( + "0x037f363f5d5394b00f8a3fd2e2e4b46f6b1a5a20ce9054e75b051c1317b8b7fa", + "0x060706ddf1ddf615f4496d838c9a4200f7b13b3a675145aa7b00fac917da7643", + ), + StarkCurve::from_affine_hex_string( + "0x06890d95308525f0bac9dc25cc1189eb92d29d4b3fe61bc8aee1c716ac17b1e8", + "0x00e6f23f78e882026b53ea4fac6950e56e3da461e52339eb43d2fdb2dade7ca9", + ), + StarkCurve::from_affine_hex_string( + "0x047366c405bb48ec3f31db4705fb7e1de598db4855e5374b5cddb076debb8924", + "0x07b6340f88acd485bae466f8eb6bb22be8a1e25066d316adeca0aff52d24b8ce", + ), + StarkCurve::from_affine_hex_string( + "0x05eb2c383a68bc62baf668b6e26fc2efc2ea0297bfa90c534b46b98db505681b", + "0x026fbca84685699c605391febb3c8adfb1153b097641a6d02eefc4a09089a8d7", + ), + StarkCurve::from_affine_hex_string( + "0x01091b7e9d959164fb0994138ab9cc3adc206a097b559237fc91db5b157b8d7b", + "0x00d1fa9c33283554f5489a648bb64233c0b7a03a476436422c24ba104e9c6b8b", + ), + StarkCurve::from_affine_hex_string( + "0x06f22fbf9ace529f20bcce8e62e6f2bacc079365ed4a1df6af75f5beaaddfb8a", + "0x030f298c469fa107d50902217e20909c7172ed64fe26075ab761756bd9d178d3", + ), + StarkCurve::from_affine_hex_string( + "0x033f1b2c7d271c3283ac0b2a1dbef7b3bfb38c7cfb8a3379d72c620e20e77235", + "0x00ee81a23414092d4511f0c3dd6802819193d91bce3116a3c649289cf35e9049", + ), + StarkCurve::from_affine_hex_string( + "0x00515035941b0f7b272f508f01db2e1ce055b2a06fb533b96c2afc0d1581ea06", + "0x0400cef56fbf74f3127376bb8619c1b32dfe03a572f4f4e65e80e04bbd6f08bf", + ), + StarkCurve::from_affine_hex_string( + "0x0663bad148a41cff759f0883290c27fab38a276edb56a81a20bfbf43810f75b2", + "0x0515f465df7de627f352e9e5ff25ae2806dd552a5f60c6fd2cdde0cd85b34831", + ), + StarkCurve::from_affine_hex_string( + "0x0748f4cf4f027efdeaed7c7f91ef3730ff2f2bb0bfc2db8f27aadde947f7d4d5", + "0x03a1cbc550699411052c76293b8c41a3a8a1ecf12cbbc029a1b2b6ea986fca93", + ), + StarkCurve::from_affine_hex_string( + "0x07321f3f581690922cd0dec40c9c352aae412ec2ccdf718f137f7786ab452cd3", + "0x05be5130c9277cdb76d7409452438ec15d246b211dd1e276ee58e82a81c98fd4", + ), + StarkCurve::from_affine_hex_string( + "0x05afd91cb45deea19ce415102a59792b8afbdbe77f6702d87d20ac7b3c6c5a14", + "0x005818722265b7a654ad6e361c4f53c712faca32ff1522841055ee39c48abe86", + ), + StarkCurve::from_affine_hex_string( + "0x06c4d6cb7e7ae70955224b8a912ff57ca218635a2436b36cee25dce8a5cdf51f", + "0x032f8c03c6db3246946e432e4148e69f5628b200c6d7d72449df6eeac0998039", + ), + StarkCurve::from_affine_hex_string( + "0x03a2e4c3c6f92402776a9e30ce3b4ddf5fecbdae85546d19220f43f7de1fd878", + "0x022b17c0a936104c38cde32caff0dcdd3e628e59cf271393b70471116d9eae87", + ), + StarkCurve::from_affine_hex_string( + "0x00d31707e941d8e4a39df7bd581a6a2ab3922c426f5af9b8ab34ac369ce20c3c", + "0x04acbde4fca11fa1975fc8a3e1aec32ba05bfe7abaf7f99cc799bb4e9a4bb902", + ), + StarkCurve::from_affine_hex_string( + "0x0796c11d20224e4030ceec79bbd02ecd406e5884d68542bff6662bb6c53083ba", + "0x04177d28e5464e1cee8ca4d6e5b58a2e0795930658f94cd538c5ad1df980d098", + ), + StarkCurve::from_affine_hex_string( + "0x01dad5f2e795ea6fa5177f110989516eacf8fb37bd6a091c7c93f1d73a2fe309", + "0x056b2298c538180e99dea3e171dbb5c6fba0bd0a9ed40537277c0c2373a8e2c4", + ), + StarkCurve::from_affine_hex_string( + "0x05d08a975cfbcc4e964468ab9d314471b3b338325f53148a31f2c93ef981e348", + "0x04c8e1817b63a0b2cfb8312666f5ba9c4021a8a7b72e9a86310047fa9ea70d07", + ), + StarkCurve::from_affine_hex_string( + "0x05db5c67073f4ac1f6524393601ace3ed5e457a33c527dd1f2cc8043f5080b11", + "0x024bfec75d33b8cd0e7efe321ae0f9b3188413c2e39151f5225d4970f92e58cd", + ), + StarkCurve::from_affine_hex_string( + "0x05e6905a69d972f6b6ddae30dcd6928c2633e5b4af187d77ab31b6470c74b585", + "0x023f3e8a974ad97e6c79374d60bdf1f7b58f90528bd6033832175e4028826265", + ), + StarkCurve::from_affine_hex_string( + "0x05b88521d73ecf48adf5808c375c56559ca051c3d842661edc5dec442ae87a5b", + "0x070b425ef3e83b094859c69fcabeebe78a6243f26e577a6c16fc62d2289f7d21", + ), + StarkCurve::from_affine_hex_string( + "0x0598ed112427bf6edbd5c7f6d50f03582163fc37e23ccc2bd982fb00dfcbe054", + "0x0606018e8717c1d2c3c5021a1dbf9928bd494cbb7d6dac5c57e724aec075d5b1", + ), + StarkCurve::from_affine_hex_string( + "0x023e37d8c4273dda97a6209821b03c06d008bed9757143cbb1aa2f6009e9534f", + "0x0043d3d6c86d7946988d63be931a9384e804b7e397ef3d83f3dbfe4cce7a6427", + ), + StarkCurve::from_affine_hex_string( + "0x04d6ad42369d0ca6e8f591d28d271626b43532f2f3d4e1d6c89235bc6e7e1bfc", + "0x027fd3756441f8d93382620a2be4de39fd7049a17cedb053024a240616096225", + ), + StarkCurve::from_affine_hex_string( + "0x01610605baacc9bc62c4cc923dc943347cfece7ae241e746fbe6c2c878221dbd", + "0x0431a82d657e0d109d00dea88cf3fa9b999845221b7b5590a20c40fc71368c1c", + ), + StarkCurve::from_affine_hex_string( + "0x06a4f5c787fb09a5be2b04d2eafa1e6f3d3c863ee22960eb0b64f6eaf6659162", + "0x014dbc3eaea6146ee7eaace5a91ed9430dad3a47e9ca2f68b455171f8fe6a7b3", + ), + StarkCurve::from_affine_hex_string( + "0x025e73ef966cf87711e4c367ec01966bb6afd402171f695a6923e60fb33bba72", + "0x0738383b20ba06b299bad3bc16e6eb971856c89cdb1a4828f2de81d5e8f63540", + ), + StarkCurve::from_affine_hex_string( + "0x000738415b73e55412b0e582e45ff0d7bf4b1bf2922db581783fdcc75559f40e", + "0x033825aeb3fd8459999eb418d15102ba5864b069c6ea517f0c6e9eab8d9aca47", + ), + StarkCurve::from_affine_hex_string( + "0x02957724f392dd396f07242001af51214fc4c35ed15acf507d2bfbf79da66350", + "0x021d1f3c135e28b01d550228ad041cff4014194872572221d0063755e66ad1dd", + ), + StarkCurve::from_affine_hex_string( + "0x0468a271b950a44059cc93b8d6000b6ba378e06b5cf0a9d92fb01883776931b3", + "0x077829a2c43b90b4f351908e4d3d8679bbc879d0c2a9edb477f5e49cfc54783f", + ), + StarkCurve::from_affine_hex_string( + "0x05748f5c43e13d0620c50e2f73639b56e623309125fe14695291681c6ab8499e", + "0x037c565885e96f59712a545d1cc24da9c510eecad6daadd55e11a3ede6e4649b", + ), + StarkCurve::from_affine_hex_string( + "0x02603e72ce53985c70782774057a17944f7b4ce224a809be4e2b5af3606aa1d8", + "0x0092822921809c42318f42dac4d773325f41c43069e990adac7818a45e2554dc", + ), + StarkCurve::from_affine_hex_string( + "0x0207755b2d5186c09ec9bdf40830aebf55e4c09b18785ff1d9fc5b8a84b78a10", + "0x02b055c58617086dee864a2a48eef389c6f51f0417dcfe4e99c80835454a17d2", + ), + StarkCurve::from_affine_hex_string( + "0x059a15120fc2d5b5f32112189104832feb9e135a4e18880036e875f95d89b8bc", + "0x078a7382e1f991cc976c50084c8425dddfec0ec4d3cbedeb5edbea347ef14b8d", + ), + StarkCurve::from_affine_hex_string( + "0x057683840d1e0325dc77187f01c631d90a722df60ce2602da5cb126fa1a797e9", + "0x07087ffbf35b7d32c3c5df2f9efd8514b45b7aa1618034488d661fc349b3054b", + ), + StarkCurve::from_affine_hex_string( + "0x043db4cdae07442fd7ba6843a782b6e3aff1872d82ce8dfa037c8058d47cf84a", + "0x046174366bfdaf149509daacd555745bc75fff47fe7662653ccc19d5a5575b6d", + ), + StarkCurve::from_affine_hex_string( + "0x029e63215e51f9162da1a131dad5c4de499d62df1dbd7a386f5b9f330c5129a2", + "0x07111a09f63a9b043a594c65454c9f39c4c868c2eb64a3d07efa4b73430870a0", + ), + StarkCurve::from_affine_hex_string( + "0x0326c00f300157c86e4ec7171d83fedfea58c414a97123c6bacef59680476233", + "0x0599822be567a0eecdf908d1a36164b9022f91c4be30b311355ffa17c2a6921a", + ), + StarkCurve::from_affine_hex_string( + "0x012e680d1872aca17829fcf35b925442d0b059a0b7cd6dae930d3338c980ee53", + "0x0500f390d87f2b3350fa15aa9fd2578000040a5d3533da05fc9161796a5ef2ca", + ), + StarkCurve::from_affine_hex_string( + "0x0181cd967ab4615357cc96c82eae9152ce7598c1a1dfdd91a458bddb016ae9fe", + "0x05d562fdaeb0e12647e230e50eaf216bed52fa73c6b7378821a3bfc4cd66d4ff", + ), + StarkCurve::from_affine_hex_string( + "0x01121726069b9ef5954ba6490100b226e0be53fef3e071b7c58a1286174b789a", + "0x04b25594cf4e9eb2d14b3f52f2661a9992234fc222c0a0d44517cb77deb9c16f", + ), + StarkCurve::from_affine_hex_string( + "0x0059d70f1f5af1e1b0be565b9a38d422e1fcebf0ebe7100dd22a63db42521407", + "0x033e8210993e81268e03fdbaf4fbc89f4a461041d45b3960c7c3a6a9be80ab68", + ), + StarkCurve::from_affine_hex_string( + "0x00e543663969b915337f105f80995a77b356f1a51d8b4a4fb12d44364130e873", + "0x034b2e3c009fdab4cb7349a580df2e64c0098a123280078e5da6623a9ec6b44f", + ), + StarkCurve::from_affine_hex_string( + "0x01f61e12d22eec4bda7a35687fd0dd34d7b1676db852ecfced3347bb59957d37", + "0x00497e1f230a83d592b734f03fbcc852f58a27f4a24c262003e28f56733a1817", + ), + StarkCurve::from_affine_hex_string( + "0x0096359fcca452303402d17f99817b07442ed93862e4656228081ef9d0f41452", + "0x004444041c5f31cf617dba4eafc8af0991851edab15d6c66f7cb4e4b9f7dd497", + ), + StarkCurve::from_affine_hex_string( + "0x029a66c92d3739b24d93b87288b516603615c707cd42db417ad5c420db7a891a", + "0x06f2304c8334a5ea6957dad2c70c73688ed76fd692353edbb6a8a0f49b05d24f", + ), + StarkCurve::from_affine_hex_string( + "0x04e2f8909bb62de5ef65600e61bbf969293815296b6e23702875e049b3ce5c45", + "0x003cb81f2c21f22a7add26fa38a9ce5d9cce1bb251bd2698f90c34ff0a84f7af", + ), + StarkCurve::from_affine_hex_string( + "0x01c9a943d8f663621b4464b72d851a4a550b0038061500c60cd5ea88d0704947", + "0x07e73d2a9720b043c0fdb226f0c2b878460add44cc26ef134cf020e52f5053d9", + ), + StarkCurve::from_affine_hex_string( + "0x03755e10b47e2d60435e16c7267a270f20abe35b7df6845fa78f400c573391aa", + "0x07daec8b1715f5612e8ed9dcf587dac5d2319ec71fd94bec0d9dfc006974d6ab", + ), + StarkCurve::from_affine_hex_string( + "0x044dea1759ddc7f182adb3ae0e1941cd11ac62a157556377cf512c175ba0f9b8", + "0x0326df591f7894fda39cc028f6a119b3f02aec12a14963e66c5ec2daeaa6e3ce", + ), + StarkCurve::from_affine_hex_string( + "0x00864f3640295da5d276321d37628bddb02e801399a4a505352ee3ec01412687", + "0x0110f880c70ddb4e08f8efac560a8ade433650f973a4aae4f090193c4be024b8", + ), + StarkCurve::from_affine_hex_string( + "0x0454064383ffe86179a98c7d9e847f7e6205c7f19b77b4d88b6017275bfaca17", + "0x063a3823a4da2801efe749c94124e1357405b6bd176cada1d70789083045e508", + ), + StarkCurve::from_affine_hex_string( + "0x0327029691408702e6e430533b1f456278c19e2af5785eb20ce6c99838c5a7cd", + "0x0436bf52e02d031d5b219d5b49a44340734be38bcf56fc87f0ead935dd284a9b", + ), + StarkCurve::from_affine_hex_string( + "0x0522231210ea3e60df50a7e47e09daafd82377dea2a8bf10298ca000602ce582", + "0x020e4f50fbf2cb1590a8454e4b1812a77ceae12af0b30ac16dc0282b68f7db98", + ), + StarkCurve::from_affine_hex_string( + "0x037b546e403a1ba970c17b67c2f1361ab9c803f8d2b5cd93803014faa08861ed", + "0x037079184ea46272f5809b523d060686633f7995167897a153be1772fd6566f6", + ), + StarkCurve::from_affine_hex_string( + "0x027bddca77f7bd7f66b3693567a4238f2e6751d95b0bcb409f6b24d08f84798c", + "0x06417a85cbfd6fc02df560d3963a241a986baacdfa423f65d7227ce49a96c57d", + ), + StarkCurve::from_affine_hex_string( + "0x03945a4beffad92a5a08d9d49b073fcca77acc8dfd41fcfeeef5d334b4c86ee2", + "0x019f6fea2dd54c24148e8ce0daaff3652d448698ef564d7a2c640877b0e30604", + ), + StarkCurve::from_affine_hex_string( + "0x02de71a39aa043057d1bc66e45f804542acddf18f7a6d88c0d7fb0ca240debdf", + "0x0306c1ce39ab46300f7cca0f3a2fbfa77296a27e24bc66b0b8044968ec0ee413", + ), + StarkCurve::from_affine_hex_string( + "0x068d064e368144ca4c8eb76f2f88e4ee77ecf909f22105b83a9db24b72eb1ee8", + "0x075f951d9b573048f0ec3213deb1af979246719dbb3d0c148158573b7518f618", + ), + StarkCurve::from_affine_hex_string( + "0x0008f8e0befce09e70eb4a6716d8128f0981a7d81cf687488163cf4962c797a9", + "0x054cc88cf27c9e9ee0f96879a4ae118f906f9d9a6df98f8b645ddbdc49b1c52a", + ), + StarkCurve::from_affine_hex_string( + "0x05c758c0075321475692a682072aeb333fc4d36d7aea945987024cef80cbe0ab", + "0x0628586e827c609b776cdb06829f6f5f53669254339ad265e41f0365abf84f13", + ), + StarkCurve::from_affine_hex_string( + "0x0307c877154364c0c03534e7327d5a88e1380ceef6481567ade37a14ee7c1a72", + "0x03404bc7dbfb33b95d922d0693aaf9358f77888d7d95e773c38d83dbe2e5f995", + ), + StarkCurve::from_affine_hex_string( + "0x0459f3f57739281c648ef1930e4cd39df0fa584466a8b10953b896118794a5cb", + "0x032836fbfccdd1c73bdca25a155f203346b5f179a68882665a1e3e1268d1abd5", + ), + StarkCurve::from_affine_hex_string( + "0x0746a8f305ed62347cdfca3c043709b9dd154c6ea1f6cadae9d06cc82d1728b4", + "0x042c178827e551577045a73e5fcc24f09412071d003ddc67d29e65352e070bce", + ), + StarkCurve::from_affine_hex_string( + "0x07c641e896b9c3866dd899694e8b19aa3f9dfc1eb2886189e014f811a2ed3951", + "0x04b513b82e65099ec1aada8bdfb00c92180597242446255ddcac67608f5cdfb3", + ), + StarkCurve::from_affine_hex_string( + "0x06f79d579f1fec937dc715916a3368a4082469d98baee09f4670c37d547fa383", + "0x00407329a5f2339464bebd4abe4049b146bbe240ed94e1cf515e98b1414c9578", + ), + StarkCurve::from_affine_hex_string( + "0x01231bbc6fe7253f9153355e24c945ce6621cdeeffa6414799ad661098e730ef", + "0x0060c4334a1dfb438b647b635d3c404cf110b187fac6edd8a06cc9df780c48c0", + ), + StarkCurve::from_affine_hex_string( + "0x0062f56a0a7e94a612fc879df4bd1e4f2519a8e0645328467c3eaaaa3fdf1f7f", + "0x0757306400fbf5c3d5293df3e936c9a7d8568f9272d311df40f57a5dd08015bd", + ), + StarkCurve::from_affine_hex_string( + "0x07b86081b991cb4b765458a8c6921d01beb78cb2c5a55a9ee7137142fd5cb28e", + "0x0494fce0a7f58737e7f4a69f8529b5c381e682c374ee5716c8e888a75213425c", + ), + StarkCurve::from_affine_hex_string( + "0x079f09ff7c60850e5f5ea020722659a1ed27db4c95dca131f99552f785c8afbc", + "0x040429528c099349b426ddbf129497176951a64a53db5f9d8bd2be0252cb22b2", + ), + StarkCurve::from_affine_hex_string( + "0x04027dc6b56d446e5972f35464eeac85c5254ef377c902d9fe37aea841bb5292", + "0x07c3ea37689ef679fa2f5c7e031a78e23d484a8317990fd34d44d95cc1db3717", + ), + StarkCurve::from_affine_hex_string( + "0x011c27f9ca5aa652cebed25ab12bd6847babcd620dc296c22e41ad109ba0d3da", + "0x05b838159b4e62be7389f00f3f2ad74080aad8b2fe6f8791f7c89f2e9bb8ffb5", + ), + StarkCurve::from_affine_hex_string( + "0x0645dbf78a3c228c4b7151450b5e65edb58e71f37e1e4bc5f471e0f1abd6d9c2", + "0x015cfe7850f327b256e23b00627451560c5c6ab60db78d45b7ab286afb6f13ab", + ), + StarkCurve::from_affine_hex_string( + "0x06b095a3dd8dd4e59b94eb894883744a8ecb23ef0ef03a203f52626848d30f1d", + "0x020f532e9dd6c71cb9a92337cae5b6e9310b7547158aa943900f184ff9988772", + ), + StarkCurve::from_affine_hex_string( + "0x05b3132c6e985d667d1ff6a3f25433324ba238d14748b479931d4b15bb98a089", + "0x073be3acab3d3d3f34fa8c16aac3fbb76351f2300b6bba98bec67aa0f1861272", + ), + StarkCurve::from_affine_hex_string( + "0x006958c365c5c17504d559497c102d2e3ba8c6924ab8ede1ca87350558dfd893", + "0x04d5148bb677361907d20614f436c632bf5281631db26f536c54f03d6a180dc1", + ), + StarkCurve::from_affine_hex_string( + "0x01503ca373757677ad1d911a2b599d01c46eb879d1ce21ae171c7e439846a85f", + "0x0583eb269b7030da6a0c324026919de3f9489d2ff6ae0e6320c36f05469ad66c", + ), + StarkCurve::from_affine_hex_string( + "0x07d43c4400a7ade9fee36a22518996847b17b543f4d2a7de777c4ac951ff5fa6", + "0x01975ab13353ec269342d117dfd67eb1616071dce91f404056bb3997b8190d24", + ), + StarkCurve::from_affine_hex_string( + "0x0499f4fcabe7c0ff4fd32d67aee7874642d75578417629952b9d9a99405b77f7", + "0x00d42e30d5dfd77550074ffec85bba3b22ddeff37d51a0ec4ec45cd1c93e6c21", + ), + StarkCurve::from_affine_hex_string( + "0x00fea9ae779288a6c9c01f80ac8ea877d3577727329b5cf6837b44b10adee9a0", + "0x0650d890ddb87ae39ff41b093e0cb361025b24051433f4f75608c4e80dfd5409", + ), + StarkCurve::from_affine_hex_string( + "0x02612191653c9a60d5019f825129e555256ba642cf7fbbd620c0c88324646f95", + "0x03b813d57bf4a09bb675c534ff8b543c9b8e1986dd5adfac551a7eefc13939fa", + ), + StarkCurve::from_affine_hex_string( + "0x0530a660937b20eacaf2ef4e2ae54788eb0160b21e92f2cac659c124fbe3f5b8", + "0x049330524ef1934ed75b7ac6626e48fc2d727015d6d5fbd2621f213d42abdbd6", + ), + StarkCurve::from_affine_hex_string( + "0x02e556484ea475a926816e102c9413ec9c0c768285511a0770e0af1c9c117bca", + "0x00d6ff6fc23668b46e29740ebc96b75e2ce3099f523c081b5e88d13ff6c25b93", + ), + StarkCurve::from_affine_hex_string( + "0x047098b1cb935549a63341c6f4d166b6aef7689e4c2e90c809740acc835db5f5", + "0x04037cda3699e88ec219eecf2aee240a49dea1a0369467e1c58c91dd4f5ad023", + ), + StarkCurve::from_affine_hex_string( + "0x066e1819ba3ec4ad4ae9f7d7588d23baa004e29d3aad2393d52af204a81626ca", + "0x0505249980cbe6273b82ad5038fe04a981896f4117345ac1abcc67e2525c0ee4", + ), + StarkCurve::from_affine_hex_string( + "0x05ec20dbb290254545f9292c0a8e4fbbfb80ad9aab0a0e0e9e9923f784d70ed1", + "0x00bdb1ca3a859227cf5d00eaae1f22584e826ed83b7ccdb65483ed5213dc4323", + ), + StarkCurve::from_affine_hex_string( + "0x01acd22d622dc63eee1c988b91cf853217aabd30047c1c7b4440a45b00a02c80", + "0x03b616688c30255a25c10568c063903e2e3e0fa49284da52ab28dd4b183db99b", + ), + StarkCurve::from_affine_hex_string( + "0x00a5c1a5011f4b81c5c01ef0b07c0fbf0a166de77280f0ae241f2db6cba15194", + "0x04444521fb9b33d7dfeb1247d0ee1a2b854ad166cb663d9dd2e686909362a689", + ), + StarkCurve::from_affine_hex_string( + "0x01c5ee84a34040624e802bb53fadfde50b8f2a8f9b54543d940fadbad0091ea9", + "0x03fc87aff5402328f0f239740e6607cd82f06a58da72b8e7753d9134db78a732", + ), + StarkCurve::from_affine_hex_string( + "0x07aa75ed7172955831eb7a20a75e867122c03957c11cef89fb9b58ee50ff88b0", + "0x01194797f8829b1982f66932a6980c834e80cdf4c4a96987357e7bd8e8045b21", + ), + StarkCurve::from_affine_hex_string( + "0x00e0661276ee5aac208777768865856677a66265d58f4828fedca7560446f3f4", + "0x007ba8e58ef481c78a148c3ba6f060feb661c295f7e9b79163c384056e12ab2b", + ), + StarkCurve::from_affine_hex_string( + "0x01f35335de40e00c62642dac2fda8b30f071986ce4f11db849df11bc45ad4e0c", + "0x007801a2c761b90fd4477ba0be9a775003d5dfcd959b1ed198b4681f15e7acbf", + ), + StarkCurve::from_affine_hex_string( + "0x00382e78bec2fe8d53fbcb13826d50848ce028bb445f2b191f54e5d519c801b0", + "0x02f261e72e518135126205006fc736e9f2efbf39ed1afe3bca034da090c4a288", + ), + StarkCurve::from_affine_hex_string( + "0x03e5a1e8dca6c93d9827a259a0049c98dc678b74c7950a32bb56d64330ba8245", + "0x062f102c147a4daf93c6ef0f887f213444d555deeaf3cdeeb6cb8d8aceb68d80", + ), + StarkCurve::from_affine_hex_string( + "0x0273bef66da95c6ed715440b340d1eb9730f19fa7130f9013e5a2c62cb05a9ff", + "0x0588eab72769e7094578058088632a46c735d63da01b2a486a8a96644e5b5503", + ), + StarkCurve::from_affine_hex_string( + "0x03b0c51e20d61408e347dedec0cfbaa34ca04fc1e029b9e71438c58573a82a8b", + "0x03ff0dd46b01caf3fd24d127cc5775d6deb26e02d5e59e6a9752f29d9b0ff68a", + ), + StarkCurve::from_affine_hex_string( + "0x077bd59dc7df3015ac199afdad5db86d349255176a03f761ce93b8a65bea5297", + "0x0681750b67dcb4aeed1474dd113950a3a1c80df2eb44c98cc77cb4de64baec6a", + ), + StarkCurve::from_affine_hex_string( + "0x077e6f8594a91992f0e44d3a96178b86f5d125555dd3f9189e306fc369b20803", + "0x044c06eb3adc7267369fd9072d714d8f528eb3f0367641ec9f28826fe3c092d0", + ), + StarkCurve::from_affine_hex_string( + "0x021546915709005f642d4e490aeeb8fb2330f6cfe0e45e667decc1632b0212ba", + "0x065b23ab2fbfd3ae968f3eb6983f2ac34fe0a5e75b3dfaa15542ee2fd1816e68", + ), + StarkCurve::from_affine_hex_string( + "0x0048db4798cf6821c1ffb8178b1d3bb6020e04186c96aaf4670972d367f4ed5f", + "0x0781019494df95b888f1578f1b4a3f8e125ea60eca47ef9207a10630671217a3", + ), + StarkCurve::from_affine_hex_string( + "0x017f653d904210148a8e74d8e719a3061683c164aa6d79c902a19f185ab437bd", + "0x06780e97985932c3860d810af1e065d454b1cb4be0e7ffe2d8cea7d52526e223", + ), + StarkCurve::from_affine_hex_string( + "0x02d1b540f579838588dfa276f3a195cb6ca5a6b6495185777fdb5664b8c29f6a", + "0x033d40a323d0de3ee07aad838c2cb7ff519f91dbce32b3e6d7461785f8e0f04e", + ), + StarkCurve::from_affine_hex_string( + "0x05c4d0c7432f9b0070436240f9855adae1467cdc9826952ae01b68cd52a3ad89", + "0x01c5747f968ed91261b7ae9bf1023c999da9816e37de602d6a1a50d397752bff", + ), + StarkCurve::from_affine_hex_string( + "0x04e1c5a8d17673c52b85020fb4b75aa52d827114320304d47ff0447ef921e41a", + "0x03338b901f02c559cd742ccbb04e5f2e842a17c4cd7aa84aaca196d182e11d9b", + ), + StarkCurve::from_affine_hex_string( + "0x0433c74ebcf7dd0449dd00312cbfcd36670de81627fb7f0fbd95b49783b1446b", + "0x07d592a22c5f7aac250c05ce39d0c0f90d42f1014622ad39578a811069c590e5", + ), + StarkCurve::from_affine_hex_string( + "0x0645fe11244707738663cebb6c5a94aacac9ff3a37e7053874907cc0811ea7f3", + "0x00b5297d575b121fef7c0b6654f1435bb51c6c5026f0584517963de03fcb7e40", + ), + StarkCurve::from_affine_hex_string( + "0x06fedd7639fdaa2f7bad4ca0b391710f6f8a7e890250ae8ae4252bb8b39a1e58", + "0x0436a215f655a3fd3778b2335ffdc9aca6b98474e43d764c1f8362830b084f0e", + ), + StarkCurve::from_affine_hex_string( + "0x04fc250f6844e9d58f02535bbde5fcb66c84eb36ab6fa74477be6ed321a278fb", + "0x030f67f2ad2446c64fc581d4c2527a83893dbc562be63afd7e7c9adad0961751", + ), + StarkCurve::from_affine_hex_string( + "0x00c668ad3fda304b586a20dc152eeb24e18413050c136e3c3f75a4612c814bdb", + "0x0625e2716d8eebe8ed8b89942197b4aba8605e7ebf3a39213e3ab1ab0a965eaa", + ), + StarkCurve::from_affine_hex_string( + "0x076b251def8b318dc92b09cdddbe3f54ed8848f5cfda788fb0818f023dfc4d0d", + "0x0641bc104fc17ec9609cc5df8fbfa769788802aaf56e58b8d0791799c6268876", + ), + StarkCurve::from_affine_hex_string( + "0x0667eef30499e978444ec5b80cbbc39f7d3fc9e0a98dc85003cd13b6f33fefe6", + "0x002efe7acb1da522fa9ec46fc384ac3b6f67c7a653ca9aa8bf133c85097c7b59", + ), + StarkCurve::from_affine_hex_string( + "0x0455b390a2f72c9184adea9bae17a62c8f5d8eac71b8a2de6b40f4d676282a23", + "0x0459927256c1e015ce8389acbeb3911b43fb9b5a4d559f2b210f33ddd621939e", + ), + StarkCurve::from_affine_hex_string( + "0x07af1ca3fba7c2ac09de2ca757a8cec062eeef6e289728781e52a5aff87e61d5", + "0x027f6cfc40e6da7a2be02b3f55a7b83a6a84c0ca97d044ca679af941343c8160", + ), + StarkCurve::from_affine_hex_string( + "0x0291594827d151e56f42702410515bb0d3da66ef8ea2e29893868651ebc58dfd", + "0x01b933c4975a2420ad30930645214311f0b35f2420877297b49bf0a5623a2562", + ), + StarkCurve::from_affine_hex_string( + "0x07fbd45a889c5e9d127bb4f8474d6be7cb9796bbfff923b75e42a1ad4cae37d6", + "0x0484bd12622a6ba81cd53049c550d9ed682a8e765b656b1cbff9bbea637bd1f4", + ), + StarkCurve::from_affine_hex_string( + "0x017d984d47937263f7966a3e7b1eea04071e678494bd749c9e02b48b3234f06d", + "0x07b341ff08722c4e161005d0037204a7a2001fdda7af2cc1a0b04a027f115a0f", + ), + StarkCurve::from_affine_hex_string( + "0x063b08255b049cec06b86800f14da03e7ee6cc54af59bb5cb623f3f15e788808", + "0x0080d5906cd22d6bb1a8a109fac00f27b33342e8bd0cba525053f0ece61c9f1e", + ), + StarkCurve::from_affine_hex_string( + "0x07f1822045db45ea07e1519c3ee1f7705915f35fe4dd8db1e8921b5d1c740edf", + "0x033d41e06b93320ad1b3d9580380ec797a05dac3f1cc8008899110ebefde2f78", + ), + StarkCurve::from_affine_hex_string( + "0x059194ba71a37f172f4d8a4ae88cac43d5dbdfd5fb22cf8ef83e4eb4a28ffe17", + "0x07ac142e2df173b9fdf0c0f51d18b4fcda407ff9fe2a612355fe87a535bf0d9f", + ), + StarkCurve::from_affine_hex_string( + "0x032a3e995437b109dce5f420308bf606e37f118523b7278d2eacd1219e9901b8", + "0x0428a6e1ee864aec33aef8da76c03a808721ce7778304f0d7fc45b8de4dc5267", + ), + StarkCurve::from_affine_hex_string( + "0x017ef03a590baf1a2496b00645fcf726e82895e52e1340e27c129e200d527c58", + "0x01cca147ce1b706184a1c8d45467f873706364e10ae9045730fbd401690d8f2d", + ), + StarkCurve::from_affine_hex_string( + "0x07b19453ecb74b7d0e2a66b9890ff73bfbbcd61a266abd6d82dbe665bf32f34d", + "0x06dba2355420dac582b1f349609ea1c89b89bba2d1a68a0642f1dd12d86e73cb", + ), + StarkCurve::from_affine_hex_string( + "0x042913c4376deaeb58c556a8828d17a9bd6f81fe5bff018b378934c134a9f8df", + "0x0644256a32e89515af6bcc9902051ea5df0c8c8777cc73a86ecb4a13816eb764", + ), + StarkCurve::from_affine_hex_string( + "0x0273d3003dec5e98d9f965c4f1680fb0c68111a2e3fd6863ce53087fe65af0ed", + "0x0531ea6686322bb17a41acb26b45c498d34e9d15eee45e883790b82b38b7de96", + ), + StarkCurve::from_affine_hex_string( + "0x057ef83d7d570a9140bccf0cb23d0f9adb75c4fc23411bef91e15b22a22a9931", + "0x02d0bd457ceee3f2bedee242ee3a4e1f507679c56ec68864ec8580ce81c7fb93", + ), + StarkCurve::from_affine_hex_string( + "0x0544c0b2c2893b4e67fb034cef9367daa8aa2e82f19a80ec0690328e12a06f46", + "0x00a3d91100884e2df807b1c6362f5092beb732576d4b462f1e42472ecd135e94", + ), + StarkCurve::from_affine_hex_string( + "0x00904eeedf44da63610bf1987feef89d79ea936052ecca1b471b3710e56d6d04", + "0x07056ef600b82464518b30d0e80f1f787c9ebb35497f5c366cc2015a7e5a0d4e", + ), + StarkCurve::from_affine_hex_string( + "0x03e69b16cd25ad9345a3776d464b2038c0795c119f624f1feee6bdda1f1dd8dd", + "0x071121b1c8b054a6379cf436bf8690ab5b9a1ad4e1d7c8f8d9d3720fc82de359", + ), + StarkCurve::from_affine_hex_string( + "0x0381fce0a606184fe957de3fc04185f184446b309569696a1b1e879ba3f9fa4a", + "0x02a7d4a0220a4b8741192f06d8e2b16bc321c19f787f2235334c6c9c60a81cab", + ), + StarkCurve::from_affine_hex_string( + "0x0273e82a15f395ddf2489a95685bec8bac62c4b459d1b28987d3cb27e4bc9128", + "0x0653375b48a4cf5d5b101c9ef533039bedce5dbeef3f59e8f168bdc99b06ca5f", + ), + StarkCurve::from_affine_hex_string( + "0x03006c9e7fc6a553d8eb4e8a47ce9f10d1a39576ac255ae9e0a4ce3869e76212", + "0x065fe9e2ef2aae608be309332d464f57e28f1df5de1a6a519751b056971f932e", + ), + StarkCurve::from_affine_hex_string( + "0x049e5a6c45b8d82b9d7cfa292b542afacc01cebb5408e3e042d5cd438968265c", + "0x079f12098047b9560274a04fa94ad01c52782cd45fbf78036c6ffa7ac5afd819", + ), + StarkCurve::from_affine_hex_string( + "0x05e8f384c8a4607fbe9789fcc52d54249d304d698562597d114c1d81452d3dee", + "0x03c8bc78066b5d947dc1e405e326ee55ea606c7988f666748d259850fa259a22", + ), + StarkCurve::from_affine_hex_string( + "0x036f4e45b4a817a313dfa20d99c9f212bf5e6cb4d6e3e9fe77501b79b95c47b4", + "0x052443861f81ee35d1f4c5ee727cf2ccfe376cf6c28725af939bf82f5e37a0b9", + ), + StarkCurve::from_affine_hex_string( + "0x02d8ca29c488b43b6a00a59ed65fd2ffd8d13f81767f745b57f267af97a5d95c", + "0x0436e84f52329c4adb73142f419fe6da804bd8920ee1910ede5b00255c818102", + ), + StarkCurve::from_affine_hex_string( + "0x06ad159b6ad14621711c17b577235107d2db5c6a8a6c1b1f4fe172bce0cfabbc", + "0x07164bd8e0a0c41919c90e0a91a7f52399bbd0bbcfddea5e9580c06daf7831ba", + ), + StarkCurve::from_affine_hex_string( + "0x07841b2102e9aa103fb53a642b3e167b21113ea44751ab38e0b5ef8312654db9", + "0x071bf5c8308fcf9c4a7847494cd9bdd946fddf7d3a37e8bb0b201ff2343deb8e", + ), + StarkCurve::from_affine_hex_string( + "0x008f4137f8cb223a377efb244ce5f9ceac155212f8e9fbcbf1cd34904a6c5db9", + "0x01487ce95f025febd74347e8405be27da5e36f84f39580688ed7d5392a714651", + ), + StarkCurve::from_affine_hex_string( + "0x068ec1b3226d4f91400b325c86730a882a2326cb5574fcb54e05663ace637581", + "0x05ba3ed46f0741eb85dcd6e9aae4e418d5e761398415f7d9b7a4efa11b62834d", + ), + StarkCurve::from_affine_hex_string( + "0x033c828201a063327834d4d59d7b99552c26d0d7c7f19d60d4dc499f96818c41", + "0x0442c4de6d70c4779eb065e1aae7543e67c70ea34606db0810d9d04b83947d0a", + ), + StarkCurve::from_affine_hex_string( + "0x07cdcb994fb12c4273e59e19f4937ce556df37feab2f60167e197fc8bba4dd10", + "0x002907a8af1319403426cf33cb0d467afa70cc70fe87ff3d2e16357c9df55d5d", + ), + StarkCurve::from_affine_hex_string( + "0x06621db2707aebfd207c1b9b5a2bb0d1624ff3bdae0d73884269d1491830e7d4", + "0x025a4633b141e6160bfe93567fe5043e75ee1bb5128784ae75d3022258e73904", + ), + StarkCurve::from_affine_hex_string( + "0x027baf81c94831c602e61e587f2cbf2962cfad26d40f4d12eec66c672698f867", + "0x078f085f78b9aeb4d3764f89fb13e82ca4fc0e8272e68f849d2f7984e9cfb273", + ), + StarkCurve::from_affine_hex_string( + "0x074a608cce56959affd8eff7e08b35d315440dc3b6fc4354860625749b700094", + "0x038c5d824438bf5c8b43cbb05c3517d2fbcef8935542228397ce8772ae894e17", + ), + StarkCurve::from_affine_hex_string( + "0x040f68027420c11e3ade9aae041978dc18081c4f94943463aac92d887f922a62", + "0x0499c6062594a6c7e21a3cb91ea451813393bff365a27a08f1a515439b83cf42", + ), + StarkCurve::from_affine_hex_string( + "0x06ce77a50d038b222634e87948df0590b79d66087b01e42b9b6d8fa30ebb1465", + "0x035f5c46bb1be8555a93f155a174d54ec048c2ac8676e7c743054ddc52709d37", + ), + StarkCurve::from_affine_hex_string( + "0x00736c2ede8fc02ab8815c5cad23261530a22e299427c9fd02d2ade08eda86ce", + "0x07957d7cb14c9a2dbcb29e1e4fcc17b30ee39624a0cb68cdafbcde1a2be5f0a2", + ), + StarkCurve::from_affine_hex_string( + "0x0604f8b9f2dacb13d569262864063c2d4bb2b2cd716db6eeb2b1eeabc57746f6", + "0x068c6799e24f3b44eec3049973445174727a66970f1614a782efa2b91ab1e457", + ), + StarkCurve::from_affine_hex_string( + "0x0777b0a8d908bd7e8bf654b59908778171e39eb78925c86e1ca92881fb006248", + "0x03bb8d2b69e24fe4ae7a56b1c7bef85c5da3f35d00c6b478ae808ffebcca3efb", + ), + StarkCurve::from_affine_hex_string( + "0x0575aab8d6745a981572baa6b27cd2599dc9adbd100c130ae2d12aa96d1c05b8", + "0x078d9e6e0da2e4ba68a36d9e1e9b00f7751b2e26aca93a2abaff048c3f538342", + ), + StarkCurve::from_affine_hex_string( + "0x06b9099675f39dd198e5095f78bfa64f80dcbc8c4ac95e9af535a3856bcfa80d", + "0x077df7ac8fb836df2dcb099bdb8d2b1d5f7344b47a70c9cf040175f41bf80e50", + ), + StarkCurve::from_affine_hex_string( + "0x073d620f3bfe77f672943d448d7dc05327adf64b8e7af50039c469d7f7c994c4", + "0x04859deb36eaf0c802f0d1514602368143a33ec6ce8fd55248b59025debc6afb", + ), + StarkCurve::from_affine_hex_string( + "0x03243094da07edb8466fe2146c1abbc5b8e7cf95f40fcd0c650204c288e0a5d2", + "0x048f594f9edb6710658ad3810ad7a70f2928f3bd4eb40128a2a5d23d367a89bb", + ), + StarkCurve::from_affine_hex_string( + "0x07c2ac93d02652c7d72461dba1ccaab48240e230814624ac3ca2bc5e7a9f943c", + "0x0728d95900302a5e8fca52a56f5922eecd1282a1ed5d1ed381dbc299f9303509", + ), + StarkCurve::from_affine_hex_string( + "0x01e10190de36549f56aef2f28c49727f29fdc6e73c467f6d779214bcc79abb71", + "0x019dd2b7f4398b9927a3a54d5576642532270358d78eb2e0d38dd694ba8fefe0", + ), + StarkCurve::from_affine_hex_string( + "0x043d8c30ff16f3bb40143b41e90b924a973895aaeb7dfb784639bd3ac9281aba", + "0x0401c67318ce44802707746c58931d20b82a74339ee59dee44dd7950555a3f27", + ), + StarkCurve::from_affine_hex_string( + "0x05d53add964c98248725920057e77b533a942231895beb322346847efa23ca87", + "0x02f2414ea6d9d8460c23e443592a682cedeaa0eb25a027e28dfe536f923b4e99", + ), + StarkCurve::from_affine_hex_string( + "0x007a24b85593c3c9b8484f1624240804f302b110e0e90ad67343e786632ed595", + "0x02b65319c91ea4315500bb235eb1432640ab8a258d6f262125eec8003bcce754", + ), + StarkCurve::from_affine_hex_string( + "0x041c5492d3fbc9798e05d36f119698a99ac1e22a57abd71e8539b17a6bb61ef1", + "0x031f01bb7cdd4487d730ca579e1d1cfe29bf47fcda5e3f243f7e09c86277895f", + ), + StarkCurve::from_affine_hex_string( + "0x003fd2bcd1c89d706a3647fbd354097f09c76636e93ae504973f944d8fc3bcc1", + "0x0677ef842cf5eb2444941f527abec567725e469469192354ad509a26ebb3d0e0", + ), + StarkCurve::from_affine_hex_string( + "0x039222ea924ac17b533c72ffb2c47ffdc11d6a7f7c70fbde3a10fb0b8f35eb2f", + "0x020dc4bd1089019bc1d7379b4feb3eae6eb5af59e9f253845da9fd633057e952", + ), + StarkCurve::from_affine_hex_string( + "0x00058e8f3c2429d8dbaf94ec77a44983cfd2037d2dd2fd2578879a9d1ea8a81b", + "0x015f742fe4d87d7d11bbb72f21ccc8eea1003679fb2a0e633af4523982ba879f", + ), + StarkCurve::from_affine_hex_string( + "0x00326f58994e1347f62e4102183215b5db956378d2f61f14aba4dec94577f53c", + "0x007a03284c296003bbe05178a1d82efdb7b8125511d63e20e50aed789c2e52e1", + ), + StarkCurve::from_affine_hex_string( + "0x02ef3a8d8709c50fe7f607c521b28a717ee680318d92249e39d191813ba84862", + "0x0657e7807042474cffb4d36623584b64dec4040f327846f6489dd0f923be66c1", + ), + StarkCurve::from_affine_hex_string( + "0x02f5adda5b6e74a339dbd6d433065146f7c987bdbea8dbd647e7f33215492e76", + "0x07e4a3cebbf3d4e2becbe1d5da42c11704f922f5fdd35519c5cf037a234c6dd2", + ), + StarkCurve::from_affine_hex_string( + "0x03a0a41e20690f89c04364b9ea4cef27780b946881c2a56d2ab05d5e7b67a332", + "0x0062975a106b472b87e9babd70d286527ae0ae02647b1afb52c290be1dc49243", + ), + StarkCurve::from_affine_hex_string( + "0x053aa8939c74d4ee58f03bc88bace5a45c7bfcf27466201da05dc6723a5f5632", + "0x02e32535ca7732904a048183247b04b426ecf9b39fc393a9cebe92fb1dc7a7f1", + ), + StarkCurve::from_affine_hex_string( + "0x033622fc5febd7a1733cae0368bd6013ac3a62917157d83cbbb2f1be2d77dc36", + "0x01dcba95e11cf5b194ec71772017b43b8784c5170c60e126b745ff08721e1b8a", + ), + StarkCurve::from_affine_hex_string( + "0x0776b06bda00fe3fda9bcf07b015596bea0e2a7db0fbad721789ca5a2585957b", + "0x025fef87e5581035d3c88d356ab525fb0fc67bcee59223c44f12931c5e66632e", + ), + StarkCurve::from_affine_hex_string( + "0x05c70f72bd29b783054b7b73650cd20a8f4328e9c659de01ba53eb1cbbc0f9c2", + "0x0300f816ed54b252b912a0006a969d1dc6d626f85268c315ca3bd6800b85bdf1", + ), + StarkCurve::from_affine_hex_string( + "0x045735416545ebf55ab8268ded26ca46aac19cd8625767196e49f98280d1cda2", + "0x04e10fc036f3de8b0dd1a34e879aca662f650e7a89d82baa059e2345c8e2faa2", + ), + StarkCurve::from_affine_hex_string( + "0x017e15c79671804de5a83edba2bae7b79290c3af1589353be2dde9846badf248", + "0x05d2863f56bd6a8c0c65bb714c0078671aeefc7db6ec7f4f664b79b057907253", + ), + StarkCurve::from_affine_hex_string( + "0x0036df455cf7f35ac5e5c720802de319a6fb8ffa32e921782d4557eecc9a9b8c", + "0x00f8984ccd5855a2e87ce2e0a34ae1167d4b16e45f558cfcba9803d85022545f", + ), + StarkCurve::from_affine_hex_string( + "0x011cdbd6637bfe390cdad49b8984c26631dbe1da4eaa3f6ac34c85c90cd8f2d2", + "0x07e879252012298c57672e058648ddadf18f55629e471948e50bccd156e33cac", + ), + StarkCurve::from_affine_hex_string( + "0x06cee1a03145e93b3e826e6067005f09c06099c98198c91c222407ba5c8c132e", + "0x000beaecad1274e7c6e5476a100c271aa1a6f86ee5a9fa5c2f26124d5886fa63", + ), + StarkCurve::from_affine_hex_string( + "0x03ec659b8175e1be1bd5a252108714776b813e330393f587814f5f1f32a73332", + "0x0529a5cf9f8c237ae69a94217d173c8d19c156952041f5c980da557990863fa7", + ), + StarkCurve::from_affine_hex_string( + "0x060bdc9ac2d8e1cd3c90486fe917f9f977065d431ddbd8123b4ad4f45bb44555", + "0x06ba39632d53507829f72392e551da1f4191775f3c0696c323b73047c15f8cb8", + ), + StarkCurve::from_affine_hex_string( + "0x03d66ec5963d0c534d4139c8cef2e1ac48b3e7965fafabf58be26f903318af4e", + "0x03d3f2de7a95f59b683725ee6283cbaf31f97c4b600df9a4621413223a468740", + ), + StarkCurve::from_affine_hex_string( + "0x07b23cab6b512634d1c2e565331bb403b350d5ed7a5e22c1385cdd960905de80", + "0x0240a1a7714af6116b0d1505c58753560d4b16166e0ffc5027b89737cb6bcca2", + ), + StarkCurve::from_affine_hex_string( + "0x008a601282f8873dd487930f20093207fbc902ec8d5dedc87f834b4db3b757fb", + "0x002f77d4d1ab812fed8535221975b965c3fcbac91bb93e4450492d9d4fa227e5", + ), + StarkCurve::from_affine_hex_string( + "0x0030def56bd4e29132972aec831407eaf099e0626d4fe5eb1723085aa0050d54", + "0x015aa92072a2db3dbe4de580e1d99705d51bf89be0956a79bddf441b93dc3a9b", + ), + StarkCurve::from_affine_hex_string( + "0x007fb38ace8e0932fac2ea0d3eb676db8d684db1817e2e4d59da7996ce398b4a", + "0x068f92bd5768cdd4710249f9d49ef1d5654e497b9a4ba10bd2971366d83fb400", + ), + StarkCurve::from_affine_hex_string( + "0x076ba0551c2dab7a567a2aff9eea6fd178282a2aa011dadfb48eee3f10153879", + "0x0742f4e18972603a52f4c680c58a661af340c934fcc767a9837a3bc4a487694a", + ), + StarkCurve::from_affine_hex_string( + "0x01e6a1cf2f702498da2360a66c82cc9e46c234ef3238dec2c8dc79ee3e43b51c", + "0x07ec1a1a703eea055b94034b40b4ddaefed7ab5324c5c7d3fe2413cfb4d2bd9b", + ), + StarkCurve::from_affine_hex_string( + "0x0628bec0e634d99426ee04faeaa6f02a924fc9f91a8d757c2feaf7e2e47a0c3a", + "0x02121fe07a837c17ec63fb0edf211cd04434cd8558a9dfc6b621fe5cf6738612", + ), + StarkCurve::from_affine_hex_string( + "0x05f3dcbb1dabbcb0aa7a83fe921094fd3ea724778e17206c879d5faccc49c207", + "0x0623b1886d63143476de67c901123518c650b157cc76e0c674eda5b7242f65b8", + ), + StarkCurve::from_affine_hex_string( + "0x063004023c608a28476b50569b4413c2e2714f53e329f9a7eeb50d64788c60f0", + "0x056631a9f9131f416d1f724ff0a9e2da06228447221ca46eb844414c0c222d02", + ), + StarkCurve::from_affine_hex_string( + "0x0350a8fb91b446f8c813204f9185f1a5fd2c204bd2f5325a43291a0bb78e7cb7", + "0x00b52ed1494be6a55355674fe4068c3b054bbbac93eefb99e7f6215540a65ce5", + ), + StarkCurve::from_affine_hex_string( + "0x070945db4cfb76ba070207661b5f37ce68480d5ffb6b18aac313b985e6ff75b5", + "0x07e4baae4279d55e27c7c1932bfd235eda3c6e90e93374bd6d66e439669e38cc", + ), + StarkCurve::from_affine_hex_string( + "0x01c4a49314d6b4969cdd142c76ceb7682bfb868ace7f7568b0fc8635bda5a9fb", + "0x05fc0519f1f4cc10b5771312458748c036313b87707ed0540026ac64a5955aa9", + ), + StarkCurve::from_affine_hex_string( + "0x03073c95d08d3b97caea5f0be16b2789bee766f76b7e5499f8ce8f96abb0f344", + "0x052a8974b4eb9a1f6a0ae2c83cb4715bf18d73f057255fcb3f63b74f7e78f590", + ), + StarkCurve::from_affine_hex_string( + "0x02f493140db59436dd1de2ddb348643d308d886ee033ae676b9d3fb50f474d6f", + "0x025492d5539b3d34a8c5d394118810cd7646337f577695874e972ca121efc474", + ), + StarkCurve::from_affine_hex_string( + "0x044485b16d597a5de3604df6f7ed7e00b8aeef9e7e8dea8688255153b8bb16aa", + "0x06cccb0ba170123266f24b5d93a744397dc2c44820edc4f8f5b9a0f5c9b3b940", + ), + StarkCurve::from_affine_hex_string( + "0x07b88e5bda35c3ddc0bb34cbc84aed39780c2364b34b892533c16e05bffe93b2", + "0x04b04900b29083f981256ca48bdb0d344971f5ed11baadb8ee537e1d45a8e51a", + ), + StarkCurve::from_affine_hex_string( + "0x06155b935a4d5e3756f8bdf2369c083d6cc7cb6fe96e511123626c4e21c07e1a", + "0x039b3ac9955320dc6fef13891942d5c89a7f0ac3f299efdd13e9e8d4575cc8e6", + ), + StarkCurve::from_affine_hex_string( + "0x02ab492f3cde03f2ceb134101cbf28faeff2c1f246699bc2d481c2c73d208fbe", + "0x04e512794f963776dabe762a73fa7ce55d196ec7e6f244a87a0d70af51f2093b", + ), + StarkCurve::from_affine_hex_string( + "0x07618f77b7b32d512688dd62e0b48231d9574c6361e8be353a7dc04f7c3a115e", + "0x078ffcd16d80636381ca231aae70d99c9e20298b4f5388fd823ea9fa2b8ddfd9", + ), + StarkCurve::from_affine_hex_string( + "0x02c105d843cf533acf8c46b48b18fe28b9d5e8ecac1063ed424adff044c39c12", + "0x03faae6ae39fc772e2624729e54af7e2e96cce9fa7f970e322618755a8d119ee", + ), + StarkCurve::from_affine_hex_string( + "0x0427b2be45144732c4187dfa89ea2949ad626a171680b0fc2ed177bc44637e00", + "0x0391543793f251d168c54851d8dc2abff460c1a4b2614f343ec153ad57f75f9a", + ), + StarkCurve::from_affine_hex_string( + "0x0723624f9a8581a0c71d59a53bef2509c5f57757d724081e31c8ffb895944af8", + "0x036c2421cef47f30e195a15bf1f74306af89242845189519114e30465af95ea7", + ), + StarkCurve::from_affine_hex_string( + "0x03e38dbf68eb9aea4554097eb81707107df9ef7e3c7120c0be6d4864baa87144", + "0x000a8ac8a044e150a92e1edd7d79b26e9b2c0658d359a0bc9ebdc442f9b7da2c", + ), + StarkCurve::from_affine_hex_string( + "0x01ef4d04b6d7492ac32ede99c9fb5c081037a1522a49260a9b7bda4bdf4b9504", + "0x07468fb23e2859b8e9d975c649d9316e1691d3bb52e822c0378eac3aaeb2cb70", + ), + StarkCurve::from_affine_hex_string( + "0x03aabf64df75e14a762df0d1ffbc359ada60c325c9aeb0c20251d6dc47f30f38", + "0x02aedbc55f0361cba2fe7d850f5da78257b102004041f6f129ec9942dd373d1b", + ), + StarkCurve::from_affine_hex_string( + "0x07dcec9fd4895655868db3cdb8bab0ddba17ec37eb10c2a7791edb78f175fb51", + "0x045bba291fce13695216fdea4a3311ddc61f9a19a7598fda2472fcde1a7266f2", + ), + StarkCurve::from_affine_hex_string( + "0x07dc82fee1ef95cf5b3720fcc07f63246654bfe39762627839da40e51c75654d", + "0x04c0ccdd70955da74558de20c88352df8a02aa97e4d5971c500e884740a8cb62", + ), + StarkCurve::from_affine_hex_string( + "0x07fa5d460dc10cbb418b444d9bde97e92c70a99a222b99f244dccee7e62cc04c", + "0x0636163901baa5b7576c38c43407af578b8c4607e01e86011ae2dde587a89f84", + ), + StarkCurve::from_affine_hex_string( + "0x049383ff501004b4304c44c4cdb77cdff09b98327fbf5e7d816c0ee3124ea36e", + "0x00dba84f57ee6993287afaf2c4383805071559cd35e50f9153ac415c1f0850b5", + ), + StarkCurve::from_affine_hex_string( + "0x0758930d46006623a756c89bd0cc378f6a3c1f43c9a0edbb42274c35e75c16d2", + "0x01d74dd9f81c2fec811b8cbd6168a745b0a111932b2a345265ef2853b50b6245", + ), + StarkCurve::from_affine_hex_string( + "0x0201e3448efabd6295ada494cc25c13bf75b4abff8dc1dbc5159c839cc67f54f", + "0x01cf540c5874558e0555fb5ddf0405e85acd0acac48ad3059ac04b22a645b2ae", + ), + StarkCurve::from_affine_hex_string( + "0x015f222b27045576cded582cced08fc2b19f5b4d57f8e13855485d8e33a40ce0", + "0x02c0e54e64666bb76eda7abb40305d64e4ca8bb61704a571469983963c9c94b3", + ), + StarkCurve::from_affine_hex_string( + "0x00edf543dbdfe6ddcbafe5841f3699be7b08eac1d1c8df2e02b3a05a10ef6f69", + "0x061effeae5e5858b9643c50dd93bb0683abaa87356998b9c588d8bf1b1c19432", + ), + StarkCurve::from_affine_hex_string( + "0x07332ee0626b044d664ef228f8cb84df7c643e52f6a2591ae1c9007ad61ec16e", + "0x0229bd8e630572cbdee54283234cf3e9f060e6382f99943bf234119d47b54470", + ), + StarkCurve::from_affine_hex_string( + "0x0431a7fe6753d9e82afb116dd16df51a2b91722c875686593515ed96bc623539", + "0x07815bf5a34e5751d4cc6ecda8277e5175c9d131c8ed525d8ae349df2add1ce6", + ), + StarkCurve::from_affine_hex_string( + "0x01f23b9ce4093965a57acb732e63fc722e846bb9979b0c5ee848f97bb16bec2f", + "0x024fb68e0c8fe249b7858e230c12ad999cc8ab828c68412f752a834481afdf0e", + ), + StarkCurve::from_affine_hex_string( + "0x040f5914ade7ded6b8febb5129570039b6354a78c631b17ad1a23b62cfe62c6e", + "0x01eaa5e13d4d91e4d7106084878134eace23febfeef9c471f22b5bbd7889d599", + ), + StarkCurve::from_affine_hex_string( + "0x003996f47efd51bfb012758dda84079852638f6119e35be0c02e310033a78319", + "0x032c2e9b7ec376ea5b73fcbc3f355c176bf91af7e6bc52d7d76569399dbdeb49", + ), + StarkCurve::from_affine_hex_string( + "0x049d6443aef8d3c0718745cc1281542b154dfdf02fedfc3cb500e0baa06b62d9", + "0x01fedf6cd7bdaf6f9a0d6633969a217d2e788565dfbcd11e7764047c4c87c937", + ), + StarkCurve::from_affine_hex_string( + "0x021bef5400c8f0a3818adcc18e195c615ddd6378608212b8f402de78befb233c", + "0x036fa036cd7d5476a0d14547c369397c22557df229f413ff38cef2644e0cf35d", + ), + StarkCurve::from_affine_hex_string( + "0x07dd794ae4a6cb6b03c006cab6591be079f5db4f19279192e5ea7b3b7b3411d6", + "0x0637128fe2ada86f5b4ce6a72647f3b48b3a861f09610e2750c7c3ff9cf1a25d", + ), + StarkCurve::from_affine_hex_string( + "0x078a16ef803aa20a075bb2f66c61bb2dae5698bebb94a0995fa74c3d53de1614", + "0x0246d588b68edb6fed96c128349908c42dcd64c46341b205e79f4aed9b5d3675", + ), + StarkCurve::from_affine_hex_string( + "0x06e1933939bd03b67bba753cc0cbe7d2f25bad68c993887ef8c9e2fcd59b0647", + "0x0599413f7c204a11a5ce315eab11299ab7326603412bb00bc1c59ff75a37d6b4", + ), + StarkCurve::from_affine_hex_string( + "0x0400daabdc3decd249c4a0fa0c83d39c217111258d7a7fb5244984e38f5f57f9", + "0x0290a80b6a7cba1124f4b32a9b51730b4c54b0ddfa57cd4e0de72a93aeb291bc", + ), + StarkCurve::from_affine_hex_string( + "0x04a79957a5a1888ad063b51c69565a2b48e8eb917183e220a1c8d3374526d30e", + "0x01f092de0e069bba7fc5386e2e9a114c1618f88c4b95e220cd35ffe96f99fcad", + ), + StarkCurve::from_affine_hex_string( + "0x053ecf3179881cef98202f4d449c2a4c0aaed4d532990820eae84ebcd9c2263b", + "0x041055cbff3fa5dc97b11c50987eca28de21e098bfd2e550d93bad5bbe661250", + ), + StarkCurve::from_affine_hex_string( + "0x056fbcda667a4b4cbd34e63291391f172a894115a73e0e5d2d2149c7e19b9b88", + "0x01961501af46d484a0a40b8f6b83b1a5e4bd3d8cbcdb8c1a09c4bc2765628aa3", + ), + StarkCurve::from_affine_hex_string( + "0x055cf2c8ccfcb88f862cd59dbb4659c79baea9f9e2c25b9233eec8e3eab1df92", + "0x03bffaab9bccf8c6ea96e1f19e59c267263820881cc005b0f9a3de6a8e980bb5", + ), + StarkCurve::from_affine_hex_string( + "0x03148aa3df9ece39aca84f59489f2710522216f14be6055ee0027529d1d55e2d", + "0x0617e9a52a92975db0ba1977f71116f7058a0d31b869ac7f3ee2fd80b0c5100c", + ), + StarkCurve::from_affine_hex_string( + "0x05c74caef872e1514f2404690b5c38e909aecfe42312e4da88f31d1b5564456a", + "0x04d1b42f35aa9486cbf8e522801ee432d228b71eb84a6de2d5c1988671754ab9", + ), + StarkCurve::from_affine_hex_string( + "0x0391cc66116225a1a583f6de58c536058afa2581617c09af0c22af9d987d71db", + "0x007e05e6295d5f1819526a2ea4f1257819eb3ea1fb29ce5db70d05209c67d3a6", + ), + StarkCurve::from_affine_hex_string( + "0x02894c5075f1d8e2de65f9ce539c7ac50743b33587f9580ee2d5003b936c7a92", + "0x05c36e6852aa35f10a22bdd6ca2b0c9d201359885dab6ed43bfd5f9f937eae9b", + ), + StarkCurve::from_affine_hex_string( + "0x03543fd025a9322c91498be81ec250464f23fa087c0a587c8d99e28db32a7ae8", + "0x02ed30353c16754135fe543d9714643a2ae8ffe0b3b85e659ccac1afdfb154b4", + ), + StarkCurve::from_affine_hex_string( + "0x021bedcb4de7dff71d1c77c58ae190abe603bd156f4d7daa139677d874f7dd40", + "0x072f99f04058a67ff13e3c58baac805a9bd93a2cac4fe1781d5d94d46b5212d3", + ), + StarkCurve::from_affine_hex_string( + "0x062e05fdb23c313d3604bd41e19ed5b37aa311bd1e49fd9e4df6d3ddfb74edd7", + "0x02e62c83217f60c85de77a36c2396ff56ce130cadcb56f8791ef4839c9cdbb7b", + ), + StarkCurve::from_affine_hex_string( + "0x0113c38415f18fc5674526e0da14ad4bccb02dc7a537c721e65b2a044aba4678", + "0x005610233a56e9ed61fc20d4ba7d52bb5edb821a60aae36e7f617bf455a4c28b", + ), + StarkCurve::from_affine_hex_string( + "0x05c1188e72384160ae39d07328346cda4f6c12d227448e6236f04dc971625287", + "0x01643006eb3a3bc6aafd5f685cf054f2a572e6ca58c0118bcec0b833741f116d", + ), + StarkCurve::from_affine_hex_string( + "0x03f72efc93c9b71adc4c51d8fc69d3940b20d08733af2b7d05140fdb1d1c1004", + "0x07399259987c8f4ebfab46e522380707e58427d3962ee0c2a91760813f76d232", + ), + StarkCurve::from_affine_hex_string( + "0x061d180f9282787e8599005d2ecd62822d304ea4905ec9c3240c26911433a1e7", + "0x07097c017d169259c2973e6ad150ab2eceb164c38b10b880b8a989f819f971a1", + ), + StarkCurve::from_affine_hex_string( + "0x003129b34c03c51aa8f611e91d5cfcc9bd3ef108ee66e6d3ee35a0e0e50055bb", + "0x0563b18b5650085efb4cf179a029e6afff27b1d3091cd28eaa68d24fa1f801c6", + ), + StarkCurve::from_affine_hex_string( + "0x03ef215d16a59a465b24ef292f33ede9a1b3603c9bc0910a7dcc6d1283c99aa5", + "0x0278d2edd231df071a2cfae0009c2054a0f77e789d2baae027a0ebaa19a38801", + ), + StarkCurve::from_affine_hex_string( + "0x053fe7fb2ae8ea282fc7c316794a94b5a97bc9ebdf0b8e010104aba052739fd6", + "0x03763cc93d8d1a641208f8ffa49e421b15436253d5db5cfeaf420c076bdcb4dc", + ), + StarkCurve::from_affine_hex_string( + "0x07c972b2e113187705425a63ec776bfbcd026fcfd6f9dfea22cacfac71c57940", + "0x06ab379f8c7b3390dfb85554decacf2c4c315be9c5f81a81808ba9e96aa5a8bc", + ), + StarkCurve::from_affine_hex_string( + "0x016eac0f9fb4c67cf89a7fa4ee615bbe731d8edcb709a1b9b50c7d873a530f52", + "0x07ff8288b6e199ca8f316192881424a37fb080c29daa76b1f0edaccaf580a80e", + ), + StarkCurve::from_affine_hex_string( + "0x05d0f2c06196370107e11920037856235ca07e931db16aab37e0ca010628c30b", + "0x01a1713df709c2b8694d84f275d80c4fcb3dcdd6039deb2a2f4d21862644909f", + ), + StarkCurve::from_affine_hex_string( + "0x04aa276ff992d999de7f4bbfb87f5686c545528830dcb1d621fc42445d03061e", + "0x0031b2dfe0c073dff14912d41f3710d194b8c60927c165752f7c1af55b694452", + ), + StarkCurve::from_affine_hex_string( + "0x004a30043e64d178a5f158d4290518177c9c41e81f9c13a40954d5b8ea627864", + "0x06057982d4a60b7dcea50c150ff6b9a445a966af14a89c7c79ceecefa35cdf90", + ), + StarkCurve::from_affine_hex_string( + "0x043f655634b90c92ec4d9baf1bf96ed5db16b6ff318c9b624fdfaa36ecb4f386", + "0x05f3d2abc036efea68c94a23f4f3eab9119790292015152e26dc917c9445b41f", + ), + StarkCurve::from_affine_hex_string( + "0x009d6a1051eaa69ae4195d5fac4cbddc293f886ddfac0cbe15042a3181f1e9f1", + "0x02891ed5ea58c0c8900cd32ddc44cf8d424aaa94c1a58cbaad0f85c27e1850c2", + ), + StarkCurve::from_affine_hex_string( + "0x078b1ec73658f7bfd41c8270a69a1e6b429323ac047c4a53e0e879045d4c30c7", + "0x06479c010d0a214b77e33c3bff347b09ef8458f4eb9a99ab0c73449e250863fb", + ), + StarkCurve::from_affine_hex_string( + "0x01c74f51c8add189de1bb33305aca6468a2c7b8c876065840abf0bbf8e0bbab0", + "0x06e01e455fb831b59195b137e22e90282dd7b616c969c881838ed98deef29711", + ), + StarkCurve::from_affine_hex_string( + "0x075f6b6028c43ce832f65d7e8e620d43b16cba215b4b94df5b60fc24e9655ee4", + "0x035e9ccfaed2293a8b94b28de03bcb13eb64a26c831e26cc61a39b97969a2ff0", + ), + StarkCurve::from_affine_hex_string( + "0x03c6152fe093bd6316897917ec56a218640ec1b2148f21db9b14fc7a5ff362e8", + "0x06eef2df27ae7d63a28856b07b73e7aad7ca94f317201a1e675ffc6f9a1710dd", + ), + StarkCurve::from_affine_hex_string( + "0x0769c1bcf7fbf094639ac6270e308935c7abdd420db20be3ef9c924f083f7598", + "0x002f95454d140d3ef3d2527f398573fb86b98049bc4853b5723470020c591dfd", + ), + StarkCurve::from_affine_hex_string( + "0x0054e01b5fe4fd96052aad55b3f26b1d254dfc7e2525fffb9ae0a77eb8cc5579", + "0x07c3d39232ab333675b219abc766ed9b4782c840e6b046614dedb8a619696eb0", + ), + StarkCurve::from_affine_hex_string( + "0x0247d2d40015336b9cae6954d6245a7d1e913b550c43c78b0aec49102bf0728e", + "0x0421be1aec4cb3039dea78d70554d7f59dcbc6df7b2bad82266191a96eb30280", + ), + StarkCurve::from_affine_hex_string( + "0x073d64eaac7fbe52b666fab12923bb8e2a01ff3dd4953441da0183b4840da87d", + "0x066e5f63df403d34ae4350658ffb1d947ac646220e8ef8730eaea87f12d09641", + ), + StarkCurve::from_affine_hex_string( + "0x02f4e77c205fcff382538d7ec45493e8b9d72fa287ff0832e85b230a78fb51c8", + "0x0599d5a1a23ef4ec7c6b2ee60bc8592b1ec426562214fbc79f8d4a8d3bc19b93", + ), + StarkCurve::from_affine_hex_string( + "0x00d1e63f8ea8a76429cf254a6d3b668761f0dc572d4bfac4fd56d9eaf58fb6c0", + "0x02bd0a84d3908a63085824c9329a0983913006ba155b56a58eb3f9becab29c45", + ), + StarkCurve::from_affine_hex_string( + "0x064fccbbedd2913c29bc85fcc7c779b4827871cf4cd31edcd26ed1dfe946af51", + "0x030847797daef49d1d1e5da3f88d6fd8a90d75a3736bca6d09fe0e4949d8334f", + ), + StarkCurve::from_affine_hex_string( + "0x01bfa387cf795a640ae41a1ae76ce7f8a97129214cb8223f296341ded6206417", + "0x029c66c79ef035dc507e781ba2114b2cf5da8d10f412f4c406df57cdf6fb1929", + ), + StarkCurve::from_affine_hex_string( + "0x03cc0fd64500be95fa1a24172d1e2edd37f7f7a14de897693b0983049ebe9d6a", + "0x07ce0592ea04673f3432f50dc96f7f704113892516c3948cc67612f4b4b60f22", + ), + StarkCurve::from_affine_hex_string( + "0x07cb8ba4668c359e9fe675e1414dadc1b975a10dd7cfdd8f4762e207c5a05e5a", + "0x0413220916d8848b893613b714aaac5c309919e1672727b270f2b6a0fd89f062", + ), + StarkCurve::from_affine_hex_string( + "0x0681c6f30f687f86dddf187fd976163fcc17d4aa56cb752da5b87bcb6c79561d", + "0x0091313735ad18bd6608b6c3893a8f6a473aa3af9271ef472a8aebf65d01007c", + ), + StarkCurve::from_affine_hex_string( + "0x068a829db3a7838f1cf0491aca8497afa16d4fdfa33fb119d2af15b34c9c1fd2", + "0x01d21169297e9e6bae5c93904784c702d199fc079e0eb3cbd0ef599a543eca98", + ), + StarkCurve::from_affine_hex_string( + "0x030af600456837810a6460915e86e16108e476b755bbf923f3f1fc2577f6eb41", + "0x01ba0024f5eb4a683612705b6255692026978c5ffdf0d0f700c7f89451a19e24", + ), + StarkCurve::from_affine_hex_string( + "0x02d6122f2a702edd4da7385b1580796a71d13bd72be94cfb3fec01149c006c2d", + "0x070eb282fae992efa6f5915e578b640653549f23385ef3a29ab29b1b9b8ad63b", + ), + StarkCurve::from_affine_hex_string( + "0x0752fec14beaadb5ddbba6b3a17fcb86579fa588ef407fad0ea07dbb22a640d3", + "0x03feb6728eca21a1e84e8f9f23010387a53a96a1cb62d86fb37996150a1299ef", + ), + StarkCurve::from_affine_hex_string( + "0x00bfec8a42f3e09480b24243b96a91dd6def40226212f54e87ce4e9b65d82d83", + "0x00eea33bf270ccf743000e1dc1a8c3e98df9c7a1156dbfd4dfb1a491f93256f9", + ), + StarkCurve::from_affine_hex_string( + "0x063f94a92f27acde8f5ed949b459506f51d70c85bcc61a34d647264ecc53c65e", + "0x037e5dce0646ee66f4fdb93b82d54d83a054948fa7d7fa74ab6b36246fc7383e", + ), + StarkCurve::from_affine_hex_string( + "0x05002cd215b8ea16eb5b1950ec498154cc4c8ba93fc8f43dd3511190ec9adfd0", + "0x03ed5b198173b24511446cf76ae5adf844e9ad832c9f3d7867cea0a0e6a2cd39", + ), + StarkCurve::from_affine_hex_string( + "0x05ac3edefe1d8fb4b2da42a53b499fbb737384d3d283df5517e277dc7889f6f8", + "0x02ac0201990a6b3212f7f51932ebdfd34ab2568bd2b8ea9b6903667ec090d00b", + ), + StarkCurve::from_affine_hex_string( + "0x05d3f93a44bd40cf71a66eff9d211e097a7e8fba96dffdf38df77fdc2bcd22a6", + "0x0049626bd838fadf2fef43fb7b62c11ebc88ebdbdb593db6e176b5a426f38cc2", + ), + StarkCurve::from_affine_hex_string( + "0x00d6aa909287a2f05b9528690c741702c4c5f4d486c19a46c38215f52ef79c7b", + "0x05ebe1128dd81093df4aca0df365d58adab848d1be1a94b95eeb649afd66a018", + ), + StarkCurve::from_affine_hex_string( + "0x0303106fa10743784a87dc98659eeec97fca5cd8333a88c321724f3b5f62141f", + "0x05c80313575f5650cfbd3deb5fc17c539823a9a35f962ba7c1d1d3cc6a270123", + ), + StarkCurve::from_affine_hex_string( + "0x02ad41d905faecdb1eddcffbff6e5ccb5401d4deaec696c2db7ec07b4a5b5355", + "0x00657efe28e730a5680103b3276c96fdca1c748eef347f921395a43c6d8ecba5", + ), + StarkCurve::from_affine_hex_string( + "0x00b7f3cb92b3e41c358427228d450317117caf62b4e6164094c6a24f6a090c2e", + "0x03251ed3ea7b2922cb76299f91cea3a7e0cc195e167475a98b8967a33d7ae793", + ), + StarkCurve::from_affine_hex_string( + "0x060ccf33af2f1a772c99f5f394aece266ba24e13f222e99563d3b3eff5e2a64e", + "0x00b0e4910879f0c126d9d6733b09bef4864da97c921e03a4ea22ba8a99bc094a", + ), + StarkCurve::from_affine_hex_string( + "0x05c124f6159a945cb472819eab5854349b38a9713ec12601bbed025a0ea13ee0", + "0x00e9635da05d681fd02efdd93c9d19872ee753914beb7e081b4b70d83a2ab89f", + ), + StarkCurve::from_affine_hex_string( + "0x05a7225cff28925c3e9ece7165cb9df7fb2dd6a8a6f282c7711f4d76a9e67890", + "0x07d38d7dd92f4f94a4385c1cf5faa90badcfa07e2cb5e7d47dae8f1385fcf349", + ), + StarkCurve::from_affine_hex_string( + "0x05a6a93b6416f59a9609fe30faa0be9528b0d3db1836940f08d5583b8a13ecf9", + "0x0205fbbe8d0c66e651436868bc1933cc8ff8c881de2520c0f2ce755bf873ef98", + ), + StarkCurve::from_affine_hex_string( + "0x012866812b3053e2f7a9572bdaf5ef2b48c6fb62a0eed9ff0356df50e7d05557", + "0x06785f7eb2cd1c120e4c7167b46861d10117040a2e9f2ca86a71e9d67df90613", + ), + StarkCurve::from_affine_hex_string( + "0x0046a730d05330b1b13673cb8a1b8f45460035e4a9f1a1751cfba099c4355c1c", + "0x076fb0ec6cd16a8141cdcd875c8b2de9fce42d296072643d148ac7e7fa7472df", + ), + StarkCurve::from_affine_hex_string( + "0x012558b6af651c5b4c11d2009585a380dc1e5becc19ccde1567aafb1c000187c", + "0x06d734f3d9fd2ea0200ebaf6a359f71b8eda6eefe896944bdfcef483def43424", + ), + StarkCurve::from_affine_hex_string( + "0x04bd4380a22900bd34835e0a908eacf4b6edb61eda0cf483f9212453b37e7516", + "0x05e9551cd20d8d7ddbf4366880b7d5267385afa1966ff30da4baaf273b009d29", + ), + StarkCurve::from_affine_hex_string( + "0x0141d84640fabdb2fe42167367090bd14094bfede29c4744648324c74576c9bc", + "0x06ea252f822fb03131e4b4a7102438b456e48f1be71674ae5d786731ece37580", + ), + StarkCurve::from_affine_hex_string( + "0x02ef674cfec32daf6830ebd28be01497ec0a7281cc4d0926daba649daeaf7696", + "0x04aa2dad078b15232d6d4f8eedcdaf3e06e653b133ccb633b58f278d9dbfb9eb", + ), + StarkCurve::from_affine_hex_string( + "0x03f6e7adc7e80586249f70aa7d788c673fcfab4a9676c2a09fafbe444860c3f0", + "0x0318f9617b963cacff3707c6a0abe9819d39b6605a342fd4d8d79c42ed906739", + ), + StarkCurve::from_affine_hex_string( + "0x071f1994ad40baa2922424ae222663a64f93d8b67929e9a10f9e4c1ab19f3833", + "0x0085320fe68ec0d37cc19fdfd03589d66906ffa4046c80e1b094a85f27676346", + ), + StarkCurve::from_affine_hex_string( + "0x02adbfa2623e2d7e3ba8d03f25aed2898f523422282897249d85afa0827e57a4", + "0x02e5aee3306f7c481c74e2fb9878187ebe273bf3f15fccdd880bdbafcb15d4b6", + ), + StarkCurve::from_affine_hex_string( + "0x067104aecb75678cf182b3242a14cbd22bc3afb4c32f807d1cf362abc42339a3", + "0x04debfce01ae28a60cb2ac3b1175d5cc4feba73b8f8ee69eff1cd7c63efd079e", + ), + StarkCurve::from_affine_hex_string( + "0x050ea174fbcb611aa93a4c6a7d4a99bf7089b14b81c3193085f242f474489de6", + "0x05b15597d23a48a7c40f0e7f584f118ca2bdb38643aa70c73b090589c7e07861", + ), + StarkCurve::from_affine_hex_string( + "0x077fdcf770cc91662a012bfc8a4e8600206e623e893a95c80f8d71edd8d1d65d", + "0x079b06e6a93c598850e8dd825700549dcc20621c09dec81b9d2b4194fec325a0", + ), + StarkCurve::from_affine_hex_string( + "0x0515ecf3b03b8edb1e3a9739c8db804934dd986303ae007493130750d9b18780", + "0x073d0f68a3951301e6a3ca60173beed21948715c33781f6b58980aca2dc36788", + ), + StarkCurve::from_affine_hex_string( + "0x005d539ca6817226c667413c4ab0f5a33f3defd6816d692887a3c35ce6610853", + "0x02725d0fec176a2159ce9a375ed67e615cf2d7943eac93bedf7afe6910ce6ac9", + ), + StarkCurve::from_affine_hex_string( + "0x03e0f29b22535be8ccbe2fb1ad5df55348f94fe0f8106bbd5ab0dc9108470277", + "0x07649212d8561c4da490dd54cb8e3d6776f00af31d83eb0935da8e3f59bcf277", + ), + StarkCurve::from_affine_hex_string( + "0x05a63b1bf5232f28f808765c6be7ce1f81c52145b39f01c879fae0f4303bee61", + "0x03bc5d6df68bb6d0577bf9ae2ae59ec0e9b2dc7dd56ea179fb38a41e853db950", + ), + StarkCurve::from_affine_hex_string( + "0x0161ded55ff1087032381e6c1449704f63ad2d88df82dfc44a71890fa09b3941", + "0x0078a52e0013842037274ea75daaf8eb4afc04ccc4b07bfaf3f5ee47d165e01b", + ), + StarkCurve::from_affine_hex_string( + "0x008f244f5dc085b560077de5d796b22e4f12d2c41257afe1848b6abb51eebc09", + "0x044d58d9a4cad4a1218b3ffb76dc83a1fd8d4b110ceac30fd64c5c8cd4f36c4a", + ), + StarkCurve::from_affine_hex_string( + "0x01bfce5229c5fbff5c0f452a22317fcfcd9262f23df41840f84fe7d44cfba1a1", + "0x066b387872c00e63c73006a955d42cf49c46c5708fc9d1579b9ae38341b24a3d", + ), + StarkCurve::from_affine_hex_string( + "0x04a4185cf0b92cd9a7ef7aded90c581cb1448116c2054e7ef0943500c8365a5a", + "0x03202bb9679748781dd684caf45939874fab3233cd8a71adf5d8a3a9134e62ec", + ), + StarkCurve::from_affine_hex_string( + "0x07a9eb86764c411afaf46891c3d07b0e31679c0b5ec6e4b9371e009283502550", + "0x0668ab40f81fcb36d15c53d290a1be30c379af40bcd42dbc1b3006f78df31747", + ), + StarkCurve::from_affine_hex_string( + "0x01c4129456194ba97b0d04a4e8e0b3a0e9fe5669838912bf38184a26ca615a29", + "0x00cacbcc4b9caf170adc761e696ebd250c0cac3dc055694ab4a4aa910f49411d", + ), + StarkCurve::from_affine_hex_string( + "0x056d47dadc9cbd1dcb2ee3efcd5d4af5e6aea71df10815c68b54a14e81d11b44", + "0x047e966ba54df48e9b612a903685e0060a67e4725402e8cb4cf654e54e813a3e", + ), + StarkCurve::from_affine_hex_string( + "0x0796a911a7b9482a53c123735afad648aee1499cc2f6487ada2ba9d647cc2a4b", + "0x0333936bbe15bd2f3d29e93cb06619c1bac3c44e0bc126e36bf4b5e7ef91a09a", + ), + StarkCurve::from_affine_hex_string( + "0x051a6fe8647886b80c2d0c765aabaa46af9d347950295f342c13e4eef745c00b", + "0x03d13fdd494dc851fccf24eed224f5d84621891392787b729614779ecb98aaf5", + ), + StarkCurve::from_affine_hex_string( + "0x054f9b38a7337bc066ac9e408a8bba8a108e70de4587a3ab5c648cc65f9fc6c9", + "0x030e48863b33010841eabc4407922003041c7482e233851910dea30190d0545a", + ), + StarkCurve::from_affine_hex_string( + "0x056c1899a2e07bc45484fb1df3cbc3787ee36818e047d82a7feff84ec8459048", + "0x02aeb1600345d5ddc2f455f620593d275bc3ec218a0868700514dbf532596368", + ), + StarkCurve::from_affine_hex_string( + "0x051e6a409ea80df3009f348da5a103c419f03294836340da806d98f7bf4efd69", + "0x063c9da210b70d94c902327d8a9e1dca1851a1fedd8add1965825cab38efe707", + ), + StarkCurve::from_affine_hex_string( + "0x03436c3a0cfde8476c47db4fdd88a03ed71019b1b218fba62ab35f76eda69dd6", + "0x033a15679338e89cdca4dea0af203f2f9cca2dd32474b9563d77c6154ab59c0a", + ), + StarkCurve::from_affine_hex_string( + "0x04041125b3feba9448788a2b2038efcba719daba6092c065be6bec9358b73483", + "0x023cff0973b4814380a2a3efe021450ceea203a3114e5fb913cfae847271a2d0", + ), + StarkCurve::from_affine_hex_string( + "0x04b1c44438afd4ddf20a2cf612df2ee494ce84c7274c5529e857693e73018491", + "0x0430403bd31d8f0677e06abff7159384560f27b9622943fea1a3192f14bf40d4", + ), + StarkCurve::from_affine_hex_string( + "0x07f7281728fc2214aa1dbf13176a4624b53814734abd570eb6ef7c7e32379606", + "0x0312da47be347fb3fa2c9089b38df372560dcace2effeeacab4d96ab11567295", + ), + StarkCurve::from_affine_hex_string( + "0x0361c555ac7113411f792327d30b6da983c6eef788e64d9f23c7a30e22cf21ca", + "0x04eb51e586003211a8c37488880f172fed8189b7b00838ddd72d544cda7a5a2f", + ), + StarkCurve::from_affine_hex_string( + "0x016a28884a1be8183e0d3fc0db84a9afbf47126fd3be548c2a584aaafbfa7dfe", + "0x07c3f57b3b895564ba562c1cd80b71fda6d2e611665c6ab87744f5390858fe24", + ), + StarkCurve::from_affine_hex_string( + "0x00a3afe6f17c078d41833d67a2c34357518427be4c6af71466c42927f69b7bae", + "0x069da69ba34beb77a2ebff22a4b138da6baae3387871c0455b012bf2c8f01b65", + ), + StarkCurve::from_affine_hex_string( + "0x000dbfb7e943fa7643594dc1576be3d7968eec8dc0ae4c73de0849cab07af319", + "0x01b5864ffbeccee2d2d7c6d256181d444d43cbaf5660d74e0860fe3b96d74157", + ), + StarkCurve::from_affine_hex_string( + "0x05f78a3512888b833e2a57f8c339947256cc440bc7bd86de674828370c70d3af", + "0x00012623ef4842ee9c2c2dfc744ae4750a0ef4ccde41d3ea40f4b25b6b6b7cf3", + ), + StarkCurve::from_affine_hex_string( + "0x0323339f37b327a731232a9580e79952063c7c232bd1380146d8a83c285f4b8b", + "0x04f16be1d983c7232f92cce6b9690695978d42cecc8eeb8c206e125d1098a265", + ), + StarkCurve::from_affine_hex_string( + "0x07b27fc7316e417061113fe0333def1c9145ad8faf1090fa42ed3784a500015b", + "0x0749e9081f8869237dd690bd8345319a08d29443dc0f1374d0773c3fd1b4f809", + ), + StarkCurve::from_affine_hex_string( + "0x028e902b40b9f524f5d8f1b4261f8f8cd7b3346c36439169c4d6e30f9e7c80d8", + "0x0180c44ed7a1da6d622ed86c1314d362cd8ae2a99975933bc276d0a8f9fd2837", + ), + StarkCurve::from_affine_hex_string( + "0x01832ccba1b3c179283bfcef0d97dbf8f2ff85918a318382174bd21fb4c934e5", + "0x068f34ffba795aa898fb28ba2c5d1a6cab5dc696ae807e2469f2da018e87ba2e", + ), + StarkCurve::from_affine_hex_string( + "0x05b75aac2527cfb212920c21c6ac6fbb994dbc986943a9a2c9f544a7478ab457", + "0x008b4b68a1ba77030e4d51f4820014af3b103f97992b36be2b1ce6b1b56281cd", + ), + StarkCurve::from_affine_hex_string( + "0x0120f81b50527ca7c59c113c091058b239837cffe5b97c5ea315e64516b2e7e4", + "0x00f86219c54026690183519a0cc82e41278bc0b6a1b3d110b77c4e1d19129701", + ), + StarkCurve::from_affine_hex_string( + "0x04d5dc0a06b24039c22a1247d51d46886afd4fd8bf79a4214bb8b617b27de04b", + "0x0358f66ed8796925aa063b59b8ce6936bd5587debffa8f616cabd7c2d5fb354f", + ), + StarkCurve::from_affine_hex_string( + "0x0655ec274cfad2f709cc08f0c12f28ad21e0dfd6e6fd72c1507387d62a34bf18", + "0x021c07e86c25dd9958e345c8ddadf51ee80773223c2970059ac5f43f8f1a1119", + ), + StarkCurve::from_affine_hex_string( + "0x0624d26cbaa197e104eb83cebf2adeed09a5cdad359993fe5e3529d4d0def21d", + "0x0261b7da3cfb55c788977e0d8d640e3e93ae5a325d962ce85c816d7d32cfc430", + ), + StarkCurve::from_affine_hex_string( + "0x00f24ecb7ee83a3e28dab54a330dc93d0429a7aea36412e922dce8fbff40d60d", + "0x00b043e36a258d1df1d21b0cc7be9c4dcae1bd4ed326c110e668ac23d86805a6", + ), + StarkCurve::from_affine_hex_string( + "0x02eef103e51eaade5c9e2a5455371d2ec3fb3cc17f233adbcf8f3911211d7377", + "0x04feec301ee93d99c5f5aff79f6e2ddaa5dfb7f8005afad4913168eb7843a6c1", + ), + StarkCurve::from_affine_hex_string( + "0x0686cea46b710bde1231483bfdbc700cfa3da6ecd5841c0e0c782f9ea24328ec", + "0x07eb7407aa58edd6911c7c7e8d1e03bb52ead4a2415a0c33325872ff3a521dd6", + ), + StarkCurve::from_affine_hex_string( + "0x004a2a16ab498725c5cfdf397938cabc126b02ea0bb94af16d1d86a0c0a29d17", + "0x04d0c8aa8b38acdcbc04a81fe89b20bf471146ecb16950e88b253d5dc1ea6538", + ), + StarkCurve::from_affine_hex_string( + "0x03cc071360c540c8d30fbf735901135622a6e82ce350cae5f0ad211124fe8524", + "0x06a91a8fb7257fcfe043911920acfb35f6b14d41d72f1b4720a0e0cdfceee017", + ), + StarkCurve::from_affine_hex_string( + "0x050438741d0b4354b4f0680f3e9f506d4ef54222007aacf2b66bcc8934ca3105", + "0x02470830b430da95f78448fd294d64900744bb6e8d42c51001f3a5e2b9d2464e", + ), + StarkCurve::from_affine_hex_string( + "0x03866ee1186264549df3dfcdf8705c0380c9372eef6d4081c2454d3aded1720e", + "0x0634c6d3e8eb8af652a4be73e3b613452c2213104ca875b66b4b15ee5b1716af", + ), + StarkCurve::from_affine_hex_string( + "0x05707705c184cc75c401b3da7d41a785d3592f5b58e1249252f94c149061b5f6", + "0x0544343b68822d2ec4576d757d419d5b14e6610ffa05d96cd4eb84e34cd2c106", + ), + StarkCurve::from_affine_hex_string( + "0x05ff838bb1ccc370c4d94eafc43b3e16747d3a0be73764e7b95d15331952d8af", + "0x04055d4430acf34c23dca80817012c31d36b18dce4269a4661e4fa5094ef3408", + ), + StarkCurve::from_affine_hex_string( + "0x02319db44ffed66bc077a7ad28935efd1473435b61d71f9cffedb1d13289c664", + "0x05ea7aef057b200d6d815b46f60e930278430f6cd289c11858a58746111b1c05", + ), + StarkCurve::from_affine_hex_string( + "0x01e2f16a784a0ff0fa10b345271ad0cf5a4661a186813add95d03ca59d55bf8a", + "0x01c0a95a45f91b45c10164071f9b6409422bf87e194cc5d9aae7096bc3959d88", + ), + StarkCurve::from_affine_hex_string( + "0x03a9319d4dff897c877e589fe7561b6e0e49445c81385f71021a5d7656cb180a", + "0x0036bcde128a5d354c6df8e77ee87778cebd1610daeccb1856833510ca16cf3d", + ), + StarkCurve::from_affine_hex_string( + "0x07dabc5744ff138803b884c8dbb3c8ec284b29c2e9fc571185c020f7de3a3e8f", + "0x0201751247793f1d02bb071cdd3dbc5d660dfdd5268511d870ea8f72e5a3aa59", + ), + StarkCurve::from_affine_hex_string( + "0x00cda124f56d5f16096eca01f513670b429913fa092e543b7fe55d4c05b20862", + "0x02ad28e3558feef27bd6dc1dd9f4089b26ad4d37ca1bc7c124b6470fb200c244", + ), + StarkCurve::from_affine_hex_string( + "0x0484c687cd2969a1d20a58cdfb9a60f280a473284503b1ecff5de514aaf8206b", + "0x034d44d26b7427e51a646d1b924084762f5b461685450f21d6a472de565bebd8", + ), + StarkCurve::from_affine_hex_string( + "0x0203561333771fa0fe22c4033349f7b877d15b0542a5598e81e067968768247a", + "0x02b6a533aff6e2163a36a2a89cb7415848bef48db40f952ffd380f47676707c2", + ), + StarkCurve::from_affine_hex_string( + "0x000f7573d3c3bd33c72366d7fad4b74554b3121c9fd8913b92f5062b7cd33439", + "0x00586bfae026cf7ebd5a0faadce96f4765b4d11bf8d546058889bfa177138cb1", + ), + StarkCurve::from_affine_hex_string( + "0x02ffa6cca6233695760251206fc5e34c8d3692498589478cdd3d5b09f0b7c05d", + "0x06c57d605478fa9626c4ed769554d075daa53e1a1d0bd4d94174d3bfeeb11ad6", + ), + StarkCurve::from_affine_hex_string( + "0x00ec14171ad6c6f1af8d4199060a1b1a9aa926e875dd1ad77bcb4ccc09dcc8b9", + "0x074a61d094dab9efbc87c45d9af4e2d82801f1cccf85dac70dc1cac47830903e", + ), + StarkCurve::from_affine_hex_string( + "0x05683fc827e3f80739ff1b4c9aa59a8d7b4435bf4b9f2d4651e520931b68b10e", + "0x04e04466c47e1829ccb2a487b10890f21685b0bb06dc652f829065bf88443d65", + ), + StarkCurve::from_affine_hex_string( + "0x064a48f9f8b5cee75d0346b7c9e7d88faefe607db1aff2a618898d55ad495c22", + "0x03bcdff5425b6e3cb12f9bc8d4186d73bc3785d46e2fc2017948c25cb1fd167c", + ), + StarkCurve::from_affine_hex_string( + "0x05dccf0fa46a5571f204d0b033b45f299cbb3d9f80fded57253ea4f1c64faaef", + "0x030a38e131ee8756ee5ea2a3e16618a5dbc28b5b9311308bf037ecc2039dfc7d", + ), + StarkCurve::from_affine_hex_string( + "0x02e72b8f34da0240e0fe1214a4e3965b4abd58bfad3f7a1ba50a7f3c1c5d7bab", + "0x078fc90cbd98d9159ff0d9c0230870b61a0dd89b02f874c2d6fa800ffa2306fd", + ), + StarkCurve::from_affine_hex_string( + "0x0061194b1ee46ae1522187bc944aa77fe31244dac20400d9b862bb1a92fe5cf1", + "0x015a78f5d70c02690ea43e1fa562ba469aec9051a8054d051c3670199e41b324", + ), + StarkCurve::from_affine_hex_string( + "0x00d92d4795c00c6aa4248370de90301896bf5b097ed74c0c1aff52aeabd3165f", + "0x03ecedb20e1d7040d2d5a8a95c2f854838570d7b01fb5c85de04e48f1ef30d01", + ), + StarkCurve::from_affine_hex_string( + "0x034ca6a734fbf11e86b55a5548ed2c64f92778155b9bf27808563f72168eb448", + "0x05d097dc68e2c4ec523779154d78720a3c641f7a6d5c0a570c40baceaf0ece59", + ), + StarkCurve::from_affine_hex_string( + "0x040b34d454a8023bc6fb93493bdd2c88451ecb52a651a67499250f76be4ddcb1", + "0x0541c99ecc0ebca3fc9e53003399dc5631574a869762ca7f56a6c2be78548c39", + ), + StarkCurve::from_affine_hex_string( + "0x00bf9df8fd600cd47853c0cb8d380a6aebed73a3cb60f0669f5a55aa0e661585", + "0x071e469402547d53f2e851686f7c30c7c5ff5f8355f26d2f9b390fc495ed4680", + ), + StarkCurve::from_affine_hex_string( + "0x06fd3b29168bad0f36b53f5d1a6f13bdd618b4dc3f414f0a37ee6b999328ffc8", + "0x06c18bb0c5fac9856a8bd160f1e7d51ec32974c0582e52880de2364412c5ebaa", + ), + StarkCurve::from_affine_hex_string( + "0x057b0a2eaebeafd950221facdd24790d7d1ab8883e5c5d55635f0d14a1ee4741", + "0x07b41cc478fa6be38417271db8ed12efc0da6982552c1496025d2df0576bf4ad", + ), + StarkCurve::from_affine_hex_string( + "0x0611b5725101f611c387ccaa13889ecf3bb5595071a179ce350029bfca4ad7f1", + "0x03129755977abc8995fec7eec1123a1561e429fde37ff36af002d3211831ecf4", + ), + StarkCurve::from_affine_hex_string( + "0x0534d88606700023320ff5a1a864060ff7ac1534c1d9ff8d50fc85fe7bc92454", + "0x071f4e0f548f94a7ce308a876397d13343221370947c0a1ccffbce7070461844", + ), + StarkCurve::from_affine_hex_string( + "0x01c06bbd0c52fdab9fcaf680c7a93fb821e538a2ed79f00f3c34d5afb9ea6b31", + "0x03873d3bdfe0be0157bbc141198dc95497823cc222986d24c594b87bd48dc527", + ), + StarkCurve::from_affine_hex_string( + "0x067e2011abef26ef6a1684febce9e1a18c2383bd1c3f3cad858edb8bc3e9ea1b", + "0x0407da082675445aec21d9c87ed9d4f5a57c485ece71ebf1ae2c0cbec61bb3dd", + ), + StarkCurve::from_affine_hex_string( + "0x04a380429dba88681b5fec6c38a6a06ddf668e75f9b7dbb7bc4ab83b0d9dc8c1", + "0x05632172ed9fff3e3889e8ee9c116a189a862f81acf3293ef8d41e0fcbd784af", + ), + StarkCurve::from_affine_hex_string( + "0x0333df8266d79493541885b7b967410b554e888fd364d42902cdf377e4f29781", + "0x02bb17fc03d0e512c02a9579bffbc4a4c01189d850fbd2c0a3d2a0c6038bcb0c", + ), + StarkCurve::from_affine_hex_string( + "0x0275cdbabc989c615130d36dabfa55ca9d539ed5f67c187444b0a9a12e5b7234", + "0x002b7f723e68e579e551115d56f0ae71a3b787b843cc04a35b9f11084b006521", + ), + StarkCurve::from_affine_hex_string( + "0x060e28977b857537fad2dd2449da3b3d60dec4f9ec74f3ecdb2b586bb8911676", + "0x07c958adaf4c1fc141debc849fe14d62f6226f7f1c0b78f27b4a215d02775284", + ), + StarkCurve::from_affine_hex_string( + "0x063f8833b2c1c1b51e8edd5a1c44f785d947771183d10a9f308572a6f8259def", + "0x055bc502846d1383d5e76bc1891678e2f099c0fdb6cb87a18c43ee071c7a5187", + ), + StarkCurve::from_affine_hex_string( + "0x041b1737d1ee973200226a0bf3dc01ad8c73766b49c0983e82a7583355426eeb", + "0x00e356dcc2b91c94f773918046f602dbfbc4d1360b9853c6b47c0d3b65b78c5a", + ), + StarkCurve::from_affine_hex_string( + "0x0128010f9d97cc1ae5f79cab6ec1ac131b19716b094173675555b6f99fc620ff", + "0x01acd10e6d5ee79197af820e75921618e278e154df94db828d3db79e15178977", + ), + StarkCurve::from_affine_hex_string( + "0x02e0e363d5753266478468ac1df5e925e90fdc55ba85a869e50b5acd3faaa8a3", + "0x039f1b6a67dc45e025f26b7c1834d670ef112f96e4024ef1ae7051e4d72b3310", + ), + StarkCurve::from_affine_hex_string( + "0x021aaa2ca4f504e66ff59b1c1de5c5256eddc1948f6d1c9180a24430fe00aac3", + "0x01a1748762ce81f2d3c5c6ff35b17861b7096f922cdafac43fcf423730a6e3d9", + ), + StarkCurve::from_affine_hex_string( + "0x06c84363c06e7231d3d9acd69e46b717d469a3b120152df40bef92b14211d94e", + "0x00687f02c9a1637265dac105ca718897a7ef18a0a7c44c8ae657672a1d0a6988", + ), + StarkCurve::from_affine_hex_string( + "0x06cc702eb20f8b5940c7da71f8b1801f55c8c2d8e2e4a3c6c983f00bc1ffdd95", + "0x05d15b3727bc66f3aba6d589acdd139fae115232eb845abe61fbdfc51341352e", + ), + StarkCurve::from_affine_hex_string( + "0x044defb418700cee8c9bd696b872adb005490512d8bba081f8f99a9f15cc981c", + "0x03b2072cdb1d919b2b65b5cb3557f0a3381d7ca293c267ca4a38f83e77bcc96e", + ), + StarkCurve::from_affine_hex_string( + "0x048b78d75afda201bd606d11f7128354a8bfbca47709cdf1c528e8013d3297e0", + "0x00823c014201b1519da419e568652aa2d60b24f43d7aad8ec447c3f2912a1280", + ), + StarkCurve::from_affine_hex_string( + "0x00fd83ce77b1578b3a9b8c3cbeaddb1504d2fd4a19c901c21ac65961224e4966", + "0x0110cbe64fc10c6b9c66f15ca406a35f50b723b35d83c5eb9797a57f8395f4f9", + ), + StarkCurve::from_affine_hex_string( + "0x05e03233a11fb6ee8ddab18f83418077b008faa304d28f86a0d7fd7482f4c78e", + "0x06d88e4c51f4332ea05160dfeb860534c084b0bb3a6a48e350d88c7d771f28a8", + ), + StarkCurve::from_affine_hex_string( + "0x04a7bbcd5605f8f5234df6197187e57ed05399ff867026b4d9caf161f3ce9cdb", + "0x015aa5421fc2b584be5db1f8cbb2db1cc6d4c313c9e4a6091b4d290bcec7a06d", + ), + StarkCurve::from_affine_hex_string( + "0x069cc4c85825af1c4d9b315512f1a4a9c65096b49eeaa5942e5f847dae9e793c", + "0x05888756df8444e211ea00b039b03e7f426eb8008da72bb3bd9648803cb6bbbb", + ), + StarkCurve::from_affine_hex_string( + "0x009dc6ff90e341875e113bbfb507724dc7095a280d2f32cb6ba61a1e0c2d2aef", + "0x04aeb622896c852c2747454e8f172c9482955a42ecbe522d6ce07ecde79d0a51", + ), + StarkCurve::from_affine_hex_string( + "0x03397ccfef6a9e896952ac317ff57326c0784cfb0d034ca7df91b10382596a16", + "0x05b4bec200ac1abd5e155bc9120d87cbf109d0115df46c97954e22a86446c6d1", + ), + StarkCurve::from_affine_hex_string( + "0x03afc87c1bbf6ca2453c6614842e80dc513d153b6888f4d6ccd032f9e48b5e84", + "0x07983d108f7829fa62207e49be6e8ee78f762fcb22453a92f215fa7fbc701646", + ), + StarkCurve::from_affine_hex_string( + "0x03bc6fc5b4c073051c49dc626b1df9ee429eead401f188ad672f667c75b1061f", + "0x07931fb39ecfa6ef08557dcf037d5a2e0532e8ff81a86d7b853877006b6e41dc", + ), + StarkCurve::from_affine_hex_string( + "0x05d8ac61b17dac5579424bd6ba61f9e6a5ff433625c96319815e79d9485ac146", + "0x07f34b39ec531f7762c7055222b4f682f8f86cc92c66b1f96f3cc91f8a9b3091", + ), + StarkCurve::from_affine_hex_string( + "0x074d9dd8e7d8ee6b87d4ff8577244cfef1050174b9629154bb8a7b61dc165770", + "0x03f80ba57249545dea47a6eadc29d7e691f279f5667e62678a5cf6d1aee99ad9", + ), + StarkCurve::from_affine_hex_string( + "0x00d6612c8202dd509b75980f904a8977c8185b78e64418e52fa3939952b4d950", + "0x05da4e6a9d1e1b97f5db7bb794bea787efbd5fc3786a5581912e7afb9795a6f9", + ), + StarkCurve::from_affine_hex_string( + "0x026ef94d55fa03989b937643eb272f9d4f2cd3a86932a7968222ec77f3ea8355", + "0x00f58f502ffd3a58623453f36d4f56574ea26cc42a52e9b9b7c59f08635f17c1", + ), + StarkCurve::from_affine_hex_string( + "0x071c58b0e47b9dd9107ebd8a8c8fa9f0534e78231bac612c1ddc7a94edf33eb7", + "0x07f90edaf4792bf8334adbaa0f4ee7c654312725af188682d75f34874c4eccb9", + ), + StarkCurve::from_affine_hex_string( + "0x01f6de1f14988778ceb2dfe844f92394f1f1e72fd1581ceb3bf336c95ce50345", + "0x04f6007ed4e022d2ee9fe4ca8207c5f6c766c4f3b85260e941fb24ad0dcbf0bc", + ), + StarkCurve::from_affine_hex_string( + "0x001c25186a0da54cbe3ba4c73ede4249f5b26e471155a2cd40ad4ce564ecca52", + "0x019b589555e4a9095b28d5e819b704a5783f6e7649b709eba1c809698a0cde87", + ), + StarkCurve::from_affine_hex_string( + "0x03ddc3ac25ede4a67a97547ed27dc920239b585fb3624177e2e8d59eba678115", + "0x00a9afd8f8bb759cbd1dff2addc63f47da4ba1291ea34229c09c0637dc5c8d24", + ), + StarkCurve::from_affine_hex_string( + "0x0472e2cc849dd25e927ecd762187bb6291425d677f40def5a4b204a5c294e3b3", + "0x058f716919d2a17719a14d72d398a0a460eae4d1944e8331a047dca802d364f0", + ), + StarkCurve::from_affine_hex_string( + "0x07b1fc000286e8f7a6b268f1758c0e22656f4ab87fe2cd4d196b88ff60026223", + "0x02a34cf0c815f7df065e8ccc6ba7f2164c1754ae71583dcf5da7704d4d822c69", + ), + StarkCurve::from_affine_hex_string( + "0x053dee9166f00f6ded28ee1950071d4fb25835f9b4b67691b26e72431ffaad44", + "0x049e1258ce0473f61b0bcda93e462ca0a4b8776286a5eda0645d7545a868bd3c", + ), + StarkCurve::from_affine_hex_string( + "0x000c56b0269d8431556e471cab9d70edda3a37b391696f107b2dc370631de51d", + "0x0729c52f6b134f733eb750c14bd9f95c077f0f6f6ff4005701e5bedc6544599d", + ), + StarkCurve::from_affine_hex_string( + "0x06ccd902e91b17091ee85c2f63658eac609748debebc615825a6e7351592ae11", + "0x071934d01841022a29c3bd9fc764ce02464ce54df03324c741b9c57de466caa2", + ), + StarkCurve::from_affine_hex_string( + "0x04115ec6c94edf032eb80b2c75c33645891d1a403cd55df10a1fa1f39fcedcfe", + "0x00cde9950c871d15b8720e9598242c6c33f0f7dc6dc56e4f232bf1453108b62f", + ), + StarkCurve::from_affine_hex_string( + "0x025ed5dddbe20714431f925b8aad44b157fcec576dc92b617b43eb5f980f8a01", + "0x02db255522783bf45fac701873ee413dec183449cd4af42a904622744c12da4c", + ), + StarkCurve::from_affine_hex_string( + "0x047d284d7f8fb7c87337ec19e063fe4a471ddecffb2a630a7a6e35458e14a012", + "0x026a5fdac510cef76014b1a74eb692ac339ab69f59389903555fcd60304fbfb9", + ), + StarkCurve::from_affine_hex_string( + "0x01f7641df9ef20a2fcc29c19bddf669bebc1070e45dc8fab8a6d533d177a9089", + "0x0091590699b44b2a73886d25a7a58c32a57943e414022969dd42666503bc72dc", + ), + StarkCurve::from_affine_hex_string( + "0x00a782d9462094566f35dfe663f9e9319298aca16693f7795544f02aaefcf889", + "0x03dafeba6c703d52059af170eeb870ded629f4ad876741f20796a38917ad4ef9", + ), + StarkCurve::from_affine_hex_string( + "0x01a052f00989183b003eb979269fef8c84480a3e46e45cfee0455bc589bcae97", + "0x01144731d763961a1421faf04febe8b643c0d72b321f133d04ebfd1c4e195796", + ), + StarkCurve::from_affine_hex_string( + "0x044d32ce19ac6807cb22e4f25fe1486a36a13926f147fbfa054b63ff0446177d", + "0x0212a21e8c124c9cd37c80d2dd66913ceaa6b6f666522f115c39382b2d5925e8", + ), + StarkCurve::from_affine_hex_string( + "0x0035dfc16f3ae6ccc06a267bf6d931601e52f3e45359ffc513570b65b96adc4f", + "0x074311d10f4bece01b5ae65a6affe5c931463aa1b73a3320eeb41bbb7bb1ff62", + ), + StarkCurve::from_affine_hex_string( + "0x0420c2b90d0c14548ef5cda3da07aaf2a8e6171c01afbf358acaa69576f1269d", + "0x044025acd7660f15fa341f10b111983a4407b7240658c0c08a7361983052c0a0", + ), + StarkCurve::from_affine_hex_string( + "0x00e0acd9d2d907031b319b80121dc90699d003d220ea785d50e5033cdb3b1a03", + "0x03911ba78d6e507485d6374b0f7d2e6198f6462a7d6d3cf046404a07af690357", + ), + StarkCurve::from_affine_hex_string( + "0x01025c1030382b6e6f614b08b587d976c4dbd00fdfa871d1cc2e946fa1000a9f", + "0x04fba10f3839035418d1b8737ced238633ba2138c3d3e103efc4e3d61fc77a83", + ), + StarkCurve::from_affine_hex_string( + "0x0761ade8ccb2a59bec3c850586207ac8ff3951d1949a8cb4f0c03204f0697734", + "0x0092943b4aba2b09d568c36154b8311e034501f17ac72d4b7aec959a486dcfa7", + ), + StarkCurve::from_affine_hex_string( + "0x068931e0035581e3ea3dd02e469dcf553ccc40595cfcac0f19e159359b37a574", + "0x05c304771c7610450e3da8cb656b686015ff9f54f41cb7b8aff64400622a1724", + ), + StarkCurve::from_affine_hex_string( + "0x03c57918ca254c0cb7dac251ef4e10c7d82327969552eae15d26c4c52660922a", + "0x05fd5f5ff3f14e671548074114c72c48409df8a2e71fc8aa3c8acb506e2a88df", + ), + StarkCurve::from_affine_hex_string( + "0x0393963888652c14c45549d63651990cb82ab06c3133c3d7dab3d0a4d6fdb43d", + "0x012bceb7d92b63d1c73c306ea3a4eca4567c76938a6a2933986abd99f5851ed2", + ), + StarkCurve::from_affine_hex_string( + "0x0440f508554c5e863ed6b45c927b8cdb0041aac51cbed9374dda2e101d0d9272", + "0x07629196c45abbe213ad90cbe7b7e0ad4ee5406a3579a4de00346e028d7f27f6", + ), + StarkCurve::from_affine_hex_string( + "0x01f1ebfbabab002667188577797cea57ab0fc2d368849bf390f770077ec28db7", + "0x04c005210fb301c187e7011b8b12335211fc118d2589e493785fc7ae1e3214e0", + ), + StarkCurve::from_affine_hex_string( + "0x041a9f79b7494ed4e346c5c11eca7e92557f022597e13c2b57b008dab7a974a1", + "0x02ed67246fac7f9da43fc8e08e6b6ae7dea1d2e6793518b8eac91949de94d5e1", + ), + StarkCurve::from_affine_hex_string( + "0x026eeac8f3c44b015f2a1f54863877cdd49032d57a8c8fbc58aca863274ebc05", + "0x02481d5ecd480c2843be0241c46a91e6d545e5a89634648eeb9d0d1b1d43355d", + ), + StarkCurve::from_affine_hex_string( + "0x059fb55fcf372e96ae9d576660b52aa6ebfc0f24d18cfa9e0ef56c06442de276", + "0x046783bfb29c5f4c056830b841425da6fe1118a7fca9c25805470d514ac7882c", + ), + StarkCurve::from_affine_hex_string( + "0x01d46b2f1ab549be129401971da46b15ceaea911167b33714915c9c19a9f0fe4", + "0x051643906a861e733bc43cc355d4570d73ffb7bd71a6ff73ae974fb444c17120", + ), + StarkCurve::from_affine_hex_string( + "0x0222ad8b61e219ba2b581f606b7c996516850a46a3db72fe1f72b5a9be6c324c", + "0x072015a5e2db648112abd284fd867b59fc5606645177d26cf6e9a655c9912d42", + ), + StarkCurve::from_affine_hex_string( + "0x03c86d5d774bc614469768ad38f7be9a53e9a233942c5c553b82e49aae684764", + "0x0480febea8229e130dedffff89c11f3c43e11724e6bd89d5566d78752859d41c", + ), + StarkCurve::from_affine_hex_string( + "0x02d0970c2be9cb6120895a6d3f947297902fd946e6c2a8c30c60b5d4e7ca6571", + "0x076162cf8c9bb6382ed15c8dedf89050035b9f5fa5c5085dd5fbb90d5c0faf6a", + ), + StarkCurve::from_affine_hex_string( + "0x00adb73bb8352d0c10175df371f7868ef2c9e0c79ac788430c480c0f7d85c187", + "0x060b564785248111502e6f39c4994d6293fac22bc25f4d764b2fb1957d3c9bd8", + ), + StarkCurve::from_affine_hex_string( + "0x00b7ca8292655bac4aaabd53f31bd2649fee32da17bee88b4dfe8bb0cb7853b1", + "0x048b473689a22416f26fd615dc08d3c5d2518abfcbd0511c7b1b76bc18117931", + ), + StarkCurve::from_affine_hex_string( + "0x01d9d84b55339c229b5c3632494e59cf3f73a849fc07c7b3f4c23ed14a1c6f07", + "0x06434948b8081d7d3dd1df868200e46cf8c33e44154049c16c6af3cedcf3697b", + ), + StarkCurve::from_affine_hex_string( + "0x0647d50273b09e3417cdfa03faf938a9415c9705d7caba2c65b46c6395267108", + "0x052d8ee9202fec44953f621e178202c3d862c3347ee5b1db90cb65afd582d623", + ), + StarkCurve::from_affine_hex_string( + "0x03836ab8b46cf4f453a22532c886940b982029b29c42adca90ded5bf77e6bcb9", + "0x07b15e91d6355f147b171a90b064a9d8b2d7bf3699bbf4987664c61c950d8996", + ), + StarkCurve::from_affine_hex_string( + "0x064d0b6d17bef5bc98fd7905f117997f9a021f2c4e260fa5297a7b22f938f173", + "0x063163a07b21c7898980bc23931e39b397deaae2bf117450963e24340f40b251", + ), + StarkCurve::from_affine_hex_string( + "0x05ec0644d2dd23eed036ca45a58ed446d0c17132ce0bac9d8960baa8c7ee7ce7", + "0x000a5b30a784385e146f35e5abde5c39d47a3c9884807f62bcbc98607aa72dd3", + ), + StarkCurve::from_affine_hex_string( + "0x052014f24e6c1a07b9dbc608f11a6e8584969bff221c6beced53c9b35cbbcaaa", + "0x01e03d3b16e4ba42d2fff5e47356c4b82210b017fb3d36aaaa77cdf54ef016d5", + ), + StarkCurve::from_affine_hex_string( + "0x0319ca0aa9bdc80bdbbf76f14f0e07596b5ea123956ccff6c376202c00330a2d", + "0x046c04407519d17b77165402dcc6d168227ee9d72c97648a719190aff252ca91", + ), + StarkCurve::from_affine_hex_string( + "0x04631d4ab18d4a07478c37472dc5ec104a9e9110d5b88585a06139a40f0a753d", + "0x0062aedc709ff2c28926b1c91fca55c4b5a4840f9b0de84f32ba4c4047617d52", + ), + StarkCurve::from_affine_hex_string( + "0x0560a88ab68def3d133d978ae6ea62f3cb5f67bc3089ec5cf3f155dde2f36b85", + "0x07b677d6aa2920980bb0e3a83f4354894ddd40475ff5b6ff3ba8abfd98d3a0cc", + ), + StarkCurve::from_affine_hex_string( + "0x01cdf983c83be7473b6c5187d41983f83ce01ec07e902c97aafcb0777c6a9beb", + "0x07741301e24db34ce1086c2eeaa666594403548c3a24f41eb05f9f63510cac2b", + ), + StarkCurve::from_affine_hex_string( + "0x012ed96af1a97c45ec31f1531e96f6fb28a03ba52ab8484545fbe0dddc97bb32", + "0x06d1f522b6c6cad0940cff8e23decc72bb8d4164696af031415508b025aa8be1", + ), + StarkCurve::from_affine_hex_string( + "0x027382994ae5878223ef802e9b4882f481a1b4008f1eec8484483471f7aa742b", + "0x00c31750d242b3975b0026a0e86ccdd17d0f680a8c6f53f197fc25eb1f777917", + ), + StarkCurve::from_affine_hex_string( + "0x02148d73de34495484d84816a0e0901233d96539f43b2373f9acb45578a7cf4b", + "0x00ebae1afcf3122640b22e382ee8a9829b9c5ecb958c7db152ad6a0f5f650cdd", + ), + StarkCurve::from_affine_hex_string( + "0x0431677eba3715455bc235557518a74f3b111a88844ef13e159ad44bc16de3e6", + "0x030000e1eb6a17d9df776981e65c6e500fded1ac12003adc9446b269812c9197", + ), + StarkCurve::from_affine_hex_string( + "0x02c0a92fa84264abe2a19418f4629fffc159c4ebbff51ba289803273ef6e786b", + "0x0796c49944c3c5cc22223a0ef78f2db12baf4d57024137fb707c53da0c813d23", + ), + StarkCurve::from_affine_hex_string( + "0x017bf82561d58e92cbfb8f61aef57d7aa7fc5aecd644e350b62ee5c9bf127a6a", + "0x0263a8951a4a0c9a19179524cc6ac216f8b5fd40d48744a78a0afdeadf25666c", + ), + StarkCurve::from_affine_hex_string( + "0x00b239da82e298a6cdfc564fa3751d43535f1fee823810bb5e258fc70c32c4ed", + "0x04408db51699579aa590ed9cf9642bae4c43a79e17a59cebed9d1223055c410d", + ), + StarkCurve::from_affine_hex_string( + "0x04b563e6f42589671579eabfa2cda5502b361c46a5ac8d45c8ed44741a925b33", + "0x0627bdb41678443fdd1aa607709e9699b652308615f4bea760a3b79ee0d9ab5c", + ), + StarkCurve::from_affine_hex_string( + "0x07c5fa431f474ce848fdc97484aab384f638e02f086ad0fbd9b44da6c5e52df4", + "0x05e35c0faf1b3266257c9a7592d5ce9777f1343b1b4bcdd14ca18e24c98d9de1", + ), + StarkCurve::from_affine_hex_string( + "0x051eb273841e9c95bc2d5432fd0a2010cd7f4c43020ef2c3568f7e61cfeab90c", + "0x03a994ce81794588a15e3b7cce63223562c1a7c7a53d5df20ca7e1d698b50eac", + ), + StarkCurve::from_affine_hex_string( + "0x02be8b2ac06e4f80d8561bd0d3461fd32a9ecfe8c36ac073770bc6447d5b904f", + "0x01203fcfd2a0b21a0a6c61aaa80eaab51068abf1cb75df4802bd8d50f7ef896a", + ), + StarkCurve::from_affine_hex_string( + "0x0063497eec407da7a6584d103961649d767bc55ce21317e62305cd1c701e7364", + "0x065bad74cd20b191e42eafb57f01aa2c7d4bec2f9a23fca8dcd7d5aea6e781b7", + ), + StarkCurve::from_affine_hex_string( + "0x0268b87223eff0ca84fa328dc26963d671b6dcc02282c88ff328b25d95ff4818", + "0x0155383241414813e5b3b89df457a0aa7c62563f7130676622a524d32bb6a22a", + ), + StarkCurve::from_affine_hex_string( + "0x01cd01fb7dbcf1a3d2b50bf0abc6e80d91914ce88cf6a050ad629ca7a6e9621a", + "0x046652b17d0c5468794a413b6af84f46ed815b2477e961f76be857faff9f4069", + ), + StarkCurve::from_affine_hex_string( + "0x059a444dc5eed0e2a2898414e2ce49a3037466dda53aff4a1446af91b55ebd6f", + "0x077cb38dbf12e343460b378ada644ed434e7471d2c2fa4df4b77f087e74655a0", + ), + StarkCurve::from_affine_hex_string( + "0x02932fd3f81fc973ca9def6b7f1bb50f980fe589187cfe9e9f52ba4d356cf2c8", + "0x01e6bfd00fa976c4770263a227048214c38850fe0f059e7b3d2c7871ef07d68f", + ), + StarkCurve::from_affine_hex_string( + "0x00e44e4f3d96d9dec775b996be57e57fdc28e7c68023109b221c414a244a0dbc", + "0x0058b1e52fa274812e5184e00e9ad812bec2463140adfb4bea3b2d665867dcc9", + ), + StarkCurve::from_affine_hex_string( + "0x06846ad9722de2861fb2601bb4fb5ae73f61cebf36d4523cac3d6dcf28e3e0c5", + "0x02d33fc71f742c03e492f3b5615bcf69dd93eeae048bdead003b76c18b2d7d1a", + ), + StarkCurve::from_affine_hex_string( + "0x07fcb89be1f4bec745887bb891e53fefd665c53d00a9e74de16b8a7e1f7adfb5", + "0x074af0b06633f779897e199609c71cc5649bbb65bc2c0abd4c678f0480c198d1", + ), + StarkCurve::from_affine_hex_string( + "0x012dc9e413f30f2c4a31a0c817fe53745678a416ada41df5f6d16ec1cc7de47e", + "0x041a7db3f297a185063ef5449304c5a623314bfadc8f30abf8a99f32c406bfda", + ), + StarkCurve::from_affine_hex_string( + "0x03b56dc90e776ade9a27aa6973e7c4a65da8c018546da5411f4830597041d24c", + "0x05bfdb79523764025d13c9bdc8ac82b4aba0a2c0377e24f2704af2c7e9bcb28b", + ), + StarkCurve::from_affine_hex_string( + "0x05645fa61c1f4ba2ba7d72d394bda48e8e6a14d076b1dc9ff2b9c2aaf6170308", + "0x01a1616adc34b274f50b3e156b71c31bc6b9153b60b5825cc5f867a9eb1f58de", + ), + StarkCurve::from_affine_hex_string( + "0x062a381ffb904ea3ff4d451d4c8459457cdbc3dc2fd2da646a95d8c1e90c0b7b", + "0x01ba058658e09db9e319fa73de8ab4a992b71e4efc22c273725bdcab84e2a315", + ), + StarkCurve::from_affine_hex_string( + "0x065a04e4b1988beb9537c99a969d1a6309701c33773a7e4ec353ebccf6a6d0b7", + "0x0669d76d634c76bc1d94866e9280bdf89f45bdb65773c099e4f3621c06b074fa", + ), + StarkCurve::from_affine_hex_string( + "0x02c8f6ca447361cf789037b5f5757db5ca9fe8251cab80096a63f33c4ca491e7", + "0x01823694ce31bd83b356fe945b669f7df41f34fe168731ec9f5664b6b8c6a81f", + ), + StarkCurve::from_affine_hex_string( + "0x062a0ef4215dccf112831a4f842c67322a5c061e7663710cd3308d34b9583df4", + "0x0420db8176d16172247f61bb4898b032aa537a6de5d9dcc2b667cfdaaea6d7ff", + ), + StarkCurve::from_affine_hex_string( + "0x01a340b3a6aa365fde137c1f63191e5931569067f813046a765d8b1df0bd8560", + "0x0036f5d03aaa9effe8f8774608dd008f1f97d326f51c1d4c0178b6a5d7078dd7", + ), + StarkCurve::from_affine_hex_string( + "0x002ec944d2aeaa21841e70e5c7a1bfffe87d6be95bc653f0d132888490e7eca1", + "0x01d268478716141dd155bb433e0a87cf76f83126ff5ea3b85c5ffdf50eaeccca", + ), + StarkCurve::from_affine_hex_string( + "0x07b86fb1d0d40133e7ae192492d212b3340bf6cb5c021e137fa26f819bac53e2", + "0x03c88742cd28d490d0f7e58de6a93cedcad0f070eb48e8a317e4f04d056e11fd", + ), + StarkCurve::from_affine_hex_string( + "0x02fae39160059ffae1e20fc4031762b9289639869d61003f9f49db4b73b1f838", + "0x004c6eb92e40146b8b36a9f257d6405b7d717c4799fc2ed4fd17571d0135e264", + ), + StarkCurve::from_affine_hex_string( + "0x01b0fbb7a84c67e668450a54449c7a46261a2d355589f8b84ebfbaf9a77ee938", + "0x0044f8fffa33dd33a6146c35d196595e22cc4a215f61ee9197cd751400970a1b", + ), + StarkCurve::from_affine_hex_string( + "0x078fe920bd96a356d4d95ee34adafe8fecf071d3107c36f047b4024ddc4b3eea", + "0x06162f29607fdbec10181fbac6e57d5cb41b922c5791fb24bd28bcdd75d16c41", + ), + StarkCurve::from_affine_hex_string( + "0x01dc3bafc577709a33473edf7ef50bc16883fe17f5641268aa371937bde21189", + "0x02a6512e334a9c03ea96bea7e5fcfe9852c6cf2aed2a59dc334cb6c6f3da164e", + ), + StarkCurve::from_affine_hex_string( + "0x05629b849e026e65d119ac11821d7ab7efd9c52226f75c7427505d6818bb0c8d", + "0x01539c0f90970ee8b490e45bbe5568170e5708521a0e59f976be680595906feb", + ), + StarkCurve::from_affine_hex_string( + "0x06396195b1ac7eae21320c20ba5da0c6f7c9720028cd7d14a5164a60a1d67e76", + "0x00957015fc5930cea0981e8b371e07018375ded46e8700d34f286f4ede8f3b4e", + ), + StarkCurve::from_affine_hex_string( + "0x00492cc823c805f6795331c1bb3fec3dd6a2ff6b69b3ada97a46fcd5d401b92f", + "0x01fed5ac67dc00d58dbab4c5c9cc6f614f9316abd092570e92de8ea574c4055a", + ), + StarkCurve::from_affine_hex_string( + "0x0082879bb0dac70fd540b8ec4924fc06591aa7c5add7dc3d28327fbf206ca32d", + "0x064e30e4d3ba2c61b6270621dcc56983fed19951cdcec9ece4da8fdb71eab5ae", + ), + StarkCurve::from_affine_hex_string( + "0x062bc853f349bac8c6e5921d27ba85dbd9ba20a375d70a7bc008928f3e123b04", + "0x06acfeb1de05ba43c3ef1a9110a983a320e77b3ca294abbc04aeca19b194f26f", + ), + StarkCurve::from_affine_hex_string( + "0x0790e2f2f5d3a780b92b73821975d3a49adfccbed19dc8c1f2b727dee1aa8171", + "0x050c6b38ce050c4445b625a88a84c8bef5c2d00de12de51846aa940831aabde0", + ), + StarkCurve::from_affine_hex_string( + "0x04c836990e790d02ffbf4b4953e15123d79af2d9ca04ae2f9f65900c183bb2a5", + "0x03178f65e1f0c5214294697b7507ca8a4ef614c21c5c515776d0f7033070e55b", + ), + StarkCurve::from_affine_hex_string( + "0x01e951a0f13d7a4752d05d188bd2961a11c78f32b0131c629a823762d9343fc6", + "0x031f3feb36f3c363250aab536ddb30a6939470e4947fb24ea4eb804e07c9f4df", + ), + StarkCurve::from_affine_hex_string( + "0x0635a065bc09198d9690b777508997bb4e1c4bfe421d2344636440cfd3c79b50", + "0x070f087231ab21ba96f8939ca9b02d8b644b97ef2885110ceea7da6e54d349f4", + ), + StarkCurve::from_affine_hex_string( + "0x01ffaeafb97922fbf2bca32f0f62dd98be866340cd17b49664983a874f92db05", + "0x06b81139c899d89d4b570fd3674377271d7bf1f2493d444500cf0ed139292c46", + ), + StarkCurve::from_affine_hex_string( + "0x04934c80283f0866459c0c571720cd78b50b3d26eed1d33e1d5b4138d0d604fd", + "0x02a812556c46a34be2152c73197a02538fa3ddb6ce8c5b634659c48bb5c4668f", + ), + StarkCurve::from_affine_hex_string( + "0x023409d867df6cbac5868df16338412e16115f25f9c8b5b6dd22fecfec02e3a2", + "0x0488b92c7b001f7225f03347dd25c84a48bcabe2bee51a80e8a1ff42194195f4", + ), + StarkCurve::from_affine_hex_string( + "0x04cf4bed663464418285cbae359b5d84ec76b5997d24f3640984c7663421190f", + "0x000941f818e3e3e8fb1568da85217d17f9250ebc948379014d900a7b1a848494", + ), + StarkCurve::from_affine_hex_string( + "0x052ff3d9ffe9a302f6dfaaf74bab57c08027d5cb699a69b30830540c0a2d47a1", + "0x00987dd8876873778d933fbfed37aab2f7d6f669c37024f926b1edcb2ca55782", + ), + StarkCurve::from_affine_hex_string( + "0x0527b1301c348e4a2f8626ba9209d316fd01bf68c6753cd0162c16066b2f9adf", + "0x07a0b350bbf53839a52112af4e8a6cb065f526bf68d5787eaf7766c826494634", + ), + StarkCurve::from_affine_hex_string( + "0x01109ee32f0bc53de6bfa457060b366e909d7c18061ec9845f46ac715496897f", + "0x038f36f172bdfd454b9285f86e6bdece8fdffc95182c7d801b03c671cc55139b", + ), + StarkCurve::from_affine_hex_string( + "0x0429db4350228f9501cf7d615071815607a6d3d425f918e4606bfc6b493087ee", + "0x02ab8f3ad69a7c797a20cc5fe191f24641563b4b8c0289617be7d5c815a60989", + ), + StarkCurve::from_affine_hex_string( + "0x004ffae056c2b824c7a38526c2fe913d52e28809975bfed7eb8eff28ff38e55b", + "0x051325ddcbb6240173fae1c3a3a1a2bd8f02af1a5f13afa7203a27152d85de73", + ), + StarkCurve::from_affine_hex_string( + "0x027e049b547e5053a60b4a93555ac20c663588debd1f228f12a023446d096dcf", + "0x06c213b2702c89e107aa5d971ff12bf2f96db358ed23c8a11eac172d20cfd643", + ), + StarkCurve::from_affine_hex_string( + "0x04b4482f1d84efe23dadf3bb10df3dcaa251312dcdd604f616f1eb540e1f3232", + "0x07c9c149dcae9135f940fb54482f9c3cd8193721643a6e23157b8020410d439c", + ), + StarkCurve::from_affine_hex_string( + "0x07306146650157978f4b268a226bb00936e5c3f88cf505b7d5ff16abf3536955", + "0x0535f08a06205a1c7f80957ccad62cae26781d00efd3eab74d8c8f0b976fe795", + ), + StarkCurve::from_affine_hex_string( + "0x049f5e978d14d4e8efdd9e96dcb616805a934bdfc551a43ad78c4b29d1eabed2", + "0x02ec4ff772c902e9921836f3ee5feddfb1ac1e0f75e16ccbbb6cb28e7fa27995", + ), + StarkCurve::from_affine_hex_string( + "0x03c0e4f177444f3630e78ec694b0e58bb2c793d3c59b85bfb8484bf634e4a991", + "0x07ba13bd579fd5bf1504d4cc010472dea9c26cf55122fb06b69849818e2ffd51", + ), + StarkCurve::from_affine_hex_string( + "0x00cb36d89aa5ad3a705b823b4e99f090aae802a488b348bde9464064a341e06c", + "0x042a158b3e1e91512e306f24e983a533608da6c7283a2759a18e2a9447c34c05", + ), + StarkCurve::from_affine_hex_string( + "0x06e77b9dce963db4176185d3ba91e26740b2aa908a3c480e20f36208fbc94f06", + "0x04fda2d11d78c71e4c5b4d483cd0f129ec768e5a97c5cd76dfc4f38aaf11613d", + ), + StarkCurve::from_affine_hex_string( + "0x02759d50d6c303eb8f3440c9cf30598da418d99b26180f39b1d781b2df9ba7be", + "0x030536ae8943fe3856cff04656d82c2116581b8e7da78c17842ede40262b8f86", + ), + StarkCurve::from_affine_hex_string( + "0x06c92fa88f7f78c4970d16f45968010cc543eb48e323c70ebfdfa066bbb169b0", + "0x0621460854f3a789a6a8695b957c165d108e74b66641a0ca6c9f5e662660c47b", + ), + StarkCurve::from_affine_hex_string( + "0x069cb459b9e415b7581ca163611c470d875971d5d7949de732d1f0f200544a73", + "0x00a7136fa9dd00c0469863b7def3f83a5611ed628810d7e807e7a873da5a9897", + ), + StarkCurve::from_affine_hex_string( + "0x00b66a4e32ac9a4baa8f64780acd94ed3628b2b0ea874ba4dece629af65f9e62", + "0x024328ba9996a24389658e3467b8b90dc3927ef8419fe28b3f55b1c1aaa51915", + ), + StarkCurve::from_affine_hex_string( + "0x037da1e4e8602cde371b3497ae73599edbc9dea033e60dbbe4a457d48126ff00", + "0x06b0c77e59c5514a07675e7c953384321fcef8064a50c5c652cba9d8d5d50b47", + ), + StarkCurve::from_affine_hex_string( + "0x05ecc3080062dd451236de0e4eb91c5c75100733364bc5469f5fa76f79021ecb", + "0x06da4abb9031a27b5be94529324fad8026e7d871570780081b0f424d4fe543c9", + ), + StarkCurve::from_affine_hex_string( + "0x019cbe53344765a866ab1c5d910f396a3bd838c2f0f21be599f0e00613b95225", + "0x03f7a6ce3982eff776497894473d7ee3fa9cd7488a01b844d1ee8ef73c8ea52a", + ), + StarkCurve::from_affine_hex_string( + "0x07221da860b384859ab1a50a1fb9c86270deebf75df946a47b6e35c7141e064a", + "0x0518b7d44d4cb7fa6ad1919f382baf9384cb05859750dc1bac288fda637c59ae", + ), + StarkCurve::from_affine_hex_string( + "0x0781ea0d1bc46ebef49ce1b9d0f6d12c68c6b35e6b069f32532861348a50ec62", + "0x0483b5d54930c3fe545cd03559bf59d47eef8de9d7bae402fa90540724eb5855", + ), + StarkCurve::from_affine_hex_string( + "0x01e3146f00880bb22486d5bc73e54367d54251f4002bcf342d0393b05a4b9ce0", + "0x023b6fb8e945d3205f633ba724202db5a99305f807137edf942cd60eef867699", + ), + StarkCurve::from_affine_hex_string( + "0x03221c723737943a5dc0c7e74e781e1c98accce6be1d84b89f37fc01f89ecb95", + "0x0371ad10746ed2e47465249f981cc13bac3db505ec2c341fd83d8b159a260358", + ), + StarkCurve::from_affine_hex_string( + "0x04c6575c751bd0aaef9e24b9dc284131a19d458ad8219bf459a01f075c3bce02", + "0x04b50c007fff0fe40189baf8ffd70e206c4d6b0b8e3e9c3f9f9ed47f8457a24e", + ), + StarkCurve::from_affine_hex_string( + "0x06616b79131333ccfb5dc96fe61c26d5097486923f3a3fe42bb6a2253f5c37ff", + "0x033a0887b14cfc1a2f51d7189fcd0c1c6c1b209c28d0628d90a5b03dbc49b58f", + ), + StarkCurve::from_affine_hex_string( + "0x00aa53f0b7ac8d48cbb725ac302ecdbb537645727d30c0764778851f4ac87d2c", + "0x05cb395f55be629611fafaaedfd627ece586303c57f344ad72e6f387770812ac", + ), + StarkCurve::from_affine_hex_string( + "0x037d5b9cb0e2a9f97fa0fc26cd00805588f6e4a21de2e0737dec75b326acb626", + "0x07d34fe6650be7488cb6b7dec609dea8125e8b54f54fc7cdfde90ca4a523cc7f", + ), + StarkCurve::from_affine_hex_string( + "0x001bc6ecad63ec5c7f8f0b0db03acd057743492ff1dbbccf00773fe581737678", + "0x059d8be572bc6fbf7710c34c3e48cf557bd1880bd8e6da1b391ef99812401723", + ), + StarkCurve::from_affine_hex_string( + "0x032885039ddc8b160171802cf05c187ad2127bf5fedecd3d930241a2d066ab2e", + "0x004f40ad14a0752f34305bfe5fd315908979087e9dbb80b67917d9eda103b4bf", + ), + StarkCurve::from_affine_hex_string( + "0x02e1da8013285598b899f026c6974185db12c97b4c63509769d3d4ad1d18a4e5", + "0x01e7e7b668674d1593c39d58bc7bccbf568208732b3519bc2cdf93db34366862", + ), + StarkCurve::from_affine_hex_string( + "0x00d26c3f389d81709506f184b53871497c8d36c5c9eee8e3737358204c1acba3", + "0x034649c3d39f3b825947fedbca215ae30c5a5995e93b1c8efca4944cf85a082a", + ), + StarkCurve::from_affine_hex_string( + "0x002cdc55304abe626bc35092043c09b06c1b2692a132405ed0970283d79c15ce", + "0x020e8520bb837de7bd8b4ff7c1b268c5b09420866a618ab3d818375064e37c63", + ), + StarkCurve::from_affine_hex_string( + "0x0091300478a83595d548f32f259033291fc7d083953b0b8bde88c7559660c563", + "0x00e5d2bff57fc6551e9b80c06ac7314a71907cdcc66ce82f2cce721a670df10a", + ), + StarkCurve::from_affine_hex_string( + "0x04bb03a18945b84a6373eb925df1e3f01175c32eed9a075dce2422eee2fe8cd3", + "0x05180166e1f01dc697aed464fe1b09ce4196456250de2630f79148a7c3df043f", + ), + StarkCurve::from_affine_hex_string( + "0x04fbf02374b8bcbc574f686d838fb28bec8aee59a3b0485644a6005782621a94", + "0x0392123b437c8439059d84e77afef0c62315ab20ed46f55172f3766e6016afa8", + ), + StarkCurve::from_affine_hex_string( + "0x0768caa0b9b5ebefa3f5af1fe2fb3e38cfb47de7cd0bb43b620e60aeb9463cfe", + "0x023b51f3fb1b7a7fb6009230569e97888af74138b727ede5ba10861d79d2284e", + ), + StarkCurve::from_affine_hex_string( + "0x01f7abcb9d462c63ffe92aa56619ae8590089cca4d93ee3e5f34a63882452cc7", + "0x07e9f85c7b7ca6e9a4f3a026d1048adbeef69ea9d876c6f647c257b879a81bdd", + ), + StarkCurve::from_affine_hex_string( + "0x0572426011020072b59e28f98ff8aa1780ebe2ec272a038db8917486d19e84cd", + "0x07c51e7eaa4ac7cad8a8b9f8af3a84fd879cacc760c0b7d6d474c0a1fb7a8e55", + ), + StarkCurve::from_affine_hex_string( + "0x02968ef4d9dd1b8aef61ea432ebf2ee5466c297613861243c0a3e9c81e1f88a7", + "0x05d6f0c3fbb464d4c5d07dfc660bcd5f4bbfee371001e4d734136322326565e5", + ), + StarkCurve::from_affine_hex_string( + "0x0014f01391fb6d31a8a5445afaf9e1650636dbbe349be822e88e0f24cf75b283", + "0x00a3dba6361c6d972eab7a3ca59811918f062a89f7fd793b8a769341daca37a2", + ), + StarkCurve::from_affine_hex_string( + "0x04f751be55a6f85062796c72997c3b602f869b51084b2f6407b1f669fb7dd0fa", + "0x0238393a5f4a768ee08d18456ca7e9c1d30cf8ea4754942fdb5f5d2c86f35821", + ), + StarkCurve::from_affine_hex_string( + "0x04d4741d3299b7bbb31cec532b71d44e172256ea07813df153a5c785bdd725c6", + "0x03444d9a0d5fe64b773390572a8f74bc4ce5e4a15a307ec0331a87da7a1cb442", + ), + StarkCurve::from_affine_hex_string( + "0x04df37f84271d3f2e51ced3f0558fbd37e34576351e326f0753442a200c82dbf", + "0x0146aba4e6d484d914c0d4bef17d9d3481cefcce82220d4175666ac58a8e7fa7", + ), + StarkCurve::from_affine_hex_string( + "0x004574b476566219b42bc7ed59eac3dfd82620b28add0987027efac175f4c6d6", + "0x0193418833fa37f88ecc54fad3b5536afc3a89fce7ad785985d61f8ea0bf80fc", + ), + StarkCurve::from_affine_hex_string( + "0x04d2caa1323012e4c83b0ad387308b8aef5637bc35ddd882e7f5e41cf2ca410f", + "0x0047150e808c81a540b6f8864e9d6636589cacaa516f82caaa96506edfbd6f0e", + ), + StarkCurve::from_affine_hex_string( + "0x03c10a6083c38351deb3e6d1b386827d0acf48979b66b95249eb8700ec26b069", + "0x047e34bfe561d903cffdd1d849b85aa3cbd31cb4a9bbd8cc2e5fd2f95016cabc", + ), + StarkCurve::from_affine_hex_string( + "0x05b53ed4f24d6425fdb7d7eb14237ebd3bed6fba1e05c0c415957e2c85f423c5", + "0x03dcdc770edcc7ce9bb5ea50427344b9bdfd3c09a0ba745c22ab04c585b15cd3", + ), + StarkCurve::from_affine_hex_string( + "0x00758bd54868eec045d0b4d3d2bc415d24bce13fee47cefdfda46425c109b657", + "0x03392a7c66ea3bd7b044680bbe9f78ae86752097404c067e9d2572f55330df83", + ), + StarkCurve::from_affine_hex_string( + "0x00f96ffbd7dedac4aa2ee3eedba5e23adf118ebffebc61cd22893eac90cdba24", + "0x0174b143957fdb13f347285daa6211853402b68c8144278bf25cb19d87705eda", + ), + StarkCurve::from_affine_hex_string( + "0x077858bcf3d732c7047fa5963a549d2cb04f51417c4e26814910b715dfd8031f", + "0x0007ef16a77ddf99a464c9f7e17d3fc155456c0046ffad0a2391c02438c84260", + ), + StarkCurve::from_affine_hex_string( + "0x05560327ffc72c93962497178e4d06b11dc5d331277b5febad8cc675c2fbe8ce", + "0x06f858336742a532ebfefca704d9d12f858ea414267f0420efcaa5ab87d0cc13", + ), + StarkCurve::from_affine_hex_string( + "0x019e718e0ca1d2d6fadbc6006ee7dda7a385430e29f5e239cdd4bb7c3fdcb2f8", + "0x05c68249b7fe03ea2e13481a63b6cd4bf74ce42009a89fee0b3f8f968b3ec709", + ), + StarkCurve::from_affine_hex_string( + "0x04c5e27e68f69bbc4696dd50e1ca8e48a75e631d264ff498e1f2d1d6d3b86bec", + "0x079bbb8648c1a2d22c9613129f11f56b62ef535387a1ea9fceaa99201be70dfd", + ), + StarkCurve::from_affine_hex_string( + "0x0177d4a8d96003159a33cc36cc748b3edb08f4411900ee5050f097c9e26f23c4", + "0x074f349bc165900bc522ce173111dc9705ed6419ea61114256a7836e909f539d", + ), + StarkCurve::from_affine_hex_string( + "0x0550d63a152be00d61aafcc6e1c8124de40a1000e88ef8ad94a0296ed198dd53", + "0x078ec5b1fce73d8b513e7fc3b2028313055ad78399ce64e5d676c38787ca8fd2", + ), + StarkCurve::from_affine_hex_string( + "0x04bebe97ce3a074f4c771681875ad88ba1e6dda5a50d4bf9374c5058ff3f1fcf", + "0x01968ded44bb52bfbe62de6ce6738ebc05458ec800483d1e2b9a4463911e098e", + ), + StarkCurve::from_affine_hex_string( + "0x040b1076e145968d6612febdd16eae576938f8d4243a2c7fc405854ea200982f", + "0x05cb4251006494ad97f116838381ae308ed5d0ece47432ee91f5e38870fc4ea7", + ), + StarkCurve::from_affine_hex_string( + "0x00c4653805d6a981547c4af91e4e48643132be20caa372f0fb1e9468f4bd385b", + "0x0044f9fad9383751deb8a29421fde721382030b7d49c562d84f4536a9a73bb6e", + ), + StarkCurve::from_affine_hex_string( + "0x04f2aaff527411a971e4ecbd1d6fe2270c3e847ba0b23f72c19bf9e35daf0561", + "0x05d0a2b800355634366fe5c510a56c03187e0599846ecca358416dec49aba95a", + ), + StarkCurve::from_affine_hex_string( + "0x028077f57ea62401806367e6d54fe45d02de5b072db787ffdcc3854e12a3e855", + "0x014f3762689072f5fb41d03e94b01808c739f6d42b7b785b0e464100b150efd2", + ), + StarkCurve::from_affine_hex_string( + "0x03b8a8cefd017363ce867265af3293cec081fa589fe561830f0078778cbd338f", + "0x069ccf2383cb7b4f9c806d72535812483e7c5e9a1a5928529d64ca7e085e758d", + ), + StarkCurve::from_affine_hex_string( + "0x05c0d311a77b2fd419324f818d6f73fa20b049d1b33f16cf92ae5fea4f1ff8ca", + "0x00dac5abf087ca1b97ead9c5f3280624b2f09c8c5ab59dbfa31e3ea11c400b9d", + ), + StarkCurve::from_affine_hex_string( + "0x077878f388d22161a2953e5aca6bac1ea480e102f329574b4b201640d44a296b", + "0x07eb35706a90a03aff7c2fecca72659136547cee98038746db5aba16fd7178df", + ), + StarkCurve::from_affine_hex_string( + "0x077d38821217473825441129c4d0ddf6d879ed3ad3be6f4f6a419564e260fa7f", + "0x05b94a5a32995515b10cd565337c965d3e8b13f7657c9c7e57f1da81006fd114", + ), + StarkCurve::from_affine_hex_string( + "0x05130b867b4f876a11b8d3eb90bc54b79d0649d67f01fc2071bcddbfb141bc81", + "0x0793ac682a1d447524b6958395537c948cc7853c13a1b48533fac970f6694fa2", + ), + StarkCurve::from_affine_hex_string( + "0x028f54a4412efc429b2050acfa69341ef9d5f23ad9e07fa78163e3a2110dd910", + "0x05e9295abfb3ac059b245e66750e770f1fbaf36ae419e6814120dfb9c0e8cea9", + ), + StarkCurve::from_affine_hex_string( + "0x0097332e6da70961f2ef31b7b628f1018d21db8db015922a301fca7d6fc6a8e6", + "0x02e37b06f639fc7a82601b744570a2619e543cbfaf60e474107fcaf4686d3223", + ), + StarkCurve::from_affine_hex_string( + "0x0101877811b23c19968e225e0a70eb20f542157045438cf08a9b14143d6da8dd", + "0x01ee60ba9782a51bc7aa2bdebb9e44a9bbb8045e4ca1285e47f0d0c76a48227c", + ), + StarkCurve::from_affine_hex_string( + "0x00d852a0069dc1775aa8283db719df76a94df9ffdeb5c9c034e621cc8b419c56", + "0x07cd079f80cee5bc8d58dfaf7285d62f5fcbc94f2424b6d2580235441e133218", + ), + StarkCurve::from_affine_hex_string( + "0x0581ee77a3da2170b5107c722f6a185b5f1188f1939e8dcc03087697e364420f", + "0x02730f16e2c7789994aee2266c003c501d1b0cf9ac16d4e443e1048e032e4d1d", + ), + StarkCurve::from_affine_hex_string( + "0x070f735a05ae6e62f79507335a1c7e06a198e7c9153cfd2645faa89be8fac070", + "0x063f832b42bf9e8f1db0d68c25b00bf615033261517379565ce5f5708357476d", + ), + StarkCurve::from_affine_hex_string( + "0x037a6db1d597af51d6ea07bf3fb606182906222689a4782f41398651edb0cd6a", + "0x06205f96c84c74b5ea51ab98ec4975143ced88d898f44e638633b91f0a9feba6", + ), + StarkCurve::from_affine_hex_string( + "0x03102084d2cc51ce1249caef5e970410e35e92a67026c736fd4cec07d71e387e", + "0x02c29071a77eed579ad7826ea899eaa20b1f1395baad34c463ec7b3d52c2f90f", + ), + StarkCurve::from_affine_hex_string( + "0x063bd66fd96ad49bac08e7550bbd576dfc8bdbb6f82693bc72e050ccf7509f98", + "0x0027cb2e583bdb530039bb144969698ffe7c21e812b8952dad52e11d75be369e", + ), + StarkCurve::from_affine_hex_string( + "0x00a81518d452d3aac48bf0386c3ff170ef4e684a4def242c964e129c64f4d647", + "0x037506e44c85908ec7b7adda9547fbdcc2e3605151fefa77fbf127ce3bc938f2", + ), + StarkCurve::from_affine_hex_string( + "0x00e80336b2220b1d666074f6b0dac85353d0e4c2e8bd0f37055a2236a6a9fadc", + "0x01cae76d73eda7a5964c5d9d3ad6748aff51f5543c56441d2fdb7b444a39846a", + ), + StarkCurve::from_affine_hex_string( + "0x06e1d5620b4717f966676ba9a82fc2eeeff7c164dee2290001de6388379cb8f0", + "0x02de551b0034c8fb670cfa6f64b166319043a1922b0cdde42c895a6826846517", + ), + StarkCurve::from_affine_hex_string( + "0x02c01fd8430ecb44e066f352c4f697fc9fda177dbe162f82862d7b9ea8c918de", + "0x06e1dfa99640fdf5b30603d34c7c97c1aa6e6b7f3a2c52a21fc64b0fcac7d591", + ), + StarkCurve::from_affine_hex_string( + "0x061acbe6646ba72c7fec41a5eb17bcb1a428c02e732f9565e7779d7c9350fd0b", + "0x043591b757f3e28aab5f0a38a4104d4f1dd01f301f8281f06315f3b9b399e940", + ), + StarkCurve::from_affine_hex_string( + "0x06ec3165176b8a7f35738fb92f3ea8eadca8dcbfb16ea0ef147693104bb85835", + "0x05d5eae1de56a2d0ef62aa2164687e79a44c4c887732b47d40921cbae9485cea", + ), + StarkCurve::from_affine_hex_string( + "0x03fd3d0db872902f8c2336586b8dd878bee6998854ac113510a040664e0c84b8", + "0x020c7700551bfffd7775ebf89164192f9379638d962587eab54b6401c97f1ed8", + ), + StarkCurve::from_affine_hex_string( + "0x0744e37b511cd0ddcfe15f3581947014c159de81ed055d15a13c7a2d1fa39f0f", + "0x0685caa8ff6979a6c63640ac638a3f9c75737f2031bd55322a47384357af164d", + ), + StarkCurve::from_affine_hex_string( + "0x05b82cf18d19f9f33006fa377aef9562d70f00c6b111cf906b5fc7ffff445366", + "0x07c1e725760d2adb177dd5f60b33d6afda9fa3afcb9c4a84862e3c871a5a1666", + ), + StarkCurve::from_affine_hex_string( + "0x02ac6dd6089a9f0706ff43e5f718865682554c8ef18b6fd8dad96ba60c64d8b7", + "0x038245d5b860c7c6bc27b15fb165a94208bf46204464f6366229caa1af7572de", + ), + StarkCurve::from_affine_hex_string( + "0x010fbcc48d40e7171ce955140a5884ffcbdd64e51d4d703ac0418a259bb3ee28", + "0x03a9d61527b21b3596f13f69736b249f62c356f2e719679405ca2386aa87cc5c", + ), + StarkCurve::from_affine_hex_string( + "0x04b21322ced1984734dab27834ff0835d7e11dc80e47c5bb1ca4322770ad1604", + "0x04f0f918788566ceb4c80d5dc44f93c3892e53f4225654a722b8d027c8888b28", + ), + StarkCurve::from_affine_hex_string( + "0x0107495d5480b5fa2bd416b1f3979d74d8c3c7940f23cb2ee398f7d1bd05ab68", + "0x0542049eaf3b747990ab8813601d94a17a8e646ad77aa800365c9b7d2aa8c780", + ), + StarkCurve::from_affine_hex_string( + "0x0026ae5b603e142298005b6f72038b576b6b2ae57407cb6df9b77b2037e6c7c2", + "0x065e85e4fda4b77ef3bf46d163b9c8dcbaf5dce559793047da74362575591170", + ), + StarkCurve::from_affine_hex_string( + "0x0697b161b7c6de343de22e5f88d2aeb56b42b7434351f8788ed13e1560bb9c5b", + "0x031c6fdc17c2056ef64a337cc2075c57dab41624c2784a8e965c383371599c79", + ), + StarkCurve::from_affine_hex_string( + "0x040e627ff84e1a7a9068b4368770f5956128a4d9e9e33e9cf5e24d9a242149fd", + "0x02465bd6cb20bbdf810e2bc5c3c458cecf4f3aa163a7ac99c2579e5f33417f2e", + ), + StarkCurve::from_affine_hex_string( + "0x05f635af7f554a17bceb6ccb6e637abf89ab6dadd399189b0a0390e87b1896bc", + "0x02aa6238a69f89665646c0e3ca2ba5f709cc6e14351cf71e1b00ec45201417a2", + ), + StarkCurve::from_affine_hex_string( + "0x0596b4fa4b4f2be91a068f6264c195a85a37ca3afc4801b36d0faf20a3164eeb", + "0x04812fa4485ae0617f9ae36455d4512893b734ae144693343c2ada54f5817dd9", + ), + StarkCurve::from_affine_hex_string( + "0x05edad3063c9fa8305978d7e6a4e037c9fa519b8023c7608dfc3b66e5c1e8985", + "0x049f405d07d7d01919da51159ecdad1031a5ac208c026fdfc14d38f633d92183", + ), + StarkCurve::from_affine_hex_string( + "0x02ab75fcb8298c34b6602eda6ae6ec7b174b1ff1ea72b7281f09b6ab12f794b7", + "0x0021d51d24be430277af92562e8255ed53ab630f2d2d2f96e2a49e49ad58223a", + ), + StarkCurve::from_affine_hex_string( + "0x06f0805363a53455e4750f55ce882c44767ff348748ed5c7acc382fbde1fb8f1", + "0x07a2f05341caee328ab86eecbd3b696182988ee8ef7da701b05b58d8845a9796", + ), + StarkCurve::from_affine_hex_string( + "0x02dd7afd786b5c13ba809590227e66a820232f9f6d6d6ecfc5a3c619a2553196", + "0x05403038267e0f0d01e9d35bef21f034043941240a4f44339964bc5bb802ac4d", + ), + StarkCurve::from_affine_hex_string( + "0x02fdf2e8a45858c12926a1f25a62255fb2d02d0149a15ef669f859806683e649", + "0x061cfb686bb31e2524470d4ad2ae09e3cc91b16305a21d748098feb1d8ce3b3d", + ), + StarkCurve::from_affine_hex_string( + "0x02aa41f69fcfb3047f343fef5cee789dadc889b475a9bdf3da0c80a79b4f50e4", + "0x010d686a8788c9cec2ecb4b56e1a080265c0adb9ac13a22ed073e33c7915f563", + ), + StarkCurve::from_affine_hex_string( + "0x0164aaf5945ec0709666b07bd1c6a4ec64e10e818f6eea2bb65f92e9d4cba0a7", + "0x02db2ee0fdb9c3d3059a4c4641817c935048c345f5729019195fee15b83ced37", + ), + StarkCurve::from_affine_hex_string( + "0x06af6d604e815a29a69ed7fb8f01d34fbf93e511f1657b376497b41f9a583dfa", + "0x02d437f9ceefa2c91137f8a6079d706ca7b337b44f8058d7b57a79d4186e6e23", + ), + StarkCurve::from_affine_hex_string( + "0x07ea26b17dbb2f147c1ba2a4755f4db6a7e02f9971b57b5e81a406894d7333e4", + "0x05550c4ddba908424755a2a32ea4e0b4a97a5439e1e3e77d750e6cb7e8af4469", + ), + StarkCurve::from_affine_hex_string( + "0x000535267265c637a80e79fbb3b3801f91e847178344f2c647c191b58ff377d9", + "0x0130382369b6adb9209922a513de990be6ffff1ce98fa0a58fee158d0f6a1be0", + ), + StarkCurve::from_affine_hex_string( + "0x079931da10835559bd6ff885d0fff6a1aa668dd7199b9e8dacef8bed2d706096", + "0x0025c52b0ccdb02a146cf5836246a0faa8e46571c493619e9050a527c9db08ee", + ), + StarkCurve::from_affine_hex_string( + "0x020a6724eb9658d77945e66697da9532e730c28093694baed1256592b65567d9", + "0x06a0455ca25db01fd56897a5fbb8a76818103ba0401da3350d0e636b389c685d", + ), + StarkCurve::from_affine_hex_string( + "0x00ecdbd7c37f1dffa3943977278da3bb429afdf948b4ea6cdebace3d3be82381", + "0x0190b67fb34f7f3ad6afd3d6b6427aa327547d8ac0fb4deeb0feeba1f63d6c60", + ), + StarkCurve::from_affine_hex_string( + "0x0233021b483f578dfa5222f8cccba5766ceee0ac65f6d4a3b1673b302a21fb3c", + "0x07d4b6d44d175d4b593f06f5a6dcba2cdbc4eaa2097abaf613123546866cf4ef", + ), + StarkCurve::from_affine_hex_string( + "0x051029f3049a0ed76fd975a5dbf96f95c5b8071fedb3ab22ca083170d756f5c0", + "0x01dba5faa0820305932740596754768ada613702d1e2de597b714befabcc41a2", + ), + StarkCurve::from_affine_hex_string( + "0x042db4e953c2a7a743de9fe20c5798f2247f51db4eabc6f40e86c13909a310ce", + "0x012c1a0764a0b9f3666e431923ce15e7fcd0ded5ab153f0b48d362cca1604e65", + ), + StarkCurve::from_affine_hex_string( + "0x064b9aa4e47859754e7ab88bab75a9bfd1af39328a6d4781e04ef6ab80827a20", + "0x03e9c0181198487589210d982f9e8ab75a52a389ee64f9bfba1efe802ccd9a55", + ), + StarkCurve::from_affine_hex_string( + "0x0478b386fc0fa614edf59e9acf8328cea4ee522c8e12ad76e8d6fad6d0585fe0", + "0x0425a32f3ca1469672c8fc4b42e65b2c1f2eb9918cee7de5ecde296419f4290b", + ), + StarkCurve::from_affine_hex_string( + "0x0494e197a80bbf91143b6fc297b6bd713e43530c417a1e8efcf75ed54bd1d108", + "0x0260151e5dd70acdb8d2a9f039d41f68e640583a27ecd73a532e54bdcce6feb1", + ), + StarkCurve::from_affine_hex_string( + "0x030d539e2b545fb957e40e2255f6463b52d227c9808472cee6a3d521aa283a44", + "0x05f9eccf747fe6313570f99e845db32b40070acee9ce9e34da7f3c29ca53a07a", + ), + StarkCurve::from_affine_hex_string( + "0x0556e72a989a93ba4f7ff619f33baceffdcdf04f511fa5a85c87febb6ae9816b", + "0x005923f16d1dcd28803b4c4f9887226e0a6b8f9a4d02de3e5e5bbfe3482d5526", + ), + StarkCurve::from_affine_hex_string( + "0x05eb5dc7881f1abdba0cc5f972aa48c7caa6e5e55f903d6942b88c869a36ac78", + "0x01ef6017ce1503269642c5540d1f7cad8ea2cd969dff046a78eebb90b6a487ab", + ), + StarkCurve::from_affine_hex_string( + "0x07a9659d97d654c41e0290ce6f01d0ee565e882d19874c72c18326b6132ab319", + "0x068747f827fed829de8852a4e8054658ef01ad65abf10d2b4091c48180a09bc8", + ), + StarkCurve::from_affine_hex_string( + "0x025762c16d4ef475217a408df6365e01c9e80f7e08770ee0245aaa027a67920c", + "0x05dfdafe1ccf4653e1ccc2a5b6a4302543549e4dea5d174a77a8c9caff1d6aec", + ), + StarkCurve::from_affine_hex_string( + "0x07b12a68b0e65a7c159a9e746b43ad689f2770d88646556e177351f1e390dfcd", + "0x073866127f7ccef3018574cb4c8c3c24643476c76301ca1562595db007e18874", + ), + StarkCurve::from_affine_hex_string( + "0x02ebbfdff1587fcbb837a3a59399efb97d9e5703d01f69460e24253a9c96e052", + "0x013c5ef28a8fea7d55c86f13dec8eee8d3b145e5266002e022f34fa7918cb558", + ), + StarkCurve::from_affine_hex_string( + "0x048029ab9b4e0b86f9d061a72b02ac89b594a4f353ddc2eb6c5adec7504d25f8", + "0x02c092af8e180b5ac407efdf7206785ceda893846649a5b70aa67bc71d7af7c4", + ), + StarkCurve::from_affine_hex_string( + "0x04bd64e5ade3e2733580a6116b4af328751198e7128f9acfe3a3496b545efb5a", + "0x04d584768900dabfc0dbaa086632b8051bb3905ef79b84d96c01514441d0cc93", + ), + StarkCurve::from_affine_hex_string( + "0x062d6e771f02e591557197d13c3e77dfa2d1794ac1808407bd8227c4be31b466", + "0x05c6f5607c1808e899ba36a425911fa8566b7ea9cc80de8a80538c0fceb837c0", + ), + StarkCurve::from_affine_hex_string( + "0x01c17db731647525315a5006f75898ffc3b7a53f5cf21a7ea08637c689991ddf", + "0x038c4d265fe7ce9943ab7e5346100caff63b38d96b3975c6a336f745714a8463", + ), + StarkCurve::from_affine_hex_string( + "0x05ce406218cb2852b1d2fe1836b19462f664631785216e87ffbce26030e2101f", + "0x005225f107743c255ab50e7be4a090fe39478d1ef4ff558468559d8cfa87bb94", + ), + StarkCurve::from_affine_hex_string( + "0x033e45993f953dea9cc0087d52024d87d941d4bf2e509e68ed50b259095cce3b", + "0x00cbe182982e1dfeab42c35518862f225365fe347b28fe254b13053fc22e4ae3", + ), + StarkCurve::from_affine_hex_string( + "0x0519b060a183f426c47c74561219779e29347c69d3b51910ed4b79fb0ba9aca8", + "0x049fc4b63fceac087d70bf823ce543d11cda3991a494824dc40ca66a8d6d49c0", + ), + StarkCurve::from_affine_hex_string( + "0x068af44505ffe94e26652f548ae1319aa989f59f8efe43952d7b33c6e3bac277", + "0x009949cecb638169b38c98df2147dc476f96bb503dced20e40acb7d3e3cc0ded", + ), + StarkCurve::from_affine_hex_string( + "0x0670286486e8dda3dc66b0ed3149be7697d3e06c8279844079daa7e42d5af728", + "0x026becabe7430380c56e320f5ae3329569cae7b0af06fd5327ee23979d200eb0", + ), + StarkCurve::from_affine_hex_string( + "0x06f3efe2d20646cc6e806ef82f8f2f130173ccf94686fa7cbc4c962ef16b1b45", + "0x055015d129700edee2a352ed976655c05c09eed935152b89a5cba022030abd05", + ), + StarkCurve::from_affine_hex_string( + "0x0239c80cdf883fd008cf25b5add33dcf7093035e460052c99f84bd25f9ca1d76", + "0x022e4ee53720e10c5c1296b2bec17a4d52d56b086ca78c8a090e91ad73c54d6b", + ), + StarkCurve::from_affine_hex_string( + "0x058e0b033f76f5833dd48a12b23d100011e04c507b88a83cbc093b5a57ff1167", + "0x02d3ed5b8698128f533d67c6ba6a28c1f50d0fd53b72c6a8939d331412bab946", + ), + StarkCurve::from_affine_hex_string( + "0x052afea921387b3463ea450060c4c30f5f9d9afffbcf0f9c28dcb2bc14ba6cdc", + "0x03fda9f9ca9b9840bc3fd186ba2fdbb45f8be60f966c2b131efcfa6ee2e8ae51", + ), + StarkCurve::from_affine_hex_string( + "0x025b98f27cd574a32078c99ea97c8d6a1a06d7e86c45d6ff0bd45574d4d851bf", + "0x07f035b3a6438b2f7ce7b1636d55987f6bb634c119cef3df144c4540ed12c1a6", + ), + StarkCurve::from_affine_hex_string( + "0x01ac708b03df8eb469da19f0db6c20ba49152b3c2d36fe97c8f17c67e0a7ac98", + "0x029e686736becb59e5b945f235d0c0ef5f93ef800bd144bfc09e702f3d873c57", + ), + StarkCurve::from_affine_hex_string( + "0x01b6835d1eb2a092e256965ecf72910dcce98f0fd266021296b91e93f718a0ca", + "0x00b85fd80a6a422fd9fd05a746ceed661728d90a6650d0ccc5c1f71f8226c304", + ), + StarkCurve::from_affine_hex_string( + "0x03ef448df33a4394c43e93e5850cd0c5a6dcb18ae1cd865d00fe8ede9336a9f5", + "0x056711f6ab7e0e4f7365ac34e284ac2879f40208c46f6febcc1dcf7146ecf015", + ), + StarkCurve::from_affine_hex_string( + "0x04b63fc130288e92f2d6ba238caa7a6364804e29829ac037c57df32fbf762bc3", + "0x01eb8c80af55278b4113286c038fff2bfad2da62763bb03426506b869139da0e", + ), + StarkCurve::from_affine_hex_string( + "0x0239033445549ba6cdd16832e9a1fcad3173b950fc400ffd4074721244e1d389", + "0x01d352dc5e2c354a08ed973cd8f381542bc3a17946a53d10ac7236d1e7ca488f", + ), + StarkCurve::from_affine_hex_string( + "0x04e7e998557b29a95f805a6e2e26efc1e970108272d4755738c04f28572295c0", + "0x0097cfcc2f447bde61bde71049d8200a74a3028b21703bc139143d81a3623f09", + ), + StarkCurve::from_affine_hex_string( + "0x0521199f9446fa5d400b26435a0a168d0d3742b20a5f18de81fd04e3b81e4cf8", + "0x07cbf600a847e8b9c5b66ecc148409d81cbdefa075414b05b031bd8b7aefd185", + ), + StarkCurve::from_affine_hex_string( + "0x001f43845a2d8c93cc2bf5becc94510c8fd4f2e683a22d6f7d7938967be3d196", + "0x005e98376cf19793c9d416ae241d441fcf8f0b3edc559573e63d79c3d00903b9", + ), + StarkCurve::from_affine_hex_string( + "0x029d28ae549b22987b41d92dab8b01e7dbbb246fe68a1e0d6698eec0cb952f61", + "0x04d2bf6aad6108f969db49579167a0a606e368d509677fac5b8dd3e30fa83b22", + ), + StarkCurve::from_affine_hex_string( + "0x0574b67898f02964c408f68e9470e7b615be037e40b824e6617f89cb56c21219", + "0x049392d5f8e6740a1b0b7444f56d7a17363f8656c6e4c628678c86223f2e46c8", + ), + StarkCurve::from_affine_hex_string( + "0x078ea7321924e2ec59229cdebd581112d64d8853248a68930533477f76ec150d", + "0x0258e8bc39de0bf3d409c42f214e7e12e2fa57aff0023d995205c08c842eede2", + ), + StarkCurve::from_affine_hex_string( + "0x03ee62bb150966cd8e4c311bb0d44aff011cffe3a1fe9b0138c6940a6d39c4c2", + "0x06267246353880cb8bd575593070bfc4cafe070efd44c5abbc2f1007b4915cc4", + ), + StarkCurve::from_affine_hex_string( + "0x01a1376586c9cad5996152a2c91e66487b78b49779ba222a1e56027b3b452521", + "0x0058614d4a2593b3f345a8a93e1d7f0884ad91924ec53b8f67b2d3bc67012103", + ), + StarkCurve::from_affine_hex_string( + "0x02ea507b8f9626a7bbb31f57da7acced896776b243de80fa4171dbdc0d364616", + "0x0553bb634865ebb75217ead801db3a3eb9d2a657923f9c047f5ce04cda31d6d7", + ), + StarkCurve::from_affine_hex_string( + "0x04cb4c44c846d16756a832f94d0cb3b34255fd0af1acdd8afa6e2a139900ea5b", + "0x02e4a6000a2b0558568d521573a17b3b4d0352a7ba65854fb8247feb029eaff5", + ), + StarkCurve::from_affine_hex_string( + "0x05717689f7852539acb02bffda0b4a4f5d94dbad8c102919640316d4c8908e29", + "0x01b042f9bd3da92b2781375832a7124b83ff4387e2ef05eb3a71f0b024ef13bc", + ), + StarkCurve::from_affine_hex_string( + "0x0737e12d5cfa91f74b566eafd2e1e983237df9b5e801810cf7e5df439e0717fa", + "0x01506afe2ecf878cca82b1ab6c4aac0a89d81d6a503defcad62b41d0b51d08d3", + ), + StarkCurve::from_affine_hex_string( + "0x07e8cb50ea5d5c1b09e219e7305bcb601d99b6d7185b1c388aa8e36fe1e56554", + "0x047fefa308645455c12ccb5817da338f0c4f423b341aff4a9d158891a4fd69ba", + ), + StarkCurve::from_affine_hex_string( + "0x067266dea9e71b4ed2bf24a597a823dd048cf31e725db511edceac72998c9ef6", + "0x0039babd65850befde1f7c28e41dbdbb4caf82bbcf3bcb5b33161f1c2960b2d8", + ), + StarkCurve::from_affine_hex_string( + "0x0428e9e475a6e9cfc7dff82c61736a59493213532d7b5fe156bc938f5351c95a", + "0x02e5329d24947f6d4b33d93f6727e6296500b32bba4efd8b6b9e8fd77a42d36a", + ), + StarkCurve::from_affine_hex_string( + "0x063e99c2cb9c74eb9227d48065e27abb8f606df8fc83b2c44e4ea38b046bad2b", + "0x0060494a53dd13ecf34e08079d343c88fb655d6d810785af81f08d5aa9bcdcf9", + ), + StarkCurve::from_affine_hex_string( + "0x015bc22fa74be34529d89e9caa3447c8aa69b59876f5c246b172fde0e633a804", + "0x04b060da7352bae45339126507f06de98e338869ab7af88290eaf05fec133ca5", + ), + StarkCurve::from_affine_hex_string( + "0x0581210824055a3abab598b09969b9c7ee5e1647a0829296b494dc9a5d5d8790", + "0x002c3bea3a5a48b28edea978527a034b3d0eedf31b5e2f84bc219e4eb4f87091", + ), + StarkCurve::from_affine_hex_string( + "0x04154df9c2e7cb35dd9406bb5abef8fdc604a878645fdfcaa20c74e0f90ac26c", + "0x0232d1195108b296641da56468c5f966c0747446000e6a1349118fddf0a73b42", + ), + StarkCurve::from_affine_hex_string( + "0x03cf0600b0f5a2a4eb78c487cd385350e8c7848e3f6983231881d7f1bbe28543", + "0x056dee4288528de609976ef6b903b652127c37b0590e91a2fdbebc3f11df2628", + ), + StarkCurve::from_affine_hex_string( + "0x000cb84502bb9f4d522687fb257a294ba567777709db826c9bbff2279efb547b", + "0x05ba8245f44f9ed7d910adbd1612fbe741e4c877ecc3a1a1a7b278cd96b5bda4", + ), + StarkCurve::from_affine_hex_string( + "0x070cb9810272a4b0f942f633fba3803e5fb8bc0bfd13486ff2d972ea75b443e6", + "0x07d74d480975481b74055b6df39779e94b9962b4025e119c762bb8886a777226", + ), + StarkCurve::from_affine_hex_string( + "0x034e5a569337b4f739505bb37f71c338fcd9d2c0b44b77f33d77c32dff812221", + "0x036d152a8c4621a21c0b3d29182083c2039ae18a77bfce79a56fccbf6294a4ee", + ), + StarkCurve::from_affine_hex_string( + "0x00cc765de9b91f130842acdc9359394c914f3b295e5090a48aeb70b55dd79d70", + "0x04153f4dc6bf533f42e74f0ea7e4746f71521f46ba551a0677eed8751e2bf6d9", + ), + StarkCurve::from_affine_hex_string( + "0x0118250c46e57fe8b35a0a491b1033b1f20de59a06abeb56cb6654ba07a2d049", + "0x016cd5be1a5b84e79bee29d6ffb0a591e6f780dccf409654d1f39dd30bff7bc7", + ), + StarkCurve::from_affine_hex_string( + "0x079e1ba69cff094a869ca36b47c370062be11d3ca6529f36505394f6a822c2aa", + "0x0327cc3c2def161f2f8c5165c465f9900fa14c8dce3baa1b74d1debe8a30e2e5", + ), + StarkCurve::from_affine_hex_string( + "0x043c260e99112734f558d9fe7e6ca1ef8c9a64f881e0fd9b480c899bff94750f", + "0x06465cd19d30d38e42426829e012f9adfcf2cd319e01b2d92f8784d17ff635aa", + ), + StarkCurve::from_affine_hex_string( + "0x0758f09245fa4b8b23d290ee2b3bfcede199b4fdb11f3cf2502a8ceedd61b129", + "0x0622d9baadfde781e985d9722e0a04715666769a4cc7a9bea0b96d6386be1746", + ), + StarkCurve::from_affine_hex_string( + "0x038e1a45b81492aa95d7abea2b08b8c14dc0b8a41108b036871fb737910ae18c", + "0x0145c611262656385e5ed6243568cd3f9f59dbfed7a01ba11e22bb8bb272e08e", + ), + StarkCurve::from_affine_hex_string( + "0x03bf6bff466cf5c43854a9373c81c31628165be11694ef1d6701e3342a4150bf", + "0x031c1af03ee713ee15b08838a9147a6fa56a15eedd15f5687a1df41f9bfe100c", + ), + StarkCurve::from_affine_hex_string( + "0x0206e54ca53a2f155bd4fc45bf2edb77798ae6623defd4cf22f2dd4a7d119dad", + "0x06c94e7f0825ad81680e4cdbcaaaf4df806d57a0d1fb2331926c3fe2b79d22e8", + ), + StarkCurve::from_affine_hex_string( + "0x0302a4ba23137ad9bccbfccb328dc25b8e1173e097b59810d79f207cfdf7ef6b", + "0x006c952eb7fb3f585322f8d6fd133f6b78303b191618a189d6ecf7decf966412", + ), + StarkCurve::from_affine_hex_string( + "0x0106a9c62c5405334ed27a16ed12341ab2c17e913a05ba001cda623b06d88adb", + "0x0158427080f8ce96d15a3128ed44e4f54e23419eb8626601d270ba52df8fe942", + ), + StarkCurve::from_affine_hex_string( + "0x04a6aa904f920990b1ae1ade15b37a3de3f93e0fdad78e6cb4fc262edeec939f", + "0x030071f5b6c44b91d0fb0be4200580393b7eaa2db8eb52c550413b8f78e0a008", + ), + StarkCurve::from_affine_hex_string( + "0x0056e98d2862893caebf66180e84badf19ffc8b53041eaaa313ae7286a8fac3d", + "0x0526306f9c01afd6e0c1198ea5de17630f5a39c4ecd02d8e6f0d613c355995c6", + ), + StarkCurve::from_affine_hex_string( + "0x0384acdf41ad76c51f898f1b8e66f6fc984b43f70a0303fae6847ed28eecd6c7", + "0x04ceeebe5412944e58b9d16a5a8b1a0bf6b90a872e52d52ff8c2214137e8ec56", + ), + StarkCurve::from_affine_hex_string( + "0x07e28dc225059412f4f6a2379038e7c00ffe6053a05bf41fd6c0c2bb653d083e", + "0x065ceccb9843608d93a1295920c8bddd8e964740b432e83bfb40aae90895ee74", + ), + StarkCurve::from_affine_hex_string( + "0x05f29957de1b7dea65521a1e8328fb263952bcb5e749bff3fa07c7c7326d9134", + "0x047184c0bdc7dd4f44816eb3791cf8d6b757876abd3d9badd5cbe9060a90ac82", + ), + StarkCurve::from_affine_hex_string( + "0x042a869b5b30304833d084c561ae7531aba65dba7f03acfc9c71f61e7910fd2e", + "0x02778f94f220608443d0f6fecd1c09118a7e6edd72929c7421317abeb6eba5cf", + ), + StarkCurve::from_affine_hex_string( + "0x0704d2c3675084df3e661f548142c2d3fb8d6bfbf13a2f52ea53019fd2e96388", + "0x02805669a0e5e23fe38f58fd2b70e0e102c499d91f239881d8c635e75eacfef7", + ), + StarkCurve::from_affine_hex_string( + "0x04e09727e95d09ae53f9036380e0bbd64e4078688eb8013a79366fe59d65986a", + "0x033478da9435044a5f47d2dbfbf0b015e575916f4f32751be1a433450e5516ca", + ), + StarkCurve::from_affine_hex_string( + "0x01e52b3479c49a28a60362bcf8f0e607462f8d50fca5d4050c036d56ab6d51e3", + "0x0056992cf01cf709780853a8696eb929fcf5bce93eead6638f36d6d931c7996e", + ), + ] +} + +pub const fn points_p2() -> [ShortWeierstrassProjectivePoint; 15] { + [ + StarkCurve::from_affine_hex_string( + "0x04fa56f376c83db33f9dab2656558f3399099ec1de5e3018b7a6932dba8aa378", + "0x03fa0984c931c9e38113e0c0e47e4401562761f92a7a23b45168f4e80ff5b54d", + ), + StarkCurve::from_affine_hex_string( + "0x0450cfaadfecdb8a2fbd4b95c44cb1db723ee5ac9677c9c188b3d7c8eff4ca58", + "0x01a552bdfc0c81be734f1f6ca9a6dd3ab4daa61c11fb53ebb7046eee25d617c7", + ), + StarkCurve::from_affine_hex_string( + "0x05f3c42968a2445f7784eca32c75bd399e9a455b96cdeeac3fb1e4c4b7d83c50", + "0x07199b045fbce7d84b22893681d2ea2ef18ac5eae7cc54d3206bbdddb8849b5b", + ), + StarkCurve::from_affine_hex_string( + "0x06fe20e5c8a8004e33eafc84d16ef770f2f0b7bace19adaaa150f987d295a34d", + "0x028a35040a2ebe9a14a162d3208d5eabc6e2f3a8310f926bd80be65aa71775e2", + ), + StarkCurve::from_affine_hex_string( + "0x016133bb52fbae14156cf016efff8fdd75ca7015430f57c435c2ff037422bc09", + "0x0512ff1fef37e3d58a1e440c5b657564eec7e28423cbf485e101647d0a98bb9b", + ), + StarkCurve::from_affine_hex_string( + "0x07b538804570a7441a0ae68824b42b2bbd131f5136f3aa20462538f2be66cee6", + "0x05a43a2f1cd9473c474eb7cd16145e663d0ec7d6d6615d08b971e473301f906e", + ), + StarkCurve::from_affine_hex_string( + "0x062241bd2e386591860d327f584fdbe23a527310158b45e70a182a73366f6e6a", + "0x035b798367c75565fd2992d8116cd7b319587fb860e91f367309e7f49c3d1068", + ), + StarkCurve::from_affine_hex_string( + "0x01bd65f45a35bf62ae8f9ffcbd7de2976b90518b6820c219f039c50043bb1edf", + "0x00fb5f0f8659f9b6ed7cb0ddd7999506d0c20b26bbe69d1915a31842cfac41eb", + ), + StarkCurve::from_affine_hex_string( + "0x003c5bff101300681fbf53fbcd5d2c6336e2bccaac0f50bc13d5762a3a0fd1fd", + "0x047cbfb37b195d96a8d6e97fd77f5d4d021372d1182c31053a97cdc382b5507e", + ), + StarkCurve::from_affine_hex_string( + "0x05c1babb3bc6c9523c8fbe21c7b2f47e78872fec5dc8d7ad9059999e61688858", + "0x03b26d5842e25a83658936c2f9c73006e8cb38d5ade1c12a019bc15ae5d8a540", + ), + StarkCurve::from_affine_hex_string( + "0x0388b9b148376f3798ab8a98e5841e51af6d0776010d1cb1ab79fe581d836f02", + "0x06b1fc368952a8a3ba7a2e7b002fccefbd502268ad3a45a2bccf773420797dd3", + ), + StarkCurve::from_affine_hex_string( + "0x051f7cc598d932c162dc4feabc484e032122f13f0c23ef1e2683c147d763fc86", + "0x0292f639305626362e677e5ad5520674d996012c6dfe9f3c4f96e607892ad73a", + ), + StarkCurve::from_affine_hex_string( + "0x0698ea44aef29dccf0ca89c3e0bb993a8f2d1d8c080c2c9475ae0f8116ba9aa0", + "0x03ddcd75da2cfe6f55dc28e76ebd22bcae65153297f9c8c09e93b958688623dd", + ), + StarkCurve::from_affine_hex_string( + "0x023650abad25aebb28499719de43930a68af8c9fdb76fec5e4e52b319c7fceb9", + "0x031664dcdedc69ddac2aaa4eeb3afef71c3f1dc0dcfd9ee78cbace6f7c897d24", + ), + StarkCurve::from_affine_hex_string( + "0x05106cb5ad3f20feed8426e97c2bd3fe9f13e2d0c69536700d14fd041e5d2a9d", + "0x079c66396d43746dfc11afc1446bcce12ab0078226db534dc6642a6f1b8f750d", + ), + ] +} + +pub const fn points_p3() -> [ShortWeierstrassProjectivePoint; 930] { + [ + StarkCurve::from_affine_hex_string( + "0x04ba4cc166be8dec764910f75b45f74b40c690c74709e90f3aa372f0bd2d6997", + "0x0040301cf5c1751f4b971e46c4ede85fcac5c59a5ce5ae7c48151f27b24b219c", + ), + StarkCurve::from_affine_hex_string( + "0x021cfbc678f5a279ebb6ed124273c8df37eaf12a2d04180403ae6b5ec0b1e1ef", + "0x04478ed6a346d899ad7b0b10350270aad39ddd5b68529297e4c91a54357f0a7f", + ), + StarkCurve::from_affine_hex_string( + "0x04dec38409d5dfa77f4ca0a06c15426874cbe0cbc6ea99142650e0686187835a", + "0x048807c844c79d243a4bab8ba138e983fef7560fa3f2a0763bb42f96d8df9d6c", + ), + StarkCurve::from_affine_hex_string( + "0x0350bfefbe3d864eaadac9cc1195c14159bb736be743aed7380d2384cadd2046", + "0x05e2a4b3ad0e1d7b9b8ef72b10d68a80e5ee691d7db591fcfbaad6240d41da8b", + ), + StarkCurve::from_affine_hex_string( + "0x019e6016dde5ddffc7e7f0bc62a6d8b2449c350b1fd840ccf884c8ec50e02c19", + "0x059af2e3bd3001fb9204ddf012dfc235d3ad98cce0baff76e1b5b9f4619b0d3d", + ), + StarkCurve::from_affine_hex_string( + "0x00efe19f848cb8e36d2f616fecef330e1b623af75aaaaf2e11d292a64eda55ec", + "0x023ad1628d291b58a643958bf7cd5b98ccf79c24fcaa9eb078b7d961e34bdc0b", + ), + StarkCurve::from_affine_hex_string( + "0x07814f68038950e432aff0cef8e96db5e4527a84cf05993c1e1d240bc7a0e6b9", + "0x0572872b92a17a89d5a2683f227b4770cda6257aefa7ce8fcf14f406739960d6", + ), + StarkCurve::from_affine_hex_string( + "0x0529acd569127f73c8d34345f87e96cebfb48ee12a00a3861cda209337ed94e6", + "0x003120671a89b705e5bfd99b0e7fd2118b4914a3ac309b3d74527cacb5ad7491", + ), + StarkCurve::from_affine_hex_string( + "0x0304f0eb6b09116061646f88e8a7721c656716c96910633d18e3c0756189877f", + "0x027ae2fd82000986a20fa0206eabf4b1b7ad5453dbb6c61dc6d13abceb49112b", + ), + StarkCurve::from_affine_hex_string( + "0x02101df17e022d3d0c125e8fca21268c512cc2c0f85477b42914ab1f4cf1cd8f", + "0x07d825bb842cc4f72cb6d230d4d7f28c635205c7857470bb72059c580538d670", + ), + StarkCurve::from_affine_hex_string( + "0x0660cc21392a3befa682f428644662749be4393f65a16a7618d09946c58ffe84", + "0x035ce3168f6d250dfab31726d06d40dd5cf95e1371496a0471f83ebd4f809b70", + ), + StarkCurve::from_affine_hex_string( + "0x052e9229d27d295d6ff60ec4778d701b4d128814b266bdf88be36e43735ac6a8", + "0x0655ec98747fa55c63ddac1b84eac72a5993268802c1056c185dec406838fc7f", + ), + StarkCurve::from_affine_hex_string( + "0x037b591892f3493f6d0513bcc535e03321359555c87249955899babc04a06845", + "0x024c4904a48358bfe7ffb2ebe06c89952e1b6b912ba646c166dd766f5692c386", + ), + StarkCurve::from_affine_hex_string( + "0x034c93ecb083343ede2a6083fe14b3d9244160f1796d80b2576acc8276fbf0ea", + "0x009d5dd7ce78850029b7adeb6a402993b64eff29f129977d3d1960a0a154de48", + ), + StarkCurve::from_affine_hex_string( + "0x05ed0e3fb9cd1367a1148d1ba9f0c9f83f59886499de433833312a05cdf5afe8", + "0x0457078a1b1168fad9859d5d21173e1b601b4a7bd203390ee298a08cbcdd5ddf", + ), + StarkCurve::from_affine_hex_string( + "0x055d3d7956a97d10e65a4d8ffeba40deaf0db0b57f8e022cdb3df6df613f5c6d", + "0x0159e59a6f92f48fcf85aa96c1a03749a4c4e2cf9e2bc94dd36796daebd9b8b9", + ), + StarkCurve::from_affine_hex_string( + "0x0405f019ee8f2e972a005c549b0884b5051f63d1e78480b73208dc07d8c65a1f", + "0x04301a3d0c285ad309ff24a12c100ead7f48ba1368143712f32ac141ab4d9e8d", + ), + StarkCurve::from_affine_hex_string( + "0x004a3a53db1f9b9da9081b4aee2073c7621b3ea3e06a0afbd312802f6af2b612", + "0x01e51ff9719903acbd54bdd956980b21531f9392f1932e9c80123f27b47b5883", + ), + StarkCurve::from_affine_hex_string( + "0x0376d59b298d982f02dccad0edd5bbd4e5e8fad7898750675ed0856850a7babe", + "0x05233b12bbc50564eb61cc098a17d3d97f06ec7a230380e4c5d3b725cc318eba", + ), + StarkCurve::from_affine_hex_string( + "0x041f40e1cd7cf3527052219197c3d298470d78798fb0df1b1326a1c5f336ead0", + "0x00c4e8c3c95c83107325cbf0d916ac4c639fe0509fc07e3cdeebfb1c61494cf1", + ), + StarkCurve::from_affine_hex_string( + "0x010c9eb3842bd85b01e1f52736e6e177d38b537eefafeb808d59367afaed0e89", + "0x011fb431eaa96cfac413899040e10611cc2bf8973dde41d3e83608d4af4a0f4d", + ), + StarkCurve::from_affine_hex_string( + "0x0548a0ce82097f8a4ec3388ac2987143e1d250878886beb3d551483659a6d763", + "0x026317a88f7055099b51feb102f57181d122908210c65169c5bea4683ffe1371", + ), + StarkCurve::from_affine_hex_string( + "0x02f55624af6109ef04b2ed035a44a904ace8627f55889f011f768aabf4de9a38", + "0x07f64209ce7dfb63337ccf3d8c14f4093295f86996cabfee23b1655549aca089", + ), + StarkCurve::from_affine_hex_string( + "0x0418bed0918cfe3322317668e820d25b6bc78962ec5f55b5c7e11a1b88de23ee", + "0x073b10b241574ee4318c5026084b11054321bffadcc42c98c09a218c33275a14", + ), + StarkCurve::from_affine_hex_string( + "0x03c4fe3b6c73cc17a200f5a4b8706dfcf2d91722c93d4cfd2ccaf40145fd2e2b", + "0x0139692d8a1d9d39cda0f209d7700185f8b0f75bf84f24378b4ea39f1a29c855", + ), + StarkCurve::from_affine_hex_string( + "0x0742001cdef8cbcf4eb9c804b75be16e990a265956f141983172193b8779b4dd", + "0x02d626fc4750300560c321172ec01964d3b5f93e631a87d8cda92cecd5fd564e", + ), + StarkCurve::from_affine_hex_string( + "0x013ce745617e5c71273a73e2464150a2be427202b391b6c01a32b91595689660", + "0x02b8b4dee326ec51aa3b76dc79f98050a6386a01ec2e06071b9c5326c8e7b57f", + ), + StarkCurve::from_affine_hex_string( + "0x053c4b17a2b539c6a887276dd1d9463a0cdf4e888a215768b9a4148e2ed64e0d", + "0x044f48ba14d14bb381a547f66fb58676c19be8761d34f00b52d94efbf69c1364", + ), + StarkCurve::from_affine_hex_string( + "0x075fede304ee6293c97470c326ceae4ca168f566eba8a15f17c260b2be1d6980", + "0x0451a66bf37550bc4f592d04a8cdd2e754f4cc827513cb9b5dc12d9ae11b3221", + ), + StarkCurve::from_affine_hex_string( + "0x07c8a1c03451fb029b3fd3114ebe650f54bbd520e7b1e0d0798e2cca9cf2ec1f", + "0x044e2a33de1c4e0b455c64540f77f2ed95817c27a1d4cac86d646f5fb5b43880", + ), + StarkCurve::from_affine_hex_string( + "0x03b8965e942bed2714bc2e685fb103496e1e3595ac6a343d6df45fb5ef6979ed", + "0x05b7cac7a165cb69ae103dd9052fb39c00ed0aad47989005aee53972d82d45b5", + ), + StarkCurve::from_affine_hex_string( + "0x07abfe3accdec1eae1a50049efdd9a8eb7c2921a08e8bf1fe606e9d5a4039ec4", + "0x03af178e7e831f8148244d2d2b284a32991852db6212ad0a9d77540ef648a5fe", + ), + StarkCurve::from_affine_hex_string( + "0x0794fc1d8e830e2f4182ef3dd6b41685ab7d85a06c7716fe4eec0d0c060e89ba", + "0x0042a20a755edfd403c1d228895db56b980d5c342e0c01c4bc7d8be25f54b979", + ), + StarkCurve::from_affine_hex_string( + "0x004983196df6ad7d6f0a8d76f86af3863ad8611374a03fc0fd00793181dbde9d", + "0x0204c1f91b70f975a21d24a8face664e496f00f602daaafa69a3b56098a4cf89", + ), + StarkCurve::from_affine_hex_string( + "0x05c36cc51a2930800753eab7cd35277c8b4a2ac14d3cb77e32befd481a0bc5ba", + "0x00bdaa1c3ba1e4278c4108e03f9a90a822792983d9f5c26c49d6402c3c290183", + ), + StarkCurve::from_affine_hex_string( + "0x010ef4b6c1285d98fdd0fe7f864232eb5d47e38640eff4446e45a67785f7c328", + "0x03b677e28c8c02c7efdfea02fd49abdcb2abbb24f0b34ec5606fd7e9b928e0a0", + ), + StarkCurve::from_affine_hex_string( + "0x0663226ed3db0a6c2a779d8e2b1de45b4800090b84eca8bcd6ba6d9cc47cb009", + "0x0072ad587d2603a0ac6060b87f2fb77b06e66e2d25b2d17806d96b0a87a32d54", + ), + StarkCurve::from_affine_hex_string( + "0x079e2b91c1531a3b16dbd53e72d94e16bf265cbec261658151acfaea3718ea72", + "0x03d9bdb47e8b148c1c5e9e694ffbc2cf71aac74ae1a85e8d8c3f77e580f962eb", + ), + StarkCurve::from_affine_hex_string( + "0x06e5cb8b0bb52870189e94e9c7c0d703bb08769d66cf0b4bdb33ad7e8fe7f4da", + "0x050b26e2ae3a8b70d9aa791beee8447910557170a4c60310332fb20062651acf", + ), + StarkCurve::from_affine_hex_string( + "0x007f19a8e17b4e687c9a5205df4c69f1307187cc3f20dc7001bbfe52053684c4", + "0x011e63df803fabe7527105605ea85944d8600c398f6e6d2572392f69085e0d3b", + ), + StarkCurve::from_affine_hex_string( + "0x0782a55f8a32c94b46dde8241fe8e4f51b68eb40307f103587fbb7258ee0cf39", + "0x028313026a74f835a08e84872999486258cd384f6ee6bd56fe9b2a027cb26849", + ), + StarkCurve::from_affine_hex_string( + "0x0302691b7d41fc2d3686bd46a94845c0c5cb1c54117c1efaae5e4398421bbd55", + "0x06ed8532eef856e173800652bb6b48802ae14b4f96e24709cfa6724dfcf9e4eb", + ), + StarkCurve::from_affine_hex_string( + "0x04bc2083470c9df21669c3e31f49aacfe21d516c78d332c3d311322193ed70aa", + "0x038cd1630dda3d20c3cb5de34e67b3cd4b5094ce1ef71af88ffab8f6403897a1", + ), + StarkCurve::from_affine_hex_string( + "0x0010ee4dffd9bf4d0fbdee753fd0a04cae23211db39b2ec2a6d0d742b896accf", + "0x03cb4bcbd4c95ab4b1d7a6a11ecca0fb18432dbc412ce4ecf3d6fb3e3fed5853", + ), + StarkCurve::from_affine_hex_string( + "0x01a418a71ff9f85580631ca6b5dfa138e3264b7990b8737159267051fef81681", + "0x00a0fb1f9cc1f3b9f0f43c99da31524c13083d50d615f3743c61af8e55a24d67", + ), + StarkCurve::from_affine_hex_string( + "0x0297efceec61b3be17565843cae465c52524b4ecd9331a4170f54f7de8c4556c", + "0x06ccef1733624cc8b973ac63dd54e7a53604929affe81c3439525ae5ed6af993", + ), + StarkCurve::from_affine_hex_string( + "0x044f04b1966264a23ccdc870c8563ad2efcd4c8087b5469b90e792287a5581c7", + "0x01c417f0e9829fa3d3cbb7c3cf4dc7aac04c5bf66ff3f86b833a42c533aed1fc", + ), + StarkCurve::from_affine_hex_string( + "0x05dc4584988cbfcc33f3e44af8e7bad9aa648b99756459a1698d19dac0efd46d", + "0x04b9a9aaabc2cd918f9408b16c02a0a342ce1219189e76ea771ae7e15025445f", + ), + StarkCurve::from_affine_hex_string( + "0x06ff83f5d8b51db3be0bda80eed2e2adb7037f2f58f705e88f0f98197431ac26", + "0x064f59b8428894c2b7afd740866065ded42e716c7d48accd3f117f22768ed9fd", + ), + StarkCurve::from_affine_hex_string( + "0x019da6c65b8bde1ede2fd0a7cf8335333b7078b3a209cac17e7bc118a8cc6977", + "0x042d6ec6092eccd2c7606af389a7a60573021ce675586f288bab5d86b3de5711", + ), + StarkCurve::from_affine_hex_string( + "0x03492095a2562f7056fd844f9b750017e5364386e821978186fc3d3f5e06044a", + "0x07c8e782407d703e5813b3582fdbeb606a993bd0a78d3f8fcaacda63e405d7d9", + ), + StarkCurve::from_affine_hex_string( + "0x05e49cbaa5d643915dce7ce34c4b9be9094098fb0a79e76dfded0d27bafbcfc8", + "0x06b97baa9a1e2b83d63721813878aaf93f08dd7305b611fe32227c1c67e078a5", + ), + StarkCurve::from_affine_hex_string( + "0x014aa8187c9559f77cd1cf96b2dfc949182529936f2b0b4050ea56e134073b24", + "0x05f36508c68b1dc586f3fd3f4e2bd29c6d8258491b8a6aa19ede811ce0d3d0a1", + ), + StarkCurve::from_affine_hex_string( + "0x0392721dce24417d439835e6189cc7cb0b4c7d87607323f43a9d49e87f468f1e", + "0x06f920028379ca332b57819cda9aa5c450ad2299d71a38506324ae8da76bf372", + ), + StarkCurve::from_affine_hex_string( + "0x0126c25ba42d272b1bc55666a0dcd24c63b3ff81aeee1e76835685fe47e60202", + "0x072f98d116acf388dc9953693c9cddac4c2a26f2aad3aa2e8346b405fe2a3318", + ), + StarkCurve::from_affine_hex_string( + "0x02c35f6890d2ae7cb854c03dcf56e7f4c8fd9c57b39f5096623f451f24fedfc8", + "0x01c1890164ace4a805869a40d7a85d58fcd962f8900348d8aea6ca79f5335c98", + ), + StarkCurve::from_affine_hex_string( + "0x04ff71b18f39cf7dc7eff0f119d2e452566ef0057c6850721e0bd2631464cc45", + "0x07208b6b9b541702e766e39c168e706cab97a95cce50b49ba3732f92eda0810d", + ), + StarkCurve::from_affine_hex_string( + "0x0457650d1c9037944f7bcd1982a0fe91bc8dffd438d5b4b59c6ef2e3b49ddc27", + "0x06fa885219734eac81707e715d49ab8aef7d1fe7d84729183e461a6cba318f83", + ), + StarkCurve::from_affine_hex_string( + "0x0477297e9ec0aefc4b5037d448fadb7b7845d1249d7c7f474ce29a29786ffe2a", + "0x018b36ad5b02c6c189bc89613ff3d82ce1dc809ac6cd18c25607c71978830e29", + ), + StarkCurve::from_affine_hex_string( + "0x07c25236998ea2fc7b4dfe6d26d182c0da7ecc535b16df77426bebc454aff8d3", + "0x03002a12ce4bc624be6dc48a4f0494df50cc5421de416e5f762dbc72ba5087de", + ), + StarkCurve::from_affine_hex_string( + "0x0095e8882a68c5000d1c2be7c0b43e7f2a6f8de906485241f0285a5c73a27a83", + "0x01e4cb67207ab73bc1e5d19fa2146fde6d03021393b77a55df4ddda1fd28f5b1", + ), + StarkCurve::from_affine_hex_string( + "0x02ae0704dacb3da47d564514b4c3543505b403ba09a248c6e74593cba1867ff5", + "0x05a4b5818088dc9ef4066b90a8893ae80fc89584f987ec1928ef9d72cea2bd67", + ), + StarkCurve::from_affine_hex_string( + "0x052a9102d7634cdd5ec71edae5ef7f59c55e9cbc77ec63d07b27d3e05eb2255a", + "0x00edf49af004ebc4cba54bc4df23e3eb1e24b52c66d54308cc8986f86eb9b71d", + ), + StarkCurve::from_affine_hex_string( + "0x061a10898a76fb99989e51c0e823cb60b95ec7ccccb917c42b2b28014f5fd94d", + "0x023d8ec1de45366d3b86c64c2da05a2ce3d171adf52ca5522e652ffd0eeee795", + ), + StarkCurve::from_affine_hex_string( + "0x07c68ec77ab515d4bac862a4b90e1fc0ef32c9da28e24c9ffe74ba9f4565ab24", + "0x069cad35c20cc963bb46aee91eca0b7b299e000eabacf30a6996821b82af5803", + ), + StarkCurve::from_affine_hex_string( + "0x05663a91851318a04e98f52440f6f1461455e61909e943bf5a7891a0902dbfb5", + "0x03445d4f7e77e36696cbaedca0a47c020fbc433f27aaebf4c42b39e0f88b1575", + ), + StarkCurve::from_affine_hex_string( + "0x07a4874656c722093e4208525c37ddae4577d8e3ac7e1a5004514d576b67d226", + "0x008fed46e8bd3d3f4a4ebc2b1fac16ce2ea79902ee0e6df2a5d201fae91e4e23", + ), + StarkCurve::from_affine_hex_string( + "0x079884133c879cf07734976fd64de220c5a972e04c2a3afb74c362d6c3beecbf", + "0x02aaa0e6d4891b792b5643fdf09873343cd0e3fbba3cbd0601b481a4083f32b6", + ), + StarkCurve::from_affine_hex_string( + "0x03f508fe9b4a43425789c8f53e7b93c1e378ded92d1b7837ea54f3d12b5225c1", + "0x00c4d7536903f82252d5b89a8a3001dbc1f03db7aecb73eed546b272cf7ab8a3", + ), + StarkCurve::from_affine_hex_string( + "0x03f9686e24827d7f1c2d30b665a5d1f27edf570cf6df5d3ba5cd2b12f769c9e5", + "0x01201efce49c7ec51aa9170d4b81ee363cfe5a98931ad29cba7baffdcc7694a4", + ), + StarkCurve::from_affine_hex_string( + "0x037ed78121c5b646af197d8f3078f8846af79ec7838fcb43b0d1d236ebcb5b3f", + "0x05615d468379ed19bcd56dfd14d714c18ba22864bc09b2f0afbf8a5f0e193387", + ), + StarkCurve::from_affine_hex_string( + "0x06e08b2acfe06aa8464877cff567e0bd75ef81e4719291badf7ab703f5635b6b", + "0x0258b4a2c5eebfbb92535e63909f066a6b6574b33b2f00468394bdd934b2bfdd", + ), + StarkCurve::from_affine_hex_string( + "0x0585c61ac3cc992056b23d8d9567e3da0044333aed49549e40005f9c3a97468c", + "0x033533784c46a6c1d288650edd49e00a2ef73df4031b0404cf46ce2bbfd6da56", + ), + StarkCurve::from_affine_hex_string( + "0x02fb835007cc824401ea1ab04e8627066a142c9752a1767d58ce3b4f4f0736a4", + "0x00dffb8a39aa9576af43b24cd2494342b20efda29fef9fd40f8401f767aeb4e8", + ), + StarkCurve::from_affine_hex_string( + "0x05f1142d250cd5e64caa2618681b4010d35c3d13e82d5c5f3edbde05fdf55966", + "0x02cb54492d2b5c2fd0f2b4ddcb69cedba054381490fe4783e02366bc39d58fd3", + ), + StarkCurve::from_affine_hex_string( + "0x045f73d2fa82be6c5ccd0f62d2237efe8727c479967d27cce28e42b9a44bad5b", + "0x02fa4932215f72d56d8be5205c5851c9b3e5f2a14468e4a7acace5437c6b27dd", + ), + StarkCurve::from_affine_hex_string( + "0x037f53f771850f52f9c8f87b53c6bf0c93c2bed76f5fd1d5697356d0b2325007", + "0x050f1a052b79b446fbc7b93ffa1a4515f6c3be3a76a2b0bc5eb8ff327549960c", + ), + StarkCurve::from_affine_hex_string( + "0x0595aae3eeff3da2adae71ed984a66b6a1340426c2d76c3b7c25d5f25f886201", + "0x0658abdbb349b9a1bbfb966ffc2f22f5bcb13cd408f7da9a3fcda987881028d7", + ), + StarkCurve::from_affine_hex_string( + "0x071bd6d23e0d2f312d47582efa609101f15b9ccc571fca8ac4fe3457c67fbc9b", + "0x03b3fdf86bd4c7fc26d60540a6439b4d179dcbf7b91efb0ddc60dfbff9a148c6", + ), + StarkCurve::from_affine_hex_string( + "0x05f35b6962a25bdc293bcdb2dba373c4922d7265357d837ba7b6229c3256c4c0", + "0x03243985db4540b453d94dfbb81ca571290fb1217ba7c5fc423e55221b93ddd8", + ), + StarkCurve::from_affine_hex_string( + "0x05be11112b9312febf8183b9a0f66434281447f525438c25640187a4d19e6b27", + "0x07b610e898e8fef237bb4a80f23f21e9b015ee86b89d47f7b7b905655244d591", + ), + StarkCurve::from_affine_hex_string( + "0x01970db181ee595110297c223257017378069666c88c2ee770e0f62af10c6e0b", + "0x0254fbcbf0f8beec2d56a13df037d888eaf82136cd0aa743b03cd10f21eb20f4", + ), + StarkCurve::from_affine_hex_string( + "0x078219ba049438385b829c13a4993874a4a326c4143de0dd581c7b9956f99b06", + "0x05505f1268dcdd4ee01b77abac3bfdcbf3f0513ab097c69ff777b4a631aaf256", + ), + StarkCurve::from_affine_hex_string( + "0x018805b9c8377e95bbb6b5d934e1a10f78e74469caf6ec2bd47c535cd5498e26", + "0x01f6ce8c91fda451d38a6fab4a6eb66986d0e3bfeb3b0e17190200883b8caa8a", + ), + StarkCurve::from_affine_hex_string( + "0x058e529584d6d7ee726754da514cf147c80dcf79f24013b37c54257d7b3e84f0", + "0x001d8d14a75a43719dacf70ce24e5ba6b7b58660895c974483ffcab319c0a5e0", + ), + StarkCurve::from_affine_hex_string( + "0x01b968d76a94d38228ff5eefebe51cf628030be3034bdadb287de61fc6c7be92", + "0x025995753fbf161c9bf7bfc5873c82c3770488142132719c5baea6b25f9f9c54", + ), + StarkCurve::from_affine_hex_string( + "0x02dfcf10c0b304288087a4b4fa5dc483ede39cce6b1b0f57c1943dc67485558d", + "0x03d6a3a696b1548b7a2f7b70a4a97e0d0ed57c790d9d310b67c0245ca91bc73d", + ), + StarkCurve::from_affine_hex_string( + "0x0700d752eca6ef16c1d5642c5f5e760601387f22715aa1259608ca00b07158f2", + "0x0259a841ef4c066645233371b4c42938a1e36b3fed9b6776dc8586af884992d6", + ), + StarkCurve::from_affine_hex_string( + "0x00bba1e79a8b8fa7175424b7d98bec32b73aa6d5d2c996a00c28b7eafadd57c1", + "0x01d9def7a03c3828c833a77b79cdc439c1c3564ccb600eb1af22db5c6687606b", + ), + StarkCurve::from_affine_hex_string( + "0x01157f24135a5e8294e654996fbe020b1e2a9f166813d5a8917944ffe088fad8", + "0x06596ae5aca2e72e368112b738af2e82e9140be8a48abc30f0979aa9c9f7da46", + ), + StarkCurve::from_affine_hex_string( + "0x00b81e924a86536dcf68bc5a2ca2065a61103ba6c9eb0ae4cf8cce9dbe286f15", + "0x0653a6dfb51acfe8a844fb8362795e5549d424aed88d3a090366a44f840b5b83", + ), + StarkCurve::from_affine_hex_string( + "0x0441c0d7b7aa705046dc0e07ba5f33a7d9df23f694a05192ff8c2d7be2aa3fdc", + "0x04c06568c0902bb99d428bfa0a946ed0f0ca0a51fbf07cad88e06e9c78e38a59", + ), + StarkCurve::from_affine_hex_string( + "0x03728639d7cf8eebfbc002a79b328a463ff24601183321240acadcc9587e3767", + "0x0671aa472daa74f5993f9992b4a82475b338cb7152fadc2601841c22285d6b1e", + ), + StarkCurve::from_affine_hex_string( + "0x02569c8c78b6d6b92533f29f767c95720d377fa63ad5a3b9827ee0a74b0488aa", + "0x04b59c81d3cfe08834f946d9d57614f5366e0bcd9349475aaaebe01341196fe0", + ), + StarkCurve::from_affine_hex_string( + "0x00f6d665342b80627ddcb069b61ecabaaf8f5b213442a00b51739ffe39b4ed0c", + "0x02f9fc8ef2fd66b51170f471ec06e21b87ff4d810fafecbbe44e323a295d5245", + ), + StarkCurve::from_affine_hex_string( + "0x0001e5ca1d1ce63423cda48ff8978d27908ec52c86b8437e847fefe80a2fe766", + "0x06d7f1588f9166487e42a63a973a03880d4fcaa56b7a49af283e0c611a2f2a1e", + ), + StarkCurve::from_affine_hex_string( + "0x034983ecf4a4e7cd23703493ce702c1b1cf5c28976b954d2250e9143035f0ade", + "0x079c3fd94e3896f2e41e4ecdf1bbb15cdb86f67e5f421b46e37985c771f6a616", + ), + StarkCurve::from_affine_hex_string( + "0x03f2fa285a0471647b214eac652bbad9d58a9f2dd2e812aff0210d0d8a6eb32f", + "0x04cdb18e1c2848c2b52c1a6557165bd1a8f55c2f7562f5cc0b326f73c25b696c", + ), + StarkCurve::from_affine_hex_string( + "0x0214ea0dfbb162fd437ca7bb7bf7d6ea9a5924df8666fb9ee2aef21fff4fca94", + "0x049a0e19daf78ab1b0648cc5bc48b245d39c269e7025c9ac3d2a8a5403266541", + ), + StarkCurve::from_affine_hex_string( + "0x00db5bdab2baeed2b87b0269c2047853e5b6dd84ae6ae57f79350cbfcf80fc39", + "0x04b052085533263ac1ea1545780a0c24d212bda42edd26abc9c11826f5327883", + ), + StarkCurve::from_affine_hex_string( + "0x0380aebf6666de3b6f5fd8ec8530ad175eb963b35764cfffe0c8caa6636a6083", + "0x00b92de03383e48625af0a70fbecf4db732212a19ee310eb0a0d870433fee3f4", + ), + StarkCurve::from_affine_hex_string( + "0x00cb423b34696fb300374349ef4239196492ec2efb7b9c273412fa65d521f59d", + "0x0719f279ee42c4618731d74637ba537fe43e251c342964d86f55b96ff3a3f325", + ), + StarkCurve::from_affine_hex_string( + "0x0594fe9f6e79a24e348766e8f18e12b9657f97b37f36382f8e80d8771a83f04e", + "0x0287eee382fae17d61002f1124d6c5573bbff0ec55fc32c15bc68ce0b4ed97c1", + ), + StarkCurve::from_affine_hex_string( + "0x016b7942b9394d9041ee1e797bcd7130202849eb688a637ea35498ff52c9b1fd", + "0x01ac4a56e6ab7c0e51a19e5ee3e41b88052a4639e0bdd2f5c6f08a4043c9b1f7", + ), + StarkCurve::from_affine_hex_string( + "0x07145415c6ce8287a8219eeba64f96691ea0c951c6bb6fc7bcd9fc3d37ee5387", + "0x05a2930527a2e7ffb29a2502d108f9e3e5842cb3c072fa3367bacdc43bd03a48", + ), + StarkCurve::from_affine_hex_string( + "0x05bb5141ab4fcc5290ae9151b8045a2cd8391547ce7b3b33cbbb10f8fb538092", + "0x05a36bfd52acc6a83a9913b937ec086cc27fed030b5fa70dbc5d3c12c9515f56", + ), + StarkCurve::from_affine_hex_string( + "0x003f3fed272edf91aa7f8ca5d70005d390fbc67830ffc69c5fa3ae17582d2771", + "0x0459057e0883c44d8776fa217405f443e5954f08c4a5db68e437becaa664a999", + ), + StarkCurve::from_affine_hex_string( + "0x00e3955ba718bc1d4b50eae9a2ed33644c041737ebd736b249f47f4a405201d7", + "0x025e1b48486661d8c38be7728ef8f732a86be0cf58fa7bddde88fa6176154011", + ), + StarkCurve::from_affine_hex_string( + "0x05237ca6656237a717a739a4509f70db1b9dedbb6cd232f60c9bd8c4563a6b1f", + "0x056c7799dd02896dbe7d69dd8bb9718270549592099569d107b7b49c34bf5a49", + ), + StarkCurve::from_affine_hex_string( + "0x05fb749e9f9405a16549d00d561872238afc21080d3fbe0bbce2f530dcda950a", + "0x05d2d48b6d12c72519cf8d38d49a9ad1e765000eecd4e295cf2cde0487451a8a", + ), + StarkCurve::from_affine_hex_string( + "0x07940ed9f12f77e45d5b668dbed8069ba8d83592ef0f204cbbfa2c2fbd8cc1ae", + "0x059c53213e1a5a58ea78381203df409ce0faf39f3cf9786374e2ee5ed6b87ce3", + ), + StarkCurve::from_affine_hex_string( + "0x030d942fd3fe0bd92fa4de9b46f8eb71709f208aa07e44ff0540d8196e83708c", + "0x078074a76b5965fb635465a13086a2aef4d2220cded3003948e96e50d6835a86", + ), + StarkCurve::from_affine_hex_string( + "0x01cf6b8499ac881e0b2fc7def9bc1a28937033b2fc52de99e75909a620c7a281", + "0x05769cf4f735366fa386b6858043dc99a100f86fbc77b16d57d77766197ba27a", + ), + StarkCurve::from_affine_hex_string( + "0x05f8de2f9c8fcf6045100b1d6900b8b6f3177fa5420bcdbc0a68d61e224f8ab4", + "0x073caf2f738970e95cae1d2e248f836729ba04eef9d8fdf15aed43d5f3d4832e", + ), + StarkCurve::from_affine_hex_string( + "0x03698a5e6cc83b6fb4d819b9e1a112700275ae53c55ad4ad23cbfc35b6a306f7", + "0x0339c7154689dd8cb0ef6b86131d64efc9670d67885a536078a649dea001350a", + ), + StarkCurve::from_affine_hex_string( + "0x04ed313f3baa288e51e69a2fada972bb7b315819446645dba7a67a857d6a2850", + "0x031e42c11a16dc9ca7135a25d6e9a050d43b13a5f54991d3095391370879a42b", + ), + StarkCurve::from_affine_hex_string( + "0x00b2e1f52cde371df78821dbfcafa437d60d271ddef9434bcbc409c46052d394", + "0x0362af7b4d8a941cbff9d17546d2d54e7f60e685a2929e587034f8720dbca5b6", + ), + StarkCurve::from_affine_hex_string( + "0x077ecc001a1986145dfb5ec99765f2a3c2dd0a91f09f7fb84182b0604b894e3e", + "0x0758db97f799a9fe0a74baf42359a94843dc6a1101ad223d3d9cdcb465391bf3", + ), + StarkCurve::from_affine_hex_string( + "0x062e91224aa6e13ff6f552f962c71e768e7dd327b17cb41f43c4424e3732e3f4", + "0x03839967aa18168952fb6333fbb1def6fbb2f3ba8338eb7ebf30daccd11b4499", + ), + StarkCurve::from_affine_hex_string( + "0x04074c5ce88f6521a26bb855dff1336a67c391e32560d8e0e08d4f2fd842c58b", + "0x046563301af63b5a56414499f3afb1c14f21273891b15be45ac6e1c023ff6fcc", + ), + StarkCurve::from_affine_hex_string( + "0x01b74b8a6b86dbf9638cdb0601e1a332b8d880753423d38c3394902c57f15e40", + "0x06bb2dc10d2ecbb913219d0ebdc8d3337d644ed8b6c4e70637ef4c7e50887488", + ), + StarkCurve::from_affine_hex_string( + "0x061e4da415661bba52a4737e2bcde1a837787c4796b2e1854778534f1582c29b", + "0x027c43e632cb7652e8508c9c38e3b4ad0d3dd6ba748d42dc84ec2685e64b9aad", + ), + StarkCurve::from_affine_hex_string( + "0x04ceb49d6ea67777518845e768d9099ff63f1d385e0460237d4ea2d1c409c20e", + "0x0784f7046c1ff3641c5758621b33e070481b8756c730cf1c11996477d67b3647", + ), + StarkCurve::from_affine_hex_string( + "0x07c460a204d23f20ce86596dae6ac9b36734e4a9f7c5b43262c97a36c6a41c6e", + "0x0481a11f9300ab4c4bf6924c5ca884728cc361247377065920966785d043fbbf", + ), + StarkCurve::from_affine_hex_string( + "0x0316e41a001dab34cc2196a5ffad1e33be174e85d538d2c27fe7b1db2360df3e", + "0x034a01bc3eda96cc2561ad828f99a178a8692c5ce313706dbdd58193cfb95faf", + ), + StarkCurve::from_affine_hex_string( + "0x0759aabe4f4690d005e6b4b3091842a1d9254f8e5e5db6ca9eb7854ec2bb1de2", + "0x028ccf1ac0ae95b72ac2e2865da2e4d95fdfa91ca0a52387ae601eb56b27c4c1", + ), + StarkCurve::from_affine_hex_string( + "0x01adef58ab446968fa727b46f8bc251a2f50bb7b8f85bf930dbb170fdb823616", + "0x059977dc2c4f2401d99a8361fb5b9021956c342c5019d3acc07b4f5b48f101f1", + ), + StarkCurve::from_affine_hex_string( + "0x0124ff5e55e4effa40daa5b9618d75c49c8b6fad95cbe8c0bfdd83cb9bed8316", + "0x033a2ea15d0f71f58a00de71acd7f22ccf9002115e49dd1f7631faa0d32f9987", + ), + StarkCurve::from_affine_hex_string( + "0x0717fc14712a3dcb1a658f3d2d1220411dbda54f0a99ca199d9a77cb728afa3f", + "0x03d2f2be108b9018f522271e64d7eb81f590db2e7381b64c44b2b51803c0e7f1", + ), + StarkCurve::from_affine_hex_string( + "0x041603d7260f1bf0b5bd9b1dd6cf113aeaa2a243e26e78474d18539cfa15d293", + "0x07c0a2900502f33f1388b1bbd9590d16f010412f42aa7e6e984ca119289fe705", + ), + StarkCurve::from_affine_hex_string( + "0x04b1681c44c44aab7b7511aaf4f1c99b1dd50fb060966ea6eb219271b1c2a528", + "0x00f9b801493f02c463001bbd3cf049aa449d1f455ec7f5a205f665e143530a30", + ), + StarkCurve::from_affine_hex_string( + "0x02525bb94b8339dedb194025db9caf7ff468ab2a7c88ae32b3fdac7462bb2198", + "0x00dd2887cd3169a98a76502c324665f78df35170f8d4e8ecdd5062624754843a", + ), + StarkCurve::from_affine_hex_string( + "0x0008f6eb23a88507d5fcdcf483599fa9540803bf633904859e19cdca674b08c0", + "0x065aa8947a971309c13ebd7c66f21b1a6fc0e8e7694cf109e1235b0ec08ebf52", + ), + StarkCurve::from_affine_hex_string( + "0x0387fd28efe4e0cba41ab3a99be2d4ceb9082bf51d3ad702956acc3de2752553", + "0x065a97eab03d453ba028fc908ba4ba093fddeda36c5d18eaa15435e93c44647b", + ), + StarkCurve::from_affine_hex_string( + "0x0170e087d168b741ccbf9f9d0d72bcb8e5c6259e89ecedef709f70d837200fe3", + "0x0213f42d633f8ae52683ebecc40e4ce63fe696c22ac0a6ca82c190e819ba6c7f", + ), + StarkCurve::from_affine_hex_string( + "0x061c9f8fc86715e95ff43583a865c5a6515f93381839d557ef884a68637eaf4c", + "0x05877daaa42bbab9083b571e12648a9d62ced4470d71653092b6546f4a5acceb", + ), + StarkCurve::from_affine_hex_string( + "0x070a6b9a9e5d1fcc07dd9ebef6d8f5fcf04c6cb34932d0fe2335330ac6dc8d3d", + "0x003f0cbd332ac56922e886656bee74f6e9bb4bb88f7af7bba9098678af1f38fc", + ), + StarkCurve::from_affine_hex_string( + "0x0739fd7af848404a91fc63890db1117183de6febc061764d9caa6a569e4287c3", + "0x077911ad848b26fb4bc1f806d170febdf16544aafda4af9dadcb38044f6dcc5d", + ), + StarkCurve::from_affine_hex_string( + "0x041db8a0f1ea78443a39e08a54323743c8897eed1ddc28f41aec6f2655040d9f", + "0x07d4bf32f8f4719c2e4af8b7889f3b65cfdd033dc2f971798a12170f2b26efce", + ), + StarkCurve::from_affine_hex_string( + "0x0159e2b2e323d484a7675e1e3ebdd579cdc386e3c65ccee80c742c6742d543ff", + "0x02e511a7903bf0869f7bb670b79095fcb0c3dc13d7167427d7e855abb2ce51ca", + ), + StarkCurve::from_affine_hex_string( + "0x05cea50f0d4178ffb718f7e4c1e42aa34d30bcce6e552302d47e74ede2d9ddd5", + "0x06529f4ebf630bfa3d449213ad7f6f7a052f7ead64676ef6d2a6003811bbdd00", + ), + StarkCurve::from_affine_hex_string( + "0x06c59f931da4afa684e7de19a00aa6af64c8f21b548f2b98d5161365248bdc30", + "0x05d0dd17421ab33d2d2085a78144af93a5bb8f70f06e44c66b9a50279bf17e14", + ), + StarkCurve::from_affine_hex_string( + "0x00062f035e01acdfe841104942d6c8c07f0fbd618cb85998ea24bcc24cfac1f8", + "0x01caa886104b7d753fda93645a746989794cd825c62473b526ea34b3d51b5771", + ), + StarkCurve::from_affine_hex_string( + "0x006b541e895fee53f6e9f37fd1e0dc287a3afb0585682e983214b8c83c2e259e", + "0x00ee12c9dbeccf9be03b893349f5be20cfad96abc7ff04358cf7ab3d9f9009cf", + ), + StarkCurve::from_affine_hex_string( + "0x0169f96807f4ab71cbef3cc922e5cae880ba86cc6a07f79ac070925d318bd6f4", + "0x04d19f0ff1e6f6ea77b43d84384397953062235e09e0842994f3472b2109a608", + ), + StarkCurve::from_affine_hex_string( + "0x012fdc0e005f89db96707421317247234001b03f354c65317479d474b8e2cf23", + "0x04e654668f2752517a06bdb29283ed42d3a0aebd4b38b198c366f8139970cddf", + ), + StarkCurve::from_affine_hex_string( + "0x021016c3f4a04b5a114abfb28b8f78036a22729165c9e03819db7dc7143b4b03", + "0x066c99a8ae9171bc602b4fd226ebf0206d1c42a9908528d18f646a472bef5043", + ), + StarkCurve::from_affine_hex_string( + "0x0644046c819e1098d25efb3001f7cf0a49d110620dac15c66bd49bbe02efc478", + "0x0709e88424ea2679173ef3df367c057e4d513ba356c6f6a5397806bb40a638c9", + ), + StarkCurve::from_affine_hex_string( + "0x075a4f8e18ea05a26c68dab86da57f5f19630613c416af913ea24a47eae5b830", + "0x02e2b8706783f9712c6f41eb4f60ad9ecfcb9d326cb2e6c54c9ea4908e9834c5", + ), + StarkCurve::from_affine_hex_string( + "0x04e438503af6a0b82d98156f5ff38fc5f1b0944adb2d6807eb8514ed41f53a0f", + "0x02821130b45f532ad531463fd8ec07ca86ec513e2b78a50881e1c1b6719ac5a5", + ), + StarkCurve::from_affine_hex_string( + "0x0441c6f016d270e86c19843727b83b864cec060cafc813b23d7e41e5abb1a60a", + "0x029fece4e40400f3acae0586f4fc8ed535e805e472123ec38d662d8a0b01c086", + ), + StarkCurve::from_affine_hex_string( + "0x02c791ba0fb0b66177815c98191fa6188dba9c795e34a7c3c8a19086215e3cee", + "0x011123151389d4b330db6a665a560407e7cd8c3807c749e2b0cffd9c3074ba77", + ), + StarkCurve::from_affine_hex_string( + "0x02f0abc241d61b901a8348e4e109dded5fd1ecb13c19a7cd053ed3e3eec12b28", + "0x01d2a9b55626ec6904202ff176923dbfad7bf4ed4e03822cbddafde156b77e2e", + ), + StarkCurve::from_affine_hex_string( + "0x05292da4ca71ae75ed0554c267747e39c7a129b3b863e1af3ebb3e368439c4ea", + "0x063af6a5016deea8cc674c44f16c63c1db31f09af4fb4d2ea7917c28116661fc", + ), + StarkCurve::from_affine_hex_string( + "0x071649676550675f2bf10141bbe9ab21614f2ef59e8f0e71b416db801021a4f0", + "0x02d77359eac272be257b8e264af49eb8ced935ce3e8cbe215c3229f8390a4450", + ), + StarkCurve::from_affine_hex_string( + "0x062e6f34672dffb96325cdbb2c77eedcc00b9ec6edbb6d43b58744c9816e9089", + "0x0762e7a7e25f8e7496e6170722848eb44ae5a059ba6d442b60ae2313fbdff970", + ), + StarkCurve::from_affine_hex_string( + "0x00804c254f5a01dbbcec99491b4aa7b4ae2ffd3382c5d5b86c24f73bfe8f0650", + "0x01765a69e51ca3fa2de05b32159237a7a8d2822c7c08dd76c8c5437546de54e6", + ), + StarkCurve::from_affine_hex_string( + "0x03367388d5d1b7758dc3d92e244f227bb8a54e3d9909e7b7dd62ab5965e3efc7", + "0x07ffb4833071e4b03ea755ccb9938487a478248fe9b1158a08f1ac298801c092", + ), + StarkCurve::from_affine_hex_string( + "0x020a064c7395c76cd5b26e05f444e8976c44d68e1b1953b78dcfc181185cf830", + "0x033011dfe2b9788b973344248519b14a193263db8178f9ede6c99ecda896ccd1", + ), + StarkCurve::from_affine_hex_string( + "0x024ced8f62cc5106dc96b89b02d2e4ca9d9b7c52f4df379533d72db68d74c72b", + "0x0110175b6ff45651c89650285231f270f4f01ed507bdb44d2317a25a6759205d", + ), + StarkCurve::from_affine_hex_string( + "0x04294e72376b0bd4c9a0140979a4231ff802219afada3be76d3d606a6a565343", + "0x02b036f2f62efa2dda4c6e607f247655e88dcc3762846863e5674d40f1fe35a3", + ), + StarkCurve::from_affine_hex_string( + "0x00892c8ba47a582f663e4372414017c6abbf94d38cff76c774bcda2b175d2f66", + "0x01392a012b69525a9e00fca0c6848523efd63c66299a884fae1e50323abef0c1", + ), + StarkCurve::from_affine_hex_string( + "0x03b1d6c1294ee4863a24217440f9e23e2871c9fd544ae95e9eaae9dac55c3923", + "0x0436520ddf289b25ce699caa3f2006474d2fe2c853a0e4b50b60eda24811985b", + ), + StarkCurve::from_affine_hex_string( + "0x07a6c3f4c7a4ff83500313505241fc1b8fce63e885ec8ba2d72f45fb0cc4a3d1", + "0x04343bb67e7022025b3d097727fafbcf518c2ae0a84b5aea761a3fa95947ec75", + ), + StarkCurve::from_affine_hex_string( + "0x0172535754b3bd4b319a52a3c5589f1ba5de87cf6d7099ff661eb30639d6f61c", + "0x068b064bd40b15b12ed2975f734aa181d91572d2e0b873c9cb6b0ae3107747a9", + ), + StarkCurve::from_affine_hex_string( + "0x0095c863314b7f18090f8eee602403be823a367a1b416d54c32e5f914e67d922", + "0x0159c2824f899171deee23e0ed520d4825bd667983df0a8d45d3a1f7156d91f9", + ), + StarkCurve::from_affine_hex_string( + "0x0621c6e08b3c57404644ad49ac7629832c141273fa1f323781b3395393fe985c", + "0x065d1eb0140652958c4371ebec791e03317d6b2e689d90e304666f1b610783dd", + ), + StarkCurve::from_affine_hex_string( + "0x041b7777aa32943d95add393c1499a667430b222e644902af5af8b7178df48f5", + "0x0769135182534902c9848d7b4a38cd3e876639a288760f9228555d6fc3882f18", + ), + StarkCurve::from_affine_hex_string( + "0x054313129bf13993952cd2b31ed06013aba85e74c1b8a00e062031f32188a84e", + "0x0680129efc9eb8ec07fc180e8f6877e5f0f9f44e3000a2c586ed4ce49d12a313", + ), + StarkCurve::from_affine_hex_string( + "0x02b513b910f25c66a041e07a6a93b9991fe2dac8069eccfba1f1bf8814e97146", + "0x07208fa7df0c2a562648e33a17b57f436758bbf60d6dadeccdba3f0a0a7d47e8", + ), + StarkCurve::from_affine_hex_string( + "0x0516a8512e7a5592ff0aa93c0ce7121047357ee0b5b42dd5d3c5cc248c6994ce", + "0x01973ea1f0021ac44cd870290b6f8c995e454aafd86f38ea88613fd13638595a", + ), + StarkCurve::from_affine_hex_string( + "0x008dbd47f7352d90f73608a7df59af329e62b24d082240e8ebf0929a2ed7a5ba", + "0x06945dc36b81dd1f46a78d5af3b3ef04377a67970f2068f673c4a17794ac7297", + ), + StarkCurve::from_affine_hex_string( + "0x0021ea57a1c8286bb45872e78617853c47b89091670ba51c124afa3362e7260d", + "0x07087e5c1536df233ec9bfe2f983e8d7622892b9bf64c450c9823898e2cc2fc8", + ), + StarkCurve::from_affine_hex_string( + "0x03d3bf4cf73db45b5dcfa9c96464ad4f96ea37b5bffd4eb5ad8872d1048b54a8", + "0x01ecd83a43ff5ef05c599592e857850251085939889cf68cea8aaf5bef7c30d3", + ), + StarkCurve::from_affine_hex_string( + "0x02d84eafef737e8e8d42e419fc64b279cadc660b4406a3ade9543284a169b235", + "0x063e43a876bcbf00f3aa6b5b7cb31d5c8b0e7dfa9d36f8e62d994aad2fd4b7e7", + ), + StarkCurve::from_affine_hex_string( + "0x02d22e1af66c7e876263afdec03835165eda1d528093493b986f7e85a07afae5", + "0x01bdb69904278aa70502845292bec0dea986f5dff4cee952504e1e133b248ffa", + ), + StarkCurve::from_affine_hex_string( + "0x0289b37bca81aeabc77b1a36d3421e14bb5c87cbea062ec336449aa2b807f81f", + "0x04f72ac8b842499c729f88a690c129fe1bd9e8acb954d1f3ecdff39523ea5d81", + ), + StarkCurve::from_affine_hex_string( + "0x00d3f48e575f4f36b6e5442c9a8a6f03544a00a677ad95e8f1b109cd463a14bc", + "0x031957ed6f127945cd8ee5d7e0b5627db6d894a02a9cf0ac9c8ee7378748811a", + ), + StarkCurve::from_affine_hex_string( + "0x02854289de6f8e0e63f4c1d0bb60a1491401ef72d9db342acf1b4e344c09c00e", + "0x03ff63a45d44c2aed954aedeb7f2320c979bb63f965b561d620f91759293882a", + ), + StarkCurve::from_affine_hex_string( + "0x03fa2852a7c7f4782b5889ba2f60a403b99d2b0ecada8c2d7f72c0af708b6e94", + "0x002c99b4d2005a1e5f2013aa8a398b26b8e4f8f209c5b248e59b011f35b6936c", + ), + StarkCurve::from_affine_hex_string( + "0x03793b05b99e7a57d88db4ed0dbc3b771285abcd9052da50f88595354409f3f3", + "0x012164105041c056f127e737c7cd63981e05f246bd2b6b65d1f427019c7c3801", + ), + StarkCurve::from_affine_hex_string( + "0x000befd345cef5fcae22ac37dacd6b9128cc58cbba3e3fd774e11b421c2ba392", + "0x06209d25f24f88f7876ca604db23d05f78e6b3b67fb033f2f1bee221f352b8c8", + ), + StarkCurve::from_affine_hex_string( + "0x05cad32be449c82850a4007d3b3c4b7ea28e22172075746e00e6f5365093b979", + "0x033e0aa796ec42e28941a9f79f7b74abb2f714eab6136728700a542f8115921e", + ), + StarkCurve::from_affine_hex_string( + "0x015fa536045fda4c65ff74f10b4e669ce88b9996c6772288289d3ad725987fa6", + "0x030e0c2124a35e265e931ccc66ce5ac3697d982814beb407144ff6762cb691df", + ), + StarkCurve::from_affine_hex_string( + "0x06d480c6d389b792b68f21e41f717f828ddb529a17281f09ed044668ad2c32c1", + "0x0344fad8d68d430117f6fa9a72a6f39e57f7938536bfcd65ddff5cb267757503", + ), + StarkCurve::from_affine_hex_string( + "0x013aea09a0f7b4514c5dfa3a4f72f6dbe05662ffd780e2eca7483ccba1d2f173", + "0x016bed3a91a3da10f5edd537fb6702a4f975111bc360300f5250ab2859a324bc", + ), + StarkCurve::from_affine_hex_string( + "0x00eace861a8db6bdbf106cc80370854b39ebabcc24b2f803cffd9cc21e97de59", + "0x002f6c20793153f7cf40c6103f9708e1e589a767e89a2fd24ce96bc6bc465d37", + ), + StarkCurve::from_affine_hex_string( + "0x038b795bd77ac573576dc204857a488cac2cce19809882631ca2069598c577c8", + "0x0786ba555d55ebef688b068bb9186a34a08cb00bdfef51619bbf911890ae9a13", + ), + StarkCurve::from_affine_hex_string( + "0x0173cd1aa758920be5961068bb592fcc42861380472c80ad00289db52f15723a", + "0x03636d38557af345abb47c77f68fa9bff95f0c6d9520db375585cd4679f71391", + ), + StarkCurve::from_affine_hex_string( + "0x07b3d7e2364440691e4fa6fee5c2199f1d853aadb4992c20bfa9abc2ec10f557", + "0x02778b1959387a2a91a539e503ec59aa35d042344680a7dfaf7c2bbc851d5037", + ), + StarkCurve::from_affine_hex_string( + "0x054f2da545ac99aa172926ce71483937b107c90ca1e752da043dd77cdb1a687f", + "0x076ac79ce43918f1f5c5847ccfd2a30f43b3fe54a54e3bd2131e28c467d7d1ae", + ), + StarkCurve::from_affine_hex_string( + "0x0177e16f8cc0dfb7e49a42591383b53e914c2cecf5b49230bc5d4c5b672e8444", + "0x0732658defe4d9b4e3ba28eb24ab0f392f2497a7c8062d744dcb7350678a2265", + ), + StarkCurve::from_affine_hex_string( + "0x05d1cfd8ab18f6cf9cd47cc6240c373b8913d7bfaf129e1a64c4fd2b0d2ab80e", + "0x025d7bcd17eb185eb1e4ec0d0261935a41c59cbdbc99031547f99edf26c7e956", + ), + StarkCurve::from_affine_hex_string( + "0x0282a6c8145ce35184f6227df76eb668dd740a4993c370342b31a954ec2b25e6", + "0x06b5aea7261b85b75e114fed14d76685170eb7e8c60a42d3e74507df913e522b", + ), + StarkCurve::from_affine_hex_string( + "0x03914ce111868d81d8cb2e87715dc00f8272f8e6cd6d909138ecabfce292090b", + "0x0096dc27fd0ff7bcaa6b91a014f3185f19cb3d676650f25dce44b75daa830310", + ), + StarkCurve::from_affine_hex_string( + "0x06c66853592196c3eb8d9526dc155205e2c64097adf8684bb0e15eb460ce1c72", + "0x01bb4ebf654f4250c8dd1061a4e1b464b31a8a9999ac9960446ef8108a66871a", + ), + StarkCurve::from_affine_hex_string( + "0x05b08dfbc87ad9c00b88e78816973ad2f9c10c70f2156908892cc7b7a2a1fd30", + "0x01151f407a77e2556073173d8f5c9ff561d8a23742121ca15f7d0ac391af50ea", + ), + StarkCurve::from_affine_hex_string( + "0x067a24b09dee0bb902ad5434d3a806671d3a7224ddd1671c537e9fbbb16d4bbb", + "0x05b1b3e8203f239afecc5d5d61f61f8797444b77f3ef087961b88be942acb4c1", + ), + StarkCurve::from_affine_hex_string( + "0x0309190eba106aa6ead54b5ca5817969aa68b4b4c627700799a49fc6bdd32ba1", + "0x0505b6a2bc7b0d78ca6ce2abe7dfb7312369918a4599cccf8a615f6701cfd851", + ), + StarkCurve::from_affine_hex_string( + "0x002c1ff0aca0d3f74a56d9abe58130a0a0c7007e1155ec6c1b04625008b79fdd", + "0x01914edfa6ab70419c2a930913b75e71f78dfec19f136efa3644501e09cd3f42", + ), + StarkCurve::from_affine_hex_string( + "0x06d77f24ddb891e2031ee521f591cc4c8a86609b63e8b6c850a98a02b30b58a4", + "0x0474140abfdb05ed935ae0a64bb2675502f11eaff78340d79629864f908a7cb5", + ), + StarkCurve::from_affine_hex_string( + "0x00f123a294e185d6d6c3156cca2d4cb7516d70279fb2f099c7fbae1a9e4ab770", + "0x026b84939e7aad8ac077cdc5f2d9fcac10c69a787b285479b32adf60f3602f89", + ), + StarkCurve::from_affine_hex_string( + "0x0089cc205966af08acc8910d563af7443d5dfbb5d88dae79c013c678c65dcecc", + "0x01f8cf955694b246a423ac725791231257b88936e00347ecaa1e17045c0ab540", + ), + StarkCurve::from_affine_hex_string( + "0x02912aea3d45f7b5b945fb13921f27f06bd8a81369aa4faa5fe33bbd60d6493c", + "0x076b3864d28f94c9b785ae3985e508b37bdb887db52921ade33dc776f8fa0460", + ), + StarkCurve::from_affine_hex_string( + "0x07e17a6136bc3388c6fc1d63d598e27fe05d2225747a86eb8bcf6833789d0eca", + "0x01ad5f31e1194615d3a76ab3194435be709e2a987cd716f077fdc6a997576d08", + ), + StarkCurve::from_affine_hex_string( + "0x05732c263a4f3f8a898a4a05b4bda4248cac361ebda93bc43965643405c2c558", + "0x008e3c8b16edc7b9d805ba26b7a8c9f6884499a8daa6223ce71dcde8bc53bf83", + ), + StarkCurve::from_affine_hex_string( + "0x0385b5587c464c693887d511531e76e9c248d9e74d05e495167d2e0ce2a02840", + "0x044ac3a9befbc5513f68dd35a42c8e3d1b401e0c4000317c48373617eff49118", + ), + StarkCurve::from_affine_hex_string( + "0x051c918ca73965795e944ee1aeb194f43e1aa34c12adc0e01e779b42df6503bb", + "0x031239df2fc80758b318b8fb8108ea1ad77acdf0d2face94bb70460591610816", + ), + StarkCurve::from_affine_hex_string( + "0x00b68b8d3dced3585eae8b820aaaa45fa2522edefdaae7b3d48a4a557c467f70", + "0x048e9889eaa63f65e1ee5db89d7290188e01e2721e36140fa2c70176657dae3f", + ), + StarkCurve::from_affine_hex_string( + "0x0137b0d71e68f57690cbf5a2357a729501a2b90a89a58ff96ce85a6a7274e5bc", + "0x020793d55a72449765d0a846fa4aab0ba479fa165c650a4c9eecd6a51a7a3ca1", + ), + StarkCurve::from_affine_hex_string( + "0x0480086b61a80c36cf1e1a350baf554e58ee8d9333186b70c9c512fb9e9d5a84", + "0x0511edfe58f8d36a6170df743731da1ff525cfd5108be20e30ac4183d1281570", + ), + StarkCurve::from_affine_hex_string( + "0x03caf14fb1d2e90a13ad4eb091250fe37133aabf6029633e905e5a93ead41dbb", + "0x049122aff6059dfda19e4b973aba5ebe3804c91728936c6381c1ed1ea9380920", + ), + StarkCurve::from_affine_hex_string( + "0x01e5ff67f17a15734714c64ac2cb8b65e071e9e53b73b20e0a63921138fff4c7", + "0x06855c48df6b8e729da7a709d7cfe41c5b01f583e00a276c434c869b9d56a5fb", + ), + StarkCurve::from_affine_hex_string( + "0x066d1b8fb2cabc46cd79741ce1cb7326077ad8ea3227a6427244bdd3806bdadd", + "0x04a52eb74f4d5371ba3265dffd61c844f9e68d4ff0b44dc4936182f9280bb66b", + ), + StarkCurve::from_affine_hex_string( + "0x05b8c55df79a4bce0bec0e694914e6014a5d4b37d163346853ce59823b5226ae", + "0x021248280c0c0641433a108cd46a76569313fe73b394730e2a4eda43ba0ce803", + ), + StarkCurve::from_affine_hex_string( + "0x07faf291d2d8b98612d2ee1fd82ddf022d706570d03282ab5e518e86b56c89b5", + "0x025f7baae2e8cf4c85cf27dd9f852dadc01c59cbb1c6e4c1f4152b3d0a20167d", + ), + StarkCurve::from_affine_hex_string( + "0x03b0bbdd094d53a35ec8d9c8fc5fdddcbd03337d35c21cd77141d187f0c1c010", + "0x06b73f732c08eaeb8e0507c9227acedea85d87eb3fad2f1437c3c2b0db1f749a", + ), + StarkCurve::from_affine_hex_string( + "0x0373330c5afd53c31257fcc9050fef873e15ea9f81d9810f30744309b04e02b3", + "0x05889806607b3dc97a9c5b0c8a2f16d1792099a22866b879ca480cb89a11ef5c", + ), + StarkCurve::from_affine_hex_string( + "0x00c628bf6f8b2f79b4fcd28392dc35d884f4fb3809e0f2bfa49df7a1dc781fe6", + "0x0003286c40fb6b534247c6dbd8a95fbbec1288b74d6495adf1857edfdb26c29a", + ), + StarkCurve::from_affine_hex_string( + "0x0379861d375911d79cd19cbd91092e14edd21a1821d07b92e64d0169734b947f", + "0x001a01962f1577f85d233f9b7826c268fd180f0f382a977e7ce5235cee1ac79d", + ), + StarkCurve::from_affine_hex_string( + "0x05b3fb1821541a27363330fd2bf4a7f2080a3b8295febeaaa5b720bba2dd45c6", + "0x049c81e666c2175a45fd694e6b436ab039f8460d90c1b020f2dc7604382b009e", + ), + StarkCurve::from_affine_hex_string( + "0x01483c8245f046f274da2dccd69892bc487e66e7fad66374064ba33e75bc25d6", + "0x0328e0457e0e610ead3668053de23b3d5c2aaf81255808321a6426d702384ca2", + ), + StarkCurve::from_affine_hex_string( + "0x063373d7e3f10c3db5244df000ec9403a759f0d738b7ee5070abcbf48d4f21a5", + "0x05465cab97ae98af1eac9860a4bf46e86462dc8e0c5fff9062ce9470984225ba", + ), + StarkCurve::from_affine_hex_string( + "0x05cac64f66aec9739875e532847c7a059621be0d3bf5f23fdfc0646158f9c641", + "0x079139808cd23b4eef3257008cbf06dcfed06f0a23518180e26f9f167689d958", + ), + StarkCurve::from_affine_hex_string( + "0x03ed77e0f6b221013d7e1bcdba9beb814a392fc26e3dc26e9d8968364b44359f", + "0x017857dd5a6ea1283e68491045fe13ede7c340de9b394934c93ab8ec234686fd", + ), + StarkCurve::from_affine_hex_string( + "0x026840d0ec69a22c6818ff64b8b14633b531508c866e21d1dc9239778ae9e8c7", + "0x0157971f9a6e3a24d3b307be0e7c8cd352e2eb5cad33cf276270c0f309ee63fc", + ), + StarkCurve::from_affine_hex_string( + "0x00ebb84848f1c38c19a754d1b5d9460e39624dadbb30800987c9419c0f933b9f", + "0x0517b297cf32f4064e6d6c8e761ba8db89809604a701c7b3aa1a9c6beb370ea7", + ), + StarkCurve::from_affine_hex_string( + "0x00036759c37a28db31a8e3c42442f602f4583b64e550adb36a3ba9250fcd44be", + "0x01c2e0dcf12987c70189b7dfd3d4295f4cac0d034b8aa92ac27c2a3a5f04f4cf", + ), + StarkCurve::from_affine_hex_string( + "0x025780380bc0795ed0dca727c55240f1d63593e552d224adb40df2d3721c0f66", + "0x010215fb5a893e0275e9f1f66b217dde35addee91ed0e8f7d79531a2ff57b8c8", + ), + StarkCurve::from_affine_hex_string( + "0x00b2accfe81760ca7dbb0579dfd7633b1939684ba449e9c3aee248cd5292f919", + "0x074b9b81fd6a8be878587ac2af9913c56cd59b694b8ca6c040311cb20f75a366", + ), + StarkCurve::from_affine_hex_string( + "0x02ba2c29c985429d9147aa8a44cf985aebd0d35ca75b03c4caccb2fa57ad7f0b", + "0x0548a9cb38c13ae2ede1e234208c3a807fa35c3631c363f4a6ae4fc291ccb753", + ), + StarkCurve::from_affine_hex_string( + "0x03320f28107b2f3a7cbd90c8924efe42281a8046685200d787d9e532969b0ba3", + "0x0427b5d3c8c520e718a58b375229b2f3c53214240863d911fe784209c6816f27", + ), + StarkCurve::from_affine_hex_string( + "0x0243e1581cd1abfbf18c31c19a4c3d1cedfe69a40bb57b607c9af2717eefc742", + "0x01296c27929f14535718c3a4ebe045f00afdc60afc74c7d398d8ce1b6609dc0f", + ), + StarkCurve::from_affine_hex_string( + "0x05405558e37b9d40a867367ff5b1027fd424b131ed33428c404cb79350927f28", + "0x017a38e1941307c9f989d3a8f3446ad1a9335ed6abb87b87de170cd3e4feeefc", + ), + StarkCurve::from_affine_hex_string( + "0x051fce5c2d263bf18ffe6794d81e178843d6cc6da1cbd3e2138fb265be64962e", + "0x02d5a1f98c2ce81c6375617f88edce8f7bd4f9868933db43a00a64b73881e00f", + ), + StarkCurve::from_affine_hex_string( + "0x017337999536b145f48c0941dde2c9e0ed472e94e6190eeba3793f4c61c6885d", + "0x01432c153dbf79c9f38523ba954a4456ecca800f45e0301273aec193839c8578", + ), + StarkCurve::from_affine_hex_string( + "0x03fc9057f7e2cfce39b11d9b776ec041f8cfe34a4493db17c4c68ae862794916", + "0x03c921ceac3d986cd550bd5918ebab5d0d7c3828207fea97746bc92eee7bd19c", + ), + StarkCurve::from_affine_hex_string( + "0x06ed213087ef501c36f27065e2262f2b9eb2b4d965d30bf75e806927929cff38", + "0x011968bd42ea3c62991079e419bee9cd333ef062120e24d2692157345aa81bd9", + ), + StarkCurve::from_affine_hex_string( + "0x0081a35ff2db5857c0c69c4d67a252b603adc2d72d42ef12df200a0bb2adbe00", + "0x01923d321fae7747c508051e84ba72926bc957b46e3b185aa6bf114ecee29615", + ), + StarkCurve::from_affine_hex_string( + "0x060a77e1743f09308dbda0c3fc59aa5fd3c391ef9f8902139a76aee73a70301e", + "0x0037aa9778a5c1ba0e0520a0bae7edc3e66b3e6b37be8146a434f8cbf174652c", + ), + StarkCurve::from_affine_hex_string( + "0x048babb8649e054bc8e0b902c89e6940c265f48464520649502ef1064eb94562", + "0x03235be7852b0526d1a16f6969ec0e5b0e09cedaadc65863dea4e47f4f398264", + ), + StarkCurve::from_affine_hex_string( + "0x0592db7c27e63489ef4bcef2eafce89f40067cd9a1ba48bc3dc76b5fc62ad9ca", + "0x048b7711b570cd9ac65910e75e752f4b751fdbfb4091a28f59b8c046d3d9f8bc", + ), + StarkCurve::from_affine_hex_string( + "0x02a291d461523e3b02c74ec54712a467b04903d0470e139c4f0c747e1634346d", + "0x07f52d5124172a406074503d8101a25fda945fbac97c70cc4748005ad099195f", + ), + StarkCurve::from_affine_hex_string( + "0x031d133456222586ae42a9ec7ce8539ee04afbe0b2ed00a2564dab0798d9b55d", + "0x00a77c52fa1fd718db5c83e7fda6d7d4d9aafef9ad95cad621470f2b753729e5", + ), + StarkCurve::from_affine_hex_string( + "0x01dfa2bab5955e74de7b5bd827fde466d48fbbebbb56dbfa05a258c6640fe2b3", + "0x04dc9e5dd8a8a1378d75de98091f8e5a6d977156e357264753f22e998dbbc52e", + ), + StarkCurve::from_affine_hex_string( + "0x031d6e6ad963214c1dae3888291a8297fea6a67dae4eb3f8be5d2b7a0d6164ae", + "0x076f7283f03053bae75ad5e6e91110d753e064999cb2d2d0031b93dc52abe8b8", + ), + StarkCurve::from_affine_hex_string( + "0x042dae32e58d27693d9dd1d9d4762a88e87830962c123f7babed9a653f3d59fe", + "0x0041ee7846bd1dbf4c12a217da3786f52cbedd4d042efb541bf41447a36cfb65", + ), + StarkCurve::from_affine_hex_string( + "0x04651668379883521e7983aafcb93811b4a72ef2975b3277773746708ef3e3fc", + "0x0512507f3f544d80ba5d47f73b571881e8d70d7b1d305b9704bdad036b7abc47", + ), + StarkCurve::from_affine_hex_string( + "0x0588f0bc31b7ae0ebc138cc71391366bab7f3605806213f65599af79f6566765", + "0x06ecc22cea23c1a0277beea58192f33b25da4ad6ddb1e0be85b19317cb279326", + ), + StarkCurve::from_affine_hex_string( + "0x06dcecfa12506355201b5b32499869013985e27c94c5fe3682b4bba582785226", + "0x06a21c3ec3238c93bd19c3474f7a317e1bd72230cd41b840864c6ecbdc736997", + ), + StarkCurve::from_affine_hex_string( + "0x031ba85e3450e3fcf88ec91f99e23b50cb1aeae90d13558574aa0c31d9ef8375", + "0x0579fb170e8c2550442bc58dd13c27884702246864d5476b04a1489452d222e9", + ), + StarkCurve::from_affine_hex_string( + "0x04429f11789162d86545ee142d280955eef51713efb298983e42ce965f8b4e4c", + "0x0206583aadae1bbd45bd8d29d789dfd2ddfd4a7194e6feb2b4ad607a8c4376a6", + ), + StarkCurve::from_affine_hex_string( + "0x06e5a5991f756775b9f5ff04bdb4e384b686a2bcbe982fab58c4224fc593b00d", + "0x0128662c953b22fc1b9cca844e41a849bc266e966c7ecc00632c1d00b3c161af", + ), + StarkCurve::from_affine_hex_string( + "0x018500d60c537342f068addb42703d3146d41afb3c4ac257b9b27bea5002db4a", + "0x012b1f12393525ca065c5051f71958f6ada62d6cf1d4122756d5ef184fd7c24a", + ), + StarkCurve::from_affine_hex_string( + "0x07b9a2d1a8c4bd9845f8c87f22678592c841b183b84378b6ef9418b5b1475726", + "0x0436b2a3e8b2cbc0f0446d3a8a34ba996eb2040b68a83a0debb801e78239d53f", + ), + StarkCurve::from_affine_hex_string( + "0x026069e359b2e847affaef604f772f36224608b7642245d0e643889ed231bddc", + "0x075ae1ec379f074ebc91270077c74b4d34347ce183b676b4dbe100bfff143b9e", + ), + StarkCurve::from_affine_hex_string( + "0x03196d01d1fa11dc3803b4813c4bbc6326869f61410f2bd14bc0f570d875aebe", + "0x020313217cac79875bd2a503db1e86d1e5559911667a02524759344468d9561d", + ), + StarkCurve::from_affine_hex_string( + "0x03fbe35d14b4de3dc76997af6fa1049d07dc478ff753cb908b59fe243c5c6c9a", + "0x07900979e0b2de8766c8f7067ad9c7fffd9eb81f1d4dfe93c220130085ce3700", + ), + StarkCurve::from_affine_hex_string( + "0x0483256607f75f06fb126addc60cadddd602154cc4782bcc08351a48745d0b97", + "0x02950a7e500ebbe9775f08be37cc2e62ccf9030de18948d1bab07a4a9173f75d", + ), + StarkCurve::from_affine_hex_string( + "0x04786957152f902149e59349a32336c1075c224c96141ed79e5b9097f46bd0bf", + "0x010a6bd4efa286277d929decd51007c075faf769a0cacde005b5824bf920acac", + ), + StarkCurve::from_affine_hex_string( + "0x0304e839c5c036fb15649f8c79402a0350dca2ecbffbadeea10df3be8197ce59", + "0x017ffa0f204094e24fb615ddc064280d9b1d5d13e3ddd64e8ab8da4d3d9c147f", + ), + StarkCurve::from_affine_hex_string( + "0x030d3f665d6793c5871338dada7d35a8a935726c529e47cc86c2f41bf9468ef6", + "0x0596f13cca6d4fabcc54d73b0205e819baa4e159559744cec728d7d0aed3de97", + ), + StarkCurve::from_affine_hex_string( + "0x065f07b6050a2fc6eebe2c29ffa62f764060f7f9d3c82d2cb5e4e368aaa442c9", + "0x0562c9654b646cb84a213b41de203c871b3eae0a05c9c105a66a53c319c06373", + ), + StarkCurve::from_affine_hex_string( + "0x03851ed963f0a72c26648887e2f3668255c9dbda6bff83f19a34a01251756b9f", + "0x07b009a1a54b0417a5b10140eea512d4984fa626530beb2412f3898494bc20a8", + ), + StarkCurve::from_affine_hex_string( + "0x0073d3d1d3d4d20ca50a5d8771bf6f049dae5d54a4347a423006cee8deb32173", + "0x046de16660a2f06b327a4d34536b7cac730465b97cd94cb4f4538ad246164cdd", + ), + StarkCurve::from_affine_hex_string( + "0x0771b6303c6ab96037ca86422edaeaf746042d1221782016410a3109a62e81d1", + "0x0257d719b33f6d3ef05a2ec4daff7dafea6d4451d30eacaf62f4b6506f7e3ef3", + ), + StarkCurve::from_affine_hex_string( + "0x07720a11436b17f330cddd2dfe9ba42b66a70dedd9a92f2d751850aa337dd740", + "0x02521d91c363b08aec46cf70f328f9c60ceaab2be0a8da60e79868c0af477e7c", + ), + StarkCurve::from_affine_hex_string( + "0x04681b09948838d1c423b1f9e93d1e43835623fadcafe1926f85348e916ce325", + "0x050738ae3794ba5116fa7170530b7f5b7249319f1b43fdf2c7fe6a3a2cdb1928", + ), + StarkCurve::from_affine_hex_string( + "0x07b5dfdb0972fcd097c3c39cf72e4f72fc3425ea481422c15da0021bdb4d0705", + "0x037e0029ab002fdf7b1898aef603ebd5820bb96897db53c20d8e26a5441eff20", + ), + StarkCurve::from_affine_hex_string( + "0x05f9df4ae9aa833b7bc48d6de4bd8dd952d1ab64e45974365deba56e729029f1", + "0x05b9f6468a2514fcf1837a60e5c6257b75119d227aa6d6801384d450f5df9fdb", + ), + StarkCurve::from_affine_hex_string( + "0x0284870f6181c43f3b01d94baa9c5b6ada0deb861145523ad9169580eb7bed35", + "0x05e03e6c40c1cfa3cafb01fd0622349871832a9d35499d06408a83edc1b76d02", + ), + StarkCurve::from_affine_hex_string( + "0x0032229810a52137f0e6c3d37595c46f6132822d4b05f42674b48d7a7ac3ad85", + "0x07babde959a0cf2c53ee59fc52c77c3adf899453f077f441965629f9aead30cd", + ), + StarkCurve::from_affine_hex_string( + "0x076d0f876ed9d4486460cd0cb29080ae229c357a03ffb5dde47928223d742e2d", + "0x029104a0b8f698f30b94d7d586e78d2a0122f4a43d143826b9b05fb043dd8b8e", + ), + StarkCurve::from_affine_hex_string( + "0x01ea8b98a6b85e74e0a2fbc18b206e290f3ed94ce99ca665e8e2351dfade990a", + "0x0478e93c4724115fb1648c8d5347422adbc1a0bbf962b2312e14aec80e1be742", + ), + StarkCurve::from_affine_hex_string( + "0x0022490883a28fb1b9642b29c4dd20f61b5aca5f1efe2d73df4e74cee3198da8", + "0x07e87095c97f950ef2b2f58df349007b53a6d6f102208f444019a3b45d7636b7", + ), + StarkCurve::from_affine_hex_string( + "0x008586b1b5f5d5bce87af6ee001d9ee4d4ccfdd017e30c75bea17dc733540862", + "0x00a5a443afb78dd4a45cb6c0150e009c2e718720d7161238ef38ef7730732575", + ), + StarkCurve::from_affine_hex_string( + "0x0039136e5e45ee3b8cff7084ff8b8cb525eb9048ac785075d51561ffc144a7c1", + "0x02642e9ea6e12ba28b3a66185afdf5a1ec22253986be68463801b1a160496344", + ), + StarkCurve::from_affine_hex_string( + "0x0270cbaa08c79140c85b864475a0bf569cc03ac785e57f543dc444f37ce746cf", + "0x03a9b8d894016680ae9d1bf3deb931d8987d4d8d8bfed45b81ccc595ec79046b", + ), + StarkCurve::from_affine_hex_string( + "0x038405dc4908a50776c584f2065eadf3cd91c8b505549931c9d781bf7f6303cb", + "0x067f50f671d02cc43c0849220c7affb458d6cd86cb8548713a231156160be965", + ), + StarkCurve::from_affine_hex_string( + "0x0421e9546780efc20075b61f32c8b76ba00956424cc5a7a8b06ff5706abff4ba", + "0x015232929e21d844839daa7565cb0421397e9fed94a3be2eaa2d5e2aa60866a6", + ), + StarkCurve::from_affine_hex_string( + "0x05adf460eaf1c6ed6be3b086eb7cbdd20fe7cfba975356a93260472a06483c37", + "0x050f0c11054771d816ef4a001992296d8e7392f82d24f6fe4c89673cd520b7e8", + ), + StarkCurve::from_affine_hex_string( + "0x01d624adb487d389718d1691be787cffaf992d993e27f1af9f373d359fdcbae0", + "0x058bef53b1c1bb6b6624e73b02c0e9802068480395e6e7bcdd71b0b013a8cbe6", + ), + StarkCurve::from_affine_hex_string( + "0x05eee9e6c1e31bda405bcab0ab7a81f439cfc31db44869e39717fef50ca81cab", + "0x04fe6a9ac7ca39665fcb43450ab02f2197d0d8c95410350fac071124f887e426", + ), + StarkCurve::from_affine_hex_string( + "0x006ee29b897b49664cf80ef8ddb140f53af3550721a1527c08beccba7cb1e706", + "0x05322f0aab4aa3815e08861d52c668e68d0ad56951ad95eea127274048e62574", + ), + StarkCurve::from_affine_hex_string( + "0x0787e7ab7c02036711355c331439e80d940ff2c9a2d3d888ba17a561fc6a22f0", + "0x0102673a0e4131d90ce88c1c4e910adfdde78ee7f88e4e0512fdabf08b7e4fd1", + ), + StarkCurve::from_affine_hex_string( + "0x06943922708b8ae5b40dd7031ef2e487abc4ac39a3591368285e83d6c9c51f4d", + "0x05f157c37d09634e8cbfbef90ea50af59815d011e419a691c67ca3402b5efc33", + ), + StarkCurve::from_affine_hex_string( + "0x048ac6a80979fab4912cf0cb557d917a0bd68825d8658ec100496eaae6ff62e1", + "0x02b6931350ab183402e39476340eb1177b7006f7a552915581e29a79bd7203a0", + ), + StarkCurve::from_affine_hex_string( + "0x00335de016042ac8754fb87914940a07075a9cbf0eb8a506a86f1b0fbcc89387", + "0x05bd030d293c047136c0e03d60bfc8e71dd53e28387e6ffc5defcb26a6219d8d", + ), + StarkCurve::from_affine_hex_string( + "0x00e3adf9517d92ef22d1e2a787740a292ba32d5ca69faa9e8675f63ed816dce5", + "0x036bccf69bb12dadd610145a3399213248d193660d8dc90a2e206f23bf2c7997", + ), + StarkCurve::from_affine_hex_string( + "0x035738b673f82d1777c2e7db5bfe1b7ae3f265afaa26a9ba9fb86fe499d9039a", + "0x01d39577e8212bec38e799e9d331c3a31ab7c97fa23e91dd5499d7443f996cbe", + ), + StarkCurve::from_affine_hex_string( + "0x05f2585ba667312b2bff9339f8a833d82d6b0f21dd5f78989b819510fbc9ede8", + "0x02a8a59f2f5d0cd9f06b2d988b8630251502fdd101181dc4fb24d3f4f663fa15", + ), + StarkCurve::from_affine_hex_string( + "0x05b0482ad579465ebaac8b7ef2eb1c05ee131d0b67afb283e6d31aaa0d943c16", + "0x0674d32043c956e73e39e65844bd28bcd625ae29285d156ae484b8a046bd53b1", + ), + StarkCurve::from_affine_hex_string( + "0x05e6c8ae5afb2fa470f767581f3d578cf6a49547e4b78665edfd45776948bef8", + "0x06cbfc11953dd7e195d2ce74e52a60df524767b44c4608bdd755be4bc85eb74c", + ), + StarkCurve::from_affine_hex_string( + "0x048623d0f9c6f55692a003783e7e8b371054a0b2793e5c97c9f1272aaabdce0d", + "0x04d0d74d29ab398ceb1be45392ab3ab1ec3c2e60aa01e2d1806887bf73bafaa5", + ), + StarkCurve::from_affine_hex_string( + "0x00495dd9232e52a4c9d03460ce5bae043ff3eaf16b0c489b0a5c668f30a3c53f", + "0x0285811214abba2f0e71f1763a9e5a525afe2feda54b64313cdb7bfc78ad8a23", + ), + StarkCurve::from_affine_hex_string( + "0x0244292e6ebc387f91de6312e0e259f50e283f828b482b4e5e7d4324a18796cb", + "0x0171ae42810a28e4f5a8ed4982cd98f96726b4ea0c4fdc4b42ff37b7a91f2bfc", + ), + StarkCurve::from_affine_hex_string( + "0x002e4cb67bec44a3ec81cd631050d567ac6153f0e4c8d24d8943ebf1f44fc5ee", + "0x05b0f3a050c08b10d535dddc01714014b7a53047d1714a81073e65b190549d23", + ), + StarkCurve::from_affine_hex_string( + "0x029459626300d862cf28ff3f48f8e32ca218753f205012227fb6b80cf99abf64", + "0x022b57e041e9e76b618c9537e079a941d1addc2a9fdb2b7712214dd619b3c631", + ), + StarkCurve::from_affine_hex_string( + "0x07f27f2d9477f25150ddc010f5ca97df36c04720278f253403e1b4c348e32bee", + "0x04c87b67f6ccd623089fe1ade54bb1d9c646f5722397e9abfc4ae9340e373a3d", + ), + StarkCurve::from_affine_hex_string( + "0x030736e373eb8c7853c3b053cd2e1d3558f9239474eaa07f86ec77495317315d", + "0x06c821509c1587c0de0d86dd7408c38a3c554628b9979c33ea56b557ca6c5b95", + ), + StarkCurve::from_affine_hex_string( + "0x015a576a1242d39300f0db3ad770983825988da0457718ecd596c63a0a0eb4a6", + "0x069a42e5f6f5a63349b57683a4609bba90f556a1680fa1ec3b02ee7d3211f903", + ), + StarkCurve::from_affine_hex_string( + "0x0274cd14e4fbf2ed07402e8ad8075b320c5f76b7ea45ea36af523e95ed63ab50", + "0x06ca640f9557c5f2d8b27f6ce95b108880ff4e4816b26b70b6506114389ce656", + ), + StarkCurve::from_affine_hex_string( + "0x0629ff44972a58fa5549b98cd9cd9087ed688a4ff27b8c6913606e0f97b228cc", + "0x03fb8eb904281feb502e20c82ab77b45968c9f990c2fa14eb324b3ee535cda63", + ), + StarkCurve::from_affine_hex_string( + "0x04d8284e132e2fe81c5f71be1e3c79ab51b229e2c56c323e207cda179999d123", + "0x0116cfc00e9fbee1cf16af6282123cdf20eed13021c2037ef4c86f94eb6e6cba", + ), + StarkCurve::from_affine_hex_string( + "0x02c6b698701f17c06a6b27cc28e69fa9ce242daac5f99fa3930a9be709b72416", + "0x03406fdd57326ecb8f10cd39a28674cc1a327ed1bbf980a335499ef7c0077d3d", + ), + StarkCurve::from_affine_hex_string( + "0x046d6508209086f0769547349e80efcb5a7c0422aaa97b29b00a600ffb782848", + "0x0430d660d10ad6679af831f5c2f1160c5f1602609845d92fd4bcdc378b87ba93", + ), + StarkCurve::from_affine_hex_string( + "0x03660fec31b8bd99f5fd1818c4f2a0091514ebfb52bc714d7361cf93b51ab454", + "0x05a864c33cd115942a0bc590cc23707d65fdd89bb2418ab02e3e107f3ac47fe9", + ), + StarkCurve::from_affine_hex_string( + "0x04056194fb5643e97991942ef5b63cadd89080bf57a01489c4398aca03f0980a", + "0x02e2cddb434fa6f6da7859c3d518f0ced8795eea043a6c9613fb3e020103339f", + ), + StarkCurve::from_affine_hex_string( + "0x00a7a8c3b7816756f73d60f285b027dbc0e11d1e57eb9973405c5c338c309666", + "0x04425f9b842f1edeec11d61654f701abd09e1e14c89bf78eefbcf5b0dfdb07f6", + ), + StarkCurve::from_affine_hex_string( + "0x0719a61ce6ab70a26f7a13141e6e9597136a54cb092e044e0a77e06034075ab5", + "0x024b10e38ee13478045cab73fe09316031df88f38f396734aefa2837e4a0f7fb", + ), + StarkCurve::from_affine_hex_string( + "0x018e086f2ff85bf94cd19aea65cdfdc21407ea132c12e10e687fbf1b1010743b", + "0x0108ca1eeaa979e69ae9373d184deee75ed941599f383f3ff5fbacd055e6c9de", + ), + StarkCurve::from_affine_hex_string( + "0x03e43067b8c950e6b98f4c4dc215f2df7cff32239e320595fb47d353ce2b4ba1", + "0x0011955e1b65495469616917a1dc8f3265ac8395aefe9865d31d768bb6c1fc9a", + ), + StarkCurve::from_affine_hex_string( + "0x077ffe5d82baae42fc11a1418524d78835de6377dc574cede264e8a3ee01ff37", + "0x00c8b4dafa79ad57c707a753c85e5a1a28ef44464b872b0447662e94fd51bdc9", + ), + StarkCurve::from_affine_hex_string( + "0x0525d6d4be6fba6bc7f3dbd519ea72992b2b215df6a84af71c36452617ebba6e", + "0x02b1f77cb7f7df2c4a38d7ca6cdf2772692c6db593d761b35da607c1d95c2986", + ), + StarkCurve::from_affine_hex_string( + "0x03446d5fec558aaf1ad20a6db37e174597f21387e9fec81363e45fde1336a23e", + "0x01a5f33f27b09d8523af4ac9778f4142013ea6a59e0154f97f600fd168577695", + ), + StarkCurve::from_affine_hex_string( + "0x05d119d5c5ce532afc0875e0ee9b026d878c8773d34237f90a0d0670da6f01b3", + "0x04a79fc025ce076b6a4742fbcc8cad313d0a8220c58024a41a5a674c0947e64b", + ), + StarkCurve::from_affine_hex_string( + "0x011800ce4061d99b9d53fd4138802335258f7798c5a935c9979f5a949ce1d483", + "0x036745a4741a5c7290eaa8f2a3f9ec955ccb7ca323272e5d35d35c2a724ffac8", + ), + StarkCurve::from_affine_hex_string( + "0x04f5f49bcf1dbb6a549e90671717f1847e24385b682c1b9a4f834ef131296d56", + "0x001c61d3c6c48dc0b9ed63b96f9b22680cc25fccacbd158b67d1427084edbdb0", + ), + StarkCurve::from_affine_hex_string( + "0x04302525bceb97fa642fd5560a4a39fba3d2c06f68e6aff3332ff1854439ebb3", + "0x00e31edfd081ce82f8177b2d7d96e69851d09e908c2517114ffb37ee12c0ac64", + ), + StarkCurve::from_affine_hex_string( + "0x072781ba09df21ba11617060a9689a46d962ef1d84a0a77e2e93525599fa785a", + "0x000c1d281b5fab2f7ab4d20eeaa852bd09816ac562bc776a0307de99bd8ff39d", + ), + StarkCurve::from_affine_hex_string( + "0x0058e95e404048f4bfa65554f7333839a8f84544bd7e58b3d172788d40b53565", + "0x041e5e2f7a7b27f3e64ea4b76dc249751c4f9cdf940dffa7a9ba408906114ad4", + ), + StarkCurve::from_affine_hex_string( + "0x06c1f528b2757a944ea30805a69034c4cbd99d246ec88d654f988980edcdb990", + "0x050d9ed12e7393b3b5270908d4258467a29260f6f9b27d5a12ede4421ba7a5e2", + ), + StarkCurve::from_affine_hex_string( + "0x02f5fcbb96f0a66fd3bdfbcc78bda361cb812570f50e7c476533d56eee01c0e3", + "0x0527428a34855b5695c479d8fb7e831a299f7897f36682a74169cc60d160df2d", + ), + StarkCurve::from_affine_hex_string( + "0x015dbbc6a872ae720cf20ef28281d9da953fc53b6a2aee201b529b4728dc768a", + "0x07fb7ecb7c1cef7eb9f4e8e5ef65c4b62898cf4fabdb25407b64d2d415bb6682", + ), + StarkCurve::from_affine_hex_string( + "0x03a60bfe56426c431fb68061da7bdc52a523d11cbac619c75cb3274458cb363e", + "0x07a9f7fc212e2f3e9f1cab0b9b02508127b5b44e3e610eadeb1dacc0e3f27472", + ), + StarkCurve::from_affine_hex_string( + "0x04ac58ba046af84c02d6dfdb45fa3b4cf412f6fac1250f9fd2f77ba6b48eef27", + "0x04c24c36b94c948247bf3013d55bb34b69f824225fcaf6e68abde59fa92322e9", + ), + StarkCurve::from_affine_hex_string( + "0x015767f416525ab20c40e6b08996c154fb3b494f5b54571a9324b9b757df711f", + "0x0327e0a79c8d857057008ca1d4b8298deec742d4896672b8c7c038fea3c9279a", + ), + StarkCurve::from_affine_hex_string( + "0x06e6fef073f6194d94de54f1562bb4fff224e46ffdb42cc846c400eeb3793e46", + "0x014bb0764de3ae3d35ce1e51bb5857773c0bff20d3b0030a7c626139891d337c", + ), + StarkCurve::from_affine_hex_string( + "0x04af3dff0f7fd9f14de1144b1c0f2f321864434d97665abf39273c6395fc7df3", + "0x067fc3e2856b864e1bb96ccc7e40008c3d758826a33d445b7445171572d03f64", + ), + StarkCurve::from_affine_hex_string( + "0x019dd220b8435e9791ea43456745870170b4e552d36f3a6dbc576130207f97b2", + "0x06db199b0169aca22c2c8f78532204b22f853afc115a40d83aeb5595f6be84f9", + ), + StarkCurve::from_affine_hex_string( + "0x052167df045ad0dc999b98de3d035aced9da4434211149b8cf4bf20e774580cf", + "0x019051d2a1ad3fab190c5dfaf45188b49b4e90cca22aae54f0a785562d3d3f41", + ), + StarkCurve::from_affine_hex_string( + "0x0541b5332491dbdb2b6f6bccceb7634970c046963891fae936dd950f4432b961", + "0x078fa54da996a51e3a9c06091d58c2405a806649da2bb1f323807c4eec50eda2", + ), + StarkCurve::from_affine_hex_string( + "0x06488440d63106ce22f779bae9fccd2c4b6ec8c21057d1338b86faa94ad5311c", + "0x062c27acb51112fc6def6e98290db37fb4960b30d3f05f069a2fa1139a92eb90", + ), + StarkCurve::from_affine_hex_string( + "0x05f11e973da659b7738f87ca5bd4f3bd02207dd3c8d978f0d3e83fe81030febd", + "0x0137aba7027069f62d25caed416e13537687bb1428e71e5f0a0c52d52f2e65bc", + ), + StarkCurve::from_affine_hex_string( + "0x052e4cec6a1877076cc5b6c7a41e465bc1b7027f9c66edf5b19d21eed270fc56", + "0x01bacd26e904a5aa09062019d6a3b5f97261e215c26b1ec8dcb08bdcc38b054b", + ), + StarkCurve::from_affine_hex_string( + "0x05e9efa3be3a7497059afdb7199530038f630154c4c7c315dbc505c9b444f010", + "0x03720f92f0677b8211b5a08c525d368d0f1dbafd14d26f88dbfd644aa20a3f1c", + ), + StarkCurve::from_affine_hex_string( + "0x014300a56b403893e8e704674d6bd44dc4903190cc3e46b7097023f561ae8b68", + "0x04a5515068a1d390e4c6475445509b6faf76197abfb3b700fd2282933c1d5f5b", + ), + StarkCurve::from_affine_hex_string( + "0x015ec941ee6c2110b819b5541be52981c09d83484c9dc735c43f39f5778718b4", + "0x04561826142dc5b56acfcf605a78a4090472bb61235bcd605a765e05d0a7e549", + ), + StarkCurve::from_affine_hex_string( + "0x02d49bbd8057cb348ff41c9d36cd7579b32797e1bd4f78fc17476ac406c6e3e0", + "0x063b2b0b25bda6f532821cb16d7096c1f67acc6e52d95cf404ab93ab2c0f2c95", + ), + StarkCurve::from_affine_hex_string( + "0x027c5cb464c908cc17ecc703cbee04ae771585517f885ee5e65fda880f744e25", + "0x044494a61e69348e1f16f7cd716b981e3d1ea1ac8980b4771d15a5747848868d", + ), + StarkCurve::from_affine_hex_string( + "0x0054fafae112161c6e664c8f88485330fe91af3aaed91cab9fa7fc95409f47d5", + "0x005216db6b0685801414ab643b6a70ced3b8f9d66f1a023f98fe0d63bf491354", + ), + StarkCurve::from_affine_hex_string( + "0x0346319e34155dd8d1834c2043a03f773b605863832ec9274c2cb233f6583b6a", + "0x04d76097e8c49620fe8ca52dccb72c35ac052aa1168b4627328711d09f57bdff", + ), + StarkCurve::from_affine_hex_string( + "0x0708b449cda79653a35336a47fe7859bc278bc9cfcb398e764531fc90c7cdd96", + "0x02d4ce9f498b2aa462b29010886cd3d2d3dd59614643e0bfb8d00915749fd13a", + ), + StarkCurve::from_affine_hex_string( + "0x022420cf72cc212faff3cc21c22a952ba83860f50f91f2088fe288f19da5b914", + "0x0243ff85318204eebf2d245c53fff8c72b4f13b701adfa3af5ad43f97e4ee093", + ), + StarkCurve::from_affine_hex_string( + "0x04d2843f85003bd0ec8139463a0ef39243447b27ad9f619d5baa0c3d15c191cc", + "0x0585f2eb1d999fedcafd5c7634b50ef682c69fb1d2d713890a266c5774e65404", + ), + StarkCurve::from_affine_hex_string( + "0x068ba398736d659522f484406110b43c68158bf4992094acf797a38979c587a4", + "0x07c1d9e1702e28afddf22fed7a7a79df4315c174d0c6c4f4c75bc77d9b56777f", + ), + StarkCurve::from_affine_hex_string( + "0x067889cea31c81a429fbae643a4fce0ecd690a5c32b99397e39ed6d7a08702df", + "0x07ea277c80b671146c9e455b98f42f45b941ac95ca2d15c8fa9ea82ee9b45e01", + ), + StarkCurve::from_affine_hex_string( + "0x05bc3c9c27590089e83affe30c56d847665a6d8f609f5d72f2c056335a825712", + "0x005169d9c96cfc10b44b95a2d7b850da492249f3c0a9ea9442c8fa02520199d9", + ), + StarkCurve::from_affine_hex_string( + "0x0596f2c68390ac26505d3c2eca5c77d46f8f3acbed192a2649d8c525a58d2334", + "0x049f3bd8c62c610d5c19c52d970bde24b270c4ff7ae900453b909e72483974a0", + ), + StarkCurve::from_affine_hex_string( + "0x00eb17d5483462d97842e6092d61f826fcd1153b42e507a581d51059dbf782c4", + "0x0720952ff0d37dbb03dcde5596bc61722815cb5ce62ae25b8d1c6057db1c377a", + ), + StarkCurve::from_affine_hex_string( + "0x0161f66d00b821c9f7559ef6b77e39ff2b723059d1cf622df70de9d6eeadb35e", + "0x045e24d2de389c9fb8e58d724af473a485d5de4a4a9c24a4bf05e035b10375db", + ), + StarkCurve::from_affine_hex_string( + "0x039ab8f276ebc1b3d3996286814c3d6292f1e9b9b46e3d50d310063b47c1105a", + "0x018b4da223e8546ef4c336a2431491f8d9748b355ebd2ba850b4f56c4c311e28", + ), + StarkCurve::from_affine_hex_string( + "0x0567779fb8b0afe592cea284629e3621ccfae3c4d7d3dc559c9fed750591a395", + "0x06010bdc33f1cdb374facefff537e7910b72a1120502f312a7ce41df0d552ddd", + ), + StarkCurve::from_affine_hex_string( + "0x038b1879e091f6b9d58fd7ab746ab1cde83b869e0536bcfa0661c970998b6a27", + "0x05f75f576dd11a570e94088ce84372f49fd669c4f2fe1cd63a337b854eea2cad", + ), + StarkCurve::from_affine_hex_string( + "0x05f3a6e334ab394b3845139dc43da172cde106db7d4501eb443f04dccfd5279d", + "0x053a040aa4c05d47e3be6dad84be345dc73d2ac85e46e0db6343278f2b0be200", + ), + StarkCurve::from_affine_hex_string( + "0x00323241e175e43ee77a8825380a573a3f1e33d7f4b22191ecac69129fe63c32", + "0x059671572a243d06abb6a6e252ee580577d42d2254027d83758681da392e8aad", + ), + StarkCurve::from_affine_hex_string( + "0x00f98b1882da6722c89d352172868b81f3f863c0b2645733918d15295d9d9974", + "0x069ef392e985d5f339f77ecc9d0b3604d21291bff2cba15a63c3f8ee482285e2", + ), + StarkCurve::from_affine_hex_string( + "0x01cf9756c5046dc3bdc7e3dea83cba62f2f1f5207d9adc94d98564a2979e26c6", + "0x06f888c58b87f40f241ed3bb05b820646686301b79a809f765793440846531da", + ), + StarkCurve::from_affine_hex_string( + "0x07fc9d929c3bed99b5bd6da8c41c8fbfc4bfbbab1b12b00544bd09d51601a8e6", + "0x0343372ee15d556f7706be279950c22738f7803418bbbbf82339563c6e757639", + ), + StarkCurve::from_affine_hex_string( + "0x075fdcea3af9a95899edc9ac7f180076baefb2de7b00bd35c76185e728bdc4a1", + "0x05917308a6a4c422144c18cc22b627b68f80fffcdab455d193c6f83f1fa1061a", + ), + StarkCurve::from_affine_hex_string( + "0x000cebed0233e810aa6a29a8b0829d28f1c92f303d14dd73d6b12da98117dfc7", + "0x04bdd51e1192a00df23aa8d0673e4915877ca41ddb8c9eaf21d39dd167fde7b7", + ), + StarkCurve::from_affine_hex_string( + "0x04c7085f066adeb6781596771972b188177e63f2e2b3788d03e033cdd5af1f06", + "0x02929ee89f525862b0cedb3ab9b5166e1680cb77fb4668f10a6a3d76b5434566", + ), + StarkCurve::from_affine_hex_string( + "0x004ae5450e87529a22fbfb1f65ff72573df15dfae8d477463427694cc749196c", + "0x06aeb6869e4405ccbd4aa669fa7de1920bb0d782153086ced211a711db921a60", + ), + StarkCurve::from_affine_hex_string( + "0x0760e341bd836899c226176f47685f69438270c150c6fe7744cd723cd1e72359", + "0x01bf09f2f1aac1a10ce8bdf20d5d178db747f01a4aa0aa8a5e4bfeef562cd94e", + ), + StarkCurve::from_affine_hex_string( + "0x005bd1ec5463160846df4fcfec271b6e73e577a63bc8a4db16fc535119380917", + "0x043cfe1bf45f76ba1517f27fb79f2b70122c48654606694bc4b5f8c5f871ae21", + ), + StarkCurve::from_affine_hex_string( + "0x00d8f9a93ad040806bf130d7015330830bd975afc29aa32cd3c8a953d1d2fdf2", + "0x0640324ec19b5019260cac9f6b260caa43a014893f47dc054f4589ba73ca72b7", + ), + StarkCurve::from_affine_hex_string( + "0x04cf2335caeee34e6ab5896eff52829df5a7943c8d1b8d2817f96112e48ed0a2", + "0x0488317dd8330e1454fb692d4dcba81bc8f823e43ef904c9eadb02afcdd0ddb8", + ), + StarkCurve::from_affine_hex_string( + "0x06016b94c00b54920027ef64902c61478244b1936337d2ad41d9a8d43dd6a4b2", + "0x03bf3dd9bce7f6d6f120de87fcbce6219340b59c2c1d75ee0d45105d33aab1cd", + ), + StarkCurve::from_affine_hex_string( + "0x07b17cbf947701e3b9a78d43ddcc3ada7dc6bc0eefe1a46040bf962749fe724a", + "0x052a5e4ff42573520b98c64353902aa7d50d43b452cf4d7231b63051fb7d500d", + ), + StarkCurve::from_affine_hex_string( + "0x02025b5d8b9c93bd4583ce9e0626be2ddd3d16dba433534ee9494fdfe18cbe1c", + "0x009bf8e4b5a16b6b703cc8866fd222dd8bd76ab37ec535169eaf008fc85da8e7", + ), + StarkCurve::from_affine_hex_string( + "0x0136cb029dd8a2fac3a2a501f03dfa59a91b285004db593e6a52b1487483d7e1", + "0x0571e04ed51b7d0212c57b32576d2dfd74741e1d98400230f95889c165b80cda", + ), + StarkCurve::from_affine_hex_string( + "0x02dc92873435322fcb9ae36298cf505d31943444f66a9efe749b47b80d7f2cc9", + "0x04d77c1aee7151c69ec03360c387e35579a3540bf3e9699254025e740202a43e", + ), + StarkCurve::from_affine_hex_string( + "0x003323a4ae01c1b24bbda9e1a891306f9e383abc61031b658965138259652a76", + "0x07819843902b27a87a49cd53385bd6b0d8ee11b82c342e52fe470036029dae42", + ), + StarkCurve::from_affine_hex_string( + "0x06298c6fa3e632b6fa00379a05dc3bb084dfa88f20b65faeb032e8291b76b059", + "0x01c5ee1f8d56cff5449b1eec3afd6dab6cdb2ba31e02fd41f3ca29a8aded297f", + ), + StarkCurve::from_affine_hex_string( + "0x036afb96ea22319033506070616a661363a42a845246444d5b64d0b1d1336af4", + "0x00a575496f5b9bb1d0bea99e4e744133add3036aecbed91b3dae73803a56439b", + ), + StarkCurve::from_affine_hex_string( + "0x04929e44ff692eb944d1045bee96e750219cda3bda0500029f0df49a1db30b5b", + "0x02e138dcbd092242699004b4ce98764ffe4e892841f56830af298581cd1e523f", + ), + StarkCurve::from_affine_hex_string( + "0x05972d0e526311bacb70a04e88969b6c63c7399b578f0dc28bbd00d65ef01da7", + "0x076b22bca9ac12d26530e7b0757e646beb3bbc5680d0f3f82fb8ee57ed4b5e39", + ), + StarkCurve::from_affine_hex_string( + "0x070d4dbdb1079fa04209b811c88c0972e388e4d986807606ecfdfd6b54b195e6", + "0x0066a102b9e281367f666d568010c1e158a762dadd3768d70a07e1add2c73cac", + ), + StarkCurve::from_affine_hex_string( + "0x02ca0a42a26e26934ca2d48db960b4719113d87c5e57fb437d557c5eb4e03ac7", + "0x062778c02561d4ec5d83a132afd7763a8349207c6b5d01fba70b56ba660cba2e", + ), + StarkCurve::from_affine_hex_string( + "0x0228b9ebb80a72db2214bed395a2bbfd962bb6adb5ba761aa467d65c8b9f3532", + "0x01494e7d332f3f24598f1f488d6fe03bcc3983f63ce5e81d94cec33d630f059f", + ), + StarkCurve::from_affine_hex_string( + "0x04747700bacc0e16e500d0b9cb961d2a39c4370a781d8238296fb746e083eb87", + "0x0497c68c50bd920f7aeb16ed31a4879d95a4c9e2b3ffcf235c1db0b93eb172f6", + ), + StarkCurve::from_affine_hex_string( + "0x01f101e30862883fa39faa19fc711aea7eae2384cada38ead56ec9615ca34027", + "0x01e08c44497a1f643015c07abc7d69cfa90a86a4e5db312c6fe7e6c46ad7ccb3", + ), + StarkCurve::from_affine_hex_string( + "0x05137ee53f076e21a2c23da09f63c0d275408c31e4634a6b6373be5cf13e6c00", + "0x014fb446c077beb78e04de3282a63bfde12f9af85caaca4ddfab506cee31c0c1", + ), + StarkCurve::from_affine_hex_string( + "0x02c4425fac7c6ee5a5df956745621b21ca3643d35cd01ee69a322e2fb40fbb71", + "0x07a833f30eff801b2e216901734b3bfe4a8cb55d2906a01d90beeb777ff7bcaa", + ), + StarkCurve::from_affine_hex_string( + "0x049afbfec06fbc5afb59f4e0153f4f365e788cede51d4da9bdec903427ea73b8", + "0x02181dd110a7c4c4a656be2c90a1a8262558845a96f55385019dda80ba59aefa", + ), + StarkCurve::from_affine_hex_string( + "0x0676e3432fbb766c015809ec94c89d6ba75ff71bd5b0ce60ee324e3a3818ef03", + "0x0496e28478a8f3f7802e82cc57a1d45c3b7ecdbc9bd0470033a2bbabca75a347", + ), + StarkCurve::from_affine_hex_string( + "0x038fa143139cd6d2ed4394999ab414d2b5c78b82b4e120d4bdaa27bc36161111", + "0x04ae0c965da852f973522eaa46606492d1b7b6d73f4117bceb80e6d6d2242d05", + ), + StarkCurve::from_affine_hex_string( + "0x023a9b680ce4ff2e32e1b8cdee298548951b0309ee2f48a195db231c4b9d3122", + "0x0650d45ea9f8b073feb7aeb682d6f4aec36ce8428f4214c0d382579293088c38", + ), + StarkCurve::from_affine_hex_string( + "0x022b88ca505546624cdab874b49f01b6bb064a257552358f17e60bf259bbe239", + "0x01d6393f60607d195544a91d8736b4f957d327d24c89b7fd573987b82c717e8f", + ), + StarkCurve::from_affine_hex_string( + "0x01d73f93cc26756e4617ad3501c27ceee9a6ce5b33c18cc86239d830492fb1b3", + "0x05ae7c42e908441e39948fdf7dcdc85c35d4b6e84a0bf463972d90b9d52494f1", + ), + StarkCurve::from_affine_hex_string( + "0x07d944853d1627b63f560aeda33acf640d35a4ee4d23a744957a2dae9d5b7c6c", + "0x00bcb411a210710acbcb9ea12680d89e3e4e652228b6786d3886e95f4d9e6970", + ), + StarkCurve::from_affine_hex_string( + "0x037d412c2ffb173a728477446b60b2b702d07a5243cb5fc8963e623a5ee75843", + "0x0672c79968908f92cd0cb0b4c65ba86e8f359b015623a89441e1bf859bba84cb", + ), + StarkCurve::from_affine_hex_string( + "0x075dd420bc3c20c75707992047fa3c4c352f7f005dd2a0c9a741f68ea61ea5e2", + "0x00f8222477bc6846d468e2992d64d886943706f87b47cb482b0657754536c631", + ), + StarkCurve::from_affine_hex_string( + "0x05b37f472aa80398bff12cc74c8ee784c4fc89757292580d3a498bff17e9f114", + "0x07d79da1aab9cfef58a5f3d1c9ec466956a45f8d2af0c1da6dd4c93f720fae6e", + ), + StarkCurve::from_affine_hex_string( + "0x0735e15bb21942f2398161e26bd92c64f0708e72f530fa45528b9abbd78f8aab", + "0x052520bffcb0cd59c308d98088e9c3ea1517eb11223cfe7c5ad88b9e5da835cf", + ), + StarkCurve::from_affine_hex_string( + "0x00aec750bd9d2d2a931597f521f08096562f8cae0a56d67d9fbf5b6e6d68d446", + "0x066c792f2d850db9196e978addde139621a3692e08c693672b7607601c397e9f", + ), + StarkCurve::from_affine_hex_string( + "0x00c5eade7fe31dc819332c452883cdcb55a814bcb24deb1e5434e3ca78c2dfbd", + "0x00c7586f5778362cbb756dc43badfd414daf74b51dec8cd6d5f90abfd210f3be", + ), + StarkCurve::from_affine_hex_string( + "0x025c09b3f1188c562571536202eb0f5fc4b9a7590417b8ea58b4343685d88a63", + "0x003d5b817c73b37e9a1d24ca923351359b42ced2f3cafbcac8c2d6322dc767bb", + ), + StarkCurve::from_affine_hex_string( + "0x07d22f6db0785817b80603a6b448140b24e8b60f8973353440d5608c30477267", + "0x038eed6b0ed0ba3d3d4dd9ec54de67a1799a5e6cdc266785faff5d398157fd03", + ), + StarkCurve::from_affine_hex_string( + "0x0703c7bd289b40ffa419fecc0b461d2710a8c2db8d5f15e5d6118cd6c0943144", + "0x0640e113cd9fced918bf453eccc4d25185ab31a0f3cd156f570cea6b0ec1ad5b", + ), + StarkCurve::from_affine_hex_string( + "0x01de3f19c8f92240677a3d1473c128bb6a9ca378cdafde5256bfa9210c3bbefe", + "0x0098cb0af810997ef3efce3a1be29234d0567779ca4a433dbd1959b6a1922166", + ), + StarkCurve::from_affine_hex_string( + "0x07ef17f36e55b2972b0906192c9e9f51f2205b08a2d84bc78722417aa2934e47", + "0x065fe716d3226bf703c57e46b8ee4e9ccc8ecb8c0be1194d50edde02ea71d8f5", + ), + StarkCurve::from_affine_hex_string( + "0x02ffbe161e4f3f1d123114d3c34f543b35cb359feeebfb51b504ece303551366", + "0x070e94e4b6398579b1957954f397ee6c618db781e4cff756e731918689738c41", + ), + StarkCurve::from_affine_hex_string( + "0x038f30aa7efc0788f0c9b954dba2447085c13cfa3d41fa59a81b36d67e89c4f5", + "0x02eea547c4b781721363d18c990c902ef8b60b5b1b6e2f713e0d239d28521f68", + ), + StarkCurve::from_affine_hex_string( + "0x06eabfd10074b6a162bc6f2cf6f1a9d823b9fb2cfff7138dc439132d863a3bfe", + "0x0580e269cf14c4e9458454a1f4dde74b1eedf62cd9acbdbd7319cbfffe9dc625", + ), + StarkCurve::from_affine_hex_string( + "0x032e60904e73f9756f71e0a918d302aeca17cad4acacc81bab15702ab5ff78f0", + "0x00bcf4c0204f8275072f98a65b09ac58b87cdc9c70c4edfe99fe18870a3a5459", + ), + StarkCurve::from_affine_hex_string( + "0x049c35575996c1517d2daed90d2fe4a58e674d6b4aaa7288d0642c8bf59e562f", + "0x057eeee00adea4ca80eeabab57852cbf03f1a57e21872cd44221e0550b9193b8", + ), + StarkCurve::from_affine_hex_string( + "0x02a071757dfcae601fc55bf9ef21d54ca0aaed0708eb23224d11d7f640d1926b", + "0x0727e0c2c037ca0cabe79e5bc2280982adc4160d3d50a68a4b3de7c1f4a17dd3", + ), + StarkCurve::from_affine_hex_string( + "0x010e1776b4c2a867bf1b028c6edec224cc6616c747e272f49e69b67b02a893dd", + "0x008d45d62ec8e627b56950f2f7622a0438647f9e9f28e723e4a37cebc039a1b0", + ), + StarkCurve::from_affine_hex_string( + "0x04529cab559737deecd6382e5b105a83d67f980d938523adcb8ec6fc115c950b", + "0x07171b1bf016e2ff95ea3f5ac02547e7681c616783fb3790c435881910c49a45", + ), + StarkCurve::from_affine_hex_string( + "0x03bbe92a1db3bd144807d444402db9e7e7648be36ad7244ca71c1cebec018267", + "0x036c0a901ea70034655b4b764f3ceb18dcc22a93aaff950bd6bdb78e94f7fe0f", + ), + StarkCurve::from_affine_hex_string( + "0x02b51246a5a1ff0c1a107d0d3bad567a722e1ac483baa64047a6e262c2bfb39f", + "0x07b5d0f28a590c171d4c576a5a8cf9f7bdaa72deafe21c15b0bfcfee8d5c9af2", + ), + StarkCurve::from_affine_hex_string( + "0x079a93a75ecbe943acc964fd39ecfc971dc6555b2bc335e7b53f52f4eb16cd36", + "0x0146132a68ce2ca8b48363612226771ac547eb3cf52b6eb7981718faac08aa3c", + ), + StarkCurve::from_affine_hex_string( + "0x03841fc7b70be861bae8583fd3932cf5a44626333caa6359c94f43a2e94de833", + "0x06e3d13a8b1f4903aacd63fb62c5d00361358fc0fa2fbc486ba1a7b93ddab421", + ), + StarkCurve::from_affine_hex_string( + "0x07617d181826191973027c91db8eb8064a05f79d9a50d52ceebdd9f2690ac3fd", + "0x04151da2596b54c737dfb16fd6ce3cb808fe3223394d858e12f768b577e6e7be", + ), + StarkCurve::from_affine_hex_string( + "0x07f9cebe5cc7e1cfb706781695de8e5bc1424b2db26efef6ba8c7757310ca0ec", + "0x06cbe3e0bb486693d0c74b77338c47be2653403b9f77387f75cc331004473367", + ), + StarkCurve::from_affine_hex_string( + "0x07a01fb06bd582f996ee217609bb587b88c45238af47903674d37652ca9559b5", + "0x053d9b838e4190d7df56c4310baf4135484639136b5fa41ea0f77565d263199f", + ), + StarkCurve::from_affine_hex_string( + "0x0549df7e2b644ea44f68e9ed17aaa92204533cf0e4d9de83352f6c5ada70bb9b", + "0x023888f267366a05ace872ce02a4af7c80ab39bf694f28ae3ecafcfe7b32747d", + ), + StarkCurve::from_affine_hex_string( + "0x07d467a3c5b585168333916dbc38b1097b2bc72dad8e45d689f6f8b3d1bf8733", + "0x01b02efdabd079f64f782eba3e60477a0d3e6013962321d814d703fb33d7ebf6", + ), + StarkCurve::from_affine_hex_string( + "0x06c8772e475819410a619921b89a3d9fe570a22501cdf23f5cce2d69ec90588a", + "0x04bd5ccd30b46b762cab4fcb66cd9612d00e07922005405b5917479ae8898f07", + ), + StarkCurve::from_affine_hex_string( + "0x06b22d32e0590e169504e7f19864fd646d0994e7ed3e578a5b88f6e095913439", + "0x068c3b22d859fb85e5c8fa0a8aea932285945b230957e603394333e9ad5acd82", + ), + StarkCurve::from_affine_hex_string( + "0x071ce5ec8286eb8c93b8481c6d19cf0a288ef4da4397e9c80f65023e516bc097", + "0x054470babc742780cd8a05499026e738ccbf81d4170d1731734de68a8e5b402c", + ), + StarkCurve::from_affine_hex_string( + "0x05b96327f749318df9166d14fc9572ae139bcc4764c6f623a5f3ce09103dd7f9", + "0x03fabb13f2369b0fe7f379687dc828d369310dee8ccfd155135d1c64f55c0717", + ), + StarkCurve::from_affine_hex_string( + "0x0027beb13a43bc6a1f6ce046da438b0beac5899ff4d57962dcfb6476b563f74b", + "0x014074e9e93ee45394dfbe833998b9d1691961f8ba3166224b36404448c61bb3", + ), + StarkCurve::from_affine_hex_string( + "0x05149febecd552f074abc1beb25d960419076dd5fee10da2eeb9a83d886c3ce4", + "0x003524cfa92a5cec3bc0f05d7366cac9d9754b63d17110607bba9cda73ce1f67", + ), + StarkCurve::from_affine_hex_string( + "0x057cf7f95c852bb1d17c40c5e19aa4cac2c3a340a34abee5780b397111f90606", + "0x073385d023e114c4daa21d6ad104c293b6b217bc1eaf823d745dfa23b0944b20", + ), + StarkCurve::from_affine_hex_string( + "0x07a7c0c03fecdc676edfdf47ac1a94c04cd0de8c880a277573c0c5ac2368db3a", + "0x02ccfc48e106d1e89442d7189aa40d2ecc28147483728f50128eab037d4cbe0d", + ), + StarkCurve::from_affine_hex_string( + "0x06b1de6c8f161aa6509a1dcacf2c0aa1bcf6ee9d9b40e032a9d72f77a6fa298c", + "0x005e9312eb5b59d6cbadd7d3dcbc39f1b5bd9a8346fdcfdf1107bada6f9cc048", + ), + StarkCurve::from_affine_hex_string( + "0x05a38e4aad48419248adde929c0974dc7b3436afd280aa66c8b41cc1c355f475", + "0x04bc05b4ca8bf44ac90e403a92a29da1faf7b08196e03fcc09ddec6acd8a14d8", + ), + StarkCurve::from_affine_hex_string( + "0x0581b5a3d69da43bac1449c91b6b27509f3a4e6a763292893636306cc98dbdd6", + "0x068ae0c7029855f022112c46c4e682d3ba307530083bf6a14bf18abd658af4af", + ), + StarkCurve::from_affine_hex_string( + "0x078b2e17b1c846bca93bdfab486f7e2abe368ee05e1d25d5e9a2e10a1d743284", + "0x0392b7396dad0689000fa595c712774caae7051e45431972f9f9ce5b79eae50c", + ), + StarkCurve::from_affine_hex_string( + "0x034abe1951778ab0f157f1cd087313b24fbdb58c239975db82ab203ccdefbacb", + "0x04d0523c9969b2a11633b81696d0bb09b4d81b422af29cd7bbe17ffd79cd9c18", + ), + StarkCurve::from_affine_hex_string( + "0x02b40455d3e9b2958e4a4ea8d6c4bdbe619b022fba9a1d7c8b9145a36ada6466", + "0x03809b0e22528e767f1e1e5b48802c962fa492b5e56c759b81e8c8dcbe5a689f", + ), + StarkCurve::from_affine_hex_string( + "0x047bce37acc3d67ad0296dcded981b8d6a950a2ee3b519aec3f4d0b442436ae4", + "0x0747ea488143285177ca1897eb0461f518363a343dd7b1191671dd8659c44c8f", + ), + StarkCurve::from_affine_hex_string( + "0x07a3f902e9dd5c400a999868d4e83f6a6e181e21181a9b6c23bd43bdd665941d", + "0x01ff4ec9de43cf82bc919525ba56f7c0e7d6a392069e8a4437c0a23a6e409294", + ), + StarkCurve::from_affine_hex_string( + "0x032670fc3fa43bf39974ba72ea51f0d045d92d084a81fe5282dfc8309aa900b9", + "0x0518fee521bf1af62356aac3b7e53fdbf57121e030c6e9572b3de69912ca4eb4", + ), + StarkCurve::from_affine_hex_string( + "0x04b9ca363eabed9c66091a347375f7065cd28f49f914447de7cc1461f1375f1e", + "0x03a1a3a2e5e7e72476befe2571ece708052d740d02cbe6fed58740968ae609c4", + ), + StarkCurve::from_affine_hex_string( + "0x016c1225b1c6cc302906a12b1f26f57a6eb126e7b86714c32617ca49f239800a", + "0x0642f44feb10ee93f0e29aad0005485c3ef62f9fe6313d88c43f9811bfa06e6d", + ), + StarkCurve::from_affine_hex_string( + "0x04cc6da42863a3deca62fa218b7a3b50e034eb4bafd393eccba3f4cbe192ef10", + "0x020bfa683c884f203713953b26d2821287ecd305fa2cb70570474533fc07f918", + ), + StarkCurve::from_affine_hex_string( + "0x018c485d3980760ea411bdfd35702618ce8b8556acaccdf90a5d5301f8a5d978", + "0x029c98a7dea7696c58243b0cfceb64abfed5400d85ea300eccc09a50158241e5", + ), + StarkCurve::from_affine_hex_string( + "0x06d4bc77784972378aa1d8318ee51e9d22ffc0786c096b1f2fd435ba6e119576", + "0x0306b20b7ad718d9b9e58726b1094544a4509ea0919befa8bde18608a524cb5d", + ), + StarkCurve::from_affine_hex_string( + "0x0081d255039366fb563231adc22bd6d0529bef7ef0dab5ef675c9c9de7f3609a", + "0x06168942144b6d55e30d56e6ad61e252833ce8898384c1b61245c5cad8cbc7dd", + ), + StarkCurve::from_affine_hex_string( + "0x0087705353c44a5ccec8de65cf5433be6b3d9bd21eea49b60e6c907cf1a67a6a", + "0x0112804b13eee56e3b01aff75fa08fa8374c44fc461aed8a30ad54acd09c24eb", + ), + StarkCurve::from_affine_hex_string( + "0x0452ef4a03a3e04f32f5dc9ac0625d09abe0d218f4dae795f3d1718f1a472d33", + "0x0438c4952c3362784ecc892b149908fbcff8c82659d70477a3aa88b8208650de", + ), + StarkCurve::from_affine_hex_string( + "0x0474263d3698e4d5a0c3b1bab9a44405db5ef8816d2018ca566b242824967e91", + "0x008b354c7317212eef649c4b1c80c87a3785816f36485b6cf95eda8998fe4739", + ), + StarkCurve::from_affine_hex_string( + "0x0554b21b2acd97f5bcc3951542e43cf182f42a44f0ece0a60a24ee582b1a35bb", + "0x00e29be586fe4a1a820d79f0b51ef10df8c17eff0758c76ba90838b714d426a6", + ), + StarkCurve::from_affine_hex_string( + "0x026da1cd7e5812701ec9767ad4f51fe2639d4d4685eaf7fdb75e04dd8e667358", + "0x030343a1d0b278661e4da1033aaa38a8c216f63146659142c09b795ef63c908f", + ), + StarkCurve::from_affine_hex_string( + "0x003767745e019ee0d217c8ba0cdc177ae4c9ab1fe21e6b1d4515c3cc0a0e2c6d", + "0x06d8eb16a8147e85ff207121a43d05d74cf72344164d96ecd84f97d9973dbb6f", + ), + StarkCurve::from_affine_hex_string( + "0x04cb477ea8961bd7c8d5d06f84e50625f3ac5ddd9a7d0202d2d61079d20419ae", + "0x02b80b3517e48c4d090091102a2083e6a4588857eb37db8efc5fe0bb0aba9c19", + ), + StarkCurve::from_affine_hex_string( + "0x0181a5e432f119d5116b508baa46fe2bcb68abd6af8fc2dd0e03c819015fb999", + "0x0067c6f6c33fa7873f2a2bde0cb740ba7259d9279e25fc05031065e456f18c85", + ), + StarkCurve::from_affine_hex_string( + "0x06cf6eeeb9d339c0a05f72fd5af73fc7588e6d957100ee8999109437bc126cae", + "0x054fa257cea22032eac272fcd034dadf2e00d602ef9e519cf7072023c130aad1", + ), + StarkCurve::from_affine_hex_string( + "0x019b32925048c5519d929650c833661b452ef7be7963fab0b6b328ab7dd7a28a", + "0x01bd0c14a10bf9b88ea61011c0b2e64d07da151c6203800d5a5d12063838a510", + ), + StarkCurve::from_affine_hex_string( + "0x02d2fc90a73bf94c3db720e23088769696a1e3ea91b78b335dd0f993210979e3", + "0x017e5045368eb0a7a5bff3129bf138677efe519b11a89537720dbec57c4519ac", + ), + StarkCurve::from_affine_hex_string( + "0x012a5fc5559428bc3b4eff97b21b63668b866e0722807f1db1f19696bacd9b0d", + "0x04c2eb07f0c24047a3d73b560144f3fd32c99d6dbd9fc7cd2fd2a72a6e4b24c7", + ), + StarkCurve::from_affine_hex_string( + "0x071a01cb4af0a81273641a44c4db4dc0db87c8a066764883df1ae33b2598a089", + "0x07c762d9538a956d09f1db67f86124e3aca9f31aebcbdfac01343281c97743e6", + ), + StarkCurve::from_affine_hex_string( + "0x02793ec158f20a704fd44e44c488ed4ac19114798a2fe211bdf5029889112c3d", + "0x0255b6308a754e2d729053c89b2166775d25184d44e54483737424846fcec764", + ), + StarkCurve::from_affine_hex_string( + "0x07468302558c3cd547b79898a16762024ffc496b8a0911364dfe2905e8812e45", + "0x02800043bb1e9f9fc25b9a1544b133ce623e80eea3f2fc786a3560406cc7575b", + ), + StarkCurve::from_affine_hex_string( + "0x013662b7a7d390aa76eb86a7c3bff6d9913eb28db6bd1a7c42de5cdad2e35ce2", + "0x040626aded7f56f82cc431ae30527b096f57fbfbc04d3e12a5abae3edf301cf1", + ), + StarkCurve::from_affine_hex_string( + "0x01a35ac47ee8cf1c49eb2701712b63865290d97dbb2407d4f641353aebbacb12", + "0x07b3c36b89ca33bb05059307882a3959a8f5e70e8c1788da48f6db4f9a5d651f", + ), + StarkCurve::from_affine_hex_string( + "0x03643a9482f90274b45c082cb7c772055359799cddd26672bff7839f6c6edc41", + "0x05f9eb1494afdebb2d03c3122e90af7a85e85d92c4c1a0b744c7dc7316bd0d59", + ), + StarkCurve::from_affine_hex_string( + "0x01a3288165b3d496b8041d4f36d20459ca5cc49ea7ca274d53e0b67cb82ae586", + "0x07853a238c311ee2f84b869d3b37ea78cac8b84f43d740f91c6fe7a0e2059bcb", + ), + StarkCurve::from_affine_hex_string( + "0x00f07b4aebd4dbd0f5055f99fd6c39d4adf0d327e1e1119c0732b2475a3b2ad2", + "0x07c56a471744c603a0cee4edcf9cf2190139f28249699582a4b0e417fd3d2190", + ), + StarkCurve::from_affine_hex_string( + "0x018dcf54c617cf84b10af356d4b194cc87cdd5a205838186acccfc97eb17e7a3", + "0x00a712fc9a189c28ef15710bbf696d58dd420bc28fb657ef447b41c6db5135e7", + ), + StarkCurve::from_affine_hex_string( + "0x03faa880b13272babbb38dfd022e7946690c33d457b4faf21fa4dc5bff0d225f", + "0x01a44a6c42e68f28a193ab9495b983ae8cb306e1340ef1bfc00a49e73196fc8c", + ), + StarkCurve::from_affine_hex_string( + "0x06bc656b4b8bd3626705df1333a67ee8e2c0c6de22bd29f9f511ac885636bf97", + "0x06f25f2601d50e455e2ae271656a655deef302f426f2481a7bcf893850cab805", + ), + StarkCurve::from_affine_hex_string( + "0x0255825bd49b8a2cce114360bd9c8fe8c641af64c8e7710107213cfcb006f43d", + "0x03619cce4482335232f9e76a1460be9d296f2d468d26e4f95a78c71524fe59cc", + ), + StarkCurve::from_affine_hex_string( + "0x07f83009eeed4f12f54d341bbf06066480cfcdf51dda103ac54d4bcecf6b3b31", + "0x04269519d28faafd7fd68bebfd8404d71ba05d62c4bb6d65d24aa6802fb84ab6", + ), + StarkCurve::from_affine_hex_string( + "0x01c1649a9736486d4c8526528117607c4798a25944b07acd70a2acd0f17c3f91", + "0x023336dc8874c49dbd7a437596b61f022da91f47e35d79a9d5ebf5175958b1e9", + ), + StarkCurve::from_affine_hex_string( + "0x02f325650eb316646b4eec903fe44828fcb11054f1bd42ca3a77f7e734110b35", + "0x044f976082271016f9048e22c507d97d628722bb431f8d5cc1890524e6c386bf", + ), + StarkCurve::from_affine_hex_string( + "0x0107d2f6ef804c197b9434cdc5ddaf121df4ed1d2c6cbded9b1f656855a1c5c4", + "0x0724363249716ca29d1bef965a5a44fac4254b9882daf6f3e6d8e5e2fea67ecb", + ), + StarkCurve::from_affine_hex_string( + "0x06a606fd16800b8d796d09abb8c21469050fe1768848b8740e6afbc872fd45d6", + "0x062d61a1fd28555fc562573a9e5ca876f9c6fe0aa04d3c302ae0327ec41b9653", + ), + StarkCurve::from_affine_hex_string( + "0x03fd2cbfc06b7075f137d90bfaf6462187485ca0209fa9fabb695f823cee6459", + "0x032392241f9f019c14835c76816ae60f2a4be03ea9628e7f0140c3628ca4017f", + ), + StarkCurve::from_affine_hex_string( + "0x0750b166bb6edc0ee80fae39c7c106879036738df2d79fb2294e1c21e9a24d6b", + "0x054f8aa297a1afafe2a17a3254f45861167414327e918d17003c6aad01d0b24c", + ), + StarkCurve::from_affine_hex_string( + "0x07b659395e8bb7842f125457c385c7e804ef1f9c84f3d3a6d479ade59cd3a41c", + "0x06f2a7b327cab78ab02294da77e791e6647e796ba02308f45561319887949ad2", + ), + StarkCurve::from_affine_hex_string( + "0x0794b669c83ec8d902f433df9d33de8dee9bf27983695efe38f87d3c82d0b907", + "0x07301adece3ad85d9fea3e5f75cbdf875ce3f4cbf6e6f2668acf03b616d1ad70", + ), + StarkCurve::from_affine_hex_string( + "0x04cadceddb9bf118345942ede154d71a9fe580967f5701a1d7e732c1dc77c24c", + "0x058ede3d64a50e5d727110184f31dd17ca60f77a5c52467152b5a2c84e8b006e", + ), + StarkCurve::from_affine_hex_string( + "0x016f658d75c01aa46cf319d58b6d5cc1f4d8ddf0bb3aceeded70dd37f979367e", + "0x06a87fa09d3e5919699b6e4c81cf4c9e5a7035c7ab6b73ddb175267e993154fc", + ), + StarkCurve::from_affine_hex_string( + "0x02088d6deb0b560dde3129cfe9f5e7226ceef7b4bca6970728a44420b5380f7d", + "0x05173bfe27897b347728c6ea8e1161317e6ab8a41aca12fd70adf3e6838cd125", + ), + StarkCurve::from_affine_hex_string( + "0x0766165d778749692c019adf2b9ec0b5f4c7f466bf1ad6cc12d597e23c25ce98", + "0x076053f73d3d1587fc162ebd6ac9bcbe683374faa0a15967e1bbd3065bfc6d0e", + ), + StarkCurve::from_affine_hex_string( + "0x0604203efa6b354c1b43fb22b0e0e3f907b1ee3de0ef034998d0ec9d4d1f861e", + "0x05e7167c9a52c15004e4755fd44c584d279c8afffc419b23b15279584978ae6f", + ), + StarkCurve::from_affine_hex_string( + "0x03aedb10db9cf3285cdeee375879396fac1fb50dd259e1716f8c01e66f67ca72", + "0x07feb9400f621f58c21601f23b7ec7c94a9b6b193c1cd74a8a60846aedadd359", + ), + StarkCurve::from_affine_hex_string( + "0x04ab7151702de76faa493e7a0b1ac20ee4d10c33b83fec9477547cb1236973eb", + "0x063f1f122e3ef3acc46b0915ac69c3f5772879799cad889a817f55f5853d1235", + ), + StarkCurve::from_affine_hex_string( + "0x01fef4984ac71fa5db51e6bda4e4a8e23f41232dfab5a159ad17709554a83732", + "0x07f7017955e6389e21430a8f77f97f1c6bf6154f00a005660c76a94bf11b531a", + ), + StarkCurve::from_affine_hex_string( + "0x01675ead0d20e5bc3a7a7331999a87ac4c916ae29669e54197bb02aa6364520f", + "0x04d1122da90d49e491922d9b533a6a668e2f65a2737ebb391ebb29fb7c1f8a9d", + ), + StarkCurve::from_affine_hex_string( + "0x0465634cab60985348f196d1602a932a474bcc61989aa09e0725bed9195a9bbd", + "0x06d028e36b701b721fd85896ddfa4c165bd496aa43d4fea71ba006ea4f04627d", + ), + StarkCurve::from_affine_hex_string( + "0x07ac57d51bf8173a030a6fc9952c3e487369bce7cb1c1400d771f9a1be8c998e", + "0x005539bbea9db994c5ae8ed339e3a3e14136ca8f3f10fdef11e41211ebd1b31b", + ), + StarkCurve::from_affine_hex_string( + "0x0056145b9633aee6dd42b5a7268de3cc6447693e906eff23d9b69314423df828", + "0x0661fde3d9df064099d671ce42e9547c26089f5f47a6931d573e8ae2039a35f6", + ), + StarkCurve::from_affine_hex_string( + "0x02f7148111ef53c613157aeec12e16a20f13481da4390b6ce18a85d1d8547087", + "0x02eeda779ab395597651d2a0b833ccf53b10280750139916ae2baf4ec57c633d", + ), + StarkCurve::from_affine_hex_string( + "0x04797ae2b36c492549df4e4502ba763ff59ea0d9307e685b5f9333c894180af2", + "0x0169b2819f8a703427fab0c5e21000cbfe27c54e73e66d81cd3472ca77d9a82f", + ), + StarkCurve::from_affine_hex_string( + "0x076ee1744d6dd2a5657a0349918b26732481a0ed0dd6806f57b92636c8efd4b6", + "0x0781109085344cea212fcacd660952db070e65278613f5c0a42e6db8f2696519", + ), + StarkCurve::from_affine_hex_string( + "0x063ccfda68ce7d794aa7c18f56a1698b909a03145fa62579ba72cb754702ec49", + "0x040b3d34fe9f7fe2a8f4acbc57eead33a566d24e9509a7749a141ff7819719b8", + ), + StarkCurve::from_affine_hex_string( + "0x05408adbb2c572fa635d30f4414435a4aea18d6039bee419c2003902e2b70acf", + "0x0193992ce312a57eba1303f65a8c3517208cb69095d3553071a7cb8ffbe4f3f9", + ), + StarkCurve::from_affine_hex_string( + "0x04cbecb6c850bb39fd97ab31ccfbd0e62eb8728f84669b1b0957bdbcdab74725", + "0x0537296c9f1c10c2dc28b5a0a3f2b4131460b01ba4fc3638b4b1890637983b1e", + ), + StarkCurve::from_affine_hex_string( + "0x0056a46da8277a3676e6151fa10fe7723924d7b8e51e51193071eca569acae7c", + "0x00fb87ecd90525261340abff73d0cea4132f5d531352ee3dd827b96ebc8be0ab", + ), + StarkCurve::from_affine_hex_string( + "0x01786ba4a4c2c75b9855fd65d6f861c9f959eeed746823e26d31e657b11094f7", + "0x02daf77cdc6eceba63bae70a65b7e7a54fe80f7e20501438debe490b26dc84fe", + ), + StarkCurve::from_affine_hex_string( + "0x04439c7810e7b2ba772b701ec3acdca0b80c9df23047710b87f7dc3f13b337d3", + "0x05029cfe704c602a8a4662af0a5860ec03fb88f046d0e3400f2ce7638014c621", + ), + StarkCurve::from_affine_hex_string( + "0x02248eec40b5732a6a488b681f093643af7937071bc73118acae295a32b51b05", + "0x01577e4aec30a97b648de4d0b19cf8891151b4eb11f8de9c6d7312f091552e19", + ), + StarkCurve::from_affine_hex_string( + "0x07f0a8523bca4ad80e04f1c207a145f14f50dcfce7c32162b596e1a89abcf0ff", + "0x049a3de68d88983e34a3e5e8682287b2ca6f5098a9a209fcaa1e616922fa270d", + ), + StarkCurve::from_affine_hex_string( + "0x04738424e558d4e0d87a3124ca02ea24f0adc6b7a9768b0d3945ed2a6104857c", + "0x0033576f92aca3f0c8ae689c3c274c2de6b918940d86a6852e02fc99e35d1614", + ), + StarkCurve::from_affine_hex_string( + "0x0671b3accf49c52dea432655097c72f46d5a350c69172b17a0220f973746875e", + "0x0488cc52af96f67dfd7de7addef8855334f1669587b26e937a574bcbd868f855", + ), + StarkCurve::from_affine_hex_string( + "0x058f476d9a4408cf9a2607cf4f61b54a1e6689ddc97856098d0264b113933660", + "0x06fa567773dff779e649834f9a6ee057841eeae323c89b4cacb0b18ec304bf90", + ), + StarkCurve::from_affine_hex_string( + "0x017b2dac6d06143b8c2bb010eeba4f50ec595f8fadb4f7589f39539a5ced0d3b", + "0x006e8b5ee833f19eadfcfd190d7e204ac322583c122997797e74a7f73044d79a", + ), + StarkCurve::from_affine_hex_string( + "0x07829edd8b866ebf7baaf604ed13d19a9797578f44bbc51b1cd67ca53803e96b", + "0x05559040a6083f2af1f9133ccaf5bc2ce06e56ddfc7dd410e9635c0116b62722", + ), + StarkCurve::from_affine_hex_string( + "0x077349b499ca9472df70d65db0197881dd25fab03e80be9bd075a8c98448fca7", + "0x0424768b4eb05463d6fa2fcb8dcc44e9b565a8b463847ff360846b110645a995", + ), + StarkCurve::from_affine_hex_string( + "0x0315f8b01b4e7a20113fb035201e8161f6399a5faff23c93ae31415164e51325", + "0x00452d88dd2b40e9c7e3036817b0e8d41bf0ea885c7e3a43d755e25753e1c960", + ), + StarkCurve::from_affine_hex_string( + "0x0780c31a0d31819552e95814ccc571aaac900b3f3ed845635fa05b653662ae66", + "0x030d86dbc3009cb6064ffb234e9fa13a8d143530fece7a89549c519beef75907", + ), + StarkCurve::from_affine_hex_string( + "0x050051882b947333de55e2ca92a6e4bef4e92103978b9b4cb9a183c210ba7828", + "0x04c3137031700e20c3b5e30f291f61d43e36aab26d670650c845fcf08faa6e55", + ), + StarkCurve::from_affine_hex_string( + "0x05f6ecb6f978460a6dcdae171904c67105672fae8ca690451f43bc85c6af165c", + "0x06b634d81f1d918066e033e5f73b950f60ca45c35ab2aa664c65fc81b3365a02", + ), + StarkCurve::from_affine_hex_string( + "0x0172ae2b485ee895a76f834aa0c625369239300bac9a00c70338c1a88c2c4451", + "0x06144d2ce25d2df5831a2e919c195f89d8ff75bc56ee57ffa9b7716e53e345f7", + ), + StarkCurve::from_affine_hex_string( + "0x032738bb1e6083bbb9d11cb5f564dfd256a82ca7a9858de75eff15035049f3f7", + "0x0098f2d576a36ea27f8d76e180e63745a1a3b054d364d2d50f4a25fa4581ed62", + ), + StarkCurve::from_affine_hex_string( + "0x07f927b881f2cdc05e1a69e40bb714af47b630d1425f08ab5d574ee698f33d51", + "0x026a465288e96572de303203bd38f4a03031e8158da0591cb037c0a5111d1056", + ), + StarkCurve::from_affine_hex_string( + "0x036a65598552f8753580d1655417d645a140966e10a1e1663015f9fdfae44881", + "0x033d5bbfaebf59eae72b89b1aea12ab2ba3c9617f8c3baed1ec16bdf668381b5", + ), + StarkCurve::from_affine_hex_string( + "0x01e026aa2e29e1f9232c83217b99bf168fd88d4ed727c90dfa2b136d1abecd92", + "0x07083229783d73bbe9535d3b6f6ba5644f81544248a0654533dbd59c1b766aa9", + ), + StarkCurve::from_affine_hex_string( + "0x00403becfa545c826782026ff409cc16c9d4fe428f1b5b6e630c92439d2fa5fd", + "0x047bd6f2bf5d74f710ecb479c79b01fb774fbdad590e683a415cdedf33f71dc5", + ), + StarkCurve::from_affine_hex_string( + "0x044b5e18f31d3fc996144754fc2291088e2373c8600e5e5805d04fb9e6c556d0", + "0x015e0f1deb8cd42dd8aad889ddff55749e7f54968f0b9f0e80406d0aa86d4f70", + ), + StarkCurve::from_affine_hex_string( + "0x0570d408024854a5da1b1d970309a80bb6c71e4d6fd728ef51def6b8a1117413", + "0x0260bfbd3cee508164370e0d8941b3a8e40935fe94bc0bdc489bc3fb174643fa", + ), + StarkCurve::from_affine_hex_string( + "0x02c49c728366b9e23e3d1de137cf9252765d3d5707e7ba1a03ed76bfb3418486", + "0x012600244503aeef17f2dc0197e4bdb26878dc0e5fd0802b43a6ffe7d0890b27", + ), + StarkCurve::from_affine_hex_string( + "0x03a747826d241b877d3d56b16e0b810cf088eda4fd6048da174c9991a942a5eb", + "0x02c7ba19b0a3486a2cdb84d4a388d34beb077a0e467ba44590166f93f6a09d2e", + ), + StarkCurve::from_affine_hex_string( + "0x00387f6ecc9cbdb8586cb02e94817723356ff2e004c476902113d5bb613aae22", + "0x06dca3d3d25ba6f91e3bcbf1748f696e276c7cdd177f9b691dd8870e796b919b", + ), + StarkCurve::from_affine_hex_string( + "0x02c4fae98326d7db2b7016f7555dee9bfa5cccc89dbfeb46ebcf4349101e59e8", + "0x00c1fba46b7d400fc5a920ec9704db9e89538677604e2358304095534c698712", + ), + StarkCurve::from_affine_hex_string( + "0x0206ad68c08f41ac747005c24c6cff7944f9215663da9afd17cd9ef1db40413b", + "0x04c6bec54e7e23ecec5bac1aad6c6ac7c07d507b40b0b1d082c0e9d4ed962c32", + ), + StarkCurve::from_affine_hex_string( + "0x038b6374a6e668dd993d69c39e9b911892635800b88ac4338ef922f2df743035", + "0x007143e2c4552d55f99a9d8b17bc87e31341323a4359f2bbffc0568f926117a1", + ), + StarkCurve::from_affine_hex_string( + "0x02adb8b58d38985c3b8540a3f03c19c8237e0c9eaeca8553adbdae4e0aaee054", + "0x0735a4dcf91c9b05d5cdb37d070a4f0a5e08c45570cdf17be45130f1e7011d9f", + ), + StarkCurve::from_affine_hex_string( + "0x039f0e83bb7830f481c8707b5d051c360da25c115a8c769d6b965061ca7d9cd3", + "0x05bcbac19bdfdedad3f33c990fc44f8105fc264c4a1a58979b6b2672ac2a5953", + ), + StarkCurve::from_affine_hex_string( + "0x0634969521aba3e55994492a33d9fddc52d637ed498397c72f905d0b826960b5", + "0x011a28c45aa12546379e3f3d7b453d0fcd3d4a6b811e25558a474b9fa71127fd", + ), + StarkCurve::from_affine_hex_string( + "0x03d60cd375842714b37bda89dd1f13a7e0f3ff133b522209617d031bce05a537", + "0x000f77f216451ab01ad5226844d2162a7f32744688bcb4325445539e2ce5cec4", + ), + StarkCurve::from_affine_hex_string( + "0x0235bf66f67c9100e7f0e22bb299cdfaa603644b240e0770aec7e7fd163e2a65", + "0x037110b3fa83ece3990afca2bea8d5ebb3c7aace60a0147f8e6ab733e2f2b4d5", + ), + StarkCurve::from_affine_hex_string( + "0x051977d2b2faa62cefffce4e9adfceb2869e77b1cfa0b5bba01551518255d10c", + "0x0560077d670eb1a4d0ed57fd0ffec447c78a1a42a38a5b507ddceefe86910cf1", + ), + StarkCurve::from_affine_hex_string( + "0x03b796d4eb69a55471fa86108f787b3604874e92b6887a7667a6c2bfbbd9a42b", + "0x04912d6dc0419732ef82cb3278415851d4e2d7ca89e0f4d7128cc9de51b810fe", + ), + StarkCurve::from_affine_hex_string( + "0x01d792c5ff309816f25af02ceb9685fa262a28c46751ca9e05a0e13e9ef69c8c", + "0x013036bf806d496c5437a005fe8cccd06a51fd6e188a1b339ca7aa226df54934", + ), + StarkCurve::from_affine_hex_string( + "0x02d1f875f592bffae296527bb3cf451e9003091f33164621a55d0788de772f30", + "0x012448e8f4862542b03ea4f9c5079512d542e8ec34ef96d17bbf43a613d9bd2d", + ), + StarkCurve::from_affine_hex_string( + "0x0703d11de078808301cc89d8fe0bde4d5af05afb8c7613fd2f1945f9296b2012", + "0x079b05c8a9063d1637d045dfbf7607a684f1937885115d771bbb9ebbcf79d121", + ), + StarkCurve::from_affine_hex_string( + "0x048d53516dd51e49faa7ab46c8c10db1befd10f23c6a9d9bc3640a2f0da44518", + "0x073a2fb3d064adadf21aa1362c04affc660598f38a9e069b3afb74d0a99ae9ee", + ), + StarkCurve::from_affine_hex_string( + "0x02a9a2661f93ef4062e50b1afded1cacbc5416cacb1ab3a79a931ef558f223d0", + "0x07b1a5c8fed8bb39edab6ad60d681e96a53d675639e4eee29a1cdfae75405e7c", + ), + StarkCurve::from_affine_hex_string( + "0x073a7aa0a0107ba1eefe2dba9bcea14598b22f2d85c298868dea8ded65f0a790", + "0x043ed5b808a7ae9b3dc6d7acff888a0575f3f8ffb93c1a8d54033272ceb53dd0", + ), + StarkCurve::from_affine_hex_string( + "0x02ab8a2d6790f00ef24c3799948fd3a5aef9eebeca258f47e5c40815fff07946", + "0x04326921affab9e2b2a6c81cfd05fb67ed3de36acd45e5a246d84564a2f5775c", + ), + StarkCurve::from_affine_hex_string( + "0x02a5d8f0b141da6c9b6fa22020cbda07ede6b2049841bc8d2c241937fe114313", + "0x07a55fb43b52dabb260e293a98e649a0fcec15d2d49351dec2f783c62331e622", + ), + StarkCurve::from_affine_hex_string( + "0x0066587e4dbcfc34a87513a88525065eaf8d64ae3cf48957eedbac3ac2679593", + "0x0624148e048bc661444d902b6d5f9c037c99259dcf7ffc83a0b777e521290840", + ), + StarkCurve::from_affine_hex_string( + "0x01a1bb3e0ecaafe959461c569b90a2981ac5bf2fdcf5109e0a992cfc8ba6cf1e", + "0x070d1939ece4d6ca20db1866d2f91515cb2e7e888486dcffb3c88dd787b222d7", + ), + StarkCurve::from_affine_hex_string( + "0x062b7a3f47d0d770d7f6ad07ff5f67a6b14764d6724128e7af9d62a7a013cd08", + "0x01e8938b2d03f763e95ed17713c49428b19629ad686bd2b94659600aeca01fb1", + ), + StarkCurve::from_affine_hex_string( + "0x048c32cff161ed145da0d5b73084897647abb777adf65738559ceab6939cf3e0", + "0x03d99308978e828f857c382df32b472bda81e8ec8e30c8844077ba6d6d2ba903", + ), + StarkCurve::from_affine_hex_string( + "0x02947ff091a8ec9684affbc9a62e09e598841c4a6dc638088492aa47dea57097", + "0x019a2cc97975e547f97a4d02e42f89e6ced6f5a953cfccdec347867d26926541", + ), + StarkCurve::from_affine_hex_string( + "0x06627cd70c6422a9373157874a1addf2a9d89dc90e950adab0321f2cd202efc5", + "0x0762aa84b65c2e489b6799c8642e69f7368ef08e547d1d7f40927c260832a2e9", + ), + StarkCurve::from_affine_hex_string( + "0x01960d85f30475615f82484eba0bdafb7ea7cac3809f0518a757d66f02b01676", + "0x036c8f77baabf0cc8805d993bbe62041fcf4e3239cf9d53278a4fbd91e75eeb7", + ), + StarkCurve::from_affine_hex_string( + "0x00f971b37ed54829095626f539e176a4d2a5a036242bad1a0342a32ded82f887", + "0x04c4c7cfa186c546aaa1ae161433c584365c7a9eb5d1fbc21fb852e013a14390", + ), + StarkCurve::from_affine_hex_string( + "0x0430dc5b38c1267679b86516cef74a30c44a0846acb0faefeadb5910187ef79e", + "0x00f79c5d52f98277851da8504c24e31cac35dae9b56ab86e9ca8b19d9111c767", + ), + StarkCurve::from_affine_hex_string( + "0x03ad881666c1d4dc3e57121b2909a3f2bbc53f8d73e784208fa47f814285840e", + "0x03fd5915a7bf67da6348806de84af4ca56c284a798a8cc4e898712963f84d073", + ), + StarkCurve::from_affine_hex_string( + "0x02765f28074d21d5a055340b6d40092d2bbef807e02009fabfa08ec0b9bdf38b", + "0x007fb189e0553d5df52b6843661814824b3f3cbebbd54988f042fb256c6bf30b", + ), + StarkCurve::from_affine_hex_string( + "0x0590695f1f588f848bb9a938ee14493cb53cc3bc86c619c1b091141001b606b5", + "0x025a308d4dc7f847d3307175d895783045373480c4deb2d44d7e6f3149fb5f7a", + ), + StarkCurve::from_affine_hex_string( + "0x03e44a1811d1e02404a4ab8879d5205007b81d76b1b64743367a1dd54f642eb0", + "0x067806cbc745bc13919004514e8adc8443c211c89386fa66bf601589e859b4ef", + ), + StarkCurve::from_affine_hex_string( + "0x006d3371394b7db24d5314a8c76a43df406910d6813c20667fe516427167fae0", + "0x0182cf4e97568896ce2e76493be103cf904f4564142443c8724889544733f821", + ), + StarkCurve::from_affine_hex_string( + "0x070c827f9b919dbd419892a54521e113a612f9a3b8657db4fff7f4f7d705ac46", + "0x032e94382c744dcd499b9bf75ca013a41d697ee02434e0c74da52704418eb102", + ), + StarkCurve::from_affine_hex_string( + "0x073a0e2eeb9f935a6d2387f4b90305b59e71dc8ad041bac0ac52f29bf81684fb", + "0x00ab144280f09589316a174c60f3f149194cec2e26565859c1eed8a2258bdeec", + ), + StarkCurve::from_affine_hex_string( + "0x0473f80e105bef7a7df83885211514abcbd476ab3de0a36718d1c62b172fc0d4", + "0x0250043ed68e4ecf45e430d787ed85971949b703807e3de3997ce7397f80eb6d", + ), + StarkCurve::from_affine_hex_string( + "0x010a4447f66513537e6ef0cb0ba852968f322169dd7c2bf4cc62580cf32a05cf", + "0x072e365de6c0cd941d116b6543ac87002e40240c7eb9621fc35209127df213ba", + ), + StarkCurve::from_affine_hex_string( + "0x0348836cb2aaa00212f4b1a4e2d7fc5417f246bf2fe5c9a16ebabda449e2e08a", + "0x03f7276fd7d69e0d55ce5ee1d2d830534a27227fe0b6d8a36c93f9a78b872969", + ), + StarkCurve::from_affine_hex_string( + "0x07afb9d34b6a42ea8c6d870e4b8191c274201dc1f93a1a2219a2392b7e345a31", + "0x042bbc20dc7115e0758b364a110227b16b64ec58fc535ce5ff1a9ad8b8a09fdd", + ), + StarkCurve::from_affine_hex_string( + "0x07b3ba6309fc0715974589fd653437c35b97bba522b56be4e0869fca7af92454", + "0x0593ecc14fc8f9f879d5521ab3f35b6b22689bf716384b90f630420fa2123dbf", + ), + StarkCurve::from_affine_hex_string( + "0x002cae0c2afee1767fd4c66f52e1f176d217e92e89cc19eb36d5a6c1715f641a", + "0x05335efe2d9bc3667d25ea88bf76438a4d6ab9ba5c512f9da7d0529b79b62d83", + ), + StarkCurve::from_affine_hex_string( + "0x032a4ff978a0233158dd5e1a212916fbbe39f2bbee3cd772477fb8d70cebd593", + "0x067bd970c80f213b685ffb523a32eb9178bcc4020ab48cf8ff3f85f4db99fba8", + ), + StarkCurve::from_affine_hex_string( + "0x053429b5c5f7c699373ce8afd54c9acf895d45c7a64477ebb232c638ca821779", + "0x07fe278f1f041e10a68eb6b66571444a4f1107642dc74769390b0750d09041f8", + ), + StarkCurve::from_affine_hex_string( + "0x06703aba9929d65dcbd31d04311b71a8ca48509986ecd2b8f92297828de3316d", + "0x01495b3429131d0500a9320239732b57925615dd18a4b818d8552a744bf259cd", + ), + StarkCurve::from_affine_hex_string( + "0x01cc5fde334707723c3a06f00c106db88664284a2df47bb6b144d9f960aea3e2", + "0x00dbbf610d100316938bcd8bcd078513512ecb50d4579690dbefaa419c05980d", + ), + StarkCurve::from_affine_hex_string( + "0x0031f765b5a172e29ce82db044678d7c1f93e6fb5fb97bc59ec395fb1fcf4e91", + "0x0208f69e2ea6d31784f727ea4b0e2abfcb724cbcbf2aae8d5b48fcc581e7ebcb", + ), + StarkCurve::from_affine_hex_string( + "0x022992b8b89b0078f988569854abb40e966185a09fc5486e9ed6ac14048f2507", + "0x0602df5cb61e30434fa8d7ed5be1651dfce46e3d916facf29b15394e5a0f0a45", + ), + StarkCurve::from_affine_hex_string( + "0x0578fed75d426971bf0a85d40043584f33852df77a33ca74a393cb054f1e8990", + "0x0684840ff08fb48c18f09dcb89a804201931aec7e557718ef1251de926e87b23", + ), + StarkCurve::from_affine_hex_string( + "0x02f952c31a6a768718938c810edac393c56ab5cb9b335b1b3e130711b3b99ed5", + "0x001ffdc88ff32ee24a813a3d7ce1c5a19cbe0180bf4a73defb666259651e46d5", + ), + StarkCurve::from_affine_hex_string( + "0x04abcbca5c0c47969263ddafe824829754aeb5cd31139225a35d0e09f783f7b4", + "0x05e96dfd0afd90e37cbe517ea2c88762e6f30db963824e14690a08c4e5dae974", + ), + StarkCurve::from_affine_hex_string( + "0x03a6939fb7b858a59eb4ae6ec6dddf24ad79296a8f4e256f3f001d2b72fce244", + "0x04a428159c6af46ab7d4ccd75da2bb237a7d47dbc65c56794cc177c0a695d163", + ), + StarkCurve::from_affine_hex_string( + "0x059b5370d88a523609b4bd56eb16ae3f38ff242bf5bda498900692ef4ca56b80", + "0x0219fb058c170d99090a5e66c64f1da391bf8ce7e86075847db66b1ee65fbd49", + ), + StarkCurve::from_affine_hex_string( + "0x054e90cb8f3a2998d2675c5780679e06c0556b1e618f8fdf07f9a4b2466fbf1e", + "0x016248676b6f06ec5e34994bc3115f85c8147b54f34d8500928f2fdc051e2089", + ), + StarkCurve::from_affine_hex_string( + "0x0525c70a2ba0dbdd68d75640f47f13d0d415ea595f7030f533f4625c2a46523b", + "0x058292c8675e5e1a438f49e0c05648d9a7aa997f2f1fd77d5de1944afe5d7eea", + ), + StarkCurve::from_affine_hex_string( + "0x0287cffbcf14ecee898e12b39f029ccc47c032de11e41bc67cfc16efe06c803c", + "0x04664fcb11a94f40b514cc610a0d6d109072acf683aaad0c7350d4122337585f", + ), + StarkCurve::from_affine_hex_string( + "0x054726d78d099007393348787a03107ab492e59690a46c87fb02ec554f2353bd", + "0x053b54b77184ba75a3391e0ebfa6d6974db028f3f8e34bbd5460759a5848dd76", + ), + StarkCurve::from_affine_hex_string( + "0x01872093186916b2e04353cf986515cd42748e374d30a3c346cbcc628069fd90", + "0x05fd4d512dfa06bb6a6f645aa7a85860e467087baf3a9fd4b887d6356f29dd42", + ), + StarkCurve::from_affine_hex_string( + "0x04da98d9146a6308ed3a27fd96fb043c958c8915ea588f84b3a3197a2c19709f", + "0x0795df00d87a85e59e526d10479e68c96beb400b311c30ca9da4085da4513f70", + ), + StarkCurve::from_affine_hex_string( + "0x024a916bb35b50413081d837a37cbed9dbeb069c9d2c27b9f35d2eebe54979cb", + "0x00e4ab7e5c842d5f4b4f48ee966d599bed1bb7357efb376a23ac2a73b9814c23", + ), + StarkCurve::from_affine_hex_string( + "0x04ac81a66903537769d3aac6c483ccc08535cb767b6b5e1ec8017a7393ab70ae", + "0x02cb22b77a8a05d26f11a4dec80eff292633aa05553a889c5ab16b6ac6e2ab17", + ), + StarkCurve::from_affine_hex_string( + "0x043428751740de1cea31bd3fd72529aa23c918a93d8673b77c4ca307ade9601d", + "0x004976b490b971d548dbdde646c266f8d93de1a6712a53830db7eccb8722daf5", + ), + StarkCurve::from_affine_hex_string( + "0x0086ee0ef8fb30548335b4586faeec4d5afafe1699f0009f98e6e4e4cfa24700", + "0x03fd9ed58b07fa6e37e6385640099cd08988d155b8b9d7e50ea2558225585dea", + ), + StarkCurve::from_affine_hex_string( + "0x044bdf3bdcf17c0c5e9e3f51422cf2b58aede261a976bc06c4058f561ef2e911", + "0x01cc2a11da7c3096ab66f935a1f6a12f13df95fe2d8056e0ca9fbf4288a80256", + ), + StarkCurve::from_affine_hex_string( + "0x03c21dab7935839e79774b0693bb0fba4198b56698aa94b75d05d6a5a2895694", + "0x0452d6f82329a437e204f1cb5132c33914d3c7072e01ee20b509cf61aed556dd", + ), + StarkCurve::from_affine_hex_string( + "0x04c7ce963fcad8d7f23b15b8b07b1907da775c8761607f54438e25cca65ce990", + "0x0283b2367f93779ce0d78f6ba472348d98751b9f1ff4666348eb24eebff7d21e", + ), + StarkCurve::from_affine_hex_string( + "0x02d5926394d3bfc412571b7cf88ac2646ea76d9fae5e4d602558e4419ce7e42c", + "0x029e6daf8ba52dbb542239f4f2502db13d0157e23634d16d61b1b1beb4797577", + ), + StarkCurve::from_affine_hex_string( + "0x0277259851e9b6724b2f66d72c6a4333cc7aa70badbc2513361b9168bbc77b6c", + "0x03b2aa537ba787ece4cedbace351a40f2d14529624411615b30e2716ddd1dc6a", + ), + StarkCurve::from_affine_hex_string( + "0x0021d0175349e21114988a2930b9a607d43245783cb4a0c984ce27f4c4206708", + "0x059f1f49342cc5496213d3329bf4ca7fb0044337449c579bf53147a1dac9e67c", + ), + StarkCurve::from_affine_hex_string( + "0x0167f821b381f4c8adcc39789475fb55ba639e5124fe75f26dd61be396dd5e66", + "0x022002c87d4cafb47ac9d27286d5cf5ff7a6715d69814118269b0729be9e4b3a", + ), + StarkCurve::from_affine_hex_string( + "0x06b702d0b32610a252a647801357e6c6eab9028f7cdae4753769c7c8f6cf6120", + "0x017f33cea7775c738b699eb79c9013366907e02f6ab3831345911454b9172a2f", + ), + StarkCurve::from_affine_hex_string( + "0x031010666c6db83a9f9e4db4c48173afd405783ac53852a6e38a8ff925528843", + "0x01f466dc9b5d9094107c741dbf380f9fd98d8549cd50f67169901516f8cce74c", + ), + StarkCurve::from_affine_hex_string( + "0x00102ea8e36a3776f43bd1d4d8724bdbff3367f4cce0501956a13c6c46a728c9", + "0x03a8ac494ecdadb57bd0a194ac8d215a61a1551c5da25f94ad0a420562a5f3b0", + ), + StarkCurve::from_affine_hex_string( + "0x00ba6e7d812e16b28f78e43b5a6e5fe0e60c52a87891298f158e436599ac12e9", + "0x02e8b2499d68782624d936a24f0afe4474cff8ab764fa0a6527eeed388a0edbe", + ), + StarkCurve::from_affine_hex_string( + "0x030ba4656d2f558920cb56269fc63ac6d2f6abe62f637791f2872106aba3640b", + "0x00d634df472bdbbc1bba4af926b4dafc1c68aea73da521ef5e5005a52d41745f", + ), + StarkCurve::from_affine_hex_string( + "0x01ad3875769a5053388a86edc85dd80fdffbbda6a456aea497ff81a0f1f6707b", + "0x02de7cdec5e2bad56a71bd2f33a4ae4c874e1ad4210a6ac32b443cfa34e85b1b", + ), + StarkCurve::from_affine_hex_string( + "0x060d2d2584dfaac05ddbf022260038b7f7100499d9b428a0203c8b3485c91d77", + "0x00bd195cbe56fa8296cb3adca7fe1599167d3765c77aaa8bd3af336a7bef1fd2", + ), + StarkCurve::from_affine_hex_string( + "0x05fd540087f3b2de5c6a6f1dc25e38d74bc85b4b294cb5fb40a84c89482b7aaa", + "0x06bc9cd019ae06d384a5614765111d0dd8e414d6f8e8559de5f15972cc8eee22", + ), + StarkCurve::from_affine_hex_string( + "0x04c875322d64d87d1e0e49eda60877fd018476a23141c0fc7731c62968badfe5", + "0x026f509faa07d10d89ba3b02dd59faccc988245df7bbee02c7cf34ac7f3a7bd1", + ), + StarkCurve::from_affine_hex_string( + "0x04ac1e912d8485f87a4daebd46dac1e23d5b2c39d7939a79812e16b0202e2df6", + "0x034018c5cdaddc8bb1ae3957f119a6718e12a620deaabefe0d7294910c8730ec", + ), + StarkCurve::from_affine_hex_string( + "0x0798ca71b40fdcf33e354124548417ecd057535519da2766776d70fe2a72fa4e", + "0x0241ed056d421ec76460badedd40a2cdb56438aa873c5b10df44fd2710755cee", + ), + StarkCurve::from_affine_hex_string( + "0x00a8f4c8a4c13dc5c99c2b3500ccff1eb8bb58f14f60f1b6c6f6a285d3628ba8", + "0x02a4b35487672cf5a38991cd4cb468fc528f46d3381a83a883764363880c4a41", + ), + StarkCurve::from_affine_hex_string( + "0x05e3cc5bf4ff7e41c8c47f62db31d8277ba96acb80c0c0b81664d3d29d5b885e", + "0x036da58362588ba3aa6759da2b55a15d7f9a4b367138f9721363d376dba5ba49", + ), + StarkCurve::from_affine_hex_string( + "0x00c489650fb7f459ce09cd05a456fc5a46b849b38a671298ed645bcdaab168b0", + "0x045610d092b8af1c43ceed474cd17f7bbee65120aa6fa4d37f949e7e41f25327", + ), + StarkCurve::from_affine_hex_string( + "0x0394256a5ef4d7af5459587a0bd2edb8acaf5ecfef2563c9a04daf34a4abe4c6", + "0x01ebee390dae1403c0c53994e1d064fa64e20fcb45392e209b2b99486a559ffd", + ), + StarkCurve::from_affine_hex_string( + "0x054dbc841b75941d1d565c7a0e038e311018b184360cd75b86e0fe616bad579f", + "0x0237d3513168529e1447c0b485388115cad47d4536ead738ddf66d325971d0cc", + ), + StarkCurve::from_affine_hex_string( + "0x0410a1511fead6151e9bedb089b9832d0fe01fab76d3f8459929f767525aeb27", + "0x0361f0a5ffe09fcc3ad4eff3f5e89508ac247af80267100b69de3c59df561cfa", + ), + StarkCurve::from_affine_hex_string( + "0x06caa24a4068708eae78ed0beb77a031f70e6c0eb057c570e3bcce9c3a8db7f2", + "0x0051293fae0ab0d96a1e30a404deeb0ac2320c45972a4897d2f20eac52627700", + ), + StarkCurve::from_affine_hex_string( + "0x01a17d04f7b05f418caceccb581195f589a12fdd476416d8d134a3e8b3728d64", + "0x04f763f03f036ea0c569136ae53811357826e00c2ee1e3034c4e5862f8f93bb8", + ), + StarkCurve::from_affine_hex_string( + "0x0397f7cf33bd612bb6a0b2850d04b27a0608e224a9170b9c83343eb41c9f4589", + "0x013d6ed39d562730830b0870fcd5682a2418f26370f30237097088046396eadb", + ), + StarkCurve::from_affine_hex_string( + "0x038cd437c9f659e110a869605c182ee9fdc26de36baf559d9229e258267bb734", + "0x0624b1128ea7739bf1cbd0e423af92a4884323c868d2ba0ee9d362946edee2d1", + ), + StarkCurve::from_affine_hex_string( + "0x0184f94e669e04756f978c9836fe450270aa85c34856b41bd71fed35a2a569f2", + "0x01c81a617471bea2ef8fb9bc26c5c9293e6aa88771d13127bee9345106da7442", + ), + StarkCurve::from_affine_hex_string( + "0x04ff9ee9bed0a844f3f541a0ac539b283207775aa1bb45327a5b04b1158e03ab", + "0x03d05ba8c806d2589f1584119344b9c97e01988537c9182b811b871585d6dd3a", + ), + StarkCurve::from_affine_hex_string( + "0x04d0d45d657ce19f224510ca4b555204494870703b3a7ef9e89194971528c8e3", + "0x004fcf2cf9f5e1c85e5fb19e787c939926761cafdd707e58c20ba5f5793deb57", + ), + StarkCurve::from_affine_hex_string( + "0x027ad5866bb2359b9f59560fbf92dacfb0c915de7ef86a57121cfcfbb2887b6c", + "0x0006c36512cdbd4491d54449718e0b22da3e7e27382bc1f72405a7d2490bfbba", + ), + StarkCurve::from_affine_hex_string( + "0x024c03accf09c6e90ce17ded6927f308ee5e18c0d27d005454988fd8ec2447f3", + "0x06ff398bcd17fdd1f057801a673b2f694aa7eeadbb085df3270dc91ea4bcde90", + ), + StarkCurve::from_affine_hex_string( + "0x05e5801d82e2828e2d9b2a7d2d0ce4d39d45d64d9020f4c5d62394998430857f", + "0x0305a84246dad1030452623541c3fe70940cdbfc9147c1d22af5476b44ef0935", + ), + StarkCurve::from_affine_hex_string( + "0x07e845b16ea50ef9329cd0d91d16bcf64f72f960b24b5e738a0b27fe1c2b9fd6", + "0x00cee1d347da00038b17392bec8c936d3465db8c26af58e9a7ee297accfa28df", + ), + StarkCurve::from_affine_hex_string( + "0x078b126e50b7042d2a019f95cb87a3213c664ca1bafe345999b1e9e2dac1e608", + "0x019e398196b22f4488cbe854c614ad8c353839abc5ab3a4f3f5c03c16ba8a198", + ), + StarkCurve::from_affine_hex_string( + "0x06d3a5ce91132f385a91823c5c8046c4b638f5fe63357424410d901457cdb867", + "0x07b80bae16d2d487e122495174f7a70992bc5dafbed72bf84127ead7c57302bb", + ), + StarkCurve::from_affine_hex_string( + "0x04bd5e66ab98b62e023e53039d0a1c95d5bcd420453205169973b6336dc820c3", + "0x00edd38447467b80fbda3a53ed19df9937eef7bfc5aec6ee97b7c276e4b9b72c", + ), + StarkCurve::from_affine_hex_string( + "0x032d053a904dc4d88fbe7d0b96e0cbeca22a00aa5c79c753d52b0b60abf31602", + "0x03af6a02e5cae6d6490354ae51185149e3fdb6d0d9caab90e95ff58aa0c40377", + ), + StarkCurve::from_affine_hex_string( + "0x051dd488fa0cff2b5345ee57de6817d0313017d1d7f1d34f685dafa1c6ea8c2e", + "0x02ae37ad0c25e42f428cccaad36716a740c959cc038fd1fd49478ad7850b008f", + ), + StarkCurve::from_affine_hex_string( + "0x0762df876cd550a0b52b23110031c820f97de1af79dfba0a1c629e7b158464d8", + "0x067b129eac654b12c72de7b489315ae4e880036c371fa4b8cda5a326e90e8984", + ), + StarkCurve::from_affine_hex_string( + "0x01a703aeddf27cfdf3f34b31add45d888d02ca32969c1c9a4141c18e8e778f3c", + "0x0119b01ae09ed6ef8a6cc4d8dcd2e11dffab1f4cf03404a02f4945180aa9d197", + ), + StarkCurve::from_affine_hex_string( + "0x049b1fbff5bdb0aa6938b066dde0ed772c0d81f9eff52e7fe038b0ccbd78adb5", + "0x01c6e57834eb14d507eed8b36c81ddf92fa91c242467061927a742fafa82b43d", + ), + StarkCurve::from_affine_hex_string( + "0x05a2bfda12de400870e87d3f87ef8525ad34f9c411ae9820f08976ac2175ae5d", + "0x019382ba4fc3af304db282bb3406e8dbe5f747cfbc32e95b8e9c7ffccc836e79", + ), + StarkCurve::from_affine_hex_string( + "0x054ed4775db18b6cbb0b6773438546bc03f791bc661c55ddd8034f21ebeefc18", + "0x068ab8a3eca41f8c94f9061f2498c9abc2247fada2bd779286ea2030511a6c38", + ), + StarkCurve::from_affine_hex_string( + "0x04223a8ff4857fdd3ab8282e89c6b06353799d8f6d8f5576801510b665f44086", + "0x079507001758befb3817f8199dd5636d38ccd7e4048f935e7c73da920282203b", + ), + StarkCurve::from_affine_hex_string( + "0x064b90993ce6d3d558ff2ca5553d70f4dc3e2b28830cc1cca95cacecb4b18636", + "0x077e8b51bd296249e0578ea33a923d577ad5417157ad23d29487d67495ee165b", + ), + StarkCurve::from_affine_hex_string( + "0x04adfc538d1af18246aefde88485f23f89ec8e16649ce25d38cd34b3e7fda5c8", + "0x06b3638015045a14c610e1ab0b7812bce40066ee0ba446a4f3a3e8014a4f5522", + ), + StarkCurve::from_affine_hex_string( + "0x06ba9b36a30240af617d871bf22e1de74d1166c71d5c701f4f9bff0ec7336153", + "0x03625c7f21a1a4b79d2463b1b22d3a51bedb5f774fed1c1c41dfd089f35e84e7", + ), + StarkCurve::from_affine_hex_string( + "0x060e2e23f95c86445f8f0620afaa226c3635caa5edc3aa6c711581bdd3a07666", + "0x013e40a164697b163fd8ba428660e551dd4a6c569036fd4383d694836bd2aaae", + ), + StarkCurve::from_affine_hex_string( + "0x02f28b8994ca6f234d9293d26196b43b9d1d5306844348c4a638102c05de85f5", + "0x0759cfb172eab065d477248b3569f4ff5791055f01e95fe71b94b8e615d73c96", + ), + StarkCurve::from_affine_hex_string( + "0x03c2ee954ff534f856f59188fa0f29ed8a022aee0cac52d634f6dc58cd514d70", + "0x022bd162e74925f0a876bd8a206b8767dfdd7c898576a73a490f138d9a7f99c6", + ), + StarkCurve::from_affine_hex_string( + "0x03e7a211677058697135a70c83c7edc59daa48eecadd72dc0f26ce8c2dcc69a7", + "0x02bedb69489bac2f480632b7e338919a90b7409e2f2aba97014122123359f93a", + ), + StarkCurve::from_affine_hex_string( + "0x005763a7cab001e1aaeabf9ab5b9b2fffe6cc2b299ab04ec4933da74d960e1ab", + "0x0715ee4f8ee93ab5a1dba00f0a6abc4eec47d49b61254cc27fc36a031e32f0f8", + ), + StarkCurve::from_affine_hex_string( + "0x02243457a1b5925af6eb73537955fd0520493ab73eeda45cc383d22965f97729", + "0x06da7b5fe8c87c775296ebd71be0e9ac319e917d51d55c876b9ecf0229b4354a", + ), + StarkCurve::from_affine_hex_string( + "0x05e71e52e73df10ddfcddd40e2d860903608574bba5b25783e6a0c266a87975b", + "0x048bb150db7a9c623e5dbfa6f254dce1b70dfec4d9a9800edf05dea2ffdb9cd9", + ), + StarkCurve::from_affine_hex_string( + "0x015d4b26e873732cba57172ad2205714541f33f5002b3155ff92679d472ceb8f", + "0x01af9273a4ff12aed1dc523fc438c31c4b2cd6ae63ab9dfe25a46131227c414a", + ), + StarkCurve::from_affine_hex_string( + "0x019976ad8d7b7f47c785408243a227401996b36e47c7a78a7bc7d4256233ba9a", + "0x00896b713c5d7777b0703821a73c1d9a4c3755501042120534ff13990975e1f5", + ), + StarkCurve::from_affine_hex_string( + "0x058a2f6b6e86c21eca310aebeb7d1b0dcbdd99381f31849112b91a72672d535d", + "0x0575963e5b737775b0fe17d876071a7290630156dd69880e96f3f0b2597d1f2f", + ), + StarkCurve::from_affine_hex_string( + "0x0760f919a5d381d12a8255127d34edf7bb958ccb8c3ebfc3dba0d8539fd8f881", + "0x03f7cbe54778d40b187517aa304bb1e4d3d7828b094594cc0807131cb0b20083", + ), + StarkCurve::from_affine_hex_string( + "0x02b8e4660169a4fa4bff1520240ceda9c4e9a3dedd6407d0eb69c0a164d18c8f", + "0x02470c6ef5dd219c3cd3a9c685c6154ae844371f92967dc482f2743a4abe712c", + ), + StarkCurve::from_affine_hex_string( + "0x06537321b9626a90945e4f7bbb3761c0af95a8cdce3453d8af14770ddc2a4cd8", + "0x070d28d2e9030e9a7c0c857069c5e9bfacccbb914170ee768552eb27ea93386d", + ), + StarkCurve::from_affine_hex_string( + "0x05bfdb032cda93a1e432698b26ac0cd4ac06ef8b2a2d73777bdd358a0cadaf38", + "0x0583e1e660ba5b856cf36ba48b6793ae833cdc25b8acafc5e90610aaaed28fe6", + ), + StarkCurve::from_affine_hex_string( + "0x06e1d98138b75b6ed62e79cc2f6212dbc35e9d8c66390c71890947625248e57d", + "0x0669e49259b9fbb99c200c3ab9bded17005ffc021ba01eaaaee3f1baddbb6a9f", + ), + StarkCurve::from_affine_hex_string( + "0x07200845e932230d3cad95e2ca1faf33ef55ccd896904a98e41c401ce2f747dc", + "0x06d7614692d257fca047bf41eeea309c72dc39d31b9abf29d679bf2238379777", + ), + StarkCurve::from_affine_hex_string( + "0x061674b992c29827186cab5ff454758dbbed8e89bc23d0bd33193afccc3a04bc", + "0x038e1020744c13903809ea30a0662fdb5226ae760cdcf10800faabec452e00f8", + ), + StarkCurve::from_affine_hex_string( + "0x02ea2d48bcb83c0c9cda4efe11f07165cfcbc9ccd26526e5fb12556316d4b1df", + "0x01d2d68b74ad384c5c4a9c85453104216357bfcdf635680b40215f0f800974cb", + ), + StarkCurve::from_affine_hex_string( + "0x04df09af52a5ff777d9ac4e23406fa75c2ff004335f665aa60c909e68ec3979e", + "0x059c36bf38716707bfbb4fe6f838e69d81a4467668158e8da1f4f2fd1ed6b22d", + ), + StarkCurve::from_affine_hex_string( + "0x07881212050264c40c336ed3a15dd2cd868ec9a558f5b728869eab66e8b8ed54", + "0x021aaefcc8ad8a161b8971d6880321781dbd939570c540da4c330922b8c81e9b", + ), + StarkCurve::from_affine_hex_string( + "0x0761afc4619500b4f916c8c87a473efa26431d172cc5d59d3dc59d2a6371dd6d", + "0x0530355f5420a2024cd20e8f74f5467ccf3386e3ec853251a553e9ecf1185692", + ), + StarkCurve::from_affine_hex_string( + "0x07162b4d0862e287a6484d569bb50ec6e2288038147d78a720434c552ec91725", + "0x06bcaed36b3aef9b8f82f4aed4653fbfd043450cfe3f10a2b067e9b9f872d9bb", + ), + StarkCurve::from_affine_hex_string( + "0x0540e83451162b899da47fb165dfc2751e1982427f3012310978463fdadeca25", + "0x01a89c13e28f9a87db4927bb205ee965b4a1fd375aa53fc09df604cfc20621f2", + ), + StarkCurve::from_affine_hex_string( + "0x00b6be88ce0461d20f59c5199573cda0170b61decf6e8e69a6d32f1695adc4ed", + "0x05536e4808370716f2bb3423a9a49a38ddbfe91faf3b7a35eb53d3519238b6cf", + ), + StarkCurve::from_affine_hex_string( + "0x01b65d53cadecf8627bb0927ddfaf4d246a64c18e874adb4223b628b6574cf9c", + "0x02f28f98a243b296f0e5bdefe1c0ac189d484d69c6bde75128f0269d75b811b5", + ), + StarkCurve::from_affine_hex_string( + "0x078c50f7df96774b12158f7fce97a90d0e70fec175220a9a586d64fc595a3c92", + "0x053d584bb30e14da642c7e68f955ca9c28525695d0de5f286fb3da3c79f5078c", + ), + StarkCurve::from_affine_hex_string( + "0x05792699a8ac265c6705ca82c51a94b9c420148d0dc1d299cbf908c67d0b71b3", + "0x002d7210d6f60a7a1cd92b27c917c3807d1134c04a0110f7b74a7d65fda055f3", + ), + StarkCurve::from_affine_hex_string( + "0x032fbf3cca31c91ffd59c5414a6aad1ca6782b7263a603c58eaffc717b600408", + "0x013aeb2000447cb52fd00ccbfa8d9156aa85dc686067a74cc15855f25571b50c", + ), + StarkCurve::from_affine_hex_string( + "0x02e85840066ac2e58c702b6e591e93d44c18c82439048999af4c60ea215800aa", + "0x06cd7517d893cee1d1a969c4a754f0c1452ed71a033b72cc22945a2e4781937c", + ), + StarkCurve::from_affine_hex_string( + "0x068199e5649520a9f875a2685748af77ad696fea45f9d64375c378f51f8830cb", + "0x05014b3d4c0b182e63efaf9aaa71ee7b6e067a98325db21f6d650cc9b80eaf2e", + ), + StarkCurve::from_affine_hex_string( + "0x060e4d8b358e5b3765862433e95d8d8f118ef0fc350c71d9d64ce5b3fece6782", + "0x00c7acf271efd3730e2ef248fbacb0281356b1e51d521b0a19828de9eeeb1322", + ), + StarkCurve::from_affine_hex_string( + "0x00e5972af1655eb6dde2e8c77cc58044299922441b5ee41ceaf5cafedc765bcc", + "0x0550282f37a4783dd60801c237045992d6fbe82a5902e7d837ea25f6f98c7b3a", + ), + StarkCurve::from_affine_hex_string( + "0x007efc1aad1f580d8f50274f1c114c40056be19a8c96fa8c4cb5bf85e1e7f3e4", + "0x02689f1c3898b114d668be6413643ee9f879913d40c262541fd0316264c60a4f", + ), + StarkCurve::from_affine_hex_string( + "0x06182a2a2996c29b1fc675baddfbebbff12b057f927b95556c2b5ddf65b02588", + "0x01bb2fbcca55f330424f89921fdd8ff21097732a238c048d1a1f1584a66e60fa", + ), + StarkCurve::from_affine_hex_string( + "0x07939db98037f59b0113e9d60051f75ac9c3cfd1a3eb535c73e2d945068c6c5c", + "0x0410914ca8bbf3c65cdf3e9772ca790c19131c50068d34b7346c10260a578a8e", + ), + StarkCurve::from_affine_hex_string( + "0x030ffcbed9babd48765b3fa36908bfce7e75d79f63686e82575f5e4a28253945", + "0x02d95c65f88c12b8119ecbf9a3c0030d2190a3e27936bfe5b3a488e42524db2f", + ), + StarkCurve::from_affine_hex_string( + "0x07112c99d2106a694d6d1c2e97107ae06b8cc795dc0339cf49afbe57f253894e", + "0x0741ae7df04837099a5cea8d31bd70b29468c0b79ce0882723862f2a6adeeb78", + ), + StarkCurve::from_affine_hex_string( + "0x045d9f134d8ae7b17752f12a8012f9dfd42d11b3e5fa3d5fc224c1e28f6956e9", + "0x01d262d16d9b7bf23c0ef668ab06efee158930204ead1123da051c9495a7669d", + ), + StarkCurve::from_affine_hex_string( + "0x0225b77ad00a2b83d26690190b74867326eca4f55bfbc3a13be036225ca3b1b5", + "0x0411faafef89042ce6beb64309fdaff70fa53e9d32d79a21e7f82f80e79ff05e", + ), + StarkCurve::from_affine_hex_string( + "0x07cb85261173bfc8d38a3b0ff759f834cc4d37694c605557c7b05a89eea35e5a", + "0x0017cdbe0a247cbb4f57448f612ed8d6f8d38756fd06a54d70c682c472cce809", + ), + StarkCurve::from_affine_hex_string( + "0x06767edde937c06534e8ca071620f57c8dae00977670c333325d578bd7c6697e", + "0x015ff39370e68b5729627930ca82523e3da7ad937c4281eb438e20a2ab04fc86", + ), + StarkCurve::from_affine_hex_string( + "0x060979645fac49b980dacfe1ee3f10a27ae21a4f59bfa5a881d069205cb2ca19", + "0x02011651dd09a58f0621d8bf30e39767374387cb42cc6e47003c20608484708a", + ), + StarkCurve::from_affine_hex_string( + "0x057e90543d895732f8c69c8b14500aaf2cd49520c64a1a86bf29bfce4b820063", + "0x04d55a784b4acc720827adf5a47b7f2b52367e3a7fd7a20b4d622a8617a192c3", + ), + StarkCurve::from_affine_hex_string( + "0x0311fb393f127dc1fc40e2d160429245a763310ae587d3d4c9963b75f7ce6d01", + "0x04b2530e6c5ee42425f164e1615c33947f33939066b9e9e6dc7da9c1ea660697", + ), + StarkCurve::from_affine_hex_string( + "0x079f4de0efc7e9a7733594ef61a5739c3d5105a9dfacf6c48792653680f94891", + "0x02fdbe06646fd33d837caa71460006ed285259d428f827a49f83ab19d6edca12", + ), + StarkCurve::from_affine_hex_string( + "0x0538b773dbf83aece332006e3e0fb7ad4c060c07f9722649b8647721af4931bf", + "0x0051512266c1c349d1a4f1b84f3d941505929709ed8cffe4d2b0c295f4ab9fc6", + ), + StarkCurve::from_affine_hex_string( + "0x01501e64c99c8b6658b0479f2c05c9142d246eaabfccf2fcec8dc4399539d8e1", + "0x03bab1e3339e42c9ee66c65b0b20236fdd9362d3ce786ad3a9779ab578af50a8", + ), + StarkCurve::from_affine_hex_string( + "0x0059b907b941f24fb8ea2458153e55f07534b388e835af7b69f3c9f54392a335", + "0x01d5438c4f2f68a417f3d56f916d899a6ffe910f5f2989ca31687f1b10f60db8", + ), + StarkCurve::from_affine_hex_string( + "0x01c12eaa4d72ed191b1dd7241242fca5b8644124031a00b4d3360979d3e50511", + "0x06ba5fbc974818f6a9195b553eb8b2f905444efe320e1a22b334db4a602293ef", + ), + StarkCurve::from_affine_hex_string( + "0x02887d08a26f484546f360e33abbf7a998b7170a5b30070938b84f072c676bf3", + "0x062a78e8d00e5d3a59e2fc424ffa08961567ba1ef24c8531cd7bceee6074a535", + ), + StarkCurve::from_affine_hex_string( + "0x06c001082916f31c6564e74323ec0d53259fa4ab8b1022883d6889c5b7a37b1e", + "0x041fc3640ebcae7f29555a0ed57f9a8e8a963c5046e3bac0e9402fa3eae34ec6", + ), + StarkCurve::from_affine_hex_string( + "0x00d76dd0019e5efc64a7807378fbb0e21de101584e8c11777c90ef0a7c936e9c", + "0x07d7d3a2d9c87b7712eb14dd26d269e929cbc07c71bed9735894637e2b1dcaba", + ), + StarkCurve::from_affine_hex_string( + "0x039c69e087ddb82c79978d14dcc82b9bc5f885431794366a57a574f9e4387719", + "0x0715ea99f0cc2d4810635a32d2dd4b79c3ba9da9c5c2d6368a1d064e73429185", + ), + StarkCurve::from_affine_hex_string( + "0x06e3cc8076b3d45377929033af35aab0c6d19ae4fd47c0daf844079ca04c46eb", + "0x07b90f338e4d848aa8f19d0b5c3bca916a2a9024acbf14bddb278bca2aa39e5f", + ), + StarkCurve::from_affine_hex_string( + "0x0496d685b825e26e34c22c1a26edffd712b6582eee335ef9b6bd793055fa43bb", + "0x01c844e5a97c06f4a7ef0b3298df7233b0c0fe636d5bb3cbed1d1f05c2e28952", + ), + StarkCurve::from_affine_hex_string( + "0x0547bf81b8e912577f731fdacdb350a39c9dc6d19c2f5340317af052c7f4c37c", + "0x02eec56d8bd11415fbf0954e1450e6b00d77ada0c0b6b6642e6de08ea1d83e6a", + ), + StarkCurve::from_affine_hex_string( + "0x021c1f807c822bb3dcb31bbed8f3da7f0e547612f89aedf0b60d89c65193025b", + "0x05c4db1edeb5256d73ec0f68aa46614d497e01aeff7637a0da17da284608ac0c", + ), + StarkCurve::from_affine_hex_string( + "0x06c8d85dc432ec9e91bea8f4f6afafa786c641d2989757afc724cbd0327294ac", + "0x05e81297b8c8cb2cd33ab5eadfcd378d07ce6107675365ee496d955dbd4e2349", + ), + StarkCurve::from_affine_hex_string( + "0x0646ea047e0a63d633b9b509abc5707d02aec1d5236101aab95fad26e54909a2", + "0x030099d8d0409997fa82aebde60bec2995a64ef6247c4d13dc633398112a562b", + ), + StarkCurve::from_affine_hex_string( + "0x069b769fa354620ad3a91a1478c0fbfe89b64f4b556c39d071f45e4f6f269bf5", + "0x034e6049d0c6efc1f21148490ede6fc6a708ec9259cafd780a9b14ed1ad15abc", + ), + StarkCurve::from_affine_hex_string( + "0x0195da9337ca0d1cb0ea350c2979292b0dbfaa5fc80aa6ec103007dab23db9cc", + "0x03172c11b10cd26ed3d1a63a41f8a56a2eeeb730909ea0c36391bee0ed2ffe4e", + ), + StarkCurve::from_affine_hex_string( + "0x034844dacdd3ec54a3af328bb9d67715ab33425e194ac9977ca02ef22e8f7a88", + "0x003c1affc6372f32a1634748124f9e1a03c4f0c993971da0dc28888b0801279d", + ), + StarkCurve::from_affine_hex_string( + "0x0436b192e03a49796cf9bc5e93c88268b71c9c24f9c3a85322bba634ebea309d", + "0x067a8091ef69d62abcb28ce5df4dc7d53f8dc2b9690344f75ecd03a6d9386044", + ), + StarkCurve::from_affine_hex_string( + "0x007b34e1908fc20f1f6bbf950f40ee14d8b64a4b8e1e04f165d1b6efa6ab8a2e", + "0x00d4fdb816338bd52ea2428faeb0d22d435838e73783eb66e52c3a307710c430", + ), + StarkCurve::from_affine_hex_string( + "0x0592d25b68baff87a6d7fd41ff0dadbddc1bd1316683de3b2d677501c0eb14e4", + "0x027ad1e1099683f54589010faeefb19e38569ace43653be8787a42b0591e7bc5", + ), + StarkCurve::from_affine_hex_string( + "0x044d2ccc8a2411445d359f0b3d4fa48f63ca93a4003590bb313ab6a5a4c7e300", + "0x0187a25479b2313fc4faa6ab3fb2a96094066ace2ac30efc76584a33c17aece8", + ), + StarkCurve::from_affine_hex_string( + "0x03283a28ef9d49137040c098b5941e910c8b30565f7393e429de20490063c9af", + "0x01824656c4d7739526b92d527f5b85589553e971437dc6bd8b5e4f43b67fd0f3", + ), + StarkCurve::from_affine_hex_string( + "0x02b2f2a50c79bb9d6b8ec329c49d74cb486811f4b584027889fd6430f56c3f3f", + "0x02ebd50d1f00e14bde5af28650aa0797e7827b6a54c2619798f5d648412a15cf", + ), + StarkCurve::from_affine_hex_string( + "0x0089a5111ae911512ba62e87b97f643c0219702f235c70f62c6678a129302009", + "0x0557fa3d98e9ce7b83b47545013a4498f3de43787fb66b1a54521222242f7c1b", + ), + StarkCurve::from_affine_hex_string( + "0x043d625a28ce111cc8a02cb8300b325bd1897e29c880b40fc4e4a51828ae844e", + "0x0104d513d9109c70fa10db4b7a112f5c007b43bc0ce2431c195b90ae40201eca", + ), + StarkCurve::from_affine_hex_string( + "0x0020ee5fda37becd37e0f0e46ffee8dd194bdadf46208e3402bb53d705d2e528", + "0x04c4e442a3e73ac401a114ba91bf1e392076078ca9a3ec602c123cfc5cfdead9", + ), + StarkCurve::from_affine_hex_string( + "0x039751cc920d45769b846743246ccd4485a8b91976820922f44be1db3ddf5b7d", + "0x07ca836ca40a568f69d93c2b913799e11fb64933ba0f00567c39d6e03fec63ad", + ), + StarkCurve::from_affine_hex_string( + "0x01eb5b065322067013989a3599658975a21d0ae24d10e19f63453955843dae98", + "0x03ab725194722e3c5e46eb3ec62b9ae2ab21db95e6c23d6c15b3ca3e5203553d", + ), + StarkCurve::from_affine_hex_string( + "0x024cf41ddfb1e7853b96f855f4af00b29e64664b5965f599b319aa2ae6c8e14e", + "0x0013cf357cb7966b3e46612a8f9399aabff7cda12daa4d1429e1f127fe16e559", + ), + StarkCurve::from_affine_hex_string( + "0x02ad007a1b6b53f0180991af1d5674445fa4f7f8f29cbb91ec682855c386a31d", + "0x06ea05c6033d24f51aa3cbfc751a3798f767aa600f7e83f720cfe18cebe4cbab", + ), + StarkCurve::from_affine_hex_string( + "0x008412fc6672556cb4fd6d84cf65daa41a0652532ac44be39eddb9faf1c25616", + "0x0370ee5845b5409e80428232f402c640127d387ade33110bcf860915fde5c6da", + ), + StarkCurve::from_affine_hex_string( + "0x01c9b5e53377e72da5066cb08566bbf9ec31ec1877f455d932cd9b1aa375d34e", + "0x072f79555a8bc207863f32d482fca54692825449fd8963fcea3de3a8183a739a", + ), + StarkCurve::from_affine_hex_string( + "0x00574a6e05eb14591729515be239ea8c1fa9e12d4049d42876f76c8ff37bca03", + "0x05f99b3af43ca68c1c73e8190d5f73c8de162ba643d7d5f0cd73cfa8135db6d3", + ), + StarkCurve::from_affine_hex_string( + "0x04f8f9c8efda878a0c6abe77766bb2199b5aa836811cb3a5ab3c9d8f4a5e0486", + "0x070eed1b076368fb39902a395748d956770afba02f7d9f12e0820d3872804311", + ), + StarkCurve::from_affine_hex_string( + "0x0513fc5c2e16505b2b25a2f284e167d5401194bcac0dc3ecf8b7c9acb560daa1", + "0x0687ee7a1a8954d08d3856e1a16ded808e419e789736d3f55f79f7693bad69f5", + ), + StarkCurve::from_affine_hex_string( + "0x06576fe870cb5c232048669288090dbbda89ae49fb7739e8870e78b3b6a808d8", + "0x075b82f52dd3c3f9f5f27210344f84cf2f94aa35bd57780062b98f0b2d7c2917", + ), + StarkCurve::from_affine_hex_string( + "0x0677a76c2f29f5403a1c9825601d9038fa1b5eb1ae8025a2d8fbb69b44855dab", + "0x059097f1eade3ec28c8d0d19866d207f8d5ef2a912ca3068d3eb3ecf2f038501", + ), + StarkCurve::from_affine_hex_string( + "0x0519f9db47a14a51aea3cb1dcbc78bfff5050c9fedc71659daaf12d2e8f7de7b", + "0x000e188d695032088b4c40b4b5ee23ff3770e72d1f06f349fbd6dbe3b0bdbd60", + ), + StarkCurve::from_affine_hex_string( + "0x053d48bd1205274b1c2b0a0ceb3d21c5fcd7c8892a784931603240b288a598b9", + "0x035387abd7ea59c9b956de44d36533cad1f6668c438d666651695ff3862159be", + ), + StarkCurve::from_affine_hex_string( + "0x01c2c07baab9fc694944eeaba6ef635304e8e1567a2b7a6d61df443677fd60e1", + "0x0707ff9003ade09d0afe86a016375c586864d05111000c88f24aedd17495adbd", + ), + StarkCurve::from_affine_hex_string( + "0x0127718111e66782b8a42d8ffc4a1e97b2d5f944c31afe47627682ff2ee7bd4e", + "0x04ba816ac45175b8125ec6690e8cbd1ebedd8a5c54623fd50b910134faab9f1b", + ), + StarkCurve::from_affine_hex_string( + "0x042f63fd2e0cf7a1f11a591494f39d6b510a23a8eaabc2bfb8e72acc280abb06", + "0x06ce168a0bc0a5e6cf78a88074e3f82c7f3deec19f674f96f6eafe8fad127509", + ), + StarkCurve::from_affine_hex_string( + "0x00c168fea1a035a849be27a71bfe1f652867c1399597b15c700843e5f667ce51", + "0x07da8cf4372d2fcf59f9124883dbdb8914e7c93554a352a097e3913c6836f62b", + ), + StarkCurve::from_affine_hex_string( + "0x040d081431101eaccdf4583f8f7825cc83db0bf18f026f4922870278cab9e5f7", + "0x0661853c80cbee5a2960b19908755822ea9eafb4c55e2d86f36d977089c3772d", + ), + StarkCurve::from_affine_hex_string( + "0x0020a0afb24b2e5da3e87adf069942e079fae3abf04aaca2eff8615c47b7bdab", + "0x005b53f873a748b1a29e23be2e2f4fc0e9d4346c18d2bfe5a0ad9f19079ebbd6", + ), + StarkCurve::from_affine_hex_string( + "0x06abf47a38dba78e5bf05b096a24bb941526f1a8f629df8eda8b9b995009a3bb", + "0x071c2891bda1d50db4aca94b07218dc31d20817bb6a939041f8874975f7574f7", + ), + StarkCurve::from_affine_hex_string( + "0x0213eb1ea99e08825110dd61094eb6e8145119dc1c507636f068730b1e086d44", + "0x0744f6853f4f02f4f042468d0739e0c9f64df720b87ed77d1979547084ef7a89", + ), + StarkCurve::from_affine_hex_string( + "0x0735ef017d091ca23264ad0aa7bb9b2be3309b4539605e79ed4a652ccb2fbe3c", + "0x07f0ccc7a5747c4e921fff97d431169f690763427e2cfd1ad74d7a0308d7faa9", + ), + StarkCurve::from_affine_hex_string( + "0x07f556e47e8f4fe796c402dc700cee1d4efb07457494048290bde5aca7acd70e", + "0x032eed2b2e186467e1b7754a97d2dabd3c08ca59c82741e8889641cc36452367", + ), + StarkCurve::from_affine_hex_string( + "0x03f36babc5a30070b610ed97db44997e6d9115c9c0579ad8f75d295a17130001", + "0x079047908a2474e32d5c712a07bf5c4ad522590bb5d6cefda410d30528e12ca8", + ), + StarkCurve::from_affine_hex_string( + "0x066d365eb1292b306599a40aa706d0e7e4e7cb1012884e51177876f86e176ea2", + "0x03ad1ed31126c008aeabd279d264bc30f80924c6f79667f5a06b11115270efdb", + ), + StarkCurve::from_affine_hex_string( + "0x05ef23fe0fc556e2e5cc62241ef4e58fa55c5fd94708f950522aacceed4b30df", + "0x05f1b4c4b3dca554e3b0eab09e9a5074b237236221040653e7649ab59e87d667", + ), + StarkCurve::from_affine_hex_string( + "0x04c31fda9ea575a2e82ea4d3071e50e8960bfb81ce3bbb04459e0561b09dd279", + "0x0779ccad5cb0d3cb83ae80c963f4323ed7c742bc78531a51a3a421530a6341bf", + ), + StarkCurve::from_affine_hex_string( + "0x051c04907ae88a5926b242fb2862cb1f2c651a94e6caad5bff8601c079fded74", + "0x010a585a269f460aed43f54c7de13cdf623fc8de5957526997278be939ef32ad", + ), + StarkCurve::from_affine_hex_string( + "0x065bcc7ae98ee8e619c3bbda9fd4544715fdc5a59b842e6091babdda0bb096f8", + "0x040c653faedac89c27d63a16e4240d14a2d2c927d6d1d22597b6d69b83ba1130", + ), + StarkCurve::from_affine_hex_string( + "0x02142443335c5958370142c04837289ec46372c2e9b798e3ad324dc85fc840d5", + "0x07667866914c2c41bbb3b6ab31698385cffe0ff4ee2b76cb8e2524d5bc58912d", + ), + StarkCurve::from_affine_hex_string( + "0x056f2bd9f4c37332c8f0e58a314fa7cdeea3b4689b14214480d3740d9ee0305b", + "0x00d32c7bd71966497d0167d441ef3115fa7afafb88efadcbde303e7b1454002f", + ), + StarkCurve::from_affine_hex_string( + "0x056c714415f3058375d7955b50d8240fdbb718e5bf427fc4172c02d7890bcfd3", + "0x036c54dae8a824126841282ea36fe5dabc40986eef27598f3df4cb1ba8eedfe2", + ), + StarkCurve::from_affine_hex_string( + "0x030a11a11b775c0cc080dce4607dbea2e6f3c51108baa282ddba9af9c34d0b2a", + "0x061c16bab165c3795135db7a12a847c9764d60d1d3bad74c0c28856850959cb3", + ), + StarkCurve::from_affine_hex_string( + "0x01367b40dc7f9a797ee18866afd6acbf14cf7c2952f994971eafe7a80e90f556", + "0x0424a3e513e957bf49892216785ebd90056d77358fef34f6cecbbc960c1e61dc", + ), + StarkCurve::from_affine_hex_string( + "0x05f6d6994cc25902128fb00c9924a9791e03786e648ec325eda971fd094c7693", + "0x000a9a1b470224b7cc67676b3eb180885e3b3dfa91662b9928ddfe9c0f6d7462", + ), + StarkCurve::from_affine_hex_string( + "0x00c1e1bd626a735aa2c065831317217ecce68e377eb1f67e54ce2e97bc2ef2dc", + "0x053c5af23a9b482f420be6dfd37b6886154cfd130794098e1f51c1885ac2556a", + ), + StarkCurve::from_affine_hex_string( + "0x05aff3b30775ae4758e604a4a6262803a545f5ef4e7855fa245ac6a6431a9ece", + "0x039a4799e5519047f29333bee9c86c99bfa8056d4aa381c396c4a44331fe795f", + ), + StarkCurve::from_affine_hex_string( + "0x07a4eb659c8111d725dd8d6e70b0c391f23b1b43e8a0e238040f7684768e4831", + "0x02f694db4a3a3afe5a72ca01f175913c1f5abb7ea7cd0896347b0901d9fd530b", + ), + StarkCurve::from_affine_hex_string( + "0x03d753e9723701a8e9d99b91bb93dee2eda7ffa5072fb2cd5c5fd99aebcdb299", + "0x015798bf5c17d6d5880fed1553af32dd8d8baf2888c715a886575448a24c7975", + ), + StarkCurve::from_affine_hex_string( + "0x0105547339511559be2a1b5ed273bb1095ef091272311f63a1b9c27b986f6db4", + "0x032485cf96554c920226bbd8f8e89caf0a03dfecb9382232175b64f8fc45824b", + ), + StarkCurve::from_affine_hex_string( + "0x0736acada308645ab32a4cd64ac993b5e20c2e523b190cea557a6e97016b9761", + "0x0398dff04b73b3381102759bd5c601cdbe149badf280c3020c3dfc58bbf6b2df", + ), + StarkCurve::from_affine_hex_string( + "0x05a22976f1a563642904203b1cf49000dff0fb5552dfb089d3d0649dee9b3ed0", + "0x0735d59c59e9c832ae2ef4e3a602b01cea5b51f232677943668af56bf0634b77", + ), + StarkCurve::from_affine_hex_string( + "0x06593e5078466b07a4222d2e544da826d2c583c9cc5f2eaea148b129b00d4aa0", + "0x011b352b08a0a61d3cd67d1dc08069dec3bde907b3da0f56de5011b956bf8744", + ), + StarkCurve::from_affine_hex_string( + "0x048caf1dfa3a312fee9f8141769af825cb05655a6c11a7f820938cb68ce0bd0c", + "0x016b37bb7a46debd606039edb6fdb8b51f5b72d795020248bc0cc282561f62d7", + ), + StarkCurve::from_affine_hex_string( + "0x035badc16dd993f0a3ec4555623beff1d65fb088f3f5cd3b82af654c81768970", + "0x0705edf7a7d411b00afa6e0eb1197fd8b50d0a849738dab817febac685cd60c9", + ), + StarkCurve::from_affine_hex_string( + "0x0381c962a749ff95ecd72b2f556f2f3ef61419c3c1d53b5cd47e341337272505", + "0x028e430907cceab2b1673fa145fbda3dd8f8f1c7bddbe2b1d5f44bf35e9c712e", + ), + StarkCurve::from_affine_hex_string( + "0x02ea867dc03f57fd2c673891c38357aa0009fb0986126b920640620bcc02dd47", + "0x068237b0d3ff317275205c23ad1f41d23771e9e94043a5d956c58d75cf3fc5ae", + ), + StarkCurve::from_affine_hex_string( + "0x02b37ab18c66e0ee425ecce1251eafa1069e3cda41b7b7c161ff8cc4a3c859a6", + "0x075f1106ce4f67307f8c301cd9ffae5e9c9c7b7be09fe5cf7d445af568b24c26", + ), + StarkCurve::from_affine_hex_string( + "0x0574ab8edb3bef422ef246d9300a1466b9d270815c6d202eaa5127916b6e4a5b", + "0x06dc476e19e79095e62f0a32848b73ca46a62ea5f12b68c2c3ceab028e46bcf4", + ), + StarkCurve::from_affine_hex_string( + "0x04fec9681f3e9218e3f160f7fc73da5a77709e3bad6c877af106bdf4f642a68f", + "0x0632d0cd3dbb007c8572ca4cd80e5622f5ec0e2ab2b857f98dc0bd3cf31fbe69", + ), + StarkCurve::from_affine_hex_string( + "0x07a6eb353c5be9ff03fe4a06c01fb71aad2b38144179a291ebcbb2c2417cca65", + "0x03de3ecb12f2fa699b46a9d399abf77ca17bebc3e491bfb2542dd0fba991e2bb", + ), + StarkCurve::from_affine_hex_string( + "0x002c7ead583d6c32162091034a9eddfa775b4e84b8bdbea939edb2a80dcf64f6", + "0x0461790ce40d9c276d962b2a1e9a74d66e9d7335962e234e8a2fc6963d31722d", + ), + StarkCurve::from_affine_hex_string( + "0x042dfbde92548f0371e98540e4958c7024dc432a6c5da9997eb4618547c36436", + "0x009123509ad725ffbc9aca591d3eff15fb5c1474b131cdb6279f9d0d72859835", + ), + StarkCurve::from_affine_hex_string( + "0x034285af023d9b4c2c2b88e8704bf2c05a9b553b00b2e70ff05f8c2970cb134f", + "0x033fe678e7671760a83836107428dbade68c3593fbe568f3f8f1b2c568099c44", + ), + StarkCurve::from_affine_hex_string( + "0x0368ecc587e70537f3c268e92e9ab4cbf6a80e23585911e5aec5cf8c43ac127e", + "0x019957285e7fca1c126d8c47fe3c2ff2276f6cfdbd5ab73a7563551a76758540", + ), + StarkCurve::from_affine_hex_string( + "0x02861d2d56f876748babf45435cb3becf1e1582b8967568b4ea6eb38330a4a50", + "0x0728b1c907c18c5c27306a99af372faa1e779803330fd07522d5560b94d2d895", + ), + StarkCurve::from_affine_hex_string( + "0x078fcef3146fe8a19de8819d643350fc86ca3d6b0bdce2a5769000ced0432df0", + "0x000e13cb7fd79355a97b356ee140ef8acd698356c6d715b0750447a635725de6", + ), + StarkCurve::from_affine_hex_string( + "0x06222f720a24466263db6a11842f117fc4bb78da6705f140e48869db3e087441", + "0x06eff5b9bf3aeedc962bc5a24b66e7bdad2153450ed53a058bf2c8dbf2907693", + ), + StarkCurve::from_affine_hex_string( + "0x02db18ec981852683c758a939d2363ab61f455489afe88fc85d69de596431ff5", + "0x06d804a5824c8e1c7fefd4e91eabfb8d6fbb03f6a0ca497d7c6349b2b5bc2cc5", + ), + StarkCurve::from_affine_hex_string( + "0x05b34ecf07469ed26b5719aa9c7deec98cceac3844ec6104085d897c68177eb2", + "0x00b76f8d188a6692816e599285f395eaf249ee203d664879ade372f9c046bcf1", + ), + StarkCurve::from_affine_hex_string( + "0x003075c040ca2cb40d242df9b933d0d038d670274f874281bd549329b3bd9f44", + "0x066be858643d2f64e30467416851ac0a24740ffe75538e8999bced6157e6742e", + ), + StarkCurve::from_affine_hex_string( + "0x02f244dc9f349f6b7151de259f7764e9f904f700a8fa6b1eeca14f73b798aefe", + "0x05345d8bca1995a40e818478938b7314cfa45f0677a6d5fd5b22e6141fbc9fff", + ), + StarkCurve::from_affine_hex_string( + "0x04a9dbd186db6fdac051af404a0c5e7db403cbfa501b459586566582565e0d25", + "0x04d7f12d7661248bd0209ff8028769bb975910525af57af1c27e9865e06b9344", + ), + StarkCurve::from_affine_hex_string( + "0x00d12792a21a98b772f76eed4d1a753d67b719e9f8b481a8f2443d2b32d2fa7e", + "0x025ffdfd341a3e58879eb76bae4c75ccd9b35041b2d29b4ac904e31d89f1a38a", + ), + StarkCurve::from_affine_hex_string( + "0x03fd3f8abcc4590870d92ecad30cfcfa593ca21499778dff90607d1f7ac1dae5", + "0x078aa97841d18e1d4687e9ecb6679b54f7f876d8d8e5ebcc78b95b57fac9f201", + ), + StarkCurve::from_affine_hex_string( + "0x017c6ec5ea206eb97cbf53851e37ce391080e0d2bf1e5395610f79ab0503f7ce", + "0x03adb71ca3523d88ceb1e365f12dfb24895453c14daf0046b2626cddadfdf5f7", + ), + StarkCurve::from_affine_hex_string( + "0x070859f9771a713e54974ce11cdaf44b0dcc3e9befa0c0834908d877eeaafd27", + "0x00d18f794bf0cc0623b711e7450030424e52326c45ba9b03341883ae4828a5f8", + ), + StarkCurve::from_affine_hex_string( + "0x065ebd15beb3ed8e0f4069570c97fa9ca964677646cce1cdf683262afbe98305", + "0x00f5ff85545e0afe895477de71260d32f2f8982cb0a2a5aaa2d70008024a83dc", + ), + StarkCurve::from_affine_hex_string( + "0x02a820cfd0fd4ab0871e7b303cd545a3086caf8fa818c087a4017197da74efbf", + "0x05f992683ff37f6c041b84bfc01503d333ac9763505cc8f69473da01812969d1", + ), + StarkCurve::from_affine_hex_string( + "0x044681a9eb73031c23d8ef75b12d5df25713df60bc02607daa9866d9149dd744", + "0x0122775da2fd7c94dcb831a2b4bde6128e621383c85645fca0e82314f9b8db2a", + ), + StarkCurve::from_affine_hex_string( + "0x02d9bc641ccf15bebe6517ed3956ea4586fb098b6c74694f96adc8cb7201cf45", + "0x01bbc53311496cce45322005c77f1d83a067f23c78031fba7a8bbc90850a45d9", + ), + StarkCurve::from_affine_hex_string( + "0x013ba6bc9a47ec3ea8b384d914e87ec89a314ed45b93bb2de27acefb7d9f48dd", + "0x0143b7129aa9c120cf28984bb365738e37f6fc9642c0f6f6a425b7b00613a5ce", + ), + StarkCurve::from_affine_hex_string( + "0x05b0526de2c07fe7cd73e3884f642d57a0ac5e13c68590ed03a14e530616e8c1", + "0x00eec69d0cbd92c9fca31ec967dba848bec368e792d6678797946a5e34fe3487", + ), + StarkCurve::from_affine_hex_string( + "0x015aac85b659e12eff355ef5ffd6f12d364f7b54a862b337f54c8bd27015e05d", + "0x03a7335484bd88aebbe97e2e9b71497cb962f9b10329a8d5989c6f80b5890034", + ), + StarkCurve::from_affine_hex_string( + "0x008a67e26e06db54d3e4879c6035e18220f8a81850472cd3ccb5503d7b3256d1", + "0x0771ac312423512608b1beebc05f5d8057dd072e4af98198d374786ce9b0aaae", + ), + StarkCurve::from_affine_hex_string( + "0x018c1c95bfcb49c356302fb6121ff71eab812e3e29dc70538fe1997905b63ee1", + "0x07ddd8295b92cc0db2b71595a21ac4939f6adc3ee14a7818347e6a551d88c89a", + ), + StarkCurve::from_affine_hex_string( + "0x02efc1b57562f2ae67cea6083596e9c042cbcf9a4035a0fcbd922d7d54fd7700", + "0x0110f2de4efcbb5f44c9af2acd2edc949afe50e06ab91d96b8482f7600b54877", + ), + StarkCurve::from_affine_hex_string( + "0x077e0ba159b8e19ef7f50d29a4db58c4331d20f22356dd43ff4c7862717d2d44", + "0x04233573fb814ce30ee8d38a408a721087f16835fc8da6b1e4fe56cff93cc6ab", + ), + StarkCurve::from_affine_hex_string( + "0x05281cad86e0ba84d6f81a2fa2240d8e91b1c36f872919341e5f4feb1381e72e", + "0x021ed005e763cf31ee5237cd84cd36f61b778fbbdbcfff051e7b904f9c31ff34", + ), + StarkCurve::from_affine_hex_string( + "0x025c35e11083da6d9cae5b3714631ecd406cb403ef277a2e56e516107413b43d", + "0x00d0a74f7195af1fb80ff134de7696fcfa3b394d60bb5917d2f267c47ce44554", + ), + StarkCurve::from_affine_hex_string( + "0x06cf6b3efee707210cb3a72f1e885c3d0953aefb43e5e148c740aa1641725c61", + "0x00911cb630b898e2c1a9115f9e45bafe3b819edfb1eab6e15612d14289939984", + ), + StarkCurve::from_affine_hex_string( + "0x074e913de55f1e46143cb2ecfc580f8d3d3908f200281322b84e21c989cda293", + "0x0761d2736c9ac7670ba905bc2629c6c0dbe988820a4454ff415ba68710f7df92", + ), + StarkCurve::from_affine_hex_string( + "0x07ffac5f286975623ae0f5b4f597cec900b9ea177273c313dbf3d038df4fcceb", + "0x04df4b8618c7a70ac33138d8d06576a44d3220908af4feac20919ae9215a3052", + ), + StarkCurve::from_affine_hex_string( + "0x044084305e0c911a40b7cbefe5f13cffe9a99375d1a584c4a2200958050af7a9", + "0x0249c83877371564708ea525b64b1e7e12785460d83364446531c9adcacba5f0", + ), + StarkCurve::from_affine_hex_string( + "0x04c240ab5492265852c4163ccf60732cc95ec1dc1c94ce6a4ae08750fd0a3786", + "0x002ae167b9ecffa4a9ee667ba816fc13e1650389fd1d5a0031289c4ed8315722", + ), + StarkCurve::from_affine_hex_string( + "0x04ae508f6f5b4d984150791fa9004ea89fe381334c3c49d9bc78b9c32955acbc", + "0x05bf312dca6e656862ece5c05d037e88f18fe3098d7b6c5da0a96b35e5635506", + ), + StarkCurve::from_affine_hex_string( + "0x047f3fea50bc3285c0180a7d9366b74d2be2ca717737d2fde36f17d7bad014de", + "0x0622d8c822e455807d71a8da46b7a4017079801a9073d16b18ec0986e0907c8d", + ), + StarkCurve::from_affine_hex_string( + "0x02bf71ad4d1bee1a67fb300477029f54bdb0e09f78bf2ac2e8afc7465a7adbcc", + "0x06244dd6cad282539049be57487bfd9900bb0d5da805d02b535096368fcb4cd5", + ), + StarkCurve::from_affine_hex_string( + "0x010af803ff65cfb87e1dc0a062fe31c7defa48621660faaf0268e35a137cdd5a", + "0x055467a668f3028b7c82d3052a595c0a836abf2467614c8b29cd8229785b32ef", + ), + StarkCurve::from_affine_hex_string( + "0x02f5d0a23f8822d62a36a1f253faf0c661231e843f059918fe419f85f159459f", + "0x04fd679bdb0b7b72b05ff4d6c07e04f377d5d4d687814fa2324f9557faba5e42", + ), + StarkCurve::from_affine_hex_string( + "0x028932642b5ff9f4cb9d36faef4577b4291841678eaa7ef1c1cf2376680293a7", + "0x033cc0aa065b9623115baa4cd55d2dae00007accdb2695dc4b278aa362581e71", + ), + StarkCurve::from_affine_hex_string( + "0x0269a9618cefad2b9370799f8cac232dec9b8588bc54bf97d99b33d3b304020f", + "0x074a10aa1f74c5e2d5cbda1c88b229051938d58fadf0cea5e633c96201880f7b", + ), + StarkCurve::from_affine_hex_string( + "0x0696c5910ce59323c2dd21f38b1cc80dd7b43a3b9e483d8c40c8a2199a7761f6", + "0x044561b2c51658207d9407e90be4680b3976dd9f950e03ec7292fbe67ef61629", + ), + StarkCurve::from_affine_hex_string( + "0x05cf4d8be1728a291f71b7a9cb7f9aca1084aa2effa98db4f410f61a1c22ff60", + "0x030935a29b92e07d31dbff6a906cbd6d8cabbf1b14bf2ca619105d87cb35709b", + ), + StarkCurve::from_affine_hex_string( + "0x0410368a143b069b31f4bac0cf435378f99b07f8bc7ba67f50818ed211fe337e", + "0x043d574d10d73982a53e0ec48f09663486e0b9ded91c9661c3796ba72df05644", + ), + StarkCurve::from_affine_hex_string( + "0x003a62d8f763b62def36e4089458046a49c5ecb91b861549530773e0548ff2bb", + "0x06a10a03ba61e6ac657270465c09aa9526cf1ebe96bdecdf0e7000476a47b9eb", + ), + StarkCurve::from_affine_hex_string( + "0x00284eed3a17c51e0677d4fe897f056abe9def8af07a4630e6ca5723e2aa6677", + "0x0516a06ac1d5626ed03d2eee9de6f60f0311eca703a99b0fb31b9c66b01c27c7", + ), + StarkCurve::from_affine_hex_string( + "0x0091a4972c794a03417c09eb14f44cf8215f9ae25c7ac80733771952422b3efe", + "0x017037f7ed12573eeca739d9d5eceafa96a6530fa200f859dee2dd0ec21ba114", + ), + StarkCurve::from_affine_hex_string( + "0x02a2c63b16cccd685f731d06fe93ce2cffb358d34d03dda9a7368185c1eb0c32", + "0x07180baca0ba81284809f92eca1654cd76b925a9242e5d5e0f18d0a55d13c6ec", + ), + StarkCurve::from_affine_hex_string( + "0x005c8a2f644c59045499ecc254e728cd1700949d3a49621ce07a35ef33090ac0", + "0x028d40254932fb842b411d03389168b6d6e1e8a589597f3b30399628f7448e75", + ), + StarkCurve::from_affine_hex_string( + "0x0115a22c63d5346ba2f558c45b20f953757b5c1f346920484aeeed9908cb96fa", + "0x00abf1818b944833a54370703f189d86862bf73794ef59d2004197ab0ed8748b", + ), + StarkCurve::from_affine_hex_string( + "0x02393930803623c4c46b96a1b097fbc16bc7dd61035220f4e1746602b3a2793c", + "0x00714b487bb2aeaf69b54413c07e4fc82d4aafca6aa170195d88fa8b12b3403a", + ), + StarkCurve::from_affine_hex_string( + "0x05f9466017ec09769611389ea5370ad68dda936d3f5816c9e928ff9574abf9a7", + "0x06619b5b145bb5f4f29deb7a4cd68ef4da3995312fa6537f0d01684da4267ece", + ), + StarkCurve::from_affine_hex_string( + "0x01e6ee1075012ef9057a26182edaeee83e0b6764be08bc1dcf0bca5268ffba7b", + "0x0774127fe3365b48d21dc035f43be38cf5a12fd9f5d846611274a9bae569f1b7", + ), + StarkCurve::from_affine_hex_string( + "0x023a140ae82662aee2a571f29a39689558a2d06d522686a6d0fab22e55bf8b7e", + "0x02822b2da393040069ecf4d026fb801d3bbc8c21bfa81cda3c59af389eb96204", + ), + StarkCurve::from_affine_hex_string( + "0x0772dfb873ecc2aabd917f53f2ee22879cde6ca36f1b578c3cca65679f55e754", + "0x010609d39a302b213c56e6de8fa936a0cc82f98e400bf23deef8b78d22099815", + ), + StarkCurve::from_affine_hex_string( + "0x033137e3f3cb5f7b679e4a37566ce7542d9e8a79e76a18ee9957e59607137a88", + "0x06cd489253de59762fb3e4ed73c937d64b83e34af7699292644d5213a7aae7f4", + ), + StarkCurve::from_affine_hex_string( + "0x0693103fdd16ae5d3877d0dab78c625e9b33d7f066dbbe92f9ede01f345e53f8", + "0x010657d1f44a201e6696ebddb35c3911ffea242951c857a86bcdbff2582c3762", + ), + StarkCurve::from_affine_hex_string( + "0x07cffd5305bf42b7ca96b427b7c91367980290767a37416cdb570dec8a581c06", + "0x0734bdb561d81bc7566a7864eb6a6fd58a83ab3a8992b985c5467508f37cf285", + ), + StarkCurve::from_affine_hex_string( + "0x01fd5e137a43ddddac2e7c89de7dfdb8337320856cbb9fb2acbe9c4a525789bf", + "0x0401b8979f5d15c3e3a4f92442b34d8dedb6591cd096a71e1f1e94aa3fabd118", + ), + StarkCurve::from_affine_hex_string( + "0x074f229babe01b4962b3307589c1a13019134b1db6822698388bebb55d21c30f", + "0x0156ae857ab3279f754facba0db36398dffec8c31e5e160473198f2f891b7531", + ), + StarkCurve::from_affine_hex_string( + "0x0334b9fe3a5fd99bc966ddd1309698fd32afd1f235062f2c275b6616a185de45", + "0x00221a60053583cc0607f6f2e6966b62fc9dac00538bb7eb1148e007a92116d2", + ), + StarkCurve::from_affine_hex_string( + "0x06c300a27f89d63ee9755b2ea96328828a9dee18aa344b49f9d902c128868dea", + "0x0532fdec4e0ec3cc2e2632b385d51585417e2c4facb5be357d62a38c9e79dfc4", + ), + StarkCurve::from_affine_hex_string( + "0x07ad710ba002a67c731efbaba2149d16fec5d2f7aa3d126fd9886172e9f4ea30", + "0x03a10f8e902a7a13aec94d66415347e1314f9bac83a7db176096b809b25ffb86", + ), + StarkCurve::from_affine_hex_string( + "0x07aa19a47edaed5f8a09a767d4ff4c3f4d225514a06f739488f09cc8460eaa35", + "0x02785a4061ff1058057a0dc1bdbe3f09eb5caa98450bed410d715e8244be5339", + ), + StarkCurve::from_affine_hex_string( + "0x059481b045bc04b88d6529355f25c4e4beeb3930ff686d5b3d200ff85f482514", + "0x01ed00514dedced569889e1f55ce9da003a41ab578ea8e811df97d210eb70384", + ), + StarkCurve::from_affine_hex_string( + "0x00b9abe8f72134b4968dd400215bc7f2388312749799dc2b5adfeffcd1be8a09", + "0x04638d68892214e2495b2c97cdf406679e45c7b4ec7c32b00952fa0c6ce1350f", + ), + StarkCurve::from_affine_hex_string( + "0x04306dd0a184a3283c3097ff8f7434cec80912e9dc04b7df21ba73fda9f8e6d8", + "0x006d42bd3d1a8dbddafd09e872e2aa3891ae79ec939dc1b382196bc21c4ab749", + ), + StarkCurve::from_affine_hex_string( + "0x022a254c19ec896f55126618ce4dcfb774a5d8aa5ecc6f24b08285a757073754", + "0x07c37ea255904bebe720be3a505bbee4dcfca51cb48f2bb253eeb505772a480c", + ), + StarkCurve::from_affine_hex_string( + "0x0628a3c0a1e907102a9df29030c11b64f919f76d315a6357fe9b25f3b3ca2b1f", + "0x0451bdd071feb4f2a7c48e830122eb35b2a51de0f8e424de16fb3b2382ff0812", + ), + StarkCurve::from_affine_hex_string( + "0x06380f53aff40fab369e19dc791e10b057b6d26249239b1396d3727c971e8bd2", + "0x03c181e0335ef446b068f6b9323983e3137eda28a96c6b9f2a153532c953082b", + ), + StarkCurve::from_affine_hex_string( + "0x03d93322514ca66201f1de97b06783bec46306b30bf9aa4ed04e627d2e011102", + "0x03a9ab56ffd41d08a699289335bf112d8180e99df53f52cc16cb3d756d2df340", + ), + StarkCurve::from_affine_hex_string( + "0x01c349614ecd6aecea874e846b8afc0ad521c5d174867426139d14d068f844ca", + "0x024faa512032a1da2640c8a794193d057b1fa4def9bd638a2ffaa99791018020", + ), + StarkCurve::from_affine_hex_string( + "0x020c996bae0f44b76c268b30d7143cb70985d6037b46871a4822b7f54cc0798e", + "0x064e17565fdc925b802622ebc9aa0bbeeebde1b5f80e29f055d6fbe40cac9567", + ), + StarkCurve::from_affine_hex_string( + "0x003e414fb4df29b1eb0ae3de7cf3542453bc3d0ddb8e47b5c85eb9f38479e222", + "0x0482e93b3bf4e79bae26354be0475f91eeadc8181dbebc29e5b1eabeae6ae547", + ), + StarkCurve::from_affine_hex_string( + "0x01c3f2124e1135c32a426d1d14e471edd9e0f2c7bd703ee123cbbd608e8c4be7", + "0x003cc607a3c3f1ab68dd5fa56c65996002721b8ad8ad4b0dd9e5b1467d316583", + ), + StarkCurve::from_affine_hex_string( + "0x00294af33272ffcee0b56a436de1b73759cbddebef4c07888b42c2f92b0b68e1", + "0x00d837164311d5dca8d37b99ef9eb22708643c83d1cbdfe852f63ea07b06fbad", + ), + StarkCurve::from_affine_hex_string( + "0x064f4f01829229361242a45a7e2bc1723413d30f5e7556a64063caab225f62d5", + "0x00fe83577da128e3f95db4185068217149477be155f10c16d83d67d29480621d", + ), + StarkCurve::from_affine_hex_string( + "0x0753bdb5439a19bbffdfa02b1dc24e8368f22d0a8276b109c11e6feb26f56f39", + "0x06ed396231af93647633eab467f1a034f38e76823eb85baf97cae56e2dcd9f75", + ), + StarkCurve::from_affine_hex_string( + "0x0767c032379049e1a5389f2c6020e4f4ad4ba0ad7f83df20c3ba5f9d9ae9660e", + "0x02fb39eb2c2a32fdf867d560f609882400f7f819445f330cbfc2251287f2bc10", + ), + StarkCurve::from_affine_hex_string( + "0x032f33716fa01f599798dc5e45a2af6defbace1eda8feeabdfb6af8531fb65a0", + "0x06eaae27fdc37f1c53a932e832406abb765d0239bfc794ca9702ed59575d786c", + ), + StarkCurve::from_affine_hex_string( + "0x0218e929a70b88ffc36750d319ece96708fd068e62ec510e23fd21f6c150bb15", + "0x05e1fac562d3755afdcaf2dcee8b221f2bdeecb76d7b6bd7870c9ff1af205d1c", + ), + StarkCurve::from_affine_hex_string( + "0x05674f0cb892b733fc0b50e121d8679afed0a925c32594cc65ffe83bebe7748e", + "0x07fbf0325dd38dd94905adab2c52758552292a6a103d9edfcb11938828e828c8", + ), + StarkCurve::from_affine_hex_string( + "0x07f8526f9b86b3f1926bacb2b2996637f0a4570b6c4cb35586c25540f681511c", + "0x01a2a025dd148f3665d8370f8078b0ec65bd6d4175fbf3ebb61ea76527c4ac6c", + ), + StarkCurve::from_affine_hex_string( + "0x061e6d4a1ad813d8a6f01472b8e91b5d61a4471c174e66fec05010336b4f555c", + "0x018021f27153b69b2b4eb062aff1f455ca85c8d996828af0dea96e140862029a", + ), + StarkCurve::from_affine_hex_string( + "0x0681af52d1da820127d65c65915877b64665e3a9c6d8750998d23a835caa0c77", + "0x014a799e0d0bf61acd05208752e7ed76608f537f3e183dfdc99349cbe930e08c", + ), + StarkCurve::from_affine_hex_string( + "0x0063ad7df133e439ae69a479becb8f5fb5cb6d72507771d91bcae9e6d3b0861f", + "0x074eb8c00e0d1112cc9a91d4ea16ff471f36a1fb95d3952f3e27544fcb27125f", + ), + StarkCurve::from_affine_hex_string( + "0x02f5bb99c2d30502b9dc0a16b31b9c2f341c1ba040004747e6f9bde66998aef9", + "0x01fb7ea7c629b1e69191d639f98fbf22ffe03ac928cbb873964503a40b1a6a78", + ), + StarkCurve::from_affine_hex_string( + "0x0785bb5dec3af0323f28070cf154f208a54680c5defc317932df978cc308d180", + "0x00fe48a5f6c9d6c45d4f4eb0e7ce8922f3ff5d0656c9671ea75423b05710bfbf", + ), + StarkCurve::from_affine_hex_string( + "0x0097c2d77250d0ccbafe4fde9468e68ca7f5a7202f23b42bb4c0b0543bf55fcf", + "0x06c4c89f5e6648080673c3fabb411e37d8aff4302ea4fd589796652273d1f0c9", + ), + StarkCurve::from_affine_hex_string( + "0x04a8f053573a0a74251059d0229d89b6660407ba0b491779fd10f87a5117c81f", + "0x021b70112485398bf67ec9d733df24a1df30dea718a93b786f41ed04e3ae3c5e", + ), + StarkCurve::from_affine_hex_string( + "0x0726c01ec4a08df8fc8de173311f50d4f3b97c5a9cf68c1536146f827db95ae8", + "0x015013cafadefa7f1c4e4dfdd70bd4d3979dd18bd7f0332572ce2a3fd8773d12", + ), + StarkCurve::from_affine_hex_string( + "0x06ea27424e66192d111517cb581b98205f8452681e44bdade703ea7f77ea2e14", + "0x05d5b77d05a9368ee976709c8d6192aaa3d3512181727a5bab9999587b1f91a7", + ), + StarkCurve::from_affine_hex_string( + "0x038ac0fbfa98937257460db7e6645d7e5112b6fce7234813fc8a704e8ade8da2", + "0x073c0109f86048aad08c443f781ae60ad13b99f7b9cfdf3128fe6d6eeb799a7b", + ), + StarkCurve::from_affine_hex_string( + "0x077fb5cf98618dd79dacb904176b885a5aba901ee7962ea72486fb53a30c1770", + "0x00ab24917373fa01bea67260e2be38fb6c2869049738d54bbe1f77668dd97946", + ), + StarkCurve::from_affine_hex_string( + "0x06180ffda23152742bb35d3fce07fe8857877558a33ef2e4c43a2a7bdb47c94e", + "0x008d2f0194ed6b0e6f97b356724a49241a56b51d7727a49f503870aca15333a6", + ), + StarkCurve::from_affine_hex_string( + "0x0035ea942b767b19a479d8c9a5b773efa4d273ef9486fb21fa055f9d725e5e8f", + "0x00561c91da1cb0415877d90f7e31099b8d507161193d75b2012e16cce6e21dd1", + ), + StarkCurve::from_affine_hex_string( + "0x06f6d3a38621582ace092eb50ecfe9eff265df141ebdcab8653299116fcea291", + "0x04a1bf3f39bc919c8f1b720a0b1ce952cad17f2ba98308ee6b76dd9b6f3d7b75", + ), + StarkCurve::from_affine_hex_string( + "0x02700a13c6a1870056a00b224b7ea23b176c030a732880c549b93baa1637e47e", + "0x00ad9f1c528777eb7cb5257bd17a03e9a3a516bd4ba1dbe0b7c0c178b72f32bc", + ), + StarkCurve::from_affine_hex_string( + "0x002fbf9dfafe04cfb6abcf43fba2efee5035f6c33e11497d6946a02fe2c818e8", + "0x04b5bf53516fd846d3ecabe2c3f3bb6953d961f83f97a16fe38b5663ce28464a", + ), + StarkCurve::from_affine_hex_string( + "0x047d082745dff02a344c0e76ed84c54082bc4583a266f03612e1ad26b57f58e5", + "0x076e1102bd546ff9dbece7ccb5c71c15143eef9dde0e53fd3861a9307d87bd99", + ), + StarkCurve::from_affine_hex_string( + "0x02624d1f4f49c122349478eeed032b5f506e45b66859f892a65ba1be672da661", + "0x00e21169547a5c1eb9d0f2ba8ac9a1af96d5dc8bb56cadf9828e02be359b0b3c", + ), + StarkCurve::from_affine_hex_string( + "0x05d5a067c649215f6e08ef147b676689f38303370df7561559b0e7aa86066907", + "0x06fb17040e0c920e7492c6aa5e7e1ad679efefcfd9cb2e929d60ecfe09c3fc4a", + ), + StarkCurve::from_affine_hex_string( + "0x011f9f7a2b7c113c957192e590909608c531574e8536777939c1785ff7f60905", + "0x057659297edf957dd0b96a98c44b094656378e840930483a6ecb5cb53409e013", + ), + StarkCurve::from_affine_hex_string( + "0x034ac72d93631c091aee7e831fdac1ac298e766a71dd34f0e5bd6fdefb271641", + "0x04b5a5f110182c651cc051bc3e6ea664b0001204c6379f8da98eaa51fddb7a19", + ), + StarkCurve::from_affine_hex_string( + "0x06a307fc28e1df8d9ad01766419e097797d65cb674436fa1c8f012d3de2c2a1f", + "0x026911a635ba824db004875d79dd84834a97ac12643e42829015bf88c1fd6f05", + ), + StarkCurve::from_affine_hex_string( + "0x02a74860e3336d6db916555894cc8028f41508812925db1925457afe40257155", + "0x05f8da573f4c39816ce2dba8a20224223a7cfec53117ec78973930c0e9b60244", + ), + StarkCurve::from_affine_hex_string( + "0x026c0fa942970f2a2781d1a95ae782f13a5ef0380a01f4fbb4520a660b1498c2", + "0x03bb5594e2eedbfec9f1575526ca86f9be5990a681aefa5a69122cb5a4940e4f", + ), + StarkCurve::from_affine_hex_string( + "0x04d2b49e1ed0799f719b8269f092cb489a466a645bc0ccabafdc678864c176d7", + "0x05410083df7d256f18cbf5697ae5e52c31e075d8a3b27e21d6f5177ca882f6c1", + ), + StarkCurve::from_affine_hex_string( + "0x046291c56b16d5ade6e075736e8ea4fc258cc92e8d8b3ae087c47b731a12948d", + "0x052405c4a55e978b49b7555c8955e6cf3fa3eb6d14d492754b1e6990c8fa2bb7", + ), + StarkCurve::from_affine_hex_string( + "0x04186fc02816091642948079ca033be7c1f6477f734ff8a0dc46400f952039af", + "0x03e4e732362d563429087f176b243d6f7e69e358e2d165304dbaf39afc0e968c", + ), + StarkCurve::from_affine_hex_string( + "0x05b9e5eb2eb540583d887f1d7ee02965351e8015a9f8b29310f25e379f4eb752", + "0x07493e636ed3ceeacaf4d5aaf246c8feef46e45799800c358b768a3088c42160", + ), + StarkCurve::from_affine_hex_string( + "0x0110ecb9fbf6c333d168cee473cc5ad98809b6cb9eb5d1f6cd28ab5fab504fd3", + "0x07e3c54d7533d9f8c3310f219dab0cc3ea4d39b418a748eeffd6bae2b8637a43", + ), + StarkCurve::from_affine_hex_string( + "0x0097316b88fc88e048ea7e0313ca84c09b5994d766729deac7c01897dfbe6b28", + "0x03258bfb171435fc9f8487ba95c99419ec0742b1c2884704201d3d5fbde6d015", + ), + StarkCurve::from_affine_hex_string( + "0x06dc30a8e9c2f659215036ad6fa368f648ff3fbd8c74212c263cebf12c9edd65", + "0x019f02da1639ca6a86470229aeb33a32dc13bf76e779356a0a5416952a1c41f0", + ), + StarkCurve::from_affine_hex_string( + "0x07e1c73259b587b4113b911be0b5142b600f0558e9cd3e34427d25aa4b6a8265", + "0x03597920bbed1b6e963144bb42b1605306859a0770b76d6799f0f7255eeaf264", + ), + StarkCurve::from_affine_hex_string( + "0x059802c51324036314471e33c6342a65f4737dd53e88183a7c9211a4dc6506c4", + "0x07e2b256ba1ffb790f6931cc37c2e9a7a2c3264e3c0d3f3f3c2e581fcf04ccac", + ), + StarkCurve::from_affine_hex_string( + "0x022f998bad499bc94a72855b43b07ccda3ed1225976c2385accaec5323cd840e", + "0x06efd0615e05ce0d25af73c6384e461c2fad62d6c781305ccc7889552f68b6a5", + ), + StarkCurve::from_affine_hex_string( + "0x03ad3caa8af2cc03b74b36a3561a5faf853f396725f586486b541bf0d77465a6", + "0x04c189f1c7783b424775d6ecc19e41c90133f9ede5d78179b6edf727ac761c65", + ), + StarkCurve::from_affine_hex_string( + "0x0195277d2b3aab717855be7ca829bdf8343d7588d654bf9e00f86fa6d4d375a4", + "0x01a01694e0108c982a2fb26709aebd10fe5cea3238ed41f1eb5b30900776bc80", + ), + StarkCurve::from_affine_hex_string( + "0x05be4d711b80da70e6d3ac493250bbfd16f20b25f31919b3a91cf14ffbac1096", + "0x07f55a0919f082e8885f1515e83c5b39b6022404503507498e1b4422d79c43e2", + ), + StarkCurve::from_affine_hex_string( + "0x02605125b95ca4ba93a21cbbba5762898a7cf9e988f07ab9e64cb3868e3b139d", + "0x062f0ccf55b9fc0eaf9736fc8ee484e2acdbe259813af9803cf815829a5e9d3b", + ), + StarkCurve::from_affine_hex_string( + "0x0152d0f558c392294fafc66ee37734441265afb524c357261bd2914b1ce95e13", + "0x051372ea8979979ee27713a2b9e0645d17de772b1096d65b7e4b8f966ae19832", + ), + StarkCurve::from_affine_hex_string( + "0x01092bbbf206f2a3068167c3dd99a72de31e206f6c504c071c8214d105ff814d", + "0x0309f489f68a62089f53b96df5d4fbc3ecc5a1a42eb7ece0e49bad17ad490ff4", + ), + StarkCurve::from_affine_hex_string( + "0x052b6275330dbb176400ff1141e101fe6b8cd03ce9a9e2cf83c6ef9d5ff68243", + "0x04fdf066a090c89a86f868f1a254dd5e732dc83ce20d0d69a1405599b18886b1", + ), + StarkCurve::from_affine_hex_string( + "0x01b1751727e2f67fd93a9d8c4a27d564b09e4beb4de2b3aa70f973ae30e06205", + "0x07822725cc556fdc79d01f60458f126699333f72c85ad980f05e7224f5ddd285", + ), + StarkCurve::from_affine_hex_string( + "0x006fe73b22de12675a6d0cdd1ed16f0a90b0c94f42d3ab00ec51257acdcc1fa5", + "0x06377be34f74b709d92105d6df906c09299ce3a2b9169e05ad3f5fc687c8314c", + ), + StarkCurve::from_affine_hex_string( + "0x02abdee9409d9c92559ca3f4e6bddd649c31aa09b90bfcb4a612af491241e18d", + "0x03ffa8eac180a29de3f8a69efca84bac046f921f5725e96a6ff0530be1436aaf", + ), + StarkCurve::from_affine_hex_string( + "0x0678a46d83bae6169163dd84af3d05de9688be3695620a3e496501bb529f36f5", + "0x00e6d1f41cd449c064ff71a1ec128be6447ed6ee52a03b43582975877b09a6c2", + ), + StarkCurve::from_affine_hex_string( + "0x07a6b0dca8e7d7f7ee32183f46f796de5d543dfe2a5428e06c40a815372eddb5", + "0x00bb53113a8464e93de7c3b0f8a9e3bfb32c49f53fbf1ef9e5860acd82ef2415", + ), + StarkCurve::from_affine_hex_string( + "0x0773cc68a7d80cabc25a5000f6445c4e06b012804e0eea2e8177cd37d1e84865", + "0x02f8b5fa66e1aa16933d18b9c7621cd1aa639c6f7655cf392e512f2e0594d8b1", + ), + StarkCurve::from_affine_hex_string( + "0x024b007862a191dc88844e852b6963087840fc1b72fe11002c77022243d4888e", + "0x050a7c81e0897e8e804d405e139eb4ff1b8d33a855f5a02f39e5197671919483", + ), + StarkCurve::from_affine_hex_string( + "0x01e25793355a7c264b72a76f4c20939ec8a6725c610b7f5999b605451d325fe7", + "0x03aefb6927c0f62dbffab880486f2a71cdd555c16e8b2ef36f401f2285862b47", + ), + StarkCurve::from_affine_hex_string( + "0x0684f9041f17388fff796fb3f57b5ed9705b8d4aa3bad58e24a0a1045f530f9f", + "0x0395d115fdd8d5d35166e7ebf31c7523d0eec45a65dd9032f0577ad0a2f09fc5", + ), + StarkCurve::from_affine_hex_string( + "0x07895d9967744712a9cd861e38618f8da67d17cd1d78b4cce6b860f6ea1b2d3d", + "0x01ae4e4f890b0f3ea412257c6056f37646018f301b33ee608401b75aa501ef26", + ), + StarkCurve::from_affine_hex_string( + "0x0376313f27d00bb1aae7ec991745efe6ee28c6b50de0c6cd9845cc4bb4f83543", + "0x06a8e0a9389ba528b156fa94ac090a895d7b795818d4941c29415d9e2984c547", + ), + StarkCurve::from_affine_hex_string( + "0x00a80380c71bd466a696b3f0fbf02817c9459d9798f4f3899cf32edf647fe066", + "0x06a09805e814e7cdfc76eba4b79f1df5ae559e0f0aba9f728d3cba4ea5c57471", + ), + StarkCurve::from_affine_hex_string( + "0x07d83445f0f78b41b4067a3fcd14f90dbae07b3bb347daa7b6f445e824a863e1", + "0x0397ccbb659be69ce74ad88fdf9ad180179217b839137627d7454f93edcacc9a", + ), + StarkCurve::from_affine_hex_string( + "0x0223694b921d247d989a79b9b2b2f07496036c40cb043eab074a9d6a2cd2ffed", + "0x00c247217f1b1df35e30d9e15fdaadf42d6fb0edd3a5a7e265d4cdc426c120aa", + ), + StarkCurve::from_affine_hex_string( + "0x0142a3df8be4e1eb4c83eefcbbb337ec4f546c0c285bcce6a7c49ae0f183cd82", + "0x00156ec9736364dd8b0af4bdc75f26a72dfc10dc3abbc7b849a66d33dde85eef", + ), + StarkCurve::from_affine_hex_string( + "0x01e077f82822eaf18acc39bb4b5160e0e26ebba7a6a1ca12f4ecf955004fa861", + "0x04288219a47286bca7c3b14264870f25e853562756afd05c4a7b8469f92f433d", + ), + StarkCurve::from_affine_hex_string( + "0x00eb141980706624ada5e79c105a6d768c2da5292f08f6bdeeb768f50f9b79d1", + "0x0239ef0bf0e450fa6e6ed302ad3a4daa900894af273748c46b3c7de13aa3cb82", + ), + StarkCurve::from_affine_hex_string( + "0x0102333620df278c6714bbc880fc087db58c1b9b4d77ed4d61b32a74bfc7c3e2", + "0x06a77d37727ccf71c2caeb151faf4404d4b94e9047f9f0a7c3966367f3b53c65", + ), + StarkCurve::from_affine_hex_string( + "0x029ebbb9c4c259059955dd95cdf957d5656764769e57b8592e1a7eedaebafb35", + "0x0153d9d2dece6117202fc0e60ef0668cd519815ebf1b0f4b1aa8fa53bdd71d18", + ), + StarkCurve::from_affine_hex_string( + "0x06880245b13e9e584f0ab92c5d49d05606f8b3699433650e130408397b4eca0d", + "0x034e409a698ee50bb1f2aa7faad94e2407693c7130dc6da9750542229b62d06c", + ), + StarkCurve::from_affine_hex_string( + "0x01dc97aa51567f0b142db18d1bd6d36d0ded26d45b0bbb5ef1e0e9826259d07a", + "0x07b0dff1adcf7cad388ef7630effae8567ed5678e7ba2830ae19921c50ce8953", + ), + StarkCurve::from_affine_hex_string( + "0x05cd4bbd716f36338c131f1338cff9ad5b5fe829ae0d9096d5ba42606b9e3e94", + "0x044cee813ce858e76a48b55e95c1f3c30be681b2b6ce6692b4c3d3918bce27bf", + ), + StarkCurve::from_affine_hex_string( + "0x02eb44c0bc24a14f69c357653d68de76400ed4d3cc124daf1fcc29bea0cdc8a7", + "0x04d4f21c3132b54a032f499890a16796be93903cc81f275651f1233ee71fe63a", + ), + StarkCurve::from_affine_hex_string( + "0x035fb9f7f9953b229c458b16ad65a9d0edd4b7ab3161f70aaf1553a156f48d87", + "0x07f600967a3250660d2b19e02eed88528b6bacbf2650e0004ff2cf00f3248fbf", + ), + StarkCurve::from_affine_hex_string( + "0x0003d6d14faab89c39e08cda4d3f8491c3d7cba7803557d37a83f7ac3faedd89", + "0x06fa536f469981e237e20898b6fd7536eaac249ae67386fcb0d0f62a97ddce62", + ), + StarkCurve::from_affine_hex_string( + "0x00891626f466536929ee7eadcd18b41925706dedab7528ed5f0f7abf039eb9d2", + "0x05f73d11c141c933a35b2d0d06e5cbae614a20d17dc3b439f8bcdc3413c5ea37", + ), + StarkCurve::from_affine_hex_string( + "0x0215c23fd3f073f870e5e80303967391bf173f8adcdbeec72d131c557babc203", + "0x010634332e9d9439a321597dc5b0fac9ff478834c3d6e281735f21a4a5e13266", + ), + StarkCurve::from_affine_hex_string( + "0x0698f29425628eaabc3a4ef3780d43cd230d3ef0eaff8964eef505d959aeef90", + "0x02072fc2e9f1c283c0fd131b8198fea44e41d79884086a6be6510dae22475177", + ), + StarkCurve::from_affine_hex_string( + "0x021ea0bdc1332bc36e6aeb43be9071651c27e4ea2eadec636c8d818d4af72a36", + "0x03a523d9643dccc6bb9c7c58413312caa3e60ba9c7c7f0177e0f3f469a3241e3", + ), + StarkCurve::from_affine_hex_string( + "0x07348a14b527af6e4ad8f5e706f7eb69f280899169fea261ffeee1d25efef0bb", + "0x05e6599a430ef13cd9d04167ad20086a1f650a00c5f71dca7a2501fb40d400de", + ), + StarkCurve::from_affine_hex_string( + "0x01a1aef5ddfca017179cc483c40bcce2c58c05e18dfee1f37aa662c6d8453476", + "0x04f959c61289dcb4a29b5e39f3d74a4ff0c9135fa3c83f4e175c6f392a16d614", + ), + StarkCurve::from_affine_hex_string( + "0x015104dd2249322cbe7e01744c30b804c51bb1aad71b88b6f1d3928d91d58c8e", + "0x0269e6543d36e448b79ac85f9fc4013df675b38e41210eaf4d47f07f1856e2ad", + ), + StarkCurve::from_affine_hex_string( + "0x060deaed1bffb6190beed40caaf2bfab5e43d3707aff7ad3f278d571aa247eae", + "0x00e41f71ff254c1418e6a66992af307789fe04d6606fb2670900bb1a089fd879", + ), + StarkCurve::from_affine_hex_string( + "0x02d1a26e2e133a7ccbe8e3484cc73d19acd7acad3502d3dc06215afc61b8910b", + "0x07ed72de5f803abf62be96c84e50cc25433cfbf450439d7140edbfcfe31982eb", + ), + StarkCurve::from_affine_hex_string( + "0x07c67de0144ffa919c8035e9959dd9eeb7e298af0b83461f66f18b31f71cbb05", + "0x032f16e957f1a6ed5eb683575851bfebc0f2a207fd5a929646af7c8c8deb65a4", + ), + StarkCurve::from_affine_hex_string( + "0x0728af9c327b86851d639f8df92adfae61b255f082c8f77e6234acac9eaae44e", + "0x04c3e6b7383fd386d7961c3e8bf8b3bca5cd32a990f17774fcc63032c4b346d2", + ), + StarkCurve::from_affine_hex_string( + "0x00121121aa2867bbcb260d035a5388ae4bcaaaa68a99e82d2aa58a4cbc631b5d", + "0x065611da2bd673b9d1bde2004586d3c308427825602be53b4d44f4680280c532", + ), + StarkCurve::from_affine_hex_string( + "0x017f4b0609b8b376f283f8683afd66abc94c5f06fcc4e9cd9f49508f5a7cf0a8", + "0x019ccbd820dbf69b50c7b524b380d2ba96e68fddcd71a57193c99a8536f2af0e", + ), + StarkCurve::from_affine_hex_string( + "0x0550e5ad076f4b9ef07336c5e5d2807d04598a62b74dfc5943fe71032fc1b4ec", + "0x024932ae07ee6996ab9c277b748e6158b6bb0a2e12aeb1262d81ed0bf85c3f56", + ), + StarkCurve::from_affine_hex_string( + "0x03b4a38a1b12a2ea9aab01e1cd698cc14a0f3f07635138a731c40da8db8ea2bf", + "0x07e7c92ebc93a9e355f70dd7dd4f5a13001249daf80ce2083496fc364d6ed72a", + ), + StarkCurve::from_affine_hex_string( + "0x01e1fac4a1646253fb1332fadc21fbdd3e3a24a840d129400f520ae4116a4cf5", + "0x069c406f9f46576afad68808de0ab7e8922b6226af748e721d9097e21f1800f3", + ), + StarkCurve::from_affine_hex_string( + "0x05db0ddcdf79ffe74d6454c12d2bc60b06776db03c75dc413f5be42ea9a91b5e", + "0x0134c3d6c699841f17306835bb193785228ffe7ab212a01a861c56b086a18cec", + ), + StarkCurve::from_affine_hex_string( + "0x053f2dded21057b8d6715c0fbe18fb7295b9c3795fb5267ecb1a7345faef498c", + "0x05d098198a7ed3b31aa978e43d227edf64175b8f4111b5c8825140d309b3a592", + ), + StarkCurve::from_affine_hex_string( + "0x0626814e320fb5bea505b248fd1c1389ad586c1cfe04923fe2f83173e915f4f8", + "0x07ae407a926e887206a8b85cf485f1f327c9bb8ccbb6897024e2d122877d8ee0", + ), + StarkCurve::from_affine_hex_string( + "0x022481d73d948702b1d11f662cbefe5005c2e17fc3ec9419c8e881b867626d9d", + "0x0420d41966fd0c27edb72d1c5eb9097694fec7d18039098b0e87e5fbb158e24f", + ), + StarkCurve::from_affine_hex_string( + "0x02688070f09c9725c2578819c5a49b47cc024cb45e63f2d4cabc5d926038fcc2", + "0x017beab7c707c79b047441389fdff6d4872e74359bc1da247140de9fc03375a9", + ), + StarkCurve::from_affine_hex_string( + "0x016a69a7cf1f65594afadb02879b3e794748daccd696a1735b2d34122af395d6", + "0x04dd0e24a1432070a39ebc7fd27260b6ea21468e9a90a3116103c4ece6e777d9", + ), + StarkCurve::from_affine_hex_string( + "0x0023186237dc7d3b570cea645282ad4c359731bbfa54e7f036426bf6493812cd", + "0x07d1fbab7e61a22d3b00993290d9f4cd5d820061573e787f66c2cff9a18e1eaf", + ), + StarkCurve::from_affine_hex_string( + "0x054442669b321b67eecc04ac0d44eb106e94eec55f884743853da112306db35d", + "0x079e135fc490bde123cfb435a5623d5a91267bb78af42e7c36bb7b4f1e8738a6", + ), + StarkCurve::from_affine_hex_string( + "0x0208ada8917dbbaa4fd47860342d88e2ea48f9ad8496245e823195c503c9e591", + "0x043449048fcb48958593754d47444c8006ade78bb3653620184e587357b0876b", + ), + StarkCurve::from_affine_hex_string( + "0x02e34ab0e42003b89aa2eddc291984690086e2b2ccd9652d7a3a963031d27cbd", + "0x034112f9bed212363cb62d8dabcb64d42e07239aef78be28cc4b6df8df33952b", + ), + StarkCurve::from_affine_hex_string( + "0x02d7d88f58ff5a901f89e893920f3fafa5ed0bad3e26c981be99f7297c7364a3", + "0x0527edc567207eb33cb94b0a28ae240cc9e482f8282f635e15400706a72dd283", + ), + StarkCurve::from_affine_hex_string( + "0x04a17894569ea9902cd0a985f500120364bddb3a34642b1429a9fff6d8ed7f77", + "0x02234e91e011d378154fe23ce94700b19bca1ccb6b2f979d302ad72eef531bc1", + ), + StarkCurve::from_affine_hex_string( + "0x04c0615b6ccfe7165a1ff4990bb52a5ac593a93b7f7d5523ed9e78d1cfeb1983", + "0x0230006751153f0a50c375d114dff3a493a8c09f524687a7abbbc6457c918bef", + ), + StarkCurve::from_affine_hex_string( + "0x00053a33f7ab1686308771229bc41f2e8da1bf6ce7262f73a95fcc4d7570543e", + "0x02843c0ad3ca1580d0d26099e81222946e8d1a0551dcfff5b097db60483ebcf3", + ), + ] +} + +pub const fn points_p4() -> [ShortWeierstrassProjectivePoint; 15] { + [ + StarkCurve::from_affine_hex_string( + "0x054302dcb0e6cc1c6e44cca8f61a63bb2ca65048d53fb325d36ff12c49a58202", + "0x01b77b3e37d13504b348046268d8ae25ce98ad783c25561a879dcc77e99c2426", + ), + StarkCurve::from_affine_hex_string( + "0x013961b56b9fc0e412e468c385c22bd0680a25624ec211ffbb6bc877b2a6926c", + "0x062f7f7792c77cd981fad13cb6863fe099c4d971c1374109185eae99943f16e9", + ), + StarkCurve::from_affine_hex_string( + "0x075d976d5ff2a1d52c24a9ec8ed35ba60bbf630716b3bfbce6954f3fcb9dfa87", + "0x0250632783922466251dd6abef2544ea22f5a89b2e97d0c53408a0ff0f45c595", + ), + StarkCurve::from_affine_hex_string( + "0x047abd7308c70659af3f00fafe6837298af3cb530b6c2ba710ffd07a6bc1ae98", + "0x075d0c8a7377aa9f0663d0c124a5659750847afabc29e39893fd27534a4a03cb", + ), + StarkCurve::from_affine_hex_string( + "0x079e6dd2bb4e7ca86d651d69277c8ba45dcb0081e28946933c1624f33b43c297", + "0x03da084b3dd2e894cbd3a95cfd0d3ce98dd3d679bbafbeef0359b192a658b782", + ), + StarkCurve::from_affine_hex_string( + "0x04b0af87863a15652fe3e0c7a9318f91ccac4dd1d7eb766be4769093cd5ef21a", + "0x0644cc5a94960f1aefd34fe3a75c19b5df4d690bff6e76f1122ac429b29e8e5a", + ), + StarkCurve::from_affine_hex_string( + "0x0576bd6a9723bcdac5ae9423c82a3a7306dd8ee518b585886c31dbc5cbc7ee73", + "0x00a711ed74dde7ecd3ef8f81909ea1c1072af38e2729cd088c2e286f65e85d2d", + ), + StarkCurve::from_affine_hex_string( + "0x02c6276b764fb398fa555857dbe0ce0ec18fab7a233bf23851295739801f0585", + "0x05d8f4897ce44007ec5bfcb9aeb78b8f6e1d40a514f72d213c9300d2770d2b8c", + ), + StarkCurve::from_affine_hex_string( + "0x012d65f3000d0a98cc3d172fb031a07aa63f391709b211e5c38147dfacfe71c5", + "0x05e94d3f940a0601f57fbe70ac424b62a6aa6af065d82b9394cd909a39630fa3", + ), + StarkCurve::from_affine_hex_string( + "0x009628a2d5078181628e2a6e7214f432ab6ad06d7446568e1d0e1f7eeafdad15", + "0x03812de62dcbf40d0fc38b3c22da6978132840c3336d9724dace26a91c61467b", + ), + StarkCurve::from_affine_hex_string( + "0x05fef03c9ba206f38c70829708e17a04052a699db2bbed270d3b9f641044b3e6", + "0x034a81caa74de5e03554f0feee581fbec57f3cb99b336a6b0b7121998947770d", + ), + StarkCurve::from_affine_hex_string( + "0x062423050232c4818bd34bbdb4a8127899655dfb1dae2172bccb278a7c3a0b11", + "0x065b076c15d5b8f7f24eb25f46b8147e6384f9a28a957e77a5bc1e55bcd31c37", + ), + StarkCurve::from_affine_hex_string( + "0x04aa4c2a719175731431d916ceaf28d3386a4cd73a8fcad057c0fa95b5803580", + "0x037ba35dc893cd7909f28c9c0965e0029ecb3dfcaa2bc1509e5eebf984112c7f", + ), + StarkCurve::from_affine_hex_string( + "0x0356d8851b470a0b475f5e637bd7435cb794acf1856dc37f61fc80a540861229", + "0x0001be1102267114ad5e85097e7e282a459707d4f1a7969587b59b692aa64fa6", + ), + StarkCurve::from_affine_hex_string( + "0x049d7273e1dc085a9a502054d8c627268faad04bee9d554e8bc826487c0ee020", + "0x0283007adf98c5aa81d8dc112ec0e71cf97cc63a83887ac46cfa56bcdc6454bc", + ), + ] +} diff --git a/crypto/src/hash/pedersen/mod.rs b/crypto/src/hash/pedersen/mod.rs new file mode 100644 index 0000000000..507f3b20c1 --- /dev/null +++ b/crypto/src/hash/pedersen/mod.rs @@ -0,0 +1,114 @@ +use lambdaworks_math::{ + cyclic_group::IsGroup, + elliptic_curve::short_weierstrass::{ + curves::stark_curve::StarkCurve, point::ShortWeierstrassProjectivePoint, + }, + field::{ + element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, + }, +}; + +mod constants; +mod parameters; +use self::parameters::PedersenParameters; + +pub struct Pedersen { + params: PedersenParameters, +} + +impl Default for Pedersen { + fn default() -> Self { + let pedersen_stark_default_params = PedersenParameters::default(); + Self::new_with_params(pedersen_stark_default_params) + } +} + +impl Pedersen { + pub fn new_with_params(params: PedersenParameters) -> Self { + Self { params } + } + + // Taken from Jonathan Lei's starknet-rs + // https://github.com/xJonathanLEI/starknet-rs/blob/4ab2f36872435ce57b1d8f55856702a6a30f270a/starknet-crypto/src/pedersen_hash.rs + + /// Implements Starkware version of Pedersen hash of x and y. + /// Divides each of x and y into 4-bit chunks, and uses lookup tables to accumulate pre-calculated + /// points corresponding to a given chunk. + /// Accumulation starts from a "shift_point" whose points are derived from digits of pi. + /// Pre-calculated points are multiples by powers of 2 of the "shift_point". + /// + /// Find specification at https://docs.starkware.co/starkex/crypto/pedersen-hash-function.html + pub fn hash( + &self, + x: &FieldElement, + y: &FieldElement, + ) -> FieldElement { + let x = x.to_bits_le(); + let y = y.to_bits_le(); + let mut acc = self.params.shift_point.clone(); + + self.lookup_and_accumulate(&mut acc, &x[..248], &self.params.points_p1); // Add a_low * P1 + self.lookup_and_accumulate(&mut acc, &x[248..252], &self.params.points_p2); // Add a_high * P2 + self.lookup_and_accumulate(&mut acc, &y[..248], &self.params.points_p3); // Add b_low * P3 + self.lookup_and_accumulate(&mut acc, &y[248..252], &self.params.points_p4); // Add b_high * P4 + + *acc.to_affine().x() + } + + /// Performs lookup to find the constant point corresponding to 4-bit chunks of given input. + /// Keeps adding up those points to the given accumulation point. + fn lookup_and_accumulate( + &self, + acc: &mut ShortWeierstrassProjectivePoint, + bits: &[bool], + prep: &[ShortWeierstrassProjectivePoint], + ) { + bits.chunks(self.params.curve_const_bits) + .enumerate() + .for_each(|(i, v)| { + let offset = bools_to_usize_le(v); + if offset > 0 { + // Table lookup at 'offset-1' in table for chunk 'i' + *acc = acc.operate_with(&prep[i * self.params.table_size + offset - 1]); + } + }) + } +} + +#[inline] +fn bools_to_usize_le(bools: &[bool]) -> usize { + let mut result: usize = 0; + for (ind, bit) in bools.iter().enumerate() { + if *bit { + result += 1 << ind; + } + } + result +} + +#[cfg(test)] +mod tests { + use super::*; + + // Test case ported from: + // https://github.com/starkware-libs/crypto-cpp/blob/95864fbe11d5287e345432dbe1e80dea3c35fc58/src/starkware/crypto/ffi/crypto_lib_test.go + + #[test] + fn test_stark_curve() { + let pedersen = Pedersen::default(); + + let x = FieldElement::::from_hex_unchecked( + "03d937c035c878245caf64531a5756109c53068da139362728feb561405371cb", + ); + let y = FieldElement::::from_hex_unchecked( + "0208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a", + ); + let hash = pedersen.hash(&x, &y); + assert_eq!( + hash, + FieldElement::::from_hex_unchecked( + "030e480bed5fe53fa909cc0f8c4d99b8f9f2c016be4c41e13a4848797979c662" + ) + ); + } +} diff --git a/crypto/src/hash/pedersen/parameters.rs b/crypto/src/hash/pedersen/parameters.rs new file mode 100644 index 0000000000..6558d4d689 --- /dev/null +++ b/crypto/src/hash/pedersen/parameters.rs @@ -0,0 +1,36 @@ +use lambdaworks_math::elliptic_curve::short_weierstrass::{ + curves::stark_curve::StarkCurve, point::ShortWeierstrassProjectivePoint, +}; + +use crate::hash::pedersen::constants::*; + +pub struct PedersenParameters { + pub curve_const_bits: usize, + pub table_size: usize, + pub shift_point: ShortWeierstrassProjectivePoint, + pub points_p1: [ShortWeierstrassProjectivePoint; 930], + pub points_p2: [ShortWeierstrassProjectivePoint; 15], + pub points_p3: [ShortWeierstrassProjectivePoint; 930], + pub points_p4: [ShortWeierstrassProjectivePoint; 15], +} + +impl Default for PedersenParameters { + fn default() -> Self { + Self::new() + } +} + +impl PedersenParameters { + pub fn new() -> Self { + let curve_const_bits = 4; + Self { + curve_const_bits, + table_size: (1 << curve_const_bits) - 1, + shift_point: shift_point(), + points_p1: points_p1(), + points_p2: points_p2(), + points_p3: points_p3(), + points_p4: points_p4(), + } + } +} diff --git a/math/src/elliptic_curve/point.rs b/math/src/elliptic_curve/point.rs index b7c04f3553..e4824aac7b 100644 --- a/math/src/elliptic_curve/point.rs +++ b/math/src/elliptic_curve/point.rs @@ -12,7 +12,7 @@ pub struct ProjectivePoint { impl ProjectivePoint { /// Creates an elliptic curve point giving the projective [x: y: z] coordinates. - pub fn new(value: [FieldElement; 3]) -> Self { + pub const fn new(value: [FieldElement; 3]) -> Self { Self { value } } diff --git a/math/src/elliptic_curve/short_weierstrass/curves/mod.rs b/math/src/elliptic_curve/short_weierstrass/curves/mod.rs index 8884f28e01..9c53071b27 100644 --- a/math/src/elliptic_curve/short_weierstrass/curves/mod.rs +++ b/math/src/elliptic_curve/short_weierstrass/curves/mod.rs @@ -1,4 +1,5 @@ pub mod bls12_377; pub mod bls12_381; +pub mod stark_curve; pub mod test_curve_1; pub mod test_curve_2; diff --git a/math/src/elliptic_curve/short_weierstrass/curves/stark_curve.rs b/math/src/elliptic_curve/short_weierstrass/curves/stark_curve.rs new file mode 100644 index 0000000000..c006e36825 --- /dev/null +++ b/math/src/elliptic_curve/short_weierstrass/curves/stark_curve.rs @@ -0,0 +1,54 @@ +use crate::{ + elliptic_curve::{ + short_weierstrass::{point::ShortWeierstrassProjectivePoint, traits::IsShortWeierstrass}, + traits::IsEllipticCurve, + }, + field::{ + element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, + }, +}; + +#[derive(Clone, Debug)] +pub struct StarkCurve; + +impl StarkCurve { + pub const fn from_affine_hex_string( + x_hex: &str, + y_hex: &str, + ) -> ShortWeierstrassProjectivePoint { + ShortWeierstrassProjectivePoint::new([ + FieldElement::::from_hex_unchecked(x_hex), + FieldElement::::from_hex_unchecked(y_hex), + FieldElement::::from_hex_unchecked("1"), + ]) + } +} + +impl IsEllipticCurve for StarkCurve { + type BaseField = Stark252PrimeField; + type PointRepresentation = ShortWeierstrassProjectivePoint; + + fn generator() -> Self::PointRepresentation { + Self::PointRepresentation::new([ + FieldElement::::from_hex_unchecked( + "1EF15C18599971B7BECED415A40F0C7DEACFD9B0D1819E03D723D8BC943CFCA", + ), + FieldElement::::from_hex_unchecked( + "5668060AA49730B7BE4801DF46EC62DE53ECD11ABE43A32873000C36E8DC1F", + ), + FieldElement::one(), + ]) + } +} + +impl IsShortWeierstrass for StarkCurve { + fn a() -> FieldElement { + FieldElement::::from_hex_unchecked("1") + } + + fn b() -> FieldElement { + FieldElement::::from_hex_unchecked( + "6F21413EFBE40DE150E596D72F7A8C5609AD26C15C915C1F4CDFCB99CEE9E89", + ) + } +} diff --git a/math/src/elliptic_curve/short_weierstrass/point.rs b/math/src/elliptic_curve/short_weierstrass/point.rs index 480a22b851..2275fe9f2e 100644 --- a/math/src/elliptic_curve/short_weierstrass/point.rs +++ b/math/src/elliptic_curve/short_weierstrass/point.rs @@ -16,7 +16,7 @@ pub struct ShortWeierstrassProjectivePoint(pub ProjectivePoi impl ShortWeierstrassProjectivePoint { /// Creates an elliptic curve point giving the projective [x: y: z] coordinates. - pub fn new(value: [FieldElement; 3]) -> Self { + pub const fn new(value: [FieldElement; 3]) -> Self { Self(ProjectivePoint::new(value)) } diff --git a/math/src/field/fields/fft_friendly/stark_252_prime_field.rs b/math/src/field/fields/fft_friendly/stark_252_prime_field.rs index 0703a97f6c..7f0fb6c43c 100644 --- a/math/src/field/fields/fft_friendly/stark_252_prime_field.rs +++ b/math/src/field/fields/fft_friendly/stark_252_prime_field.rs @@ -46,6 +46,26 @@ impl FieldElement { bytes } + /// This follows the convention used by starknet-rs + pub fn to_bits_le(&self) -> [bool; 256] { + let limbs = self.representative().limbs; + let mut bits = [false; 256]; + + for i in (0..4).rev() { + let limb_bytes = limbs[i].to_le_bytes(); + let limb_bytes_starting_index = (3 - i) * 8; + for (j, byte) in limb_bytes.iter().enumerate() { + let byte_index = (limb_bytes_starting_index + j) * 8; + for k in 0..8 { + let bit_index = byte_index + k; + let bit_value = (byte >> k) & 1 == 1; + bits[bit_index] = bit_value; + } + } + } + bits + } + /// No std version of `to_bytes_be` from `ByteConversion` trait /// This follows the convention used by /// Starkware and Lambdaclass Cairo VM It's the same as ByteConversion to_bytes_be. From 780b7ddcdc5b427a71b78c519404f9879376ef04 Mon Sep 17 00:00:00 2001 From: Mauro Toscano <12560266+MauroToscano@users.noreply.github.com> Date: Tue, 17 Oct 2023 10:47:32 -0300 Subject: [PATCH 12/18] Addition fuzzer for Stark Field (#601) * Add fuzzer * Remove artifacts --------- Co-authored-by: Mariano A. Nicolini --- .gitignore | 1 + fuzz/no_gpu_fuzz/Cargo.toml | 7 ++++ .../fuzz_targets/stark_field_addition.rs | 37 +++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 fuzz/no_gpu_fuzz/fuzz_targets/stark_field_addition.rs diff --git a/.gitignore b/.gitignore index 4e203d72b1..3f04df90cf 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ proving_system/stark/src/cairo_run/program.trace ensure-no_std/target # Files from fuzzers are inside a corpus folder **/corpus/** +**/artifacts/** diff --git a/fuzz/no_gpu_fuzz/Cargo.toml b/fuzz/no_gpu_fuzz/Cargo.toml index 0d0096a614..69cb2cc84e 100644 --- a/fuzz/no_gpu_fuzz/Cargo.toml +++ b/fuzz/no_gpu_fuzz/Cargo.toml @@ -33,6 +33,13 @@ path = "fuzz_targets/field_from_raw.rs" test = false doc = false +[[bin]] +name = "stark_field_addition" +path = "fuzz_targets/stark_field_addition.rs" +test = false +doc = false + + [[bin]] name = "deserialize_stark_proof" path = "fuzz_targets/deserialize_stark_proof.rs" diff --git a/fuzz/no_gpu_fuzz/fuzz_targets/stark_field_addition.rs b/fuzz/no_gpu_fuzz/fuzz_targets/stark_field_addition.rs new file mode 100644 index 0000000000..f2c35f682b --- /dev/null +++ b/fuzz/no_gpu_fuzz/fuzz_targets/stark_field_addition.rs @@ -0,0 +1,37 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use lambdaworks_math::field::{ + element::FieldElement, + fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, +}; + +use lambdaworks_math::traits::ByteConversion; + +type FE = FieldElement; + +use ibig::{modular::ModuloRing, UBig}; + +fuzz_target!(|bytes: ([u8;32], [u8;32])| { + let (bytes_a, bytes_b) = bytes; + let a = FE::from_bytes_be(&bytes_a).unwrap(); + let b = FE::from_bytes_be(&bytes_b).unwrap(); + + let a_hex = a.representative().to_string()[2..].to_string(); + let b_hex = b.representative().to_string()[2..].to_string(); + + let c = a + &b; + let c_hex = c.representative().to_string()[2..].to_string(); + + let prime = + UBig::from_str_radix("800000000000011000000000000000000000000000000000000000000000001", 16).unwrap(); + let cairo_ring = ModuloRing::new(&prime); + + let a_ring = cairo_ring.from(&UBig::from_str_radix(&a_hex, 16).unwrap()); + let b_ring = cairo_ring.from(&UBig::from_str_radix(&b_hex, 16).unwrap()); + let expected_c = a_ring + &b_ring; + let expected_c_hex = expected_c.residue().in_radix(16).to_string(); + + assert_eq!(expected_c_hex, c_hex); +}); + From a1f2fa7ad06eb85536a1b0852542a815b0f80b3c Mon Sep 17 00:00:00 2001 From: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Date: Tue, 17 Oct 2023 15:39:36 -0300 Subject: [PATCH 13/18] Stark: Stone prover compatibility end to end for Fibonacci AIR (#596) * add test * make trace commitment SHARP compatible * wip * use powers of a single challenge for the boundary and transition coefficients * add permutation to match sharp compatible commitments on the trace * change trait bound from ByteConversion to Serializable * minor refactor * fmt, clippy * move std feature to inner trait function in Serializable * add IsStarkProver and IsStarkVerifier traits * proof of concept * composition poly breaker * WIP: commitment composition poly works. Opens are broken. * WIP Refactor open_trace_polys and open_composition_poly * Refactor sample iotas * Refactor sample iotas * make fri a trait * change trace ood evaluations in transcript * wip * sample gammas as power of a single challenge * fix z fri sampling * wip * wip * wip, broken * Compiles but fibonacci_5 does not work * Opens of query phase and OOD broken. Commit phase of FRI works. * Dont append to the transcript when grinding factor is zero * skip grinding factor when security bits is zero * remove permutation function * fmt * fix standard verifier * removes deep consistency check and openings of the first layer of fri for each query * SHARP computes the trace and composition polynomial openings and their symmetric elements consistently * Test symmetric elements in trace openings to compute deep composition polynomial * Composition polynomial opening evaluations are splitted between symmetric and not. The authentication paths remain equal * check openings in symmetric elements * make verifier sharp compatible * compute number of parts * fix verify fri for original prover * fix verify sym in stone prover * rename * rename file * wip * remove unnecessary variable * wip * move verifier * move fri * fix open * move stone to prover * remove file * fmt * clippy * clippy * remove redundant trait bounds * remove custom serialization/deserialization and replace it with serde_cbor * fmt * clippy * remove old files after merge from main * fmt * make field a type of IsStarkVerifier * remove frame serialization * separate compatibility test into individual tests * remove redundant test * add test case 2 * minor refactor. add docs * minor refactor * remove unnecessary method * revert unintended changes to exercises * clippy * remove isFri trait * move Prover definition to the top of the file * update docs and add unit test * minor refactors. clippy * remove unused trait method * Move function only used for tests, to tests --------- Co-authored-by: Agustin Co-authored-by: MauroFab --- exercises/message/src/starks/verifier.rs | 2 +- math/src/fft/cpu/bit_reversing.rs | 8 +- math/src/polynomial.rs | 49 +- provers/cairo-prover-cli/Cargo.toml | 1 + provers/cairo-prover-cli/src/main.rs | 5 +- provers/cairo/Cargo.toml | 4 +- provers/cairo/benches/criterion_verifier.rs | 3 +- .../cairo/benches/criterion_verifier_70k.rs | 3 +- provers/cairo/src/air.rs | 53 +- provers/cairo/src/tests/integration_tests.rs | 40 +- provers/stark/Cargo.toml | 4 +- provers/stark/src/constraints/evaluator.rs | 5 +- provers/stark/src/domain.rs | 2 - provers/stark/src/frame.rs | 115 - provers/stark/src/fri/fri_commitment.rs | 28 +- provers/stark/src/fri/fri_decommit.rs | 232 +- provers/stark/src/fri/mod.rs | 94 +- provers/stark/src/proof/stark.rs | 699 +----- provers/stark/src/prover.rs | 1955 ++++++++++------- provers/stark/src/tests/integration_tests.rs | 79 +- provers/stark/src/verifier.rs | 1271 ++++++----- 21 files changed, 2054 insertions(+), 2598 deletions(-) diff --git a/exercises/message/src/starks/verifier.rs b/exercises/message/src/starks/verifier.rs index a23e62ef12..ab631ff0ca 100644 --- a/exercises/message/src/starks/verifier.rs +++ b/exercises/message/src/starks/verifier.rs @@ -605,7 +605,7 @@ where let timer4 = Instant::now(); #[allow(clippy::let_and_return)] - if !step_4_verify_deep_composition_polynomial(&air, proof, &domain, &challenges) { + if !step_4_verify_deep_composition_polynomial(&air, proof, &challenges) { error!("DEEP Composition Polynomial verification failed"); return false; } diff --git a/math/src/fft/cpu/bit_reversing.rs b/math/src/fft/cpu/bit_reversing.rs index 139bf615a0..68eb73427a 100644 --- a/math/src/fft/cpu/bit_reversing.rs +++ b/math/src/fft/cpu/bit_reversing.rs @@ -1,7 +1,7 @@ /// In-place bit-reverse permutation algorithm. Requires input length to be a power of two. pub fn in_place_bit_reverse_permute(input: &mut [E]) { for i in 0..input.len() { - let bit_reversed_index = reverse_index(&i, input.len() as u64); + let bit_reversed_index = reverse_index(i, input.len() as u64); if bit_reversed_index > i { input.swap(i, bit_reversed_index); } @@ -9,9 +9,9 @@ pub fn in_place_bit_reverse_permute(input: &mut [E]) { } /// Reverses the `log2(size)` first bits of `i` -pub fn reverse_index(i: &usize, size: u64) -> usize { +pub fn reverse_index(i: usize, size: u64) -> usize { if size == 1 { - *i + i } else { i.reverse_bits() >> (usize::BITS - size.trailing_zeros()) } @@ -26,7 +26,7 @@ mod test { fn bit_reverse_permutation_works() { let mut reversed: Vec = Vec::with_capacity(16); for i in 0..reversed.capacity() { - reversed.push(reverse_index(&i, reversed.capacity() as u64)); + reversed.push(reverse_index(i, reversed.capacity() as u64)); } assert_eq!( reversed[..], diff --git a/math/src/polynomial.rs b/math/src/polynomial.rs index 34580ec2df..940e49cfc8 100644 --- a/math/src/polynomial.rs +++ b/math/src/polynomial.rs @@ -227,27 +227,24 @@ impl Polynomial> { } } - /// For the given polynomial, returns a tuple `(even, odd)` of polynomials - /// with the even and odd coefficients respectively. - /// Note that `even` and `odd` ARE NOT actually even/odd polynomials themselves. + /// Returns a vector of polynomials [pβ‚€, p₁, ..., p_{d-1}], where d is `number_of_parts`, such that `self` equals + /// pβ‚€(Xᡈ) + Xp₁(Xᡈ) + ... + X^(d-1)p_{d-1}(Xᡈ). /// - /// Example: if poly = 3 X^3 + X^2 + 2X + 1, then - /// `poly.even_odd_decomposition = (even, odd)` with - /// `even` = X + 1 and `odd` = 3X + 1. - /// - /// In general, the decomposition satisfies the following: - /// `poly(x)` = `even(x^2)` + X * `odd(x^2)` - pub fn even_odd_decomposition(&self) -> (Self, Self) { + /// Example: if d = 2 and `self` is 3 X^3 + X^2 + 2X + 1, then `poly.break_in_parts(2)` + /// returns a vector with two polynomials `(pβ‚€, p₁)`, where pβ‚€ = X + 1 and p₁ = 3X + 2. + pub fn break_in_parts(&self, number_of_parts: usize) -> Vec { let coef = self.coefficients(); - let even_coef: Vec> = coef.iter().step_by(2).cloned().collect(); - - // odd coeficients of poly are multiplied by beta - let odd_coef: Vec> = coef.iter().skip(1).step_by(2).cloned().collect(); - - Polynomial::pad_with_zero_coefficients( - &Polynomial::new(&even_coef), - &Polynomial::new(&odd_coef), - ) + let mut parts: Vec = Vec::with_capacity(number_of_parts); + for i in 0..number_of_parts { + let coeffs: Vec<_> = coef + .iter() + .skip(i) + .step_by(number_of_parts) + .cloned() + .collect(); + parts.push(Polynomial::new(&coeffs)); + } + parts } } @@ -895,6 +892,20 @@ mod tests { ); } + #[test] + fn break_in_parts() { + // p = 3 X^3 + X^2 + 2X + 1 + let p = Polynomial::new(&[FE::new(1), FE::new(2), FE::new(1), FE::new(3)]); + let p0_expected = Polynomial::new(&[FE::new(1), FE::new(1)]); + let p1_expected = Polynomial::new(&[FE::new(2), FE::new(3)]); + let parts = p.break_in_parts(2); + assert_eq!(parts.len(), 2); + let p0 = &parts[0]; + let p1 = &parts[1]; + assert_eq!(p0, &p0_expected); + assert_eq!(p1, &p1_expected); + } + use proptest::prelude::*; proptest! { #[test] diff --git a/provers/cairo-prover-cli/Cargo.toml b/provers/cairo-prover-cli/Cargo.toml index f1f391e2e1..75ab6fcbcf 100644 --- a/provers/cairo-prover-cli/Cargo.toml +++ b/provers/cairo-prover-cli/Cargo.toml @@ -10,6 +10,7 @@ name = "cairo-platinum-prover-cli" path = "src/main.rs" [dependencies] +serde_cbor = { version = "0.11.1"} lambdaworks-math = { workspace = true , features = ["lambdaworks-serde"] } stark-platinum-prover = { workspace = true, features = ["wasm"] } cairo-platinum-prover = { workspace = true} diff --git a/provers/cairo-prover-cli/src/main.rs b/provers/cairo-prover-cli/src/main.rs index 35ab08794e..14273700ca 100644 --- a/provers/cairo-prover-cli/src/main.rs +++ b/provers/cairo-prover-cli/src/main.rs @@ -117,7 +117,7 @@ fn main() { }; let mut bytes = vec![]; - let proof_bytes = proof.serialize(); + let proof_bytes: Vec = serde_cbor::to_vec(&proof).unwrap(); bytes.extend(proof_bytes.len().to_be_bytes()); bytes.extend(proof_bytes); bytes.extend(pub_inputs.serialize()); @@ -145,8 +145,7 @@ fn main() { println!("Error reading proof from file: {}", args.proof_path); return; } - let Ok(proof) = StarkProof::::deserialize(&bytes[0..proof_len]) - else { + let Ok(proof) = serde_cbor::from_slice(&bytes[0..proof_len]) else { println!("Error reading proof from file: {}", args.proof_path); return; }; diff --git a/provers/cairo/Cargo.toml b/provers/cairo/Cargo.toml index 8b16793007..0ccd0960bf 100644 --- a/provers/cairo/Cargo.toml +++ b/provers/cairo/Cargo.toml @@ -33,7 +33,7 @@ rayon = { version = "1.7.0", optional = true } wasm-bindgen = { version = "0.2", optional = true } serde-wasm-bindgen = { version = "0.5", optional = true } web-sys = { version = "0.3.64", features = ['console'], optional = true } -serde_cbor = { version = "0.11.1", optional = true } +serde_cbor = { version = "0.11.1"} [dev-dependencies] hex = "0.4.3" @@ -50,7 +50,7 @@ test_fiat_shamir = [] instruments = [] # This enables timing prints in prover and verifier metal = ["lambdaworks-math/metal"] parallel = ["dep:rayon"] -wasm = ["dep:wasm-bindgen", "dep:serde-wasm-bindgen", "dep:web-sys", "dep:serde_cbor"] +wasm = ["dep:wasm-bindgen", "dep:serde-wasm-bindgen", "dep:web-sys"] [target.'cfg(not(all(target_arch = "wasm32", target_os = "unknown")))'.dev-dependencies] proptest = "1.2.0" diff --git a/provers/cairo/benches/criterion_verifier.rs b/provers/cairo/benches/criterion_verifier.rs index 396d5264d8..999b3ced46 100644 --- a/provers/cairo/benches/criterion_verifier.rs +++ b/provers/cairo/benches/criterion_verifier.rs @@ -17,7 +17,8 @@ fn load_proof_and_pub_inputs(input_path: &str) -> (StarkProof::deserialize(&bytes[0..proof_len]).unwrap(); + let proof: StarkProof = + serde_cbor::from_slice(&bytes[0..proof_len]).unwrap(); bytes = &bytes[proof_len..]; let public_inputs = PublicInputs::deserialize(bytes).unwrap(); diff --git a/provers/cairo/benches/criterion_verifier_70k.rs b/provers/cairo/benches/criterion_verifier_70k.rs index bd9034c14c..8a279da19f 100644 --- a/provers/cairo/benches/criterion_verifier_70k.rs +++ b/provers/cairo/benches/criterion_verifier_70k.rs @@ -18,7 +18,8 @@ fn load_proof_and_pub_inputs(input_path: &str) -> (StarkProof::deserialize(&bytes[0..proof_len]).unwrap(); + let proof: StarkProof = + serde_cbor::from_slice(&bytes[0..proof_len]).unwrap(); bytes = &bytes[proof_len..]; let public_inputs = PublicInputs::deserialize(bytes).unwrap(); diff --git a/provers/cairo/src/air.rs b/provers/cairo/src/air.rs index 9be92f4399..3210f6221f 100644 --- a/provers/cairo/src/air.rs +++ b/provers/cairo/src/air.rs @@ -13,11 +13,11 @@ use stark_platinum_prover::{ context::AirContext, frame::Frame, proof::{options::ProofOptions, stark::StarkProof}, - prover::{prove, ProvingError}, + prover::{IsStarkProver, Prover, ProvingError}, trace::TraceTable, traits::AIR, transcript::{IsStarkTranscript, StoneProverTranscript}, - verifier::verify, + verifier::{IsStarkVerifier, Verifier}, }; use crate::Felt252; @@ -1254,7 +1254,7 @@ pub fn generate_cairo_proof( pub_input: &PublicInputs, proof_options: &ProofOptions, ) -> Result, ProvingError> { - prove::( + Prover::prove::( trace, pub_input, proof_options, @@ -1270,7 +1270,7 @@ pub fn verify_cairo_proof( pub_input: &PublicInputs, proof_options: &ProofOptions, ) -> bool { - verify::( + Verifier::verify::( proof, pub_input, proof_options, @@ -1567,7 +1567,6 @@ mod test { #[cfg(test)] mod prop_test { use lambdaworks_math::{ - errors::DeserializationError, field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, traits::{Deserializable, Serializable}, }; @@ -1652,7 +1651,7 @@ mod prop_test { // The proof is generated and serialized. let proof = generate_cairo_proof(&main_trace, &pub_inputs, &proof_options).unwrap(); - let proof_bytes = proof.serialize(); + let proof_bytes: Vec = serde_cbor::to_vec(&proof).unwrap(); // The trace and original proof are dropped to show that they are decoupled from // the verifying process. @@ -1661,49 +1660,9 @@ mod prop_test { // At this point, the verifier only knows about the serialized proof, the proof options // and the public inputs. - let proof = StarkProof::::deserialize(&proof_bytes).unwrap(); + let proof: StarkProof = serde_cbor::from_slice(&proof_bytes).unwrap(); // The proof is verified successfully. assert!(verify_cairo_proof(&proof, &pub_inputs, &proof_options)); } - - #[test] - fn deserialize_should_not_panic_with_changed_and_sliced_bytes() { - let program_content = std::fs::read(cairo0_program_path("fibonacci_10.json")).unwrap(); - let (main_trace, pub_inputs) = - generate_prover_args(&program_content, &None, CairoLayout::Plain).unwrap(); - - let proof_options = ProofOptions::default_test_options(); - - // The proof is generated and serialized. - let proof = generate_cairo_proof(&main_trace, &pub_inputs, &proof_options).unwrap(); - let mut proof_bytes = proof.serialize(); - - // The trace and original proof are dropped to show that they are decoupled from - // the verifying process. - drop(main_trace); - drop(proof); - - for byte in proof_bytes.iter_mut().take(21664) { - *byte = 255; - } - proof_bytes = proof_bytes[0..517].to_vec(); - - assert_eq!( - DeserializationError::InvalidAmountOfBytes, - StarkProof::::deserialize(&proof_bytes) - .err() - .unwrap() - ); - } - - #[test] - fn deserialize_empty_proof_should_give_error() { - assert_eq!( - DeserializationError::InvalidAmountOfBytes, - StarkProof::::deserialize(&[]) - .err() - .unwrap() - ); - } } diff --git a/provers/cairo/src/tests/integration_tests.rs b/provers/cairo/src/tests/integration_tests.rs index e7b262579c..db64d01807 100644 --- a/provers/cairo/src/tests/integration_tests.rs +++ b/provers/cairo/src/tests/integration_tests.rs @@ -1,8 +1,4 @@ -use lambdaworks_math::{ - errors::DeserializationError, - field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, - traits::{Deserializable, Serializable}, -}; +use lambdaworks_math::field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField; use stark_platinum_prover::{ debug::validate_trace, domain::Domain, @@ -299,7 +295,7 @@ fn deserialize_and_verify() { // The proof is generated and serialized. let proof = generate_cairo_proof(&main_trace, &pub_inputs, &proof_options).unwrap(); - let proof_bytes = proof.serialize(); + let proof_bytes: Vec = serde_cbor::to_vec(&proof).unwrap(); // The trace and original proof are dropped to show that they are decoupled from // the verifying process. @@ -308,38 +304,8 @@ fn deserialize_and_verify() { // At this point, the verifier only knows about the serialized proof, the proof options // and the public inputs. - let proof = StarkProof::::deserialize(&proof_bytes).unwrap(); + let proof: StarkProof = serde_cbor::from_slice(&proof_bytes).unwrap(); // The proof is verified successfully. assert!(verify_cairo_proof(&proof, &pub_inputs, &proof_options)); } - -#[test] -fn deserialize_should_not_panic_with_changed_and_sliced_bytes() { - let program_content = std::fs::read(cairo0_program_path("fibonacci_10.json")).unwrap(); - let (main_trace, pub_inputs) = - generate_prover_args(&program_content, &None, CairoLayout::Plain).unwrap(); - - let proof_options = ProofOptions::default_test_options(); - - // The proof is generated and serialized. - let proof = generate_cairo_proof(&main_trace, &pub_inputs, &proof_options).unwrap(); - let mut proof_bytes = proof.serialize(); - - // The trace and original proof are dropped to show that they are decoupled from - // the verifying process. - drop(main_trace); - drop(proof); - - for byte in proof_bytes.iter_mut().take(21664) { - *byte = 255; - } - proof_bytes = proof_bytes[0..517].to_vec(); - - assert_eq!( - DeserializationError::InvalidAmountOfBytes, - StarkProof::::deserialize(&proof_bytes) - .err() - .unwrap() - ); -} diff --git a/provers/stark/Cargo.toml b/provers/stark/Cargo.toml index 9ae1b8434d..f8de81ef5f 100644 --- a/provers/stark/Cargo.toml +++ b/provers/stark/Cargo.toml @@ -29,7 +29,7 @@ rayon = { version = "1.7.0", optional = true } wasm-bindgen = { version = "0.2", optional = true } serde-wasm-bindgen = { version = "0.5", optional = true } web-sys = { version = "0.3.64", features = ['console'], optional = true } -serde_cbor = { version = "0.11.1", optional = true } +serde_cbor = { version = "0.11.1"} [dev-dependencies] hex = "0.4.3" @@ -46,7 +46,7 @@ test_fiat_shamir = [] instruments = [] # This enables timing prints in prover and verifier metal = ["lambdaworks-math/metal"] parallel = ["dep:rayon"] -wasm = ["dep:wasm-bindgen", "dep:serde-wasm-bindgen", "dep:web-sys", "dep:serde_cbor"] +wasm = ["dep:wasm-bindgen", "dep:serde-wasm-bindgen", "dep:web-sys"] [target.'cfg(not(all(target_arch = "wasm32", target_os = "unknown")))'.dev-dependencies] proptest = "1.2.0" diff --git a/provers/stark/src/constraints/evaluator.rs b/provers/stark/src/constraints/evaluator.rs index 9c07823cc9..f5d699f65f 100644 --- a/provers/stark/src/constraints/evaluator.rs +++ b/provers/stark/src/constraints/evaluator.rs @@ -14,10 +14,9 @@ use rayon::prelude::{ #[cfg(all(debug_assertions, not(feature = "parallel")))] use crate::debug::check_boundary_polys_divisibility; use crate::domain::Domain; -use crate::frame::Frame; -use crate::prover::evaluate_polynomial_on_lde_domain; use crate::trace::TraceTable; use crate::traits::AIR; +use crate::{frame::Frame, prover::evaluate_polynomial_on_lde_domain}; use super::{boundary::BoundaryConstraints, evaluation_table::ConstraintEvaluationTable}; @@ -272,7 +271,7 @@ fn evaluate_transition_exemptions( domain: &Domain, ) -> Vec>> where - FieldElement: Send + Sync, + FieldElement: Send + Sync + Serializable, Polynomial>: Send + Sync, { #[cfg(feature = "parallel")] diff --git a/provers/stark/src/domain.rs b/provers/stark/src/domain.rs index a287d9ad1c..4744a50d24 100644 --- a/provers/stark/src/domain.rs +++ b/provers/stark/src/domain.rs @@ -8,7 +8,6 @@ use super::traits::AIR; pub struct Domain { pub(crate) root_order: u32, pub(crate) lde_roots_of_unity_coset: Vec>, - pub(crate) lde_root_order: u32, pub(crate) trace_primitive_root: FieldElement, pub(crate) trace_roots_of_unity: Vec>, pub(crate) coset_offset: FieldElement, @@ -46,7 +45,6 @@ impl Domain { Self { root_order, lde_roots_of_unity_coset, - lde_root_order, trace_primitive_root, trace_roots_of_unity, blowup_factor, diff --git a/provers/stark/src/frame.rs b/provers/stark/src/frame.rs index c51fde5d3d..809929be5e 100644 --- a/provers/stark/src/frame.rs +++ b/provers/stark/src/frame.rs @@ -1,9 +1,7 @@ use super::trace::TraceTable; use lambdaworks_math::{ - errors::DeserializationError, field::{element::FieldElement, traits::IsFFTField}, polynomial::Polynomial, - traits::{ByteConversion, Deserializable, Serializable}, }; #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] @@ -81,116 +79,3 @@ impl Frame { .collect() } } - -impl Serializable for Frame -where - F: IsFFTField, - FieldElement: ByteConversion, -{ - fn serialize(&self) -> Vec { - let mut bytes = vec![]; - bytes.extend(self.data.len().to_be_bytes()); - let felt_len = if self.data.is_empty() { - 0 - } else { - self.data[0].to_bytes_be().len() - }; - bytes.extend(felt_len.to_be_bytes()); - for felt in &self.data { - bytes.extend(felt.to_bytes_be()); - } - bytes.extend(self.row_width.to_be_bytes()); - bytes - } -} - -impl Deserializable for Frame -where - F: IsFFTField, - FieldElement: ByteConversion, -{ - fn deserialize(bytes: &[u8]) -> Result - where - Self: Sized, - { - let mut bytes = bytes; - let data_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - bytes = &bytes[8..]; - - let felt_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - bytes = &bytes[8..]; - - let mut data = vec![]; - for _ in 0..data_len { - let felt = FieldElement::::from_bytes_be( - bytes - .get(..felt_len) - .ok_or(DeserializationError::InvalidAmountOfBytes)?, - )?; - data.push(felt); - bytes = &bytes[felt_len..]; - } - - let row_width = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - - Ok(Self::new(data, row_width)) - } -} - -#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] -#[cfg(test)] -mod prop_test { - use lambdaworks_math::field::{ - element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, - }; - use proptest::{collection, prelude::*, prop_compose, proptest}; - - use lambdaworks_math::traits::{Deserializable, Serializable}; - - use crate::frame::Frame; - - type FE = FieldElement; - - prop_compose! { - fn some_felt()(base in any::(), exponent in any::()) -> FE { - FE::from(base).pow(exponent) - } - } - - prop_compose! { - fn field_vec()(vec in collection::vec(some_felt(), 16)) -> Vec { - vec - } - } - - proptest! { - #![proptest_config(ProptestConfig {cases: 5, .. ProptestConfig::default()})] - #[test] - fn test_serialize_and_deserialize(data in field_vec(), row_width in any::()) { - let frame = Frame::new(data, row_width); - let serialized = frame.serialize(); - let deserialized: Frame = Frame::deserialize(&serialized).unwrap(); - - prop_assert_eq!(frame.data, deserialized.data); - prop_assert_eq!(frame.row_width, deserialized.row_width); - } - } -} diff --git a/provers/stark/src/fri/fri_commitment.rs b/provers/stark/src/fri/fri_commitment.rs index 60df1b6e52..b39f42f3f7 100644 --- a/provers/stark/src/fri/fri_commitment.rs +++ b/provers/stark/src/fri/fri_commitment.rs @@ -1,47 +1,41 @@ +use lambdaworks_crypto::merkle_tree::{merkle::MerkleTree, traits::IsMerkleTreeBackend}; use lambdaworks_math::{ - fft::polynomial::FFTPoly, field::{ element::FieldElement, traits::{IsFFTField, IsField}, }, - polynomial::Polynomial, traits::Serializable, }; -use crate::config::FriMerkleTree; - #[derive(Clone)] -pub struct FriLayer +pub struct FriLayer where F: IsField, FieldElement: Serializable, + B: IsMerkleTreeBackend, { pub evaluation: Vec>, - pub merkle_tree: FriMerkleTree, + pub merkle_tree: MerkleTree, pub coset_offset: FieldElement, pub domain_size: usize, } -impl FriLayer +impl FriLayer where F: IsField + IsFFTField, FieldElement: Serializable, + B: IsMerkleTreeBackend, { pub fn new( - poly: &Polynomial>, - coset_offset: &FieldElement, + evaluation: &[FieldElement], + merkle_tree: MerkleTree, + coset_offset: FieldElement, domain_size: usize, ) -> Self { - let evaluation = poly - .evaluate_offset_fft(1, Some(domain_size), coset_offset) - .unwrap(); // TODO: return error - - let merkle_tree = FriMerkleTree::build(&evaluation); - Self { - evaluation, + evaluation: evaluation.to_vec(), merkle_tree, - coset_offset: coset_offset.clone(), + coset_offset, domain_size, } } diff --git a/provers/stark/src/fri/fri_decommit.rs b/provers/stark/src/fri/fri_decommit.rs index 78ce63acd0..dbbe614345 100644 --- a/provers/stark/src/fri/fri_decommit.rs +++ b/provers/stark/src/fri/fri_decommit.rs @@ -1,243 +1,13 @@ pub use lambdaworks_crypto::fiat_shamir::transcript::Transcript; use lambdaworks_crypto::merkle_tree::proof::Proof; -use lambdaworks_math::errors::DeserializationError; + use lambdaworks_math::field::element::FieldElement; use lambdaworks_math::field::traits::IsPrimeField; -use lambdaworks_math::traits::{ByteConversion, Deserializable, Serializable}; use crate::config::Commitment; -use crate::utils::{deserialize_proof, serialize_proof}; #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct FriDecommitment { pub layers_auth_paths_sym: Vec>, pub layers_evaluations_sym: Vec>, - pub layers_auth_paths: Vec>, - pub layers_evaluations: Vec>, -} - -impl Serializable for FriDecommitment -where - F: IsPrimeField, - FieldElement: ByteConversion, -{ - fn serialize(&self) -> Vec { - let mut bytes = vec![]; - bytes.extend(self.layers_auth_paths_sym.len().to_be_bytes()); - for proof in &self.layers_auth_paths_sym { - bytes.extend(serialize_proof(proof)); - } - let felt_len = self.layers_evaluations[0].to_bytes_be().len(); - bytes.extend(felt_len.to_be_bytes()); - bytes.extend(self.layers_evaluations_sym.len().to_be_bytes()); - for evaluation in &self.layers_evaluations_sym { - bytes.extend(evaluation.to_bytes_be()); - } - bytes.extend(self.layers_evaluations.len().to_be_bytes()); - for evaluation in &self.layers_evaluations { - bytes.extend(evaluation.to_bytes_be()); - } - bytes.extend(self.layers_auth_paths.len().to_be_bytes()); - for proof in &self.layers_auth_paths { - bytes.extend(serialize_proof(proof)); - } - bytes - } -} - -impl Deserializable for FriDecommitment -where - F: IsPrimeField, - FieldElement: ByteConversion, -{ - fn deserialize(bytes: &[u8]) -> Result - where - Self: Sized, - { - let mut bytes = bytes; - let mut layers_auth_paths_sym = vec![]; - let layers_auth_paths_sym_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - bytes = &bytes[8..]; - - for _ in 0..layers_auth_paths_sym_len { - let proof; - (proof, bytes) = deserialize_proof(bytes)?; - layers_auth_paths_sym.push(proof); - } - - let felt_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - bytes = &bytes[8..]; - - let layers_evaluations_sym_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - bytes = &bytes[8..]; - - let mut layers_evaluations_sym = vec![]; - for _ in 0..layers_evaluations_sym_len { - let evaluation = FieldElement::::from_bytes_be( - bytes - .get(..felt_len) - .ok_or(DeserializationError::InvalidAmountOfBytes)?, - )?; - bytes = &bytes[felt_len..]; - layers_evaluations_sym.push(evaluation); - } - - let layer_evaluations_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - bytes = &bytes[8..]; - - let mut layers_evaluations = vec![]; - for _ in 0..layer_evaluations_len { - let evaluation = FieldElement::::from_bytes_be( - bytes - .get(..felt_len) - .ok_or(DeserializationError::InvalidAmountOfBytes)?, - )?; - bytes = &bytes[felt_len..]; - layers_evaluations.push(evaluation); - } - - let mut layers_auth_paths = vec![]; - let layers_auth_paths_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - bytes = &bytes[8..]; - - for _ in 0..layers_auth_paths_len { - let proof; - (proof, bytes) = deserialize_proof(bytes)?; - layers_auth_paths.push(proof); - } - - Ok(Self { - layers_auth_paths_sym, - layers_evaluations_sym, - layers_evaluations, - layers_auth_paths, - }) - } -} -#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] -#[cfg(test)] -mod prop_test { - use lambdaworks_crypto::merkle_tree::proof::Proof; - use lambdaworks_math::field::{ - element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, - }; - use proptest::{collection, prelude::*, prop_compose, proptest}; - - use lambdaworks_math::traits::{Deserializable, Serializable}; - - use crate::config::{Commitment, COMMITMENT_SIZE}; - - use super::FriDecommitment; - - type FE = FieldElement; - - prop_compose! { - fn some_commitment()(high in any::(), low in any::()) -> Commitment { - let mut bytes = [0u8; COMMITMENT_SIZE]; - bytes[..16].copy_from_slice(&high.to_be_bytes()); - bytes[16..].copy_from_slice(&low.to_be_bytes()); - bytes - } - } - - prop_compose! { - fn commitment_vec()(vec in collection::vec(some_commitment(), 4)) -> Vec { - vec - } - } - - prop_compose! { - fn some_proof()(merkle_path in commitment_vec()) -> Proof { - Proof{merkle_path} - } - } - - prop_compose! { - fn proof_vec()(vec in collection::vec(some_proof(), 4)) -> Vec> { - vec - } - } - - prop_compose! { - fn some_felt()(base in any::(), exponent in any::()) -> FE { - FE::from(base).pow(exponent) - } - } - - prop_compose! { - fn field_vec()(vec in collection::vec(some_felt(), 16)) -> Vec { - vec - } - } - - prop_compose! { - fn some_fri_decommitment()( - layers_auth_paths_sym in proof_vec(), - layers_evaluations_sym in field_vec(), - layers_evaluations in field_vec(), - layers_auth_paths in proof_vec() - ) -> FriDecommitment { - FriDecommitment{ - layers_auth_paths_sym, - layers_evaluations_sym, - layers_evaluations, - layers_auth_paths - } - } - } - - proptest! { - #![proptest_config(ProptestConfig {cases: 5, .. ProptestConfig::default()})] - #[test] - fn test_serialize_and_deserialize(fri_decommitment in some_fri_decommitment()) { - let serialized = fri_decommitment.serialize(); - let deserialized: FriDecommitment = FriDecommitment::deserialize(&serialized).unwrap(); - - for (a, b) in fri_decommitment.layers_auth_paths_sym.iter().zip(deserialized.layers_auth_paths_sym.iter()) { - prop_assert_eq!(&a.merkle_path, &b.merkle_path); - } - - for (a, b) in fri_decommitment.layers_evaluations_sym.iter().zip(deserialized.layers_evaluations_sym.iter()) { - prop_assert_eq!(a, b); - } - - for (a, b) in fri_decommitment.layers_evaluations.iter().zip(deserialized.layers_evaluations.iter()) { - prop_assert_eq!(a, b); - } - - for (a, b) in fri_decommitment.layers_auth_paths.iter().zip(deserialized.layers_auth_paths.iter()) { - prop_assert_eq!(&a.merkle_path, &b.merkle_path); - } - } - } } diff --git a/provers/stark/src/fri/mod.rs b/provers/stark/src/fri/mod.rs index 1ee9dde908..5ec2a68c4a 100644 --- a/provers/stark/src/fri/mod.rs +++ b/provers/stark/src/fri/mod.rs @@ -2,39 +2,40 @@ pub mod fri_commitment; pub mod fri_decommit; mod fri_functions; -use lambdaworks_math::field::traits::{IsFFTField, IsField}; +use lambdaworks_math::fft::cpu::bit_reversing::in_place_bit_reverse_permute; +use lambdaworks_math::fft::polynomial::FFTPoly; +use lambdaworks_math::field::traits::IsFFTField; use lambdaworks_math::traits::Serializable; pub use lambdaworks_math::{ field::{element::FieldElement, fields::u64_prime_field::U64PrimeField}, polynomial::Polynomial, }; +use crate::config::{BatchedMerkleTree, BatchedMerkleTreeBackend}; use crate::transcript::IsStarkTranscript; use self::fri_commitment::FriLayer; use self::fri_decommit::FriDecommitment; use self::fri_functions::fold_polynomial; -use super::traits::AIR; - -pub fn fri_commit_phase( +pub fn commit_phase( number_layers: usize, p_0: Polynomial>, transcript: &mut impl IsStarkTranscript, coset_offset: &FieldElement, domain_size: usize, -) -> (FieldElement, Vec>) +) -> ( + FieldElement, + Vec>>, +) where FieldElement: Serializable, { let mut domain_size = domain_size; let mut fri_layer_list = Vec::with_capacity(number_layers); - let mut current_layer = FriLayer::new(&p_0, coset_offset, domain_size); - fri_layer_list.push(current_layer.clone()); + let mut current_layer: FriLayer>; let mut current_poly = p_0; - // >>>> Send commitment: [pβ‚€] - transcript.append_bytes(¤t_layer.merkle_tree.root); let mut coset_offset = coset_offset.clone(); @@ -45,8 +46,8 @@ where domain_size /= 2; // Compute layer polynomial and domain - current_poly = fold_polynomial(¤t_poly, &zeta); - current_layer = FriLayer::new(¤t_poly, &coset_offset, domain_size); + current_poly = fold_polynomial(¤t_poly, &zeta) * FieldElement::from(2); + current_layer = new_fri_layer(¤t_poly, &coset_offset, domain_size); let new_data = ¤t_layer.merkle_tree.root; fri_layer_list.push(current_layer.clone()); // TODO: remove this clone @@ -57,7 +58,7 @@ where // <<<< Receive challenge: πœβ‚™β‚‹β‚ let zeta = transcript.sample_field_element(); - let last_poly = fold_polynomial(¤t_poly, &zeta); + let last_poly = fold_polynomial(¤t_poly, &zeta) * FieldElement::from(2); let last_value = last_poly .coefficients() @@ -71,56 +72,65 @@ where (last_value, fri_layer_list) } -pub fn fri_query_phase( - air: &A, - domain_size: usize, - fri_layers: &Vec>, - transcript: &mut impl IsStarkTranscript, -) -> (Vec>, Vec) +pub fn query_phase( + fri_layers: &Vec>>, + iotas: &[usize], +) -> Vec> where - F: IsFFTField, - A: AIR, FieldElement: Serializable, { if !fri_layers.is_empty() { - let number_of_queries = air.options().fri_number_of_queries; - let iotas = (0..number_of_queries) - .map(|_| (transcript.sample_u64(domain_size as u64)) as usize) - .collect::>(); let query_list = iotas .iter() .map(|iota_s| { - // <<<< Receive challenge πœ„β‚› (iota_s) - let mut layers_auth_paths_sym = vec![]; - let mut layers_evaluations_sym = vec![]; - let mut layers_evaluations = vec![]; - let mut layers_auth_paths = vec![]; + let mut layers_evaluations_sym = Vec::new(); + let mut layers_auth_paths_sym = Vec::new(); + let mut index = *iota_s; for layer in fri_layers { // symmetric element - let index = iota_s % layer.domain_size; - let index_sym = (iota_s + layer.domain_size / 2) % layer.domain_size; - let evaluation_sym = layer.evaluation[index_sym].clone(); - let auth_path_sym = layer.merkle_tree.get_proof_by_pos(index_sym).unwrap(); - let evaluation = layer.evaluation[index].clone(); - let auth_path = layer.merkle_tree.get_proof_by_pos(index).unwrap(); - layers_auth_paths_sym.push(auth_path_sym); + let evaluation_sym = layer.evaluation[index ^ 1].clone(); + let auth_path_sym = layer.merkle_tree.get_proof_by_pos(index >> 1).unwrap(); layers_evaluations_sym.push(evaluation_sym); - layers_evaluations.push(evaluation); - layers_auth_paths.push(auth_path); + layers_auth_paths_sym.push(auth_path_sym); + + index >>= 1; } FriDecommitment { layers_auth_paths_sym, layers_evaluations_sym, - layers_evaluations, - layers_auth_paths, } }) .collect(); - (query_list, iotas) + query_list } else { - (vec![], vec![]) + vec![] + } +} + +pub fn new_fri_layer( + poly: &Polynomial>, + coset_offset: &FieldElement, + domain_size: usize, +) -> crate::fri::fri_commitment::FriLayer> +where + F: IsFFTField, + FieldElement: Serializable, +{ + let mut evaluation = poly + .evaluate_offset_fft(1, Some(domain_size), coset_offset) + .unwrap(); // TODO: return error + + in_place_bit_reverse_permute(&mut evaluation); + + let mut to_commit = Vec::new(); + for chunk in evaluation.chunks(2) { + to_commit.push(vec![chunk[0].clone(), chunk[1].clone()]); } + + let merkle_tree = BatchedMerkleTree::build(&to_commit); + + FriLayer::new(&evaluation, merkle_tree, coset_offset.clone(), domain_size) } diff --git a/provers/stark/src/proof/stark.rs b/provers/stark/src/proof/stark.rs index 72d3ef53c7..96f0b4ee31 100644 --- a/provers/stark/src/proof/stark.rs +++ b/provers/stark/src/proof/stark.rs @@ -1,27 +1,18 @@ use lambdaworks_crypto::merkle_tree::proof::Proof; -use lambdaworks_math::{ - errors::DeserializationError, - field::{element::FieldElement, traits::IsFFTField}, - traits::{ByteConversion, Deserializable, Serializable}, -}; +use lambdaworks_math::field::{element::FieldElement, traits::IsFFTField}; -use crate::{ - config::Commitment, - frame::Frame, - fri::fri_decommit::FriDecommitment, - utils::{deserialize_proof, serialize_proof}, -}; -use core::mem; +use crate::{config::Commitment, frame::Frame, fri::fri_decommit::FriDecommitment}; #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub struct DeepPolynomialOpenings { +pub struct DeepPolynomialOpening { pub lde_composition_poly_proof: Proof, - pub lde_composition_poly_even_evaluation: FieldElement, - pub lde_composition_poly_odd_evaluation: FieldElement, + pub lde_composition_poly_parts_evaluation: Vec>, pub lde_trace_merkle_proofs: Vec>, pub lde_trace_evaluations: Vec>, } +pub type DeepPolynomialOpenings = Vec>; + #[derive(Debug, serde::Serialize, serde::Deserialize)] pub struct StarkProof { // Length of the execution trace @@ -31,682 +22,20 @@ pub struct StarkProof { pub lde_trace_merkle_roots: Vec, // tβ±Ό(zgᡏ) pub trace_ood_frame_evaluations: Frame, - // [H₁] and [Hβ‚‚] + // Commitments to Hα΅’ pub composition_poly_root: Commitment, - // H₁(zΒ²) - pub composition_poly_even_ood_evaluation: FieldElement, - // Hβ‚‚(zΒ²) - pub composition_poly_odd_ood_evaluation: FieldElement, + // Hα΅’(z^N) + pub composition_poly_parts_ood_evaluation: Vec>, // [pβ‚–] pub fri_layers_merkle_roots: Vec, // pβ‚™ pub fri_last_value: FieldElement, - // Open(pβ‚€(Dβ‚€), πœβ‚›), Opwn(pβ‚–(Dβ‚–), βˆ’πœβ‚›^(2ᡏ)) + // Open(pβ‚–(Dβ‚–), βˆ’πœβ‚›^(2ᡏ)) pub query_list: Vec>, - // Open(H₁(D_LDE, πœβ‚€), Open(Hβ‚‚(D_LDE, πœβ‚€), Open(tβ±Ό(D_LDE), πœβ‚€) - pub deep_poly_openings: Vec>, + // Open(H₁(D_LDE, 𝜐ᡒ), Open(Hβ‚‚(D_LDE, 𝜐ᡒ), Open(tβ±Ό(D_LDE), 𝜐ᡒ) + pub deep_poly_openings: DeepPolynomialOpenings, + // Open(H₁(D_LDE, -𝜐ᡒ), Open(Hβ‚‚(D_LDE, -𝜐ᡒ), Open(tβ±Ό(D_LDE), -𝜐ᡒ) + pub deep_poly_openings_sym: DeepPolynomialOpenings, // nonce obtained from grinding pub nonce: u64, } - -impl Serializable for DeepPolynomialOpenings -where - F: IsFFTField, - FieldElement: ByteConversion, -{ - fn serialize(&self) -> Vec { - let mut bytes = vec![]; - bytes.extend(serialize_proof(&self.lde_composition_poly_proof)); - let lde_composition_poly_even_evaluation_bytes = - self.lde_composition_poly_even_evaluation.to_bytes_be(); - let felt_len = lde_composition_poly_even_evaluation_bytes.len(); - bytes.extend(felt_len.to_be_bytes()); - bytes.extend(lde_composition_poly_even_evaluation_bytes); - bytes.extend(self.lde_composition_poly_odd_evaluation.to_bytes_be()); - bytes.extend(self.lde_trace_merkle_proofs.len().to_be_bytes()); - for proof in &self.lde_trace_merkle_proofs { - bytes.extend(serialize_proof(proof)); - } - bytes.extend(self.lde_trace_evaluations.len().to_be_bytes()); - for evaluation in &self.lde_trace_evaluations { - bytes.extend(evaluation.to_bytes_be()); - } - bytes - } -} - -impl Deserializable for DeepPolynomialOpenings -where - F: IsFFTField, - FieldElement: ByteConversion, -{ - fn deserialize(bytes: &[u8]) -> Result - where - Self: Sized, - { - let mut bytes = bytes; - let lde_composition_poly_proof; - (lde_composition_poly_proof, bytes) = deserialize_proof(bytes)?; - - let felt_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - bytes = &bytes[8..]; - - let lde_composition_poly_even_evaluation = FieldElement::from_bytes_be( - bytes - .get(..felt_len) - .ok_or(DeserializationError::InvalidAmountOfBytes)?, - )?; - bytes = &bytes[felt_len..]; - - let lde_composition_poly_odd_evaluation = FieldElement::from_bytes_be( - bytes - .get(..felt_len) - .ok_or(DeserializationError::InvalidAmountOfBytes)?, - )?; - bytes = &bytes[felt_len..]; - - let lde_trace_merkle_proofs_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - bytes = &bytes[8..]; - - let mut lde_trace_merkle_proofs = vec![]; - for _ in 0..lde_trace_merkle_proofs_len { - let proof; - (proof, bytes) = deserialize_proof(bytes)?; - lde_trace_merkle_proofs.push(proof); - } - - let lde_trace_evaluations_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - bytes = &bytes[8..]; - - let mut lde_trace_evaluations = vec![]; - for _ in 0..lde_trace_evaluations_len { - let evaluation = FieldElement::from_bytes_be( - bytes - .get(..felt_len) - .ok_or(DeserializationError::InvalidAmountOfBytes)?, - )?; - bytes = &bytes[felt_len..]; - lde_trace_evaluations.push(evaluation); - } - - Ok(DeepPolynomialOpenings { - lde_composition_poly_proof, - lde_composition_poly_even_evaluation, - lde_composition_poly_odd_evaluation, - lde_trace_merkle_proofs, - lde_trace_evaluations, - }) - } -} - -impl Serializable for StarkProof -where - F: IsFFTField, - FieldElement: ByteConversion, -{ - fn serialize(&self) -> Vec { - let mut bytes = vec![]; - - // Serialize trace length - bytes.extend(self.trace_length.to_be_bytes()); - - bytes.extend(self.lde_trace_merkle_roots.len().to_be_bytes()); - for commitment in &self.lde_trace_merkle_roots { - bytes.extend(commitment); - } - let trace_ood_frame_evaluations_bytes = self.trace_ood_frame_evaluations.serialize(); - bytes.extend(trace_ood_frame_evaluations_bytes.len().to_be_bytes()); - bytes.extend(trace_ood_frame_evaluations_bytes); - - bytes.extend(self.composition_poly_root); - - let composition_poly_even_ood_evaluation_bytes = - self.composition_poly_even_ood_evaluation.to_bytes_be(); - bytes.extend( - composition_poly_even_ood_evaluation_bytes - .len() - .to_be_bytes(), - ); - bytes.extend(composition_poly_even_ood_evaluation_bytes); - bytes.extend(self.composition_poly_odd_ood_evaluation.to_bytes_be()); - - bytes.extend(self.fri_layers_merkle_roots.len().to_be_bytes()); - for commitment in &self.fri_layers_merkle_roots { - bytes.extend(commitment); - } - - bytes.extend(self.fri_last_value.to_bytes_be()); - - bytes.extend(self.query_list.len().to_be_bytes()); - for query in &self.query_list { - let query_bytes = query.serialize(); - bytes.extend(query_bytes.len().to_be_bytes()); - bytes.extend(query_bytes); - } - - bytes.extend(self.deep_poly_openings.len().to_be_bytes()); - for opening in &self.deep_poly_openings { - let opening_bytes = opening.serialize(); - bytes.extend(opening_bytes.len().to_be_bytes()); - bytes.extend(opening_bytes); - } - - // serialize nonce - bytes.extend(self.nonce.to_be_bytes()); - - bytes - } -} - -impl Deserializable for StarkProof -where - F: IsFFTField, - FieldElement: ByteConversion, -{ - fn deserialize(bytes: &[u8]) -> Result - where - Self: Sized, - { - let mut bytes = bytes; - let trace_length_buffer_size = mem::size_of::(); - let trace_length = usize::from_be_bytes( - bytes - .get(..trace_length_buffer_size) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - - bytes = &bytes[8..]; - - let lde_trace_merkle_roots_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - - bytes = &bytes[8..]; - - let mut lde_trace_merkle_roots: Vec<[u8; 32]> = vec![]; - for _ in 0..lde_trace_merkle_roots_len { - let commitment = bytes - .get(..32) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?; - - lde_trace_merkle_roots.push(commitment); - bytes = &bytes[32..]; - } - - let trace_ood_frame_evaluations_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - - bytes = &bytes[8..]; - - let trace_ood_frame_evaluations: Frame = Frame::deserialize( - bytes - .get(..trace_ood_frame_evaluations_len) - .ok_or(DeserializationError::InvalidAmountOfBytes)?, - )?; - - bytes = &bytes[trace_ood_frame_evaluations_len..]; - - let composition_poly_root = bytes - .get(..32) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?; - - bytes = &bytes[32..]; - - let felt_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - - bytes = &bytes[8..]; - - let composition_poly_even_ood_evaluation = FieldElement::from_bytes_be( - bytes - .get(..felt_len) - .ok_or(DeserializationError::InvalidAmountOfBytes)?, - )?; - - bytes = &bytes[felt_len..]; - - let composition_poly_odd_ood_evaluation = FieldElement::from_bytes_be( - bytes - .get(..felt_len) - .ok_or(DeserializationError::InvalidAmountOfBytes)?, - )?; - - bytes = &bytes[felt_len..]; - - let fri_layers_merkle_roots_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - - bytes = &bytes[8..]; - - let mut fri_layers_merkle_roots: Vec<[u8; 32]> = vec![]; - for _ in 0..fri_layers_merkle_roots_len { - let commitment = bytes - .get(..32) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?; - fri_layers_merkle_roots.push(commitment); - bytes = &bytes[32..]; - } - - let fri_last_value = FieldElement::from_bytes_be( - bytes - .get(..felt_len) - .ok_or(DeserializationError::InvalidAmountOfBytes)?, - )?; - - bytes = &bytes[felt_len..]; - - let query_list_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - - bytes = &bytes[8..]; - - let mut query_list = vec![]; - for _ in 0..query_list_len { - let query_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - - bytes = &bytes[8..]; - - let query = FriDecommitment::deserialize( - bytes - .get(..query_len) - .ok_or(DeserializationError::InvalidAmountOfBytes)?, - )?; - - bytes = &bytes[query_len..]; - - query_list.push(query); - } - - let deep_poly_openings_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - - bytes = &bytes[8..]; - - let mut deep_poly_openings = vec![]; - for _ in 0..deep_poly_openings_len { - let opening_len = usize::from_be_bytes( - bytes - .get(..8) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - - bytes = &bytes[8..]; - - let opening = DeepPolynomialOpenings::deserialize( - bytes - .get(..opening_len) - .ok_or(DeserializationError::InvalidAmountOfBytes)?, - )?; - - bytes = &bytes[opening_len..]; - - deep_poly_openings.push(opening); - } - - // deserialize nonce - let start_nonce = bytes - .len() - .checked_sub(core::mem::size_of::()) - .ok_or(DeserializationError::InvalidAmountOfBytes)?; - - let nonce = u64::from_be_bytes( - bytes - .get(start_nonce..) - .ok_or(DeserializationError::InvalidAmountOfBytes)? - .try_into() - .map_err(|_| DeserializationError::InvalidAmountOfBytes)?, - ); - - Ok(StarkProof { - trace_length, - lde_trace_merkle_roots, - trace_ood_frame_evaluations, - composition_poly_root, - composition_poly_even_ood_evaluation, - composition_poly_odd_ood_evaluation, - fri_layers_merkle_roots, - fri_last_value, - query_list, - deep_poly_openings, - nonce, - }) - } -} - -#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] -#[cfg(test)] -mod prop_test { - - use lambdaworks_crypto::merkle_tree::proof::Proof; - use lambdaworks_math::{ - errors::DeserializationError, - field::{ - element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, - }, - }; - use proptest::{collection, prelude::*, prop_compose, proptest}; - - use crate::{ - config::{Commitment, COMMITMENT_SIZE}, - frame::Frame, - fri::fri_decommit::FriDecommitment, - }; - use lambdaworks_math::traits::{Deserializable, Serializable}; - - use super::{DeepPolynomialOpenings, StarkProof}; - - type FE = FieldElement; - - prop_compose! { - fn some_commitment()(high in any::(), low in any::()) -> Commitment { - let mut bytes = [0u8; COMMITMENT_SIZE]; - bytes[..16].copy_from_slice(&high.to_be_bytes()); - bytes[16..].copy_from_slice(&low.to_be_bytes()); - bytes - } - } - - prop_compose! { - fn commitment_vec()(vec in collection::vec(some_commitment(), (16_usize, 32_usize))) -> Vec { - vec - } - } - - prop_compose! { - fn some_proof()(merkle_path in commitment_vec()) -> Proof { - Proof{merkle_path} - } - } - - prop_compose! { - fn proof_vec()(vec in collection::vec(some_proof(), (4_usize, 8_usize))) -> Vec> { - vec - } - } - - prop_compose! { - fn some_felt()(base in any::(), exponent in any::()) -> FE { - FE::from(base).pow(exponent) - } - } - - prop_compose! { - fn field_vec()(vec in collection::vec(some_felt(), (8_usize, 16_usize))) -> Vec { - vec - } - } - - prop_compose! { - fn some_fri_decommitment()( - layers_auth_paths_sym in proof_vec(), - layers_evaluations_sym in field_vec(), - layers_evaluations in field_vec(), - layers_auth_paths in proof_vec() - ) -> FriDecommitment { - FriDecommitment{ - layers_auth_paths_sym, - layers_evaluations_sym, - layers_evaluations, - layers_auth_paths - } - } - } - - prop_compose! { - fn fri_decommitment_vec()(vec in collection::vec(some_fri_decommitment(), (16_usize, 32_usize))) -> Vec> { - vec - } - } - - prop_compose! { - fn some_deep_polynomial_openings()( - lde_composition_poly_proof in some_proof(), - lde_composition_poly_even_evaluation in some_felt(), - lde_composition_poly_odd_evaluation in some_felt(), - lde_trace_merkle_proofs in proof_vec(), - lde_trace_evaluations in field_vec() - ) -> DeepPolynomialOpenings { - DeepPolynomialOpenings { - lde_composition_poly_proof, - lde_composition_poly_even_evaluation, - lde_composition_poly_odd_evaluation, - lde_trace_merkle_proofs, - lde_trace_evaluations - } - } - } - - prop_compose! { - fn deep_polynomial_openings_vec()(vec in collection::vec(some_deep_polynomial_openings(), (8_usize, 16_usize))) -> Vec> { - vec - } - } - - prop_compose! { - fn some_frame()(data in field_vec(), row_width in any::()) -> Frame { - Frame::new(data, row_width) - } - } - - prop_compose! { - fn some_usize()(len in any::()) -> usize { - len - } - } - - prop_compose! { - fn some_stark_proof()( - trace_length in some_usize(), - lde_trace_merkle_roots in commitment_vec(), - trace_ood_frame_evaluations in some_frame(), - composition_poly_root in some_commitment(), - composition_poly_even_ood_evaluation in some_felt(), - composition_poly_odd_ood_evaluation in some_felt(), - fri_layers_merkle_roots in commitment_vec(), - fri_last_value in some_felt(), - query_list in fri_decommitment_vec(), - deep_poly_openings in deep_polynomial_openings_vec() - - ) -> StarkProof { - StarkProof { - trace_length, - lde_trace_merkle_roots, - trace_ood_frame_evaluations, - composition_poly_root, - composition_poly_even_ood_evaluation, - composition_poly_odd_ood_evaluation, - fri_layers_merkle_roots, - fri_last_value, - query_list, - deep_poly_openings, - nonce: 0 - } - } - } - - proptest! { - #[test] - fn test_deep_polynomial_openings_serialization( - deep_polynomial_openings in some_deep_polynomial_openings() - ) { - let serialized = deep_polynomial_openings.serialize(); - let deserialized = DeepPolynomialOpenings::::deserialize(&serialized).unwrap(); - - for (a, b) in deep_polynomial_openings.lde_trace_merkle_proofs.iter().zip(deserialized.lde_trace_merkle_proofs.iter()) { - prop_assert_eq!(&a.merkle_path, &b.merkle_path); - }; - - prop_assert_eq!(deep_polynomial_openings.lde_composition_poly_even_evaluation, deserialized.lde_composition_poly_even_evaluation); - prop_assert_eq!(deep_polynomial_openings.lde_composition_poly_odd_evaluation, deserialized.lde_composition_poly_odd_evaluation); - prop_assert_eq!(deep_polynomial_openings.lde_composition_poly_proof.merkle_path, deserialized.lde_composition_poly_proof.merkle_path); - prop_assert_eq!(deep_polynomial_openings.lde_trace_evaluations, deserialized.lde_trace_evaluations); - } - } - - proptest! { - #![proptest_config(ProptestConfig {cases: 5, .. ProptestConfig::default()})] - #[test] - fn test_stark_proof_serialization( - stark_proof in some_stark_proof() - ) { - let serialized = stark_proof.serialize(); - let deserialized = StarkProof::::deserialize(&serialized).unwrap(); - - prop_assert_eq!( - stark_proof.lde_trace_merkle_roots, - deserialized.lde_trace_merkle_roots - ); - prop_assert_eq!( - stark_proof.trace_ood_frame_evaluations.num_columns(), - deserialized.trace_ood_frame_evaluations.num_columns() - ); - prop_assert_eq!( - stark_proof.trace_ood_frame_evaluations.num_rows(), - deserialized.trace_ood_frame_evaluations.num_rows() - ); - prop_assert_eq!( - stark_proof.composition_poly_root, - deserialized.composition_poly_root - ); - prop_assert_eq!( - stark_proof.composition_poly_even_ood_evaluation, - deserialized.composition_poly_even_ood_evaluation - ); - prop_assert_eq!( - stark_proof.composition_poly_odd_ood_evaluation, - deserialized.composition_poly_odd_ood_evaluation - ); - prop_assert_eq!( - stark_proof.fri_layers_merkle_roots, - deserialized.fri_layers_merkle_roots - ); - prop_assert_eq!(stark_proof.fri_last_value, deserialized.fri_last_value); - - for (a, b) in stark_proof - .query_list - .iter() - .zip(deserialized.query_list.iter()) - { - for (x, y) in a - .clone() - .layers_auth_paths_sym - .iter() - .zip(b.clone().layers_auth_paths_sym.iter()) - { - prop_assert_eq!(&x.merkle_path, &y.merkle_path); - } - prop_assert_eq!(&a.layers_evaluations_sym, &b.layers_evaluations_sym); - prop_assert_eq!(&a.layers_evaluations, &b.layers_evaluations); - for (x, y) in a - .clone() - .layers_auth_paths - .iter() - .zip(b.clone().layers_auth_paths.iter()) - { - prop_assert_eq!(&x.merkle_path, &y.merkle_path); - } - } - - for (a, b) in stark_proof - .deep_poly_openings - .iter() - .zip(deserialized.deep_poly_openings.iter()) - { - for (x, y) in a - .clone() - .lde_trace_merkle_proofs - .iter() - .zip(b.clone().lde_trace_merkle_proofs.iter()) - { - prop_assert_eq!(&x.merkle_path, &y.merkle_path); - } - prop_assert_eq!( - &a.lde_composition_poly_even_evaluation, - &b.lde_composition_poly_even_evaluation - ); - prop_assert_eq!( - &a.lde_composition_poly_odd_evaluation, - &b.lde_composition_poly_odd_evaluation - ); - prop_assert_eq!( - &a.lde_composition_poly_proof.merkle_path, - &b.lde_composition_poly_proof.merkle_path - ); - prop_assert_eq!(&a.lde_trace_evaluations, &b.lde_trace_evaluations); - } - } - } - - #[test] - fn deserialize_empty_proof_should_give_error() { - assert_eq!( - DeserializationError::InvalidAmountOfBytes, - StarkProof::::deserialize(&[]) - .err() - .unwrap() - ); - } -} diff --git a/provers/stark/src/prover.rs b/provers/stark/src/prover.rs index d177621af4..e03e2238f6 100644 --- a/provers/stark/src/prover.rs +++ b/provers/stark/src/prover.rs @@ -2,8 +2,9 @@ use std::time::Instant; use lambdaworks_crypto::merkle_tree::proof::Proof; -use lambdaworks_math::fft::cpu::bit_reversing::in_place_bit_reverse_permute; +use lambdaworks_math::fft::cpu::bit_reversing::{in_place_bit_reverse_permute, reverse_index}; use lambdaworks_math::fft::{errors::FFTError, polynomial::FFTPoly}; +use lambdaworks_math::field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField; use lambdaworks_math::traits::Serializable; use lambdaworks_math::{ field::{element::FieldElement, traits::IsFFTField}, @@ -16,6 +17,8 @@ use rayon::prelude::{IndexedParallelIterator, IntoParallelRefIterator, ParallelI #[cfg(debug_assertions)] use crate::debug::validate_trace; +use crate::fri; +use crate::proof::stark::DeepPolynomialOpenings; use crate::transcript::IsStarkTranscript; use super::config::{BatchedMerkleTree, Commitment}; @@ -23,69 +26,60 @@ use super::constraints::evaluator::ConstraintEvaluator; use super::domain::Domain; use super::frame::Frame; use super::fri::fri_decommit::FriDecommitment; -use super::fri::{fri_commit_phase, fri_query_phase}; use super::grinding::generate_nonce_with_grinding; use super::proof::options::ProofOptions; -use super::proof::stark::{DeepPolynomialOpenings, StarkProof}; +use super::proof::stark::{DeepPolynomialOpening, StarkProof}; use super::trace::TraceTable; use super::traits::AIR; -use super::transcript::batch_sample_challenges; + +pub struct Prover; + +impl IsStarkProver for Prover { + type Field = Stark252PrimeField; +} #[derive(Debug)] pub enum ProvingError { WrongParameter(String), } -struct Round1 +pub struct Round1 where F: IsFFTField, A: AIR, FieldElement: Serializable, { - trace_polys: Vec>>, - lde_trace: TraceTable, - lde_trace_merkle_trees: Vec>, - lde_trace_merkle_roots: Vec, - rap_challenges: A::RAPChallenges, + pub(crate) trace_polys: Vec>>, + pub(crate) lde_trace: TraceTable, + pub(crate) lde_trace_merkle_trees: Vec>, + pub(crate) lde_trace_merkle_roots: Vec, + pub(crate) rap_challenges: A::RAPChallenges, } -struct Round2 +pub struct Round2 where F: IsFFTField, FieldElement: Serializable, { - composition_poly_even: Polynomial>, - lde_composition_poly_even_evaluations: Vec>, - composition_poly_merkle_tree: BatchedMerkleTree, - composition_poly_root: Commitment, - composition_poly_odd: Polynomial>, - lde_composition_poly_odd_evaluations: Vec>, + pub(crate) composition_poly_parts: Vec>>, + pub(crate) lde_composition_poly_evaluations: Vec>>, + pub(crate) composition_poly_merkle_tree: BatchedMerkleTree, + pub(crate) composition_poly_root: Commitment, } -struct Round3 { +pub struct Round3 { trace_ood_evaluations: Vec>>, - composition_poly_even_ood_evaluation: FieldElement, - composition_poly_odd_ood_evaluation: FieldElement, + composition_poly_parts_ood_evaluation: Vec>, } -struct Round4 { +pub struct Round4 { fri_last_value: FieldElement, fri_layers_merkle_roots: Vec, - deep_poly_openings: Vec>, + deep_poly_openings: DeepPolynomialOpenings, + deep_poly_openings_sym: DeepPolynomialOpenings, query_list: Vec>, nonce: u64, } - -fn batch_commit(vectors: &[Vec>]) -> (BatchedMerkleTree, Commitment) -where - F: IsFFTField, - FieldElement: Serializable, -{ - let tree = BatchedMerkleTree::::build(vectors); - let commitment = tree.root; - (tree, commitment) -} - pub fn evaluate_polynomial_on_lde_domain( p: &Polynomial>, blowup_factor: usize, @@ -104,731 +98,807 @@ where } } -fn apply_permutation(vector: &mut Vec>, permutation: &[usize]) { - assert_eq!( - vector.len(), - permutation.len(), - "Vector and permutation must have the same length" - ); +pub trait IsStarkProver { + type Field: IsFFTField; - let mut temp = Vec::with_capacity(vector.len()); - for &index in permutation { - temp.push(vector[index].clone()); + fn batch_commit( + vectors: &[Vec>], + ) -> (BatchedMerkleTree, Commitment) + where + FieldElement: Serializable, + { + let tree = BatchedMerkleTree::::build(vectors); + let commitment = tree.root; + (tree, commitment) } - vector.clear(); - vector.extend(temp); -} + #[allow(clippy::type_complexity)] + fn interpolate_and_commit( + trace: &TraceTable, + domain: &Domain, + transcript: &mut impl IsStarkTranscript, + ) -> ( + Vec>>, + Vec>>, + BatchedMerkleTree, + Commitment, + ) + where + FieldElement: Serializable + Send + Sync, + { + let trace_polys = trace.compute_trace_polys(); -/// This function returns the permutation that converts lambdaworks ordering of rows to the one used in the stone prover -pub fn get_stone_prover_domain_permutation(domain_size: usize, blowup_factor: usize) -> Vec { - let mut permutation = Vec::new(); - let n = domain_size; + // Evaluate those polynomials t_j on the large domain D_LDE. + let lde_trace_evaluations = Self::compute_lde_trace_evaluations(&trace_polys, domain); - let mut indices: Vec = (0..blowup_factor).collect(); - in_place_bit_reverse_permute(&mut indices); + let mut lde_trace_permuted = lde_trace_evaluations.clone(); - for i in indices.iter() { - for j in 0..n { - permutation.push(i + j * blowup_factor) + for col in lde_trace_permuted.iter_mut() { + in_place_bit_reverse_permute(col); } + + // Compute commitments [t_j]. + let lde_trace = TraceTable::new_from_cols(&lde_trace_permuted); + let (lde_trace_merkle_tree, lde_trace_merkle_root) = Self::batch_commit(&lde_trace.rows()); + + // >>>> Send commitments: [tβ±Ό] + transcript.append_bytes(&lde_trace_merkle_root); + + ( + trace_polys, + lde_trace_evaluations, + lde_trace_merkle_tree, + lde_trace_merkle_root, + ) } - for coset_indices in permutation.chunks_mut(n) { - let mut temp = coset_indices.to_owned(); - in_place_bit_reverse_permute(&mut temp); - for (j, elem) in coset_indices.iter_mut().enumerate() { - *elem = temp[j]; + fn compute_lde_trace_evaluations( + trace_polys: &[Polynomial>], + domain: &Domain, + ) -> Vec>> + where + FieldElement: Send + Sync, + { + #[cfg(not(feature = "parallel"))] + let trace_polys_iter = trace_polys.iter(); + #[cfg(feature = "parallel")] + let trace_polys_iter = trace_polys.par_iter(); + + trace_polys_iter + .map(|poly| { + evaluate_polynomial_on_lde_domain( + poly, + domain.blowup_factor, + domain.interpolation_domain_size, + &domain.coset_offset, + ) + }) + .collect::>>, FFTError>>() + .unwrap() + } + + fn round_1_randomized_air_with_preprocessing>( + air: &A, + main_trace: &TraceTable, + domain: &Domain, + transcript: &mut impl IsStarkTranscript, + ) -> Result, ProvingError> + where + FieldElement: Serializable + Send + Sync, + { + let (mut trace_polys, mut evaluations, main_merkle_tree, main_merkle_root) = + Self::interpolate_and_commit(main_trace, domain, transcript); + + let rap_challenges = air.build_rap_challenges(transcript); + + let aux_trace = air.build_auxiliary_trace(main_trace, &rap_challenges); + + let mut lde_trace_merkle_trees = vec![main_merkle_tree]; + let mut lde_trace_merkle_roots = vec![main_merkle_root]; + if !aux_trace.is_empty() { + // Check that this is valid for interpolation + let (aux_trace_polys, aux_trace_polys_evaluations, aux_merkle_tree, aux_merkle_root) = + Self::interpolate_and_commit(&aux_trace, domain, transcript); + trace_polys.extend_from_slice(&aux_trace_polys); + evaluations.extend_from_slice(&aux_trace_polys_evaluations); + lde_trace_merkle_trees.push(aux_merkle_tree); + lde_trace_merkle_roots.push(aux_merkle_root); } + + let lde_trace = TraceTable::new_from_cols(&evaluations); + + Ok(Round1 { + trace_polys, + lde_trace, + lde_trace_merkle_roots, + lde_trace_merkle_trees, + rap_challenges, + }) } - permutation.to_vec() -} + fn commit_composition_polynomial( + lde_composition_poly_parts_evaluations: &[Vec>], + ) -> (BatchedMerkleTree, Commitment) + where + FieldElement: Serializable, + { + // TODO: Remove clones + let mut lde_composition_poly_evaluations = Vec::new(); + for i in 0..lde_composition_poly_parts_evaluations[0].len() { + let mut row = Vec::new(); + for evaluation in lde_composition_poly_parts_evaluations.iter() { + row.push(evaluation[i].clone()); + } + lde_composition_poly_evaluations.push(row); + } -#[allow(clippy::type_complexity)] -fn interpolate_and_commit( - trace: &TraceTable, - domain: &Domain, - transcript: &mut impl IsStarkTranscript, -) -> ( - Vec>>, - Vec>>, - BatchedMerkleTree, - Commitment, -) -where - F: IsFFTField, - FieldElement: Serializable + Send + Sync, -{ - let trace_polys = trace.compute_trace_polys(); + in_place_bit_reverse_permute(&mut lde_composition_poly_evaluations); + + let mut lde_composition_poly_evaluations_merged = Vec::new(); + for chunk in lde_composition_poly_evaluations.chunks(2) { + let (mut chunk0, chunk1) = (chunk[0].clone(), &chunk[1]); + chunk0.extend_from_slice(chunk1); + lde_composition_poly_evaluations_merged.push(chunk0); + } + + Self::batch_commit(&lde_composition_poly_evaluations_merged) + } + + fn round_2_compute_composition_polynomial( + air: &A, + domain: &Domain, + round_1_result: &Round1, + transition_coefficients: &[FieldElement], + boundary_coefficients: &[FieldElement], + ) -> Round2 + where + A: AIR + Send + Sync, + A::RAPChallenges: Send + Sync, + FieldElement: Serializable + Send + Sync, + { + // Create evaluation table + let evaluator = ConstraintEvaluator::new(air, &round_1_result.rap_challenges); + + let constraint_evaluations = evaluator.evaluate( + &round_1_result.lde_trace, + domain, + transition_coefficients, + boundary_coefficients, + &round_1_result.rap_challenges, + ); - // Evaluate those polynomials t_j on the large domain D_LDE. - let lde_trace_evaluations = compute_lde_trace_evaluations(&trace_polys, domain); + // Get the composition poly H + let composition_poly = + constraint_evaluations.compute_composition_poly(&domain.coset_offset); - let permutation = - get_stone_prover_domain_permutation(domain.interpolation_domain_size, domain.blowup_factor); + let number_of_parts = air.composition_poly_degree_bound() / air.trace_length(); + let composition_poly_parts = composition_poly.break_in_parts(number_of_parts); - let mut lde_trace_permuted = lde_trace_evaluations.clone(); + let lde_composition_poly_parts_evaluations: Vec<_> = composition_poly_parts + .iter() + .map(|part| { + evaluate_polynomial_on_lde_domain( + part, + domain.blowup_factor, + domain.interpolation_domain_size, + &domain.coset_offset, + ) + .unwrap() + }) + .collect(); - for col in lde_trace_permuted.iter_mut() { - apply_permutation(col, &permutation); + let (composition_poly_merkle_tree, composition_poly_root) = + Self::commit_composition_polynomial(&lde_composition_poly_parts_evaluations); + + Round2 { + lde_composition_poly_evaluations: lde_composition_poly_parts_evaluations, + composition_poly_parts, + composition_poly_merkle_tree, + composition_poly_root, + } } - // Compute commitments [t_j]. - let lde_trace = TraceTable::new_from_cols(&lde_trace_permuted); - let (lde_trace_merkle_tree, lde_trace_merkle_root) = batch_commit(&lde_trace.rows()); + fn round_3_evaluate_polynomials_in_out_of_domain_element>( + air: &A, + domain: &Domain, + round_1_result: &Round1, + round_2_result: &Round2, + z: &FieldElement, + ) -> Round3 + where + FieldElement: Serializable, + { + let z_power = z.pow(round_2_result.composition_poly_parts.len()); - // >>>> Send commitments: [tβ±Ό] - transcript.append_bytes(&lde_trace_merkle_root); + // Evaluate H_i in z^N for all i, where N is the number of parts the composition poly was + // broken into. + let composition_poly_parts_ood_evaluation: Vec<_> = round_2_result + .composition_poly_parts + .iter() + .map(|part| part.evaluate(&z_power)) + .collect(); + + // Returns the Out of Domain Frame for the given trace polynomials, out of domain evaluation point (called `z` in the literature), + // frame offsets given by the AIR and primitive root used for interpolating the trace polynomials. + // An out of domain frame is nothing more than the evaluation of the trace polynomials in the points required by the + // verifier to check the consistency between the trace and the composition polynomial. + // + // In the fibonacci example, the ood frame is simply the evaluations `[t(z), t(z * g), t(z * g^2)]`, where `t` is the trace + // polynomial and `g` is the primitive root of unity used when interpolating `t`. + let trace_ood_evaluations = Frame::get_trace_evaluations( + &round_1_result.trace_polys, + z, + &air.context().transition_offsets, + &domain.trace_primitive_root, + ); - ( - trace_polys, - lde_trace_evaluations, - lde_trace_merkle_tree, - lde_trace_merkle_root, - ) -} + Round3 { + trace_ood_evaluations, + composition_poly_parts_ood_evaluation, + } + } -fn compute_lde_trace_evaluations( - trace_polys: &[Polynomial>], - domain: &Domain, -) -> Vec>> -where - F: IsFFTField, - FieldElement: Send + Sync, -{ - #[cfg(not(feature = "parallel"))] - let trace_polys_iter = trace_polys.iter(); - #[cfg(feature = "parallel")] - let trace_polys_iter = trace_polys.par_iter(); - - trace_polys_iter - .map(|poly| { - evaluate_polynomial_on_lde_domain( - poly, - domain.blowup_factor, - domain.interpolation_domain_size, - &domain.coset_offset, - ) - }) - .collect::>>, FFTError>>() - .unwrap() -} + fn round_4_compute_and_run_fri_on_the_deep_composition_polynomial>( + air: &A, + domain: &Domain, + round_1_result: &Round1, + round_2_result: &Round2, + round_3_result: &Round3, + z: &FieldElement, + transcript: &mut impl IsStarkTranscript, + ) -> Round4 + where + FieldElement: Serializable + Send + Sync, + { + let coset_offset_u64 = air.context().proof_options.coset_offset; + let coset_offset = FieldElement::::from(coset_offset_u64); -fn round_1_randomized_air_with_preprocessing>( - air: &A, - main_trace: &TraceTable, - domain: &Domain, - transcript: &mut impl IsStarkTranscript, -) -> Result, ProvingError> -where - FieldElement: Serializable + Send + Sync, -{ - let (mut trace_polys, mut evaluations, main_merkle_tree, main_merkle_root) = - interpolate_and_commit(main_trace, domain, transcript); - - let rap_challenges = air.build_rap_challenges(transcript); - - let aux_trace = air.build_auxiliary_trace(main_trace, &rap_challenges); - - let mut lde_trace_merkle_trees = vec![main_merkle_tree]; - let mut lde_trace_merkle_roots = vec![main_merkle_root]; - if !aux_trace.is_empty() { - // Check that this is valid for interpolation - let (aux_trace_polys, aux_trace_polys_evaluations, aux_merkle_tree, aux_merkle_root) = - interpolate_and_commit(&aux_trace, domain, transcript); - trace_polys.extend_from_slice(&aux_trace_polys); - evaluations.extend_from_slice(&aux_trace_polys_evaluations); - lde_trace_merkle_trees.push(aux_merkle_tree); - lde_trace_merkle_roots.push(aux_merkle_root); - } - - let lde_trace = TraceTable::new_from_cols(&evaluations); - - Ok(Round1 { - trace_polys, - lde_trace, - lde_trace_merkle_roots, - lde_trace_merkle_trees, - rap_challenges, - }) -} + let gamma = transcript.sample_field_element(); + let n_terms_composition_poly = round_2_result.lde_composition_poly_evaluations.len(); + let n_terms_trace = air.context().transition_offsets.len() * air.context().trace_columns; -fn round_2_compute_composition_polynomial( - air: &A, - domain: &Domain, - round_1_result: &Round1, - transition_coefficients: &[FieldElement], - boundary_coefficients: &[FieldElement], -) -> Round2 -where - F: IsFFTField, - A: AIR + Send + Sync, - A::RAPChallenges: Send + Sync, - FieldElement: Serializable + Send + Sync, -{ - // Create evaluation table - let evaluator = ConstraintEvaluator::new(air, &round_1_result.rap_challenges); - - let constraint_evaluations = evaluator.evaluate( - &round_1_result.lde_trace, - domain, - transition_coefficients, - boundary_coefficients, - &round_1_result.rap_challenges, - ); - - // Get the composition poly H - let composition_poly = constraint_evaluations.compute_composition_poly(&domain.coset_offset); - let (composition_poly_even, composition_poly_odd) = composition_poly.even_odd_decomposition(); - - let lde_composition_poly_even_evaluations = evaluate_polynomial_on_lde_domain( - &composition_poly_even, - domain.blowup_factor, - domain.interpolation_domain_size, - &domain.coset_offset, - ) - .unwrap(); - let lde_composition_poly_odd_evaluations = evaluate_polynomial_on_lde_domain( - &composition_poly_odd, - domain.blowup_factor, - domain.interpolation_domain_size, - &domain.coset_offset, - ) - .unwrap(); - - // TODO: Remove clones - let composition_poly_evaluations: Vec> = lde_composition_poly_even_evaluations - .iter() - .zip(&lde_composition_poly_odd_evaluations) - .map(|(a, b)| vec![a.clone(), b.clone()]) - .collect(); - let (composition_poly_merkle_tree, composition_poly_root) = - batch_commit(&composition_poly_evaluations); - - Round2 { - composition_poly_even, - lde_composition_poly_even_evaluations, - composition_poly_merkle_tree, - composition_poly_root, - composition_poly_odd, - lde_composition_poly_odd_evaluations, + // <<<< Receive challenges: 𝛾, 𝛾' + let mut deep_composition_coefficients: Vec<_> = + core::iter::successors(Some(FieldElement::one()), |x| Some(x * &gamma)) + .take(n_terms_composition_poly + n_terms_trace) + .collect(); + + let trace_poly_coeffients: Vec<_> = deep_composition_coefficients + .drain(..n_terms_trace) + .collect(); + + // <<<< Receive challenges: 𝛾ⱼ, 𝛾ⱼ' + let gammas = deep_composition_coefficients; + + // Compute pβ‚€ (deep composition polynomial) + let deep_composition_poly = Self::compute_deep_composition_poly( + air, + &round_1_result.trace_polys, + round_2_result, + round_3_result, + z, + &domain.trace_primitive_root, + &gammas, + &trace_poly_coeffients, + ); + + let domain_size = domain.lde_roots_of_unity_coset.len(); + + // FRI commit and query phases + let (fri_last_value, fri_layers) = fri::commit_phase( + domain.root_order as usize, + deep_composition_poly, + transcript, + &coset_offset, + domain_size, + ); + + // grinding: generate nonce and append it to the transcript + let security_bits = air.context().proof_options.grinding_factor; + let mut nonce = 0; + if security_bits > 0 { + let transcript_challenge = transcript.state(); + nonce = generate_nonce_with_grinding(&transcript_challenge, security_bits) + .expect("nonce not found"); + transcript.append_bytes(&nonce.to_be_bytes()); + } + + let number_of_queries = air.options().fri_number_of_queries; + let iotas = Self::sample_query_indexes(number_of_queries, domain, transcript); + let query_list = fri::query_phase(&fri_layers, &iotas); + + let fri_layers_merkle_roots: Vec<_> = fri_layers + .iter() + .map(|layer| layer.merkle_tree.root) + .collect(); + + let (deep_poly_openings, deep_poly_openings_sym) = + Self::open_deep_composition_poly(domain, round_1_result, round_2_result, &iotas); + + Round4 { + fri_last_value, + fri_layers_merkle_roots, + deep_poly_openings, + deep_poly_openings_sym, + query_list, + nonce, + } } -} -fn round_3_evaluate_polynomials_in_out_of_domain_element>( - air: &A, - domain: &Domain, - round_1_result: &Round1, - round_2_result: &Round2, - z: &FieldElement, -) -> Round3 -where - FieldElement: Serializable, -{ - let z_squared = z.square(); - - // Evaluate H_1 and H_2 in z^2. - let composition_poly_even_ood_evaluation = - round_2_result.composition_poly_even.evaluate(&z_squared); - let composition_poly_odd_ood_evaluation = - round_2_result.composition_poly_odd.evaluate(&z_squared); - - // Returns the Out of Domain Frame for the given trace polynomials, out of domain evaluation point (called `z` in the literature), - // frame offsets given by the AIR and primitive root used for interpolating the trace polynomials. - // An out of domain frame is nothing more than the evaluation of the trace polynomials in the points required by the - // verifier to check the consistency between the trace and the composition polynomial. - // - // In the fibonacci example, the ood frame is simply the evaluations `[t(z), t(z * g), t(z * g^2)]`, where `t` is the trace - // polynomial and `g` is the primitive root of unity used when interpolating `t`. - let trace_ood_evaluations = Frame::get_trace_evaluations( - &round_1_result.trace_polys, - z, - &air.context().transition_offsets, - &domain.trace_primitive_root, - ); - - Round3 { - trace_ood_evaluations, - composition_poly_even_ood_evaluation, - composition_poly_odd_ood_evaluation, + fn sample_query_indexes( + number_of_queries: usize, + domain: &Domain, + transcript: &mut impl IsStarkTranscript, + ) -> Vec { + let domain_size = domain.lde_roots_of_unity_coset.len() as u64; + (0..number_of_queries) + .map(|_| (transcript.sample_u64(domain_size >> 1)) as usize) + .collect::>() } -} -fn round_4_compute_and_run_fri_on_the_deep_composition_polynomial< - F: IsFFTField, - A: AIR, ->( - air: &A, - domain: &Domain, - round_1_result: &Round1, - round_2_result: &Round2, - round_3_result: &Round3, - z: &FieldElement, - transcript: &mut impl IsStarkTranscript, -) -> Round4 -where - FieldElement: Serializable + Send + Sync, -{ - let coset_offset_u64 = air.context().proof_options.coset_offset; - let coset_offset = FieldElement::::from(coset_offset_u64); - - // <<<< Receive challenges: 𝛾, 𝛾' - let composition_poly_coeffients = [ - transcript.sample_field_element(), - transcript.sample_field_element(), - ]; - // <<<< Receive challenges: 𝛾ⱼ, 𝛾ⱼ' - let trace_poly_coeffients = batch_sample_challenges::( - air.context().transition_offsets.len() * air.context().trace_columns, - transcript, - ); - - // Compute pβ‚€ (deep composition polynomial) - let deep_composition_poly = compute_deep_composition_poly( - air, - &round_1_result.trace_polys, - round_2_result, - round_3_result, - z, - &domain.trace_primitive_root, - &composition_poly_coeffients, - &trace_poly_coeffients, - ); - - let domain_size = domain.lde_roots_of_unity_coset.len(); - - // FRI commit and query phases - let (fri_last_value, fri_layers) = fri_commit_phase( - domain.root_order as usize, - deep_composition_poly, - transcript, - &coset_offset, - domain_size, - ); - - // grinding: generate nonce and append it to the transcript - let grinding_factor = air.context().proof_options.grinding_factor; - let transcript_challenge = transcript.state(); - let nonce = generate_nonce_with_grinding(&transcript_challenge, grinding_factor) - .expect("nonce not found"); - transcript.append_bytes(&nonce.to_be_bytes()); - - let (query_list, iotas) = fri_query_phase(air, domain_size, &fri_layers, transcript); - - let fri_layers_merkle_roots: Vec<_> = fri_layers - .iter() - .map(|layer| layer.merkle_tree.root) - .collect(); - - let deep_poly_openings = - open_deep_composition_poly(domain, round_1_result, round_2_result, &iotas); - - Round4 { - fri_last_value, - fri_layers_merkle_roots, - deep_poly_openings, - query_list, - nonce, + /// Returns the DEEP composition polynomial that the prover then commits to using + /// FRI. This polynomial is a linear combination of the trace polynomial and the + /// composition polynomial, with coefficients sampled by the verifier (i.e. using Fiat-Shamir). + #[allow(clippy::too_many_arguments)] + fn compute_deep_composition_poly( + air: &A, + trace_polys: &[Polynomial>], + round_2_result: &Round2, + round_3_result: &Round3, + z: &FieldElement, + primitive_root: &FieldElement, + composition_poly_gammas: &[FieldElement], + trace_terms_gammas: &[FieldElement], + ) -> Polynomial> + where + A: AIR, + FieldElement: Serializable + Send + Sync, + { + let z_power = z.pow(round_2_result.composition_poly_parts.len()); + + // βˆ‘α΅’ 𝛾ᡒ ( Hα΅’ βˆ’ Hα΅’(z^N) ) / ( X βˆ’ z^N ) + let mut h_terms = Polynomial::zero(); + for (i, part) in round_2_result.composition_poly_parts.iter().enumerate() { + // h_i_eval is the evaluation of the i-th part of the composition polynomial at z^N, + // where N is the number of parts of the composition polynomial. + let h_i_eval = &round_3_result.composition_poly_parts_ood_evaluation[i]; + let h_i_term = &composition_poly_gammas[i] * (part - h_i_eval); + h_terms = h_terms + h_i_term; + } + assert_eq!(h_terms.evaluate(&z_power), FieldElement::zero()); + h_terms.ruffini_division_inplace(&z_power); + + // Get trace evaluations needed for the trace terms of the deep composition polynomial + let transition_offsets = &air.context().transition_offsets; + let trace_frame_evaluations = &round_3_result.trace_ood_evaluations; + + // Compute the sum of all the trace terms of the deep composition polynomial. + // There is one term for every trace polynomial and for every row in the frame. + // βˆ‘ β±Όβ‚– [ 𝛾ₖ ( tβ±Ό βˆ’ tβ±Ό(z) ) / ( X βˆ’ zgᡏ )] + + // @@@ this could be const + let trace_frame_length = trace_frame_evaluations.len(); + + #[cfg(feature = "parallel")] + let trace_terms = trace_polys + .par_iter() + .enumerate() + .fold( + || Polynomial::zero(), + |trace_terms, (i, t_j)| { + compute_trace_term( + &trace_terms, + (i, t_j), + trace_frame_length, + trace_terms_gammas, + trace_frame_evaluations, + transition_offsets, + (z, primitive_root), + ) + }, + ) + .reduce(|| Polynomial::zero(), |a, b| a + b); + + #[cfg(not(feature = "parallel"))] + let trace_terms = + trace_polys + .iter() + .enumerate() + .fold(Polynomial::zero(), |trace_terms, (i, t_j)| { + Self::compute_trace_term( + &trace_terms, + (i, t_j), + trace_frame_length, + trace_terms_gammas, + trace_frame_evaluations, + transition_offsets, + (z, primitive_root), + ) + }); + + h_terms + trace_terms } -} -/// Returns the DEEP composition polynomial that the prover then commits to using -/// FRI. This polynomial is a linear combination of the trace polynomial and the -/// composition polynomial, with coefficients sampled by the verifier (i.e. using Fiat-Shamir). -#[allow(clippy::too_many_arguments)] -fn compute_deep_composition_poly( - air: &A, - trace_polys: &[Polynomial>], - round_2_result: &Round2, - round_3_result: &Round3, - z: &FieldElement, - primitive_root: &FieldElement, - composition_poly_gammas: &[FieldElement; 2], - trace_terms_gammas: &[FieldElement], -) -> Polynomial> -where - A: AIR, - F: IsFFTField, - FieldElement: Serializable + Send + Sync, -{ - // Compute composition polynomial terms of the deep composition polynomial. - let h_1 = &round_2_result.composition_poly_even; - let h_1_z2 = &round_3_result.composition_poly_even_ood_evaluation; - let h_2 = &round_2_result.composition_poly_odd; - let h_2_z2 = &round_3_result.composition_poly_odd_ood_evaluation; - let gamma = &composition_poly_gammas[0]; - let gamma_p = &composition_poly_gammas[1]; - let z_squared = z.square(); - - // 𝛾 ( H₁ βˆ’ H₁(zΒ²) ) / ( X βˆ’ zΒ² ) - let mut h_1_term = gamma * (h_1 - h_1_z2); - h_1_term.ruffini_division_inplace(&z_squared); - - // 𝛾' ( Hβ‚‚ βˆ’ Hβ‚‚(zΒ²) ) / ( X βˆ’ zΒ² ) - let mut h_2_term = gamma_p * (h_2 - h_2_z2); - h_2_term.ruffini_division_inplace(&z_squared); - - // Get trace evaluations needed for the trace terms of the deep composition polynomial - let transition_offsets = &air.context().transition_offsets; - let trace_frame_evaluations = &round_3_result.trace_ood_evaluations; - - // Compute the sum of all the trace terms of the deep composition polynomial. - // There is one term for every trace polynomial and for every row in the frame. - // βˆ‘ β±Όβ‚– [ 𝛾ₖ ( tβ±Ό βˆ’ tβ±Ό(z) ) / ( X βˆ’ zgᡏ )] - - // @@@ this could be const - let trace_frame_length = trace_frame_evaluations.len(); - - #[cfg(feature = "parallel")] - let trace_term = trace_polys - .par_iter() - .enumerate() - .fold( - || Polynomial::zero(), - |trace_terms, (i, t_j)| { - compute_trace_term( - &trace_terms, - (i, t_j), - trace_frame_length, - trace_terms_gammas, - trace_frame_evaluations, - transition_offsets, - (z, primitive_root), - ) - }, - ) - .reduce(|| Polynomial::zero(), |a, b| a + b); + fn compute_trace_term( + trace_terms: &Polynomial>, + (i, t_j): (usize, &Polynomial>), + trace_frame_length: usize, + trace_terms_gammas: &[FieldElement], + trace_frame_evaluations: &[Vec>], + transition_offsets: &[usize], + (z, primitive_root): (&FieldElement, &FieldElement), + ) -> Polynomial> + where + FieldElement: Serializable + Send + Sync, + { + let i_times_trace_frame_evaluation = i * trace_frame_length; + let iter_trace_gammas = trace_terms_gammas + .iter() + .skip(i_times_trace_frame_evaluation); + let trace_int = trace_frame_evaluations + .iter() + .zip(transition_offsets) + .zip(iter_trace_gammas) + .fold( + Polynomial::zero(), + |trace_agg, ((eval, offset), trace_gamma)| { + // @@@ we can avoid this clone + let t_j_z = &eval[i]; + // @@@ this can be pre-computed + let z_shifted = z * primitive_root.pow(*offset); + let mut poly = t_j - t_j_z; + poly.ruffini_division_inplace(&z_shifted); + trace_agg + poly * trace_gamma + }, + ); + + trace_terms + trace_int + } - #[cfg(not(feature = "parallel"))] - let trace_term = - trace_polys + fn open_composition_poly( + composition_poly_merkle_tree: &BatchedMerkleTree, + lde_composition_poly_evaluations: &[Vec>], + index: usize, + ) -> (Proof, Vec>) + where + FieldElement: Serializable, + { + let proof = composition_poly_merkle_tree + .get_proof_by_pos(index) + .unwrap(); + + let lde_composition_poly_parts_evaluation: Vec<_> = lde_composition_poly_evaluations .iter() - .enumerate() - .fold(Polynomial::zero(), |trace_terms, (i, t_j)| { - compute_trace_term( - &trace_terms, - (i, t_j), - trace_frame_length, - trace_terms_gammas, - trace_frame_evaluations, - transition_offsets, - (z, primitive_root), - ) - }); + .flat_map(|part| { + vec![ + part[reverse_index(index * 2, part.len() as u64)].clone(), + part[reverse_index(index * 2 + 1, part.len() as u64)].clone(), + ] + }) + .collect(); + + (proof, lde_composition_poly_parts_evaluation) + } - h_1_term + h_2_term + trace_term -} + fn open_trace_polys( + domain: &Domain, + lde_trace_merkle_trees: &[BatchedMerkleTree], + lde_trace: &TraceTable, + index: usize, + ) -> (Vec>, Vec>) + where + FieldElement: Serializable, + { + let domain_size = domain.lde_roots_of_unity_coset.len(); + let lde_trace_evaluations = lde_trace + .get_row(reverse_index(index, domain_size as u64)) + .to_vec(); + + // Trace polynomials openings + #[cfg(feature = "parallel")] + let merkle_trees_iter = lde_trace_merkle_trees.par_iter(); + #[cfg(not(feature = "parallel"))] + let merkle_trees_iter = lde_trace_merkle_trees.iter(); + + let lde_trace_merkle_proofs: Vec> = merkle_trees_iter + .map(|tree| tree.get_proof_by_pos(index).unwrap()) + .collect(); + + (lde_trace_merkle_proofs, lde_trace_evaluations) + } -fn compute_trace_term( - trace_terms: &Polynomial>, - (i, t_j): (usize, &Polynomial>), - trace_frame_length: usize, - trace_terms_gammas: &[FieldElement], - trace_frame_evaluations: &[Vec>], - transition_offsets: &[usize], - (z, primitive_root): (&FieldElement, &FieldElement), -) -> Polynomial> -where - F: IsFFTField, - FieldElement: Serializable + Send + Sync, -{ - let i_times_trace_frame_evaluation = i * trace_frame_length; - let iter_trace_gammas = trace_terms_gammas - .iter() - .skip(i_times_trace_frame_evaluation); - let trace_int = trace_frame_evaluations - .iter() - .zip(transition_offsets) - .zip(iter_trace_gammas) - .fold( - Polynomial::zero(), - |trace_agg, ((eval, offset), trace_gamma)| { - // @@@ we can avoid this clone - let t_j_z = &eval[i]; - // @@@ this can be pre-computed - let z_shifted = z * primitive_root.pow(*offset); - let mut poly = t_j - t_j_z; - poly.ruffini_division_inplace(&z_shifted); - trace_agg + poly * trace_gamma - }, - ); - - trace_terms + trace_int -} + /// Open the deep composition polynomial on a list of indexes + /// and their symmetric elements. + fn open_deep_composition_poly>( + domain: &Domain, + round_1_result: &Round1, + round_2_result: &Round2, + indexes_to_open: &[usize], + ) -> ( + DeepPolynomialOpenings, + DeepPolynomialOpenings, + ) + where + FieldElement: Serializable, + { + let mut openings = Vec::new(); + let mut openings_symmetric = Vec::new(); + + for index in indexes_to_open.iter() { + let (lde_trace_merkle_proofs, lde_trace_evaluations) = Self::open_trace_polys( + domain, + &round_1_result.lde_trace_merkle_trees, + &round_1_result.lde_trace, + index * 2, + ); -fn open_deep_composition_poly>( - domain: &Domain, - round_1_result: &Round1, - round_2_result: &Round2, - indexes_to_open: &[usize], // list of iotas -) -> Vec> -where - FieldElement: Serializable, -{ - let permutation = - get_stone_prover_domain_permutation(domain.interpolation_domain_size, domain.blowup_factor); - indexes_to_open - .iter() - .map(|index_to_open| { - let index = index_to_open % domain.lde_roots_of_unity_coset.len(); - - let lde_composition_poly_proof = round_2_result - .composition_poly_merkle_tree - .get_proof_by_pos(index) - .unwrap(); - - // H₁ openings - let lde_composition_poly_even_evaluation = - round_2_result.lde_composition_poly_even_evaluations[index].clone(); - - // Hβ‚‚ openings - let lde_composition_poly_odd_evaluation = - round_2_result.lde_composition_poly_odd_evaluations[index].clone(); - - let lde_trace_evaluations = round_1_result.lde_trace.get_row(index).to_vec(); - - let index = permutation[index]; - // Trace polynomials openings - #[cfg(feature = "parallel")] - let merkle_trees_iter = round_1_result.lde_trace_merkle_trees.par_iter(); - #[cfg(not(feature = "parallel"))] - let merkle_trees_iter = round_1_result.lde_trace_merkle_trees.iter(); - - let lde_trace_merkle_proofs: Vec> = merkle_trees_iter - .map(|tree| tree.get_proof_by_pos(index).unwrap()) - .collect(); + let (lde_trace_sym_merkle_proofs, lde_trace_sym_evaluations) = Self::open_trace_polys( + domain, + &round_1_result.lde_trace_merkle_trees, + &round_1_result.lde_trace, + index * 2 + 1, + ); - DeepPolynomialOpenings { - lde_composition_poly_proof, - lde_composition_poly_even_evaluation, - lde_composition_poly_odd_evaluation, + let (lde_composition_poly_proof, lde_composition_poly_parts_evaluation) = + Self::open_composition_poly( + &round_2_result.composition_poly_merkle_tree, + &round_2_result.lde_composition_poly_evaluations, + *index, + ); + + openings.push(DeepPolynomialOpening { + lde_composition_poly_proof: lde_composition_poly_proof.clone(), + lde_composition_poly_parts_evaluation: lde_composition_poly_parts_evaluation + .clone() + .into_iter() + .step_by(2) + .collect(), lde_trace_merkle_proofs, lde_trace_evaluations, - } - }) - .collect() -} + }); -// FIXME remove unwrap() calls and return errors -pub fn prove( - main_trace: &TraceTable, - pub_inputs: &A::PublicInputs, - proof_options: &ProofOptions, - mut transcript: impl IsStarkTranscript, -) -> Result, ProvingError> -where - F: IsFFTField, - A: AIR + Send + Sync, - A::RAPChallenges: Send + Sync, - FieldElement: Serializable + Send + Sync, -{ - info!("Started proof generation..."); - #[cfg(feature = "instruments")] - println!("- Started round 0: Air Initialization"); - #[cfg(feature = "instruments")] - let timer0 = Instant::now(); - - let air = A::new(main_trace.n_rows(), pub_inputs, proof_options); - let domain = Domain::new(&air); - - #[cfg(feature = "instruments")] - let elapsed0 = timer0.elapsed(); - #[cfg(feature = "instruments")] - println!(" Time spent: {:?}", elapsed0); - - // =================================== - // ==========| Round 1 |========== - // =================================== - - #[cfg(feature = "instruments")] - println!("- Started round 1: RAP"); - #[cfg(feature = "instruments")] - let timer1 = Instant::now(); - - let round_1_result = round_1_randomized_air_with_preprocessing::( - &air, - main_trace, - &domain, - &mut transcript, - )?; - - #[cfg(debug_assertions)] - validate_trace( - &air, - &round_1_result.trace_polys, - &domain, - &round_1_result.rap_challenges, - ); - - #[cfg(feature = "instruments")] - let elapsed1 = timer1.elapsed(); - #[cfg(feature = "instruments")] - println!(" Time spent: {:?}", elapsed1); - - // =================================== - // ==========| Round 2 |========== - // =================================== - - #[cfg(feature = "instruments")] - println!("- Started round 2: Compute composition polynomial"); - #[cfg(feature = "instruments")] - let timer2 = Instant::now(); - - // <<<< Receive challenge: 𝛽 - let beta = transcript.sample_field_element(); - let num_boundary_constraints = air - .boundary_constraints(&round_1_result.rap_challenges) - .constraints - .len(); - - let num_transition_constraints = air.context().num_transition_constraints; - - let mut coefficients: Vec<_> = (1..num_boundary_constraints + num_transition_constraints + 1) - .map(|i| beta.pow(i)) - .collect(); - - let transition_coefficients: Vec<_> = - coefficients.drain(..num_transition_constraints).collect(); - let boundary_coefficients = coefficients; - - let round_2_result = round_2_compute_composition_polynomial( - &air, - &domain, - &round_1_result, - &transition_coefficients, - &boundary_coefficients, - ); - - // >>>> Send commitments: [H₁], [Hβ‚‚] - transcript.append_bytes(&round_2_result.composition_poly_root); - - #[cfg(feature = "instruments")] - let elapsed2 = timer2.elapsed(); - #[cfg(feature = "instruments")] - println!(" Time spent: {:?}", elapsed2); - - // =================================== - // ==========| Round 3 |========== - // =================================== - - #[cfg(feature = "instruments")] - println!("- Started round 3: Evaluate polynomial in out of domain elements"); - #[cfg(feature = "instruments")] - let timer3 = Instant::now(); - - // <<<< Receive challenge: z - let z = transcript.sample_z_ood( - &domain.lde_roots_of_unity_coset, - &domain.trace_roots_of_unity, - ); - - let round_3_result = round_3_evaluate_polynomials_in_out_of_domain_element( - &air, - &domain, - &round_1_result, - &round_2_result, - &z, - ); - - // >>>> Send value: H₁(zΒ²) - transcript.append_field_element(&round_3_result.composition_poly_even_ood_evaluation); - - // >>>> Send value: Hβ‚‚(zΒ²) - transcript.append_field_element(&round_3_result.composition_poly_odd_ood_evaluation); - // >>>> Send values: tβ±Ό(zgᡏ) - for row in round_3_result.trace_ood_evaluations.iter() { - for element in row.iter() { - transcript.append_field_element(element); + openings_symmetric.push(DeepPolynomialOpening { + lde_composition_poly_proof, + lde_composition_poly_parts_evaluation: lde_composition_poly_parts_evaluation + .into_iter() + .skip(1) + .step_by(2) + .collect(), + lde_trace_merkle_proofs: lde_trace_sym_merkle_proofs, + lde_trace_evaluations: lde_trace_sym_evaluations, + }); } + + (openings, openings_symmetric) } - #[cfg(feature = "instruments")] - let elapsed3 = timer3.elapsed(); - #[cfg(feature = "instruments")] - println!(" Time spent: {:?}", elapsed3); - - // =================================== - // ==========| Round 4 |========== - // =================================== - - #[cfg(feature = "instruments")] - println!("- Started round 4: FRI"); - #[cfg(feature = "instruments")] - let timer4 = Instant::now(); - - // Part of this round is running FRI, which is an interactive - // protocol on its own. Therefore we pass it the transcript - // to simulate the interactions with the verifier. - let round_4_result = round_4_compute_and_run_fri_on_the_deep_composition_polynomial( - &air, - &domain, - &round_1_result, - &round_2_result, - &round_3_result, - &z, - &mut transcript, - ); - - #[cfg(feature = "instruments")] - let elapsed4 = timer4.elapsed(); - #[cfg(feature = "instruments")] - println!(" Time spent: {:?}", elapsed4); - - #[cfg(feature = "instruments")] + // FIXME remove unwrap() calls and return errors + fn prove( + main_trace: &TraceTable, + pub_inputs: &A::PublicInputs, + proof_options: &ProofOptions, + mut transcript: impl IsStarkTranscript, + ) -> Result, ProvingError> + where + A: AIR + Send + Sync, + A::RAPChallenges: Send + Sync, + FieldElement: Serializable + Send + Sync, { - let total_time = elapsed1 + elapsed2 + elapsed3 + elapsed4; - println!( - " Fraction of proving time per round: {:.4} {:.4} {:.4} {:.4} {:.4}", - elapsed0.as_nanos() as f64 / total_time.as_nanos() as f64, - elapsed1.as_nanos() as f64 / total_time.as_nanos() as f64, - elapsed2.as_nanos() as f64 / total_time.as_nanos() as f64, - elapsed3.as_nanos() as f64 / total_time.as_nanos() as f64, - elapsed4.as_nanos() as f64 / total_time.as_nanos() as f64 - ); - } - - info!("End proof generation"); - - let trace_ood_frame_evaluations = Frame::new( - round_3_result - .trace_ood_evaluations - .into_iter() - .flatten() - .collect(), - round_1_result.trace_polys.len(), - ); - - Ok(StarkProof { - // [tβ±Ό] - lde_trace_merkle_roots: round_1_result.lde_trace_merkle_roots, - // tβ±Ό(zgᡏ) - trace_ood_frame_evaluations, - // [H₁] and [Hβ‚‚] - composition_poly_root: round_2_result.composition_poly_root, - // H₁(zΒ²) - composition_poly_even_ood_evaluation: round_3_result.composition_poly_even_ood_evaluation, - // Hβ‚‚(zΒ²) - composition_poly_odd_ood_evaluation: round_3_result.composition_poly_odd_ood_evaluation, - // [pβ‚–] - fri_layers_merkle_roots: round_4_result.fri_layers_merkle_roots, - // pβ‚™ - fri_last_value: round_4_result.fri_last_value, - // Open(pβ‚€(Dβ‚€), πœβ‚›), Open(pβ‚–(Dβ‚–), βˆ’πœβ‚›^(2ᡏ)) - query_list: round_4_result.query_list, - // Open(H₁(D_LDE, πœβ‚€), Open(Hβ‚‚(D_LDE, πœβ‚€), Open(tβ±Ό(D_LDE), πœβ‚€) - deep_poly_openings: round_4_result.deep_poly_openings, - // nonce obtained from grinding - nonce: round_4_result.nonce, - - trace_length: air.trace_length(), - }) -} + info!("Started proof generation..."); + #[cfg(feature = "instruments")] + println!("- Started round 0: Air Initialization"); + #[cfg(feature = "instruments")] + let timer0 = Instant::now(); + + let air = A::new(main_trace.n_rows(), pub_inputs, proof_options); + let domain = Domain::new(&air); + + #[cfg(feature = "instruments")] + let elapsed0 = timer0.elapsed(); + #[cfg(feature = "instruments")] + println!(" Time spent: {:?}", elapsed0); + + // =================================== + // ==========| Round 1 |========== + // =================================== + + #[cfg(feature = "instruments")] + println!("- Started round 1: RAP"); + #[cfg(feature = "instruments")] + let timer1 = Instant::now(); + + let round_1_result = Self::round_1_randomized_air_with_preprocessing::( + &air, + main_trace, + &domain, + &mut transcript, + )?; + + #[cfg(debug_assertions)] + validate_trace( + &air, + &round_1_result.trace_polys, + &domain, + &round_1_result.rap_challenges, + ); + + #[cfg(feature = "instruments")] + let elapsed1 = timer1.elapsed(); + #[cfg(feature = "instruments")] + println!(" Time spent: {:?}", elapsed1); + + // =================================== + // ==========| Round 2 |========== + // =================================== + #[cfg(feature = "instruments")] + println!("- Started round 2: Compute composition polynomial"); + #[cfg(feature = "instruments")] + let timer2 = Instant::now(); + + // <<<< Receive challenge: 𝛽 + let beta = transcript.sample_field_element(); + let num_boundary_constraints = air + .boundary_constraints(&round_1_result.rap_challenges) + .constraints + .len(); + + let num_transition_constraints = air.context().num_transition_constraints; + + let mut coefficients: Vec<_> = + core::iter::successors(Some(FieldElement::one()), |x| Some(x * &beta)) + .take(num_boundary_constraints + num_transition_constraints) + .collect(); + + let transition_coefficients: Vec<_> = + coefficients.drain(..num_transition_constraints).collect(); + let boundary_coefficients = coefficients; + + let round_2_result = Self::round_2_compute_composition_polynomial( + &air, + &domain, + &round_1_result, + &transition_coefficients, + &boundary_coefficients, + ); + + // >>>> Send commitments: [H₁], [Hβ‚‚] + transcript.append_bytes(&round_2_result.composition_poly_root); + + #[cfg(feature = "instruments")] + let elapsed2 = timer2.elapsed(); + #[cfg(feature = "instruments")] + println!(" Time spent: {:?}", elapsed2); + + // =================================== + // ==========| Round 3 |========== + // =================================== + + #[cfg(feature = "instruments")] + println!("- Started round 3: Evaluate polynomial in out of domain elements"); + #[cfg(feature = "instruments")] + let timer3 = Instant::now(); + + // <<<< Receive challenge: z + let z = transcript.sample_z_ood( + &domain.lde_roots_of_unity_coset, + &domain.trace_roots_of_unity, + ); + + let round_3_result = Self::round_3_evaluate_polynomials_in_out_of_domain_element( + &air, + &domain, + &round_1_result, + &round_2_result, + &z, + ); + + // >>>> Send values: tβ±Ό(zgᡏ) + for i in 0..round_3_result.trace_ood_evaluations[0].len() { + for j in 0..round_3_result.trace_ood_evaluations.len() { + transcript.append_field_element(&round_3_result.trace_ood_evaluations[j][i]); + } + } + + // >>>> Send values: Hα΅’(z^N) + for element in round_3_result.composition_poly_parts_ood_evaluation.iter() { + transcript.append_field_element(element); + } + + #[cfg(feature = "instruments")] + let elapsed3 = timer3.elapsed(); + #[cfg(feature = "instruments")] + println!(" Time spent: {:?}", elapsed3); + + // =================================== + // ==========| Round 4 |========== + // =================================== + + #[cfg(feature = "instruments")] + println!("- Started round 4: FRI"); + #[cfg(feature = "instruments")] + let timer4 = Instant::now(); + + // Part of this round is running FRI, which is an interactive + // protocol on its own. Therefore we pass it the transcript + // to simulate the interactions with the verifier. + let round_4_result = Self::round_4_compute_and_run_fri_on_the_deep_composition_polynomial( + &air, + &domain, + &round_1_result, + &round_2_result, + &round_3_result, + &z, + &mut transcript, + ); + + #[cfg(feature = "instruments")] + let elapsed4 = timer4.elapsed(); + #[cfg(feature = "instruments")] + println!(" Time spent: {:?}", elapsed4); + + #[cfg(feature = "instruments")] + { + let total_time = elapsed1 + elapsed2 + elapsed3 + elapsed4; + println!( + " Fraction of proving time per round: {:.4} {:.4} {:.4} {:.4} {:.4}", + elapsed0.as_nanos() as f64 / total_time.as_nanos() as f64, + elapsed1.as_nanos() as f64 / total_time.as_nanos() as f64, + elapsed2.as_nanos() as f64 / total_time.as_nanos() as f64, + elapsed3.as_nanos() as f64 / total_time.as_nanos() as f64, + elapsed4.as_nanos() as f64 / total_time.as_nanos() as f64 + ); + } + + info!("End proof generation"); + + let trace_ood_frame_evaluations = Frame::new( + round_3_result + .trace_ood_evaluations + .into_iter() + .flatten() + .collect(), + round_1_result.trace_polys.len(), + ); + + Ok(StarkProof { + // [tβ±Ό] + lde_trace_merkle_roots: round_1_result.lde_trace_merkle_roots, + // tβ±Ό(zgᡏ) + trace_ood_frame_evaluations, + // [H₁] and [Hβ‚‚] + composition_poly_root: round_2_result.composition_poly_root, + // Hα΅’(z^N) + composition_poly_parts_ood_evaluation: round_3_result + .composition_poly_parts_ood_evaluation, + // [pβ‚–] + fri_layers_merkle_roots: round_4_result.fri_layers_merkle_roots, + // pβ‚™ + fri_last_value: round_4_result.fri_last_value, + // Open(pβ‚€(Dβ‚€), πœβ‚›), Open(pβ‚–(Dβ‚–), βˆ’πœβ‚›^(2ᡏ)) + query_list: round_4_result.query_list, + // Open(H₁(D_LDE, πœβ‚€), Open(Hβ‚‚(D_LDE, πœβ‚€), Open(tβ±Ό(D_LDE), πœβ‚€) + deep_poly_openings: round_4_result.deep_poly_openings, + // Open(H₁(D_LDE, πœβ‚€), Open(Hβ‚‚(D_LDE, πœβ‚€), Open(tβ±Ό(D_LDE), πœβ‚€) + deep_poly_openings_sym: round_4_result.deep_poly_openings_sym, + // nonce obtained from grinding + nonce: round_4_result.nonce, + + trace_length: air.trace_length(), + }) + } +} #[cfg(test)] mod tests { use std::num::ParseIntError; + fn decode_hex(s: &str) -> Result, ParseIntError> { + (0..s.len()) + .step_by(2) + .map(|i| u8::from_str_radix(&s[i..i + 2], 16)) + .collect() + } + use crate::{ examples::{ fibonacci_2_cols_shifted::{self, Fibonacci2ColsShifted}, @@ -836,6 +906,7 @@ mod tests { }, proof::options::ProofOptions, transcript::StoneProverTranscript, + verifier::{Challenges, IsStarkVerifier, Verifier}, Felt252, }; @@ -875,10 +946,6 @@ mod tests { assert_eq!(domain.blowup_factor, 2); assert_eq!(domain.interpolation_domain_size, trace_length); assert_eq!(domain.root_order, trace_length.trailing_zeros()); - assert_eq!( - domain.lde_root_order, - (trace_length * blowup_factor).trailing_zeros() - ); assert_eq!(domain.coset_offset, FieldElement::from(coset_offset)); let primitive_root = Stark252PrimeField::get_primitive_root_of_unity( @@ -945,15 +1012,12 @@ mod tests { } } - pub fn decode_hex(s: &str) -> Result, ParseIntError> { - (0..s.len()) - .step_by(2) - .map(|i| u8::from_str_radix(&s[i..i + 2], 16)) - .collect() - } - - #[test] - fn test_trace_commitment_is_compatible_with_stone_prover_1() { + fn proof_parts_stone_compatibility_case_1() -> ( + StarkProof, + fibonacci_2_cols_shifted::PublicInputs, + ProofOptions, + [u8; 4], + ) { let trace = fibonacci_2_cols_shifted::compute_trace(FieldElement::one(), 4); let claimed_index = 3; @@ -961,6 +1025,8 @@ mod tests { let mut proof_options = ProofOptions::default_test_options(); proof_options.blowup_factor = 4; proof_options.coset_offset = 3; + proof_options.grinding_factor = 0; + proof_options.fri_number_of_queries = 1; let pub_inputs = fibonacci_2_cols_shifted::PublicInputs { claimed_value, @@ -969,30 +1035,381 @@ mod tests { let transcript_init_seed = [0xca, 0xfe, 0xca, 0xfe]; - let air = Fibonacci2ColsShifted::new(trace.n_rows(), &pub_inputs, &proof_options); - let domain = Domain::new(&air); - - let (_, _, _, trace_commitment) = interpolate_and_commit( + let proof = Prover::prove::>( &trace, + &pub_inputs, + &proof_options, + StoneProverTranscript::new(&transcript_init_seed), + ) + .unwrap(); + (proof, pub_inputs, proof_options, transcript_init_seed) + } + + fn stone_compatibility_case_1_proof() -> StarkProof { + let (proof, _, _, _) = proof_parts_stone_compatibility_case_1(); + proof + } + + fn stone_compatibility_case_1_challenges( + ) -> Challenges> { + let (proof, public_inputs, options, seed) = proof_parts_stone_compatibility_case_1(); + + let air = Fibonacci2ColsShifted::new(proof.trace_length, &public_inputs, &options); + let domain = Domain::new(&air); + Verifier::step_1_replay_rounds_and_recover_challenges( + &air, + &proof, &domain, - &mut StoneProverTranscript::new(&transcript_init_seed), + &mut StoneProverTranscript::new(&seed), + ) + } + + #[test] + fn stone_compatibility_case_1_proof_is_valid() { + let (proof, public_inputs, options, seed) = proof_parts_stone_compatibility_case_1(); + assert!(Verifier::verify::>( + &proof, + &public_inputs, + &options, + StoneProverTranscript::new(&seed) + )); + } + + #[test] + fn stone_compatibility_case_1_trace_commitment() { + let proof = stone_compatibility_case_1_proof(); + + assert_eq!( + proof.lde_trace_merkle_roots[0].to_vec(), + decode_hex("0eb9dcc0fb1854572a01236753ce05139d392aa3aeafe72abff150fe21175594").unwrap() ); + } + + #[test] + fn stone_compatibility_case_1_composition_poly_challenges() { + let challenges = stone_compatibility_case_1_challenges(); + assert_eq!(challenges.transition_coeffs[0], FieldElement::one()); + let beta = challenges.transition_coeffs[1]; assert_eq!( - &trace_commitment.to_vec(), - &decode_hex("0eb9dcc0fb1854572a01236753ce05139d392aa3aeafe72abff150fe21175594") - .unwrap() + beta, + FieldElement::from_hex_unchecked( + "86105fff7b04ed4068ecccb8dbf1ed223bd45cd26c3532d6c80a818dbd4fa7" + ), + ); + + assert_eq!(challenges.boundary_coeffs[0], beta.pow(2u64)); + assert_eq!(challenges.boundary_coeffs[1], beta.pow(3u64)); + } + + #[test] + fn stone_compatibility_case_1_composition_poly_commitment() { + let proof = stone_compatibility_case_1_proof(); + // Composition polynomial commitment + assert_eq!( + proof.composition_poly_root.to_vec(), + decode_hex("7cdd8d5fe3bd62254a417e2e260e0fed4fccdb6c9005e828446f645879394f38").unwrap() ); } + #[test] - fn test_trace_commitment_is_compatible_with_stone_prover_2() { - let trace = fibonacci_2_cols_shifted::compute_trace(FieldElement::one(), 4); + fn stone_compatibility_case_1_out_of_domain_challenge() { + let challenges = stone_compatibility_case_1_challenges(); + assert_eq!( + challenges.z, + FieldElement::from_hex_unchecked( + "317629e783794b52cd27ac3a5e418c057fec9dd42f2b537cdb3f24c95b3e550" + ) + ); + } - let claimed_index = 3; + #[test] + fn stone_compatibility_case_1_out_of_domain_trace_evaluation() { + let proof = stone_compatibility_case_1_proof(); + + assert_eq!( + proof.trace_ood_frame_evaluations.get_row(0)[0], + FieldElement::from_hex_unchecked( + "70d8181785336cc7e0a0a1078a79ee6541ca0803ed3ff716de5a13c41684037", + ) + ); + assert_eq!( + proof.trace_ood_frame_evaluations.get_row(1)[0], + FieldElement::from_hex_unchecked( + "29808fc8b7480a69295e4b61600480ae574ca55f8d118100940501b789c1630", + ) + ); + assert_eq!( + proof.trace_ood_frame_evaluations.get_row(0)[1], + FieldElement::from_hex_unchecked( + "7d8110f21d1543324cc5e472ab82037eaad785707f8cae3d64c5b9034f0abd2", + ) + ); + assert_eq!( + proof.trace_ood_frame_evaluations.get_row(1)[1], + FieldElement::from_hex_unchecked( + "1b58470130218c122f71399bf1e04cf75a6e8556c4751629d5ce8c02cc4e62d", + ) + ); + } + + #[test] + fn stone_compatibility_case_1_out_of_domain_composition_poly_evaluation() { + let proof = stone_compatibility_case_1_proof(); + + assert_eq!( + proof.composition_poly_parts_ood_evaluation[0], + FieldElement::from_hex_unchecked( + "1c0b7c2275e36d62dfb48c791be122169dcc00c616c63f8efb2c2a504687e85", + ) + ); + } + + #[test] + fn stone_compatibility_case_1_deep_composition_poly_challenges() { + let challenges = stone_compatibility_case_1_challenges(); + + // Trace terms coefficients + assert_eq!(challenges.trace_term_coeffs[0][0], FieldElement::one()); + let gamma = challenges.trace_term_coeffs[0][1]; + assert_eq!( + &gamma, + &FieldElement::from_hex_unchecked( + "a0c79c1c77ded19520873d9c2440451974d23302e451d13e8124cf82fc15dd" + ) + ); + assert_eq!(&challenges.trace_term_coeffs[1][0], &gamma.pow(2_u64)); + assert_eq!(&challenges.trace_term_coeffs[1][1], &gamma.pow(3_u64)); + + // Composition polynomial parts terms coefficient + assert_eq!(&challenges.gammas[0], &gamma.pow(4_u64)); + } + + #[test] + fn stone_compatibility_case_1_fri_commit_phase_challenge_0() { + let challenges = stone_compatibility_case_1_challenges(); + + // Challenge to fold FRI polynomial + assert_eq!( + challenges.zetas[0], + FieldElement::from_hex_unchecked( + "5c6b5a66c9fda19f583f0b10edbaade98d0e458288e62c2fa40e3da2b293cef" + ) + ); + } + + #[test] + fn stone_compatibility_case_1_fri_commit_phase_layer_1_commitment() { + let proof = stone_compatibility_case_1_proof(); + + // Commitment of first layer of FRI + assert_eq!( + proof.fri_layers_merkle_roots[0].to_vec(), + decode_hex("327d47da86f5961ee012b2b0e412de16023ffba97c82bfe85102f00daabd49fb").unwrap() + ); + } + + #[test] + fn stone_compatibility_case_1_fri_commit_phase_challenge_1() { + let challenges = stone_compatibility_case_1_challenges(); + assert_eq!( + challenges.zetas[1], + FieldElement::from_hex_unchecked( + "13c337c9dc727bea9eef1f82cab86739f17acdcef562f9e5151708f12891295" + ) + ); + } + + #[test] + fn stone_compatibility_case_1_fri_commit_phase_last_value() { + let proof = stone_compatibility_case_1_proof(); + + assert_eq!( + proof.fri_last_value, + FieldElement::from_hex_unchecked( + "43fedf9f9e3d1469309862065c7d7ca0e7e9ce451906e9c01553056f695aec9" + ) + ); + } + + #[test] + fn stone_compatibility_case_1_fri_query_iota_challenge() { + let challenges = stone_compatibility_case_1_challenges(); + assert_eq!(challenges.iotas[0], 1); + } + + #[test] + fn stone_compatibility_case_1_fri_query_phase_trace_openings() { + let proof = stone_compatibility_case_1_proof(); + + // Trace Col 0 + assert_eq!( + proof.deep_poly_openings[0].lde_trace_evaluations[0], + FieldElement::from_hex_unchecked( + "4de0d56f9cf97dff326c26592fbd4ae9ee756080b12c51cfe4864e9b8734f43" + ) + ); + + // Trace Col 1 + assert_eq!( + proof.deep_poly_openings[0].lde_trace_evaluations[1], + FieldElement::from_hex_unchecked( + "1bc1aadf39f2faee64d84cb25f7a95d3dceac1016258a39fc90c9d370e69e8e" + ) + ); + + // Trace Col 0 symmetric + assert_eq!( + proof.deep_poly_openings_sym[0].lde_trace_evaluations[0], + FieldElement::from_hex_unchecked( + "321f2a9063068310cd93d9a6d042b516118a9f7f4ed3ae301b79b16478cb0c6" + ) + ); + + // Trace Col 1 symmetric + assert_eq!( + proof.deep_poly_openings_sym[0].lde_trace_evaluations[1], + FieldElement::from_hex_unchecked( + "643e5520c60d06219b27b34da0856a2c23153efe9da75c6036f362c8f196186" + ) + ); + } + + #[test] + fn stone_compatibility_case_1_fri_query_phase_trace_terms_authentication_path() { + let proof = stone_compatibility_case_1_proof(); + + // Trace poly auth path level 1 + assert_eq!( + proof.deep_poly_openings[0].lde_trace_merkle_proofs[0].merkle_path[1].to_vec(), + decode_hex("91b0c0b24b9d00067b0efab50832b76cf97192091624d42b86740666c5d369e6").unwrap() + ); + + // Trace poly auth path level 2 + assert_eq!( + proof.deep_poly_openings[0].lde_trace_merkle_proofs[0].merkle_path[2].to_vec(), + decode_hex("993b044db22444c0c0ebf1095b9a51faeb001c9b4dea36abe905f7162620dbbd").unwrap() + ); + + // Trace poly auth path level 3 + assert_eq!( + proof.deep_poly_openings[0].lde_trace_merkle_proofs[0].merkle_path[3].to_vec(), + decode_hex("5017abeca33fa82576b5c5c2c61792693b48c9d4414a407eef66b6029dae07ea").unwrap() + ); + } + + #[test] + fn stone_compatibility_case_1_fri_query_phase_composition_poly_openings() { + let proof = stone_compatibility_case_1_proof(); + + // Composition poly + assert_eq!( + proof.deep_poly_openings[0].lde_composition_poly_parts_evaluation[0], + FieldElement::from_hex_unchecked( + "2b54852557db698e97253e9d110d60e9bf09f1d358b4c1a96f9f3cf9d2e8755" + ) + ); + // Composition poly sym + assert_eq!( + proof.deep_poly_openings_sym[0].lde_composition_poly_parts_evaluation[0], + FieldElement::from_hex_unchecked( + "190f1b0acb7858bd3f5285b68befcf32b436a5f1e3a280e1f42565c1f35c2c3" + ) + ); + } + + #[test] + fn stone_compatibility_case_1_fri_query_phase_composition_poly_authentication_path() { + let proof = stone_compatibility_case_1_proof(); + + // Composition poly auth path level 0 + assert_eq!( + proof.deep_poly_openings[0] + .lde_composition_poly_proof + .merkle_path[0] + .to_vec(), + decode_hex("403b75a122eaf90a298e5d3db2cc7ca096db478078122379a6e3616e72da7546").unwrap() + ); + + // Composition poly auth path level 1 + assert_eq!( + proof.deep_poly_openings[0] + .lde_composition_poly_proof + .merkle_path[1] + .to_vec(), + decode_hex("07950888c0355c204a1e83ecbee77a0a6a89f93d41cc2be6b39ddd1e727cc965").unwrap() + ); + + // Composition poly auth path level 2 + assert_eq!( + proof.deep_poly_openings[0] + .lde_composition_poly_proof + .merkle_path[2] + .to_vec(), + decode_hex("58befe2c5de74cc5a002aa82ea219c5b242e761b45fd266eb95521e9f53f44eb").unwrap() + ); + } + + #[test] + fn stone_compatibility_case_1_fri_query_phase_query_lengths() { + let proof = stone_compatibility_case_1_proof(); + + assert_eq!(proof.query_list.len(), 1); + + assert_eq!(proof.query_list[0].layers_evaluations_sym.len(), 1); + + assert_eq!( + proof.query_list[0].layers_auth_paths_sym[0] + .merkle_path + .len(), + 2 + ); + } + + #[test] + fn stone_compatibility_case_1_fri_query_phase_layer_1_evaluation_symmetric() { + let proof = stone_compatibility_case_1_proof(); + + assert_eq!( + proof.query_list[0].layers_evaluations_sym[0], + FieldElement::from_hex_unchecked( + "0684991e76e5c08db17f33ea7840596be876d92c143f863e77cad10548289fd0" + ) + ); + } + + #[test] + fn stone_compatibility_case_1_fri_query_phase_layer_1_authentication_path() { + let proof = stone_compatibility_case_1_proof(); + + // FRI layer 1 auth path level 0 + assert_eq!( + proof.query_list[0].layers_auth_paths_sym[0].merkle_path[0].to_vec(), + decode_hex("0683622478e9e93cc2d18754872f043619f030b494d7ec8e003b1cbafe83b67b").unwrap() + ); + + // FRI layer 1 auth path level 1 + assert_eq!( + proof.query_list[0].layers_auth_paths_sym[0].merkle_path[1].to_vec(), + decode_hex("7985d945abe659a7502698051ec739508ed6bab594984c7f25e095a0a57a2e55").unwrap() + ); + } + + fn proof_parts_stone_compatibility_case_2() -> ( + StarkProof, + fibonacci_2_cols_shifted::PublicInputs, + ProofOptions, + [u8; 4], + ) { + let trace = fibonacci_2_cols_shifted::compute_trace(FieldElement::from(12345), 512); + + let claimed_index = 420; let claimed_value = trace.get_row(claimed_index)[0]; let mut proof_options = ProofOptions::default_test_options(); - proof_options.blowup_factor = 64; + proof_options.blowup_factor = 1 << 6; proof_options.coset_offset = 3; + proof_options.grinding_factor = 0; + proof_options.fri_number_of_queries = 1; let pub_inputs = fibonacci_2_cols_shifted::PublicInputs { claimed_value, @@ -1001,19 +1418,71 @@ mod tests { let transcript_init_seed = [0xfa, 0xfa, 0xfa, 0xee]; - let air = Fibonacci2ColsShifted::new(trace.n_rows(), &pub_inputs, &proof_options); - let domain = Domain::new(&air); - - let (_, _, _, trace_commitment) = interpolate_and_commit( + let proof = Prover::prove::>( &trace, + &pub_inputs, + &proof_options, + StoneProverTranscript::new(&transcript_init_seed), + ) + .unwrap(); + (proof, pub_inputs, proof_options, transcript_init_seed) + } + + fn stone_compatibility_case_2_proof() -> StarkProof { + let (proof, _, _, _) = proof_parts_stone_compatibility_case_2(); + proof + } + + fn stone_compatibility_case_2_challenges( + ) -> Challenges> { + let (proof, public_inputs, options, seed) = proof_parts_stone_compatibility_case_2(); + + let air = Fibonacci2ColsShifted::new(proof.trace_length, &public_inputs, &options); + let domain = Domain::new(&air); + Verifier::step_1_replay_rounds_and_recover_challenges( + &air, + &proof, &domain, - &mut StoneProverTranscript::new(&transcript_init_seed), + &mut StoneProverTranscript::new(&seed), + ) + } + + #[test] + fn stone_compatibility_case_2_trace_commitment() { + let proof = stone_compatibility_case_2_proof(); + + assert_eq!( + proof.lde_trace_merkle_roots[0].to_vec(), + decode_hex("6d31dd00038974bde5fe0c5e3a765f8ddc822a5df3254fca85a1950ae0208cbe").unwrap() + ); + } + + #[test] + fn stone_compatibility_case_2_fri_query_iota_challenge() { + let challenges = stone_compatibility_case_2_challenges(); + assert_eq!(challenges.iotas[0], 4239); + } + + #[test] + fn stone_compatibility_case_2_fri_query_phase_layer_7_evaluation_symmetric() { + let proof = stone_compatibility_case_2_proof(); + + assert_eq!( + proof.query_list[0].layers_evaluations_sym[7], + FieldElement::from_hex_unchecked( + "7aa40c5a4e30b44fee5bcc47c54072a435aa35c1a31b805cad8126118cc6860" + ) ); + } + #[test] + fn stone_compatibility_case_2_fri_query_phase_layer_8_authentication_path() { + let proof = stone_compatibility_case_2_proof(); + + // FRI layer 7 auth path level 5 assert_eq!( - &trace_commitment.to_vec(), - &decode_hex("99d8d4342895c4e35a084f8ea993036be06f51e7fa965734ed9c7d41104f0848") - .unwrap() + proof.query_list[0].layers_auth_paths_sym[7].merkle_path[5].to_vec(), + decode_hex("f12f159b548ca2c571a270870d43e7ec2ead78b3e93b635738c31eb9bcda3dda").unwrap() ); } } diff --git a/provers/stark/src/tests/integration_tests.rs b/provers/stark/src/tests/integration_tests.rs index 77f244658f..53b6fdfc1b 100644 --- a/provers/stark/src/tests/integration_tests.rs +++ b/provers/stark/src/tests/integration_tests.rs @@ -12,9 +12,9 @@ use crate::{ simple_fibonacci::{self, FibonacciAIR, FibonacciPublicInputs}, }, proof::options::ProofOptions, - prover::prove, + prover::{IsStarkProver, Prover}, transcript::StoneProverTranscript, - verifier::verify, + verifier::{IsStarkVerifier, Verifier}, Felt252, }; @@ -29,21 +29,19 @@ fn test_prove_fib() { a1: Felt252::one(), }; - let proof = prove::>( + let proof = Prover::prove::>( &trace, &pub_inputs, &proof_options, StoneProverTranscript::new(&[]), ) .unwrap(); - assert!( - verify::>( - &proof, - &pub_inputs, - &proof_options, - StoneProverTranscript::new(&[]), - ) - ); + assert!(Verifier::verify::>( + &proof, + &pub_inputs, + &proof_options, + StoneProverTranscript::new(&[]), + )); } #[test_log::test] @@ -63,14 +61,14 @@ fn test_prove_fib17() { a1: FE::one(), }; - let proof = prove::<_, FibonacciAIR<_>>( + let proof = Prover::prove::>( &trace, &pub_inputs, &proof_options, StoneProverTranscript::new(&[]), ) .unwrap(); - assert!(verify::<_, FibonacciAIR<_>>( + assert!(Verifier::verify::>( &proof, &pub_inputs, &proof_options, @@ -89,17 +87,14 @@ fn test_prove_fib_2_cols() { a1: Felt252::one(), }; - let proof = prove::>( + let proof = Prover::prove::>( &trace, &pub_inputs, &proof_options, StoneProverTranscript::new(&[]), ) .unwrap(); - assert!(verify::< - Stark252PrimeField, - Fibonacci2ColsAIR, - >( + assert!(Verifier::verify::>( &proof, &pub_inputs, &proof_options, @@ -120,14 +115,14 @@ fn test_prove_fib_2_cols_shifted() { claimed_index, }; - let proof = prove::>( + let proof = Prover::prove::>( &trace, &pub_inputs, &proof_options, StoneProverTranscript::new(&[]), ) .unwrap(); - assert!(verify::>( + assert!(Verifier::verify::>( &proof, &pub_inputs, &proof_options, @@ -145,21 +140,19 @@ fn test_prove_quadratic() { a0: Felt252::from(3), }; - let proof = prove::>( + let proof = Prover::prove::>( &trace, &pub_inputs, &proof_options, StoneProverTranscript::new(&[]), ) .unwrap(); - assert!( - verify::>( - &proof, - &pub_inputs, - &proof_options, - StoneProverTranscript::new(&[]) - ) - ); + assert!(Verifier::verify::>( + &proof, + &pub_inputs, + &proof_options, + StoneProverTranscript::new(&[]) + )); } #[test_log::test] @@ -175,21 +168,19 @@ fn test_prove_rap_fib() { a1: Felt252::one(), }; - let proof = prove::>( + let proof = Prover::prove::>( &trace, &pub_inputs, &proof_options, StoneProverTranscript::new(&[]), ) .unwrap(); - assert!( - verify::>( - &proof, - &pub_inputs, - &proof_options, - StoneProverTranscript::new(&[]) - ) - ); + assert!(Verifier::verify::>( + &proof, + &pub_inputs, + &proof_options, + StoneProverTranscript::new(&[]) + )); } #[test_log::test] @@ -199,14 +190,10 @@ fn test_prove_dummy() { let proof_options = ProofOptions::default_test_options(); - let proof = prove::( - &trace, - &(), - &proof_options, - StoneProverTranscript::new(&[]), - ) - .unwrap(); - assert!(verify::( + let proof = + Prover::prove::(&trace, &(), &proof_options, StoneProverTranscript::new(&[])) + .unwrap(); + assert!(Verifier::verify::( &proof, &(), &proof_options, diff --git a/provers/stark/src/verifier.rs b/provers/stark/src/verifier.rs index 38a505602a..a67c116662 100644 --- a/provers/stark/src/verifier.rs +++ b/provers/stark/src/verifier.rs @@ -1,22 +1,26 @@ #[cfg(feature = "instruments")] use std::time::Instant; +use lambdaworks_crypto::merkle_tree::proof::Proof; //use itertools::multizip; #[cfg(not(feature = "test_fiat_shamir"))] use log::error; use lambdaworks_math::{ + fft::cpu::bit_reversing::reverse_index, field::{ - element::FieldElement, - traits::{IsFFTField, IsField}, + element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, + traits::IsFFTField, }, traits::Serializable, }; -use crate::{prover::get_stone_prover_domain_permutation, transcript::IsStarkTranscript}; +use crate::{ + config::Commitment, proof::stark::DeepPolynomialOpening, transcript::IsStarkTranscript, +}; use super::{ - config::{BatchedMerkleTreeBackend, FriMerkleTreeBackend}, + config::BatchedMerkleTreeBackend, domain::Domain, fri::fri_decommit::FriDecommitment, grinding::hash_transcript_with_int_and_get_leading_zeros, @@ -24,662 +28,735 @@ use super::{ traits::AIR, }; -struct Challenges -where - F: IsFFTField, - A: AIR, -{ - z: FieldElement, - boundary_coeffs: Vec>, - transition_coeffs: Vec>, - trace_term_coeffs: Vec>>, - gamma_even: FieldElement, - gamma_odd: FieldElement, - zetas: Vec>, - iotas: Vec, - rap_challenges: A::RAPChallenges, - leading_zeros_count: u8, // number of leading zeros in the grinding +pub struct Verifier {} + +impl IsStarkVerifier for Verifier { + type Field = Stark252PrimeField; } -fn step_1_replay_rounds_and_recover_challenges( - air: &A, - proof: &StarkProof, - domain: &Domain, - transcript: &mut impl IsStarkTranscript, -) -> Challenges +pub struct Challenges where F: IsFFTField, - FieldElement: Serializable, A: AIR, { - // =================================== - // ==========| Round 1 |========== - // =================================== - - // <<<< Receive commitments:[tβ±Ό] - let total_columns = air.context().trace_columns; + pub z: FieldElement, + pub boundary_coeffs: Vec>, + pub transition_coeffs: Vec>, + pub trace_term_coeffs: Vec>>, + pub gammas: Vec>, + pub zetas: Vec>, + pub iotas: Vec, + pub rap_challenges: A::RAPChallenges, + pub leading_zeros_count: u8, // number of leading zeros in the grinding +} - transcript.append_bytes(&proof.lde_trace_merkle_roots[0]); +pub type DeepPolynomialEvaluations = (Vec>, Vec>); - let rap_challenges = air.build_rap_challenges(transcript); +pub trait IsStarkVerifier { + type Field: IsFFTField; - if let Some(root) = proof.lde_trace_merkle_roots.get(1) { - transcript.append_bytes(root); + fn sample_query_indexes( + number_of_queries: usize, + domain: &Domain, + transcript: &mut impl IsStarkTranscript, + ) -> Vec { + let domain_size = domain.lde_roots_of_unity_coset.len() as u64; + (0..number_of_queries) + .map(|_| (transcript.sample_u64(domain_size >> 1)) as usize) + .collect::>() } - // =================================== - // ==========| Round 2 |========== - // =================================== + fn step_1_replay_rounds_and_recover_challenges( + air: &A, + proof: &StarkProof, + domain: &Domain, + transcript: &mut impl IsStarkTranscript, + ) -> Challenges + where + FieldElement: Serializable, + A: AIR, + { + // =================================== + // ==========| Round 1 |========== + // =================================== + + // <<<< Receive commitments:[tβ±Ό] + transcript.append_bytes(&proof.lde_trace_merkle_roots[0]); + + let rap_challenges = air.build_rap_challenges(transcript); + + if let Some(root) = proof.lde_trace_merkle_roots.get(1) { + transcript.append_bytes(root); + } + + // =================================== + // ==========| Round 2 |========== + // =================================== - // <<<< Receive challenge: 𝛽 - let beta = transcript.sample_field_element(); - let num_boundary_constraints = air.boundary_constraints(&rap_challenges).constraints.len(); + // <<<< Receive challenge: 𝛽 + let beta = transcript.sample_field_element(); + let num_boundary_constraints = air.boundary_constraints(&rap_challenges).constraints.len(); - let num_transition_constraints = air.context().num_transition_constraints; + let num_transition_constraints = air.context().num_transition_constraints; - let mut coefficients: Vec<_> = (1..num_boundary_constraints + num_transition_constraints + 1) - .map(|i| beta.pow(i)) - .collect(); + let mut coefficients: Vec<_> = (0..num_boundary_constraints + num_transition_constraints) + .map(|i| beta.pow(i)) + .collect(); - let transition_coeffs: Vec<_> = coefficients.drain(..num_transition_constraints).collect(); - let boundary_coeffs = coefficients; + let transition_coeffs: Vec<_> = coefficients.drain(..num_transition_constraints).collect(); + let boundary_coeffs = coefficients; - // <<<< Receive commitments: [H₁], [Hβ‚‚] - transcript.append_bytes(&proof.composition_poly_root); + // <<<< Receive commitments: [H₁], [Hβ‚‚] + transcript.append_bytes(&proof.composition_poly_root); - // =================================== - // ==========| Round 3 |========== - // =================================== + // =================================== + // ==========| Round 3 |========== + // =================================== - // >>>> Send challenge: z - let z = transcript.sample_z_ood( - &domain.lde_roots_of_unity_coset, - &domain.trace_roots_of_unity, - ); + // >>>> Send challenge: z + let z = transcript.sample_z_ood( + &domain.lde_roots_of_unity_coset, + &domain.trace_roots_of_unity, + ); - // <<<< Receive value: H₁(zΒ²) - transcript.append_field_element(&proof.composition_poly_even_ood_evaluation); - // <<<< Receive value: Hβ‚‚(zΒ²) - transcript.append_field_element(&proof.composition_poly_odd_ood_evaluation); - // <<<< Receive values: tβ±Ό(zgᡏ) - for i in 0..proof.trace_ood_frame_evaluations.num_rows() { - for element in proof.trace_ood_frame_evaluations.get_row(i).iter() { + // <<<< Receive values: tβ±Ό(zgᡏ) + for i in 0..proof.trace_ood_frame_evaluations.num_columns() { + for j in 0..proof.trace_ood_frame_evaluations.num_rows() { + transcript.append_field_element(&proof.trace_ood_frame_evaluations.get_row(j)[i]); + } + } + // <<<< Receive value: Hα΅’(z^N) + for element in proof.composition_poly_parts_ood_evaluation.iter() { transcript.append_field_element(element); } - } - // =================================== - // ==========| Round 4 |========== - // =================================== - - // >>>> Send challenges: 𝛾, 𝛾' - let gamma_even = transcript.sample_field_element(); - let gamma_odd = transcript.sample_field_element(); - - // >>>> Send challenges: 𝛾ⱼ, 𝛾ⱼ' - // Get the number of trace terms the DEEP composition poly will have. - // One coefficient will be sampled for each of them. - // TODO: try remove this, call transcript inside for and move gamma declarations - let trace_term_coeffs = (0..total_columns) - .map(|_| { - (0..air.context().transition_offsets.len()) - .map(|_| transcript.sample_field_element()) - .collect() - }) - .collect::>>>(); - - // FRI commit phase - - let merkle_roots = &proof.fri_layers_merkle_roots; - let zetas = merkle_roots - .iter() - .map(|root| { - // <<<< Receive commitment: [pβ‚–] (the first one is [pβ‚€]) - transcript.append_bytes(root); + // =================================== + // ==========| Round 4 |========== + // =================================== + + let n_terms_composition_poly = proof.composition_poly_parts_ood_evaluation.len(); + let n_terms_trace = air.context().transition_offsets.len() * air.context().trace_columns; + let gamma = transcript.sample_field_element(); + + // <<<< Receive challenges: 𝛾, 𝛾' + let mut deep_composition_coefficients: Vec<_> = + core::iter::successors(Some(FieldElement::one()), |x| Some(x * &gamma)) + .take(n_terms_composition_poly + n_terms_trace) + .collect(); + + let trace_term_coeffs: Vec<_> = deep_composition_coefficients + .drain(..n_terms_trace) + .collect::>() + .chunks(air.context().transition_offsets.len()) + .map(|chunk| chunk.to_vec()) + .collect(); + + // <<<< Receive challenges: 𝛾ⱼ, 𝛾ⱼ' + let gammas = deep_composition_coefficients; + + // FRI commit phase + let merkle_roots = &proof.fri_layers_merkle_roots; + let mut zetas = merkle_roots + .iter() + .map(|root| { + // >>>> Send challenge πœβ‚– + let element = transcript.sample_field_element(); + // <<<< Receive commitment: [pβ‚–] (the first one is [pβ‚€]) + transcript.append_bytes(root); + element + }) + .collect::>>(); + + // >>>> Send challenge πœβ‚™β‚‹β‚ + zetas.push(transcript.sample_field_element()); + + // <<<< Receive value: pβ‚™ + transcript.append_field_element(&proof.fri_last_value); + + // Receive grinding value + // 1) Receive challenge from the transcript + let security_bits = air.context().proof_options.grinding_factor; + let mut leading_zeros_count = 0; + if security_bits > 0 { + let transcript_challenge = transcript.state(); + let nonce = proof.nonce; + leading_zeros_count = + hash_transcript_with_int_and_get_leading_zeros(&transcript_challenge, nonce); + transcript.append_bytes(&nonce.to_be_bytes()); + } - // >>>> Send challenge πœβ‚– - transcript.sample_field_element() - }) - .collect::>>(); - - // <<<< Receive value: pβ‚™ - transcript.append_field_element(&proof.fri_last_value); - - // Receive grinding value - // 1) Receive challenge from the transcript - let transcript_challenge = transcript.state(); - let nonce = proof.nonce; - let leading_zeros_count = - hash_transcript_with_int_and_get_leading_zeros(&transcript_challenge, nonce); - transcript.append_bytes(&nonce.to_be_bytes()); - - // FRI query phase - // <<<< Send challenges πœ„β‚› (iota_s) - let iota_max: usize = 2_usize.pow(domain.lde_root_order); - let iotas: Vec = (0..air.options().fri_number_of_queries) - .map(|_| (transcript.sample_u64(iota_max as u64) as usize) % iota_max) - .collect(); - - Challenges { - z, - boundary_coeffs, - transition_coeffs, - trace_term_coeffs, - gamma_even, - gamma_odd, - zetas, - iotas, - rap_challenges, - leading_zeros_count, + // FRI query phase + // <<<< Send challenges πœ„β‚› (iota_s) + let number_of_queries = air.options().fri_number_of_queries; + let iotas = Self::sample_query_indexes(number_of_queries, domain, transcript); + + Challenges { + z, + boundary_coeffs, + transition_coeffs, + trace_term_coeffs, + gammas, + zetas, + iotas, + rap_challenges, + leading_zeros_count, + } } -} -fn step_2_verify_claimed_composition_polynomial>( - air: &A, - proof: &StarkProof, - domain: &Domain, - challenges: &Challenges, -) -> bool { - // BEGIN TRACE <-> Composition poly consistency evaluation check - // These are H_1(z^2) and H_2(z^2) - let composition_poly_even_ood_evaluation = &proof.composition_poly_even_ood_evaluation; - let composition_poly_odd_ood_evaluation = &proof.composition_poly_odd_ood_evaluation; - - let boundary_constraints = air.boundary_constraints(&challenges.rap_challenges); - - //let n_trace_cols = air.context().trace_columns; - // special cases. - let trace_length = air.trace_length(); - let number_of_b_constraints = boundary_constraints.constraints.len(); - - // Following naming conventions from https://www.notamonadtutorial.com/diving-deep-fri/ - let (boundary_c_i_evaluations_num, mut boundary_c_i_evaluations_den): ( - Vec>, - Vec>, - ) = (0..number_of_b_constraints) - .map(|index| { - let step = boundary_constraints.constraints[index].step; - let point = &domain.trace_primitive_root.pow(step as u64); - let trace_idx = boundary_constraints.constraints[index].col; - let trace_evaluation = &proof.trace_ood_frame_evaluations.get_row(0)[trace_idx]; - let boundary_zerofier_challenges_z_den = &challenges.z - point; - - let boundary_quotient_ood_evaluation_num = - trace_evaluation - &boundary_constraints.constraints[index].value; - - ( - boundary_quotient_ood_evaluation_num, - boundary_zerofier_challenges_z_den, - ) - }) - .collect::>() - .into_iter() - .unzip(); - - FieldElement::inplace_batch_inverse(&mut boundary_c_i_evaluations_den).unwrap(); - - let boundary_quotient_ood_evaluation: FieldElement = boundary_c_i_evaluations_num - .iter() - .zip(&boundary_c_i_evaluations_den) - .zip(&challenges.boundary_coeffs) - .map(|((num, den), beta)| num * den * beta) - .fold(FieldElement::::zero(), |acc, x| acc + x); - - let transition_ood_frame_evaluations = air.compute_transition( - &proof.trace_ood_frame_evaluations, - &challenges.rap_challenges, - ); - - let denominator = (&challenges.z.pow(trace_length) - FieldElement::::one()) - .inv() - .unwrap(); - - let exemption = air - .transition_exemptions_verifier( - domain.trace_roots_of_unity.iter().last().expect("has last"), - ) - .iter() - .map(|poly| poly.evaluate(&challenges.z)) - .collect::>>(); - - let unity = &FieldElement::one(); - let transition_c_i_evaluations_sum = transition_ood_frame_evaluations - .iter() - .zip(&air.context().transition_degrees) - .zip(&air.context().transition_exemptions) - .zip(&challenges.transition_coeffs) - .fold(FieldElement::zero(), |acc, (((eval, _), except), beta)| { - let except = except - .checked_sub(1) - .map(|i| &exemption[i]) - .unwrap_or(unity); - acc + &denominator * eval * beta * except - }); - - let composition_poly_ood_evaluation = - &boundary_quotient_ood_evaluation + transition_c_i_evaluations_sum; - - let composition_poly_claimed_ood_evaluation = - composition_poly_even_ood_evaluation + &challenges.z * composition_poly_odd_ood_evaluation; - - composition_poly_claimed_ood_evaluation == composition_poly_ood_evaluation -} - -fn step_3_verify_fri( - proof: &StarkProof, - domain: &Domain, - challenges: &Challenges, -) -> bool -where - F: IsFFTField, - FieldElement: Serializable, - A: AIR, -{ - // verify FRI - let two_inv = &FieldElement::from(2).inv().unwrap(); - let mut evaluation_point_inverse = challenges - .iotas - .iter() - .map(|iota| &domain.lde_roots_of_unity_coset[*iota]) - .cloned() - .collect::>>(); - FieldElement::inplace_batch_inverse(&mut evaluation_point_inverse).unwrap(); - proof - .query_list - .iter() - .zip(&challenges.iotas) - .zip(evaluation_point_inverse) - .fold(true, |mut result, ((proof_s, iota_s), eval)| { - // this is done in constant time - result &= verify_query_and_sym_openings( - proof, - &challenges.zetas, - *iota_s, - proof_s, - domain, - eval, - two_inv, - ); - result - }) -} - -fn step_4_verify_deep_composition_polynomial>( - air: &A, - proof: &StarkProof, - domain: &Domain, - challenges: &Challenges, -) -> bool -where - FieldElement: Serializable, -{ - let permutation = - get_stone_prover_domain_permutation(domain.interpolation_domain_size, domain.blowup_factor); - let primitive_root = &F::get_primitive_root_of_unity(domain.root_order as u64).unwrap(); - let z_squared = &challenges.z.square(); - let mut denom_inv = challenges - .iotas - .iter() - .map(|iota_n| &domain.lde_roots_of_unity_coset[*iota_n] - z_squared) - .collect::>>(); - FieldElement::inplace_batch_inverse(&mut denom_inv).unwrap(); - - challenges - .iotas - .iter() - .zip(&proof.deep_poly_openings) - .zip(&denom_inv) - .enumerate() - .fold( - true, - |mut result, (i, ((iota_n, deep_poly_opening), denom_inv))| { - let evaluations = vec![ - deep_poly_opening - .lde_composition_poly_even_evaluation - .clone(), - deep_poly_opening - .lde_composition_poly_odd_evaluation - .clone(), - ]; - - // Verify opening Open(H₁(D_LDE, πœβ‚€) and Open(Hβ‚‚(D_LDE, πœβ‚€), - result &= deep_poly_opening - .lde_composition_poly_proof - .verify::>( - &proof.composition_poly_root, - *iota_n, - &evaluations, - ); + fn step_2_verify_claimed_composition_polynomial( + air: &A, + proof: &StarkProof, + domain: &Domain, + challenges: &Challenges, + ) -> bool + where + A: AIR, + { + let boundary_constraints = air.boundary_constraints(&challenges.rap_challenges); + + let trace_length = air.trace_length(); + let number_of_b_constraints = boundary_constraints.constraints.len(); + + #[allow(clippy::type_complexity)] + let (boundary_c_i_evaluations_num, mut boundary_c_i_evaluations_den): ( + Vec>, + Vec>, + ) = (0..number_of_b_constraints) + .map(|index| { + let step = boundary_constraints.constraints[index].step; + let point = &domain.trace_primitive_root.pow(step as u64); + let trace_idx = boundary_constraints.constraints[index].col; + let trace_evaluation = &proof.trace_ood_frame_evaluations.get_row(0)[trace_idx]; + let boundary_zerofier_challenges_z_den = &challenges.z - point; + + let boundary_quotient_ood_evaluation_num = + trace_evaluation - &boundary_constraints.constraints[index].value; + + ( + boundary_quotient_ood_evaluation_num, + boundary_zerofier_challenges_z_den, + ) + }) + .collect::>() + .into_iter() + .unzip(); + + FieldElement::inplace_batch_inverse(&mut boundary_c_i_evaluations_den).unwrap(); + + let boundary_quotient_ood_evaluation: FieldElement = + boundary_c_i_evaluations_num + .iter() + .zip(&boundary_c_i_evaluations_den) + .zip(&challenges.boundary_coeffs) + .map(|((num, den), beta)| num * den * beta) + .fold(FieldElement::::zero(), |acc, x| acc + x); + + let transition_ood_frame_evaluations = air.compute_transition( + &proof.trace_ood_frame_evaluations, + &challenges.rap_challenges, + ); - let num_main_columns = - air.context().trace_columns - air.number_auxiliary_rap_columns(); - let lde_trace_evaluations = vec![ - deep_poly_opening.lde_trace_evaluations[..num_main_columns].to_vec(), - deep_poly_opening.lde_trace_evaluations[num_main_columns..].to_vec(), - ]; - - // Verify openings Open(tβ±Ό(D_LDE), πœβ‚€) - result &= proof - .lde_trace_merkle_roots - .iter() - .zip(&deep_poly_opening.lde_trace_merkle_proofs) - .zip(lde_trace_evaluations) - .fold(result, |acc, ((merkle_root, merkle_proof), evaluation)| { - acc & merkle_proof.verify::>( - merkle_root, - permutation[*iota_n], - &evaluation, - ) - }); + let denominator = (&challenges.z.pow(trace_length) - FieldElement::::one()) + .inv() + .unwrap(); - // DEEP consistency check - // Verify that Deep(x) is constructed correctly - let mut divisors = (0..proof.trace_ood_frame_evaluations.num_rows()) - .map(|row_idx| { - &domain.lde_roots_of_unity_coset[*iota_n] - - &challenges.z * primitive_root.pow(row_idx as u64) - }) - .collect::>>(); - FieldElement::inplace_batch_inverse(&mut divisors).unwrap(); - let deep_poly_evaluation = reconstruct_deep_composition_poly_evaluation( - proof, challenges, denom_inv, &divisors, i, - ); + let exemption = air + .transition_exemptions_verifier( + domain.trace_roots_of_unity.iter().last().expect("has last"), + ) + .iter() + .map(|poly| poly.evaluate(&challenges.z)) + .collect::>>(); + + let unity = &FieldElement::one(); + let transition_c_i_evaluations_sum = transition_ood_frame_evaluations + .iter() + .zip(&air.context().transition_degrees) + .zip(&air.context().transition_exemptions) + .zip(&challenges.transition_coeffs) + .fold(FieldElement::zero(), |acc, (((eval, _), except), beta)| { + let except = except + .checked_sub(1) + .map(|i| &exemption[i]) + .unwrap_or(unity); + acc + &denominator * eval * beta * except + }); + + let composition_poly_ood_evaluation = + &boundary_quotient_ood_evaluation + transition_c_i_evaluations_sum; + + let composition_poly_claimed_ood_evaluation = proof + .composition_poly_parts_ood_evaluation + .iter() + .rev() + .fold(FieldElement::zero(), |acc, coeff| { + acc * &challenges.z + coeff + }); + + composition_poly_claimed_ood_evaluation == composition_poly_ood_evaluation + } - let deep_poly_claimed_evaluation = &proof.query_list[i].layers_evaluations[0]; - result & (deep_poly_claimed_evaluation == &deep_poly_evaluation) - }, - ) -} + fn step_3_verify_fri( + proof: &StarkProof, + domain: &Domain, + challenges: &Challenges, + ) -> bool + where + FieldElement: Serializable, + A: AIR, + { + let (deep_poly_evaluations, deep_poly_evaluations_sym) = + Self::reconstruct_deep_composition_poly_evaluations_for_all_queries( + challenges, domain, proof, + ); -fn verify_query_and_sym_openings( - proof: &StarkProof, - zetas: &[FieldElement], - iota: usize, - fri_decommitment: &FriDecommitment, - domain: &Domain, - evaluation_point: FieldElement, - two_inv: &FieldElement, -) -> bool -where - FieldElement: Serializable, -{ - let fri_layers_merkle_roots = &proof.fri_layers_merkle_roots; - let evaluation_point_vec: Vec> = - core::iter::successors(Some(evaluation_point), |evaluation_point| { - Some(evaluation_point.square()) - }) - .take(fri_layers_merkle_roots.len()) - .collect(); - - let mut v = fri_decommitment.layers_evaluations[0].clone(); - // For each fri layer merkle proof check: - // That each merkle path verifies - - // Sample beta with fiat shamir - // Compute v = [P_i(z_i) + P_i(-z_i)] / 2 + beta * [P_i(z_i) - P_i(-z_i)] / (2 * z_i) - // Where P_i is the folded polynomial of the i-th fiat shamir round - // z_i is obtained from the first z (that was derived through Fiat-Shamir) through a known calculation - // The calculation is, given the index, index % length_of_evaluation_domain - - // Check that v = P_{i+1}(z_i) - - // For each (merkle_root, merkle_auth_path) / fold - // With the auth path containining the element that the path proves it's existence - fri_layers_merkle_roots - .iter() - .enumerate() - .zip(&fri_decommitment.layers_auth_paths) - .zip(&fri_decommitment.layers_evaluations) - .zip(&fri_decommitment.layers_auth_paths_sym) - .zip(&fri_decommitment.layers_evaluations_sym) - .zip(evaluation_point_vec) - .fold( - true, - |result, - ( - (((((k, merkle_root), auth_path), evaluation), auth_path_sym), evaluation_sym), - evaluation_point_inv, - )| { - let domain_length = 1 << (domain.lde_root_order - k as u32); - let layer_evaluation_index_sym = (iota + domain_length / 2) % domain_length; - // Since we always derive the current layer from the previous layer - // We start with the second one, skipping the first, so previous is layer is the first one - // This is the current layer's evaluation domain length. - // We need it to know what the decommitment index for the current - // layer is, so we can check the merkle paths at the right index. - - // Verify opening Open(pβ‚–(Dβ‚–), βˆ’πœβ‚›^(2ᡏ)) - let auth_sym = &auth_path_sym.verify::>( - merkle_root, - layer_evaluation_index_sym, - evaluation_sym, + // verify FRI + let mut evaluation_point_inverse = challenges + .iotas + .iter() + .map(|iota| Self::query_challenge_to_evaluation_point(*iota, domain)) + .collect::>>(); + FieldElement::inplace_batch_inverse(&mut evaluation_point_inverse).unwrap(); + proof + .query_list + .iter() + .zip(&challenges.iotas) + .zip(evaluation_point_inverse) + .enumerate() + .fold(true, |mut result, (i, ((proof_s, iota_s), eval))| { + // this is done in constant time + result &= Self::verify_query_and_sym_openings( + proof, + &challenges.zetas, + *iota_s, + proof_s, + eval, + &deep_poly_evaluations[i], + &deep_poly_evaluations_sym[i], ); - // Verify opening Open(pβ‚–(Dβ‚–), πœβ‚›) - let auth_point = - auth_path.verify::>(merkle_root, iota, evaluation); - let beta = &zetas[k]; - // v is the calculated element for the co linearity check - v = (&v + evaluation_sym) * two_inv - + beta * (&v - evaluation_sym) * two_inv * evaluation_point_inv; - - // Check that next value is the given by the prover - if k < fri_decommitment.layers_evaluations.len() - 1 { - let next_layer_evaluation = &fri_decommitment.layers_evaluations[k + 1]; - result & (v == *next_layer_evaluation) & auth_point & auth_sym - } else { - result & (v == proof.fri_last_value) & auth_point & auth_sym - } - }, - ) -} + result + }) + } -// Reconstruct Deep(\upsilon_0) off the values in the proof -fn reconstruct_deep_composition_poly_evaluation>( - proof: &StarkProof, - challenges: &Challenges, - denom_inv: &FieldElement, - divisors: &[FieldElement], - i: usize, -) -> FieldElement { - let trace_term = (0..proof.trace_ood_frame_evaluations.num_columns()) - .zip(&challenges.trace_term_coeffs) - .fold(FieldElement::zero(), |trace_terms, (col_idx, coeff_row)| { - let trace_i = (0..proof.trace_ood_frame_evaluations.num_rows()) - .zip(coeff_row) - .fold(FieldElement::zero(), |trace_t, (row_idx, coeff)| { - let poly_evaluation = - (proof.deep_poly_openings[i].lde_trace_evaluations[col_idx].clone() - - proof.trace_ood_frame_evaluations.get_row(row_idx)[col_idx].clone()) - * &divisors[row_idx]; - trace_t + &poly_evaluation * coeff - }); - trace_terms + trace_i - }); + fn query_challenge_to_evaluation_point( + iota: usize, + domain: &Domain, + ) -> FieldElement { + domain.lde_roots_of_unity_coset + [reverse_index(iota * 2, domain.lde_roots_of_unity_coset.len() as u64)] + .clone() + } - let h_1_upsilon_0 = &proof.deep_poly_openings[i].lde_composition_poly_even_evaluation; - let h_1_zsquared = &proof.composition_poly_even_ood_evaluation; - let h_2_upsilon_0 = &proof.deep_poly_openings[i].lde_composition_poly_odd_evaluation; - let h_2_zsquared = &proof.composition_poly_odd_ood_evaluation; + fn query_challenge_to_evaluation_point_sym( + iota: usize, + domain: &Domain, + ) -> FieldElement { + domain.lde_roots_of_unity_coset + [reverse_index(iota * 2 + 1, domain.lde_roots_of_unity_coset.len() as u64)] + .clone() + } - let h_1_term = (h_1_upsilon_0 - h_1_zsquared) * denom_inv; - let h_2_term = (h_2_upsilon_0 - h_2_zsquared) * denom_inv; + fn verify_opening( + proof: &Proof, + root: &Commitment, + index: usize, + value: &[FieldElement], + ) -> bool + where + FieldElement: Serializable, + { + proof.verify::>(root, index, &value.to_owned()) + } - trace_term + h_1_term * &challenges.gamma_even + h_2_term * &challenges.gamma_odd -} + /// Verify opening Open(tβ±Ό(D_LDE), 𝜐) and Open(tβ±Ό(D_LDE), -𝜐) for all trace polynomials tβ±Ό, + /// where 𝜐 and -𝜐 are the elements corresponding to the index challenge `iota`. + fn verify_trace_openings( + num_main_columns: usize, + proof: &StarkProof, + deep_poly_openings: &DeepPolynomialOpening, + deep_poly_openings_sym: &DeepPolynomialOpening, + iota: usize, + ) -> bool + where + FieldElement: Serializable, + { + let lde_trace_evaluations = vec![ + deep_poly_openings.lde_trace_evaluations[..num_main_columns].to_vec(), + deep_poly_openings.lde_trace_evaluations[num_main_columns..].to_vec(), + ]; + + let index = iota * 2; + let openings_are_valid = proof + .lde_trace_merkle_roots + .iter() + .zip(&deep_poly_openings.lde_trace_merkle_proofs) + .zip(lde_trace_evaluations) + .fold(true, |acc, ((merkle_root, merkle_proof), evaluation)| { + acc & Self::verify_opening(merkle_proof, merkle_root, index, &evaluation) + }); + + let lde_trace_evaluations_sym = vec![ + deep_poly_openings_sym.lde_trace_evaluations[..num_main_columns].to_vec(), + deep_poly_openings_sym.lde_trace_evaluations[num_main_columns..].to_vec(), + ]; + + let index_sym = iota * 2 + 1; + let openings_sym_are_valid = proof + .lde_trace_merkle_roots + .iter() + .zip(&deep_poly_openings_sym.lde_trace_merkle_proofs) + .zip(lde_trace_evaluations_sym) + .fold(true, |acc, ((merkle_root, merkle_proof), evaluation)| { + acc & Self::verify_opening(merkle_proof, merkle_root, index_sym, &evaluation) + }); + openings_are_valid & openings_sym_are_valid + } -pub fn verify( - proof: &StarkProof, - pub_input: &A::PublicInputs, - proof_options: &ProofOptions, - mut transcript: impl IsStarkTranscript, -) -> bool -where - F: IsFFTField, - A: AIR, - FieldElement: Serializable, -{ - // Verify there are enough queries - if proof.query_list.len() < proof_options.fri_number_of_queries { - return false; + /// Verify opening Open(Hα΅’(D_LDE), 𝜐) and Open(Hα΅’(D_LDE), -𝜐) for all parts Hα΅’of the composition + /// polynomial, where 𝜐 and -𝜐 are the elements corresponding to the index challenge `iota`. + fn verify_composition_poly_opening( + deep_poly_openings: &DeepPolynomialOpening, + deep_poly_openings_sym: &DeepPolynomialOpening, + composition_poly_merkle_root: &Commitment, + iota: &usize, + ) -> bool + where + FieldElement: Serializable, + { + let mut value = deep_poly_openings + .lde_composition_poly_parts_evaluation + .clone(); + value.extend_from_slice(&deep_poly_openings_sym.lde_composition_poly_parts_evaluation); + + deep_poly_openings + .lde_composition_poly_proof + .verify::>( + composition_poly_merkle_root, + *iota, + &value, + ) } - #[cfg(feature = "instruments")] - println!("- Started step 1: Recover challenges"); - #[cfg(feature = "instruments")] - let timer1 = Instant::now(); + fn step_4_verify_trace_and_composition_openings>( + air: &A, + proof: &StarkProof, + challenges: &Challenges, + ) -> bool + where + FieldElement: Serializable, + { + challenges + .iotas + .iter() + .zip(&proof.deep_poly_openings) + .zip(&proof.deep_poly_openings_sym) + .fold( + true, + |mut result, ((iota_n, deep_poly_opening), deep_poly_openings_sym)| { + result &= Self::verify_composition_poly_opening( + deep_poly_opening, + deep_poly_openings_sym, + &proof.composition_poly_root, + iota_n, + ); - let air = A::new(proof.trace_length, pub_input, proof_options); - let domain = Domain::new(&air); + let num_main_columns = + air.context().trace_columns - air.number_auxiliary_rap_columns(); + result &= Self::verify_trace_openings( + num_main_columns, + proof, + deep_poly_opening, + deep_poly_openings_sym, + *iota_n, + ); + result + }, + ) + } - let challenges = - step_1_replay_rounds_and_recover_challenges(&air, proof, &domain, &mut transcript); + fn verify_fri_layer_openings( + merkle_root: &Commitment, + auth_path_sym: &Proof, + evaluation: &FieldElement, + evaluation_sym: &FieldElement, + iota: usize, + ) -> bool + where + FieldElement: Serializable, + { + let evaluations = if iota % 2 == 1 { + vec![evaluation_sym.clone(), evaluation.clone()] + } else { + vec![evaluation.clone(), evaluation_sym.clone()] + }; - // verify grinding - let grinding_factor = air.context().proof_options.grinding_factor; - if challenges.leading_zeros_count < grinding_factor { - error!("Grinding factor not satisfied"); - return false; + auth_path_sym.verify::>( + merkle_root, + iota >> 1, + &evaluations, + ) } - #[cfg(feature = "instruments")] - let elapsed1 = timer1.elapsed(); - #[cfg(feature = "instruments")] - println!(" Time spent: {:?}", elapsed1); - - #[cfg(feature = "instruments")] - println!("- Started step 2: Verify claimed polynomial"); - #[cfg(feature = "instruments")] - let timer2 = Instant::now(); + /// Verify a single FRI query + /// `zetas`: the vector of all challenges sent by the verifier to the prover at the commit + /// phase to fold polynomials. + /// `iota`: the index challenge of this FRI query. This index uniquely determines two elements 𝜐 and -𝜐 + /// of the evaluation domain of FRI layer 0. + /// `evaluation_point_inv`: precomputed value of 𝜐⁻¹. + /// `deep_composition_evaluation`: precomputed value of pβ‚€(𝜐), where pβ‚€ is the deep composition polynomial. + /// `deep_composition_evaluation_sym`: precomputed value of pβ‚€(-𝜐), where pβ‚€ is the deep composition polynomial. + fn verify_query_and_sym_openings( + proof: &StarkProof, + zetas: &[FieldElement], + iota: usize, + fri_decommitment: &FriDecommitment, + evaluation_point_inv: FieldElement, + deep_composition_evaluation: &FieldElement, + deep_composition_evaluation_sym: &FieldElement, + ) -> bool + where + FieldElement: Serializable, + { + let fri_layers_merkle_roots = &proof.fri_layers_merkle_roots; + let evaluation_point_vec: Vec> = + core::iter::successors(Some(evaluation_point_inv.square()), |evaluation_point| { + Some(evaluation_point.square()) + }) + .take(fri_layers_merkle_roots.len()) + .collect(); + + let p0_eval = deep_composition_evaluation; + let p0_eval_sym = deep_composition_evaluation_sym; + + // Reconstruct p₁(𝜐²) + let mut v = + (p0_eval + p0_eval_sym) + &zetas[0] * (p0_eval - p0_eval_sym) * evaluation_point_inv; + let mut index = iota; + + // For each FRI layer, starting from the layer 1: use the proof to verify the validity of values pα΅’(βˆ’πœ^(2ⁱ)) (given by the prover) and + // pα΅’(𝜐^(2ⁱ)) (computed on the previous iteration by the verifier). Then use them to obtain pα΅’β‚Šβ‚(𝜐^(2ⁱ⁺¹)). + // Finally, check that the final value coincides with the given by the prover. + fri_layers_merkle_roots + .iter() + .enumerate() + .zip(&fri_decommitment.layers_auth_paths_sym) + .zip(&fri_decommitment.layers_evaluations_sym) + .zip(evaluation_point_vec) + .fold( + true, + |result, + ( + (((i, merkle_root), auth_path_sym), evaluation_sym), + evaluation_point_inv, + )| { + // Verify opening Open(pα΅’(Dβ‚–), βˆ’πœ^(2ⁱ)) and Open(pα΅’(Dβ‚–), 𝜐^(2ⁱ)). + // `v` is pα΅’(𝜐^(2ⁱ)). + // `evaluation_sym` is pα΅’(βˆ’πœ^(2ⁱ)). + let openings_ok = Self::verify_fri_layer_openings( + merkle_root, + auth_path_sym, + &v, + evaluation_sym, + index, + ); - if !step_2_verify_claimed_composition_polynomial(&air, proof, &domain, &challenges) { - error!("Composition Polynomial verification failed"); - return false; + // Update `v` with next value pα΅’β‚Šβ‚(𝜐^(2ⁱ⁺¹)). + v = (&v + evaluation_sym) + &zetas[i + 1] * (&v - evaluation_sym) * evaluation_point_inv; + + // Update index for next iteration. The index of the squares in the next layer + // is obtained by halving the current index. This is due to the bit-reverse + // ordering of the elements in the Merkle tree. + index >>= 1; + + if i < fri_decommitment.layers_evaluations_sym.len() - 1 { + result & openings_ok + } else { + // Check that final value is the given by the prover + result & (v == proof.fri_last_value) & openings_ok + } + }, + ) } - #[cfg(feature = "instruments")] - let elapsed2 = timer2.elapsed(); - #[cfg(feature = "instruments")] - println!(" Time spent: {:?}", elapsed2); - #[cfg(feature = "instruments")] + fn reconstruct_deep_composition_poly_evaluations_for_all_queries( + challenges: &Challenges, + domain: &Domain, + proof: &StarkProof, + ) -> DeepPolynomialEvaluations + where + A: AIR, + { + let mut deep_poly_evaluations = Vec::new(); + let mut deep_poly_evaluations_sym = Vec::new(); + for (i, iota) in challenges.iotas.iter().enumerate() { + let primitive_root = + &Self::Field::get_primitive_root_of_unity(domain.root_order as u64).unwrap(); + + let evaluation_point = Self::query_challenge_to_evaluation_point(*iota, domain); + deep_poly_evaluations.push(Self::reconstruct_deep_composition_poly_evaluation( + proof, + &evaluation_point, + primitive_root, + challenges, + &proof.deep_poly_openings[i].lde_trace_evaluations, + &proof.deep_poly_openings[i].lde_composition_poly_parts_evaluation, + )); + + let evaluation_point = Self::query_challenge_to_evaluation_point_sym(*iota, domain); + deep_poly_evaluations_sym.push(Self::reconstruct_deep_composition_poly_evaluation( + proof, + &evaluation_point, + primitive_root, + challenges, + &proof.deep_poly_openings_sym[i].lde_trace_evaluations, + &proof.deep_poly_openings_sym[i].lde_composition_poly_parts_evaluation, + )); + } + (deep_poly_evaluations, deep_poly_evaluations_sym) + } - println!("- Started step 3: Verify FRI"); - #[cfg(feature = "instruments")] - let timer3 = Instant::now(); + fn reconstruct_deep_composition_poly_evaluation>( + proof: &StarkProof, + evaluation_point: &FieldElement, + primitive_root: &FieldElement, + challenges: &Challenges, + lde_trace_evaluations: &[FieldElement], + lde_composition_poly_parts_evaluation: &[FieldElement], + ) -> FieldElement { + let mut denoms_trace = (0..proof.trace_ood_frame_evaluations.num_rows()) + .map(|row_idx| evaluation_point - &challenges.z * primitive_root.pow(row_idx as u64)) + .collect::>>(); + FieldElement::inplace_batch_inverse(&mut denoms_trace).unwrap(); + + let trace_term = (0..proof.trace_ood_frame_evaluations.num_columns()) + .zip(&challenges.trace_term_coeffs) + .fold(FieldElement::zero(), |trace_terms, (col_idx, coeff_row)| { + let trace_i = (0..proof.trace_ood_frame_evaluations.num_rows()) + .zip(coeff_row) + .fold(FieldElement::zero(), |trace_t, (row_idx, coeff)| { + let poly_evaluation = (lde_trace_evaluations[col_idx].clone() + - proof.trace_ood_frame_evaluations.get_row(row_idx)[col_idx].clone()) + * &denoms_trace[row_idx]; + trace_t + &poly_evaluation * coeff + }); + trace_terms + trace_i + }); + + let number_of_parts = lde_composition_poly_parts_evaluation.len(); + let z_pow = &challenges.z.pow(number_of_parts); + + let denom_composition = (evaluation_point - z_pow).inv().unwrap(); + let mut h_terms = FieldElement::zero(); + for (j, h_i_upsilon) in lde_composition_poly_parts_evaluation.iter().enumerate() { + let h_i_zpower = &proof.composition_poly_parts_ood_evaluation[j]; + let h_i_term = (h_i_upsilon - h_i_zpower) * &challenges.gammas[j]; + h_terms += h_i_term; + } + h_terms = h_terms * denom_composition; - if !step_3_verify_fri(proof, &domain, &challenges) { - error!("FRI verification failed"); - return false; + trace_term + h_terms } - #[cfg(feature = "instruments")] - let elapsed3 = timer3.elapsed(); - #[cfg(feature = "instruments")] - println!(" Time spent: {:?}", elapsed3); - - #[cfg(feature = "instruments")] - println!("- Started step 4: Verify deep composition polynomial"); - #[cfg(feature = "instruments")] - let timer4 = Instant::now(); + fn verify( + proof: &StarkProof, + pub_input: &A::PublicInputs, + proof_options: &ProofOptions, + mut transcript: impl IsStarkTranscript, + ) -> bool + where + A: AIR, + FieldElement: Serializable, + { + // Verify there are enough queries + if proof.query_list.len() < proof_options.fri_number_of_queries { + return false; + } - #[allow(clippy::let_and_return)] - if !step_4_verify_deep_composition_polynomial(&air, proof, &domain, &challenges) { - error!("DEEP Composition Polynomial verification failed"); - return false; - } + #[cfg(feature = "instruments")] + println!("- Started step 1: Recover challenges"); + #[cfg(feature = "instruments")] + let timer1 = Instant::now(); - #[cfg(feature = "instruments")] - let elapsed4 = timer4.elapsed(); - #[cfg(feature = "instruments")] - println!(" Time spent: {:?}", elapsed4); + let air = A::new(proof.trace_length, pub_input, proof_options); + let domain = Domain::new(&air); - #[cfg(feature = "instruments")] - { - let total_time = elapsed1 + elapsed2 + elapsed3 + elapsed4; - println!( - " Fraction of verifying time per step: {:.4} {:.4} {:.4} {:.4}", - elapsed1.as_nanos() as f64 / total_time.as_nanos() as f64, - elapsed2.as_nanos() as f64 / total_time.as_nanos() as f64, - elapsed3.as_nanos() as f64 / total_time.as_nanos() as f64, - elapsed4.as_nanos() as f64 / total_time.as_nanos() as f64 + let challenges = Self::step_1_replay_rounds_and_recover_challenges( + &air, + proof, + &domain, + &mut transcript, ); - } - true -} + // verify grinding + let grinding_factor = air.context().proof_options.grinding_factor; + if challenges.leading_zeros_count < grinding_factor { + error!("Grinding factor not satisfied"); + return false; + } -#[cfg(test)] -pub mod tests { - use std::num::ParseIntError; + #[cfg(feature = "instruments")] + let elapsed1 = timer1.elapsed(); + #[cfg(feature = "instruments")] + println!(" Time spent: {:?}", elapsed1); - use lambdaworks_math::field::{ - element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, - }; - - use crate::{ - domain::Domain, - examples::fibonacci_2_cols_shifted::{self, Fibonacci2ColsShifted}, - proof::options::ProofOptions, - prover::prove, - traits::AIR, - transcript::StoneProverTranscript, - verifier::step_1_replay_rounds_and_recover_challenges, - }; - - pub fn decode_hex(s: &str) -> Result, ParseIntError> { - (0..s.len()) - .step_by(2) - .map(|i| u8::from_str_radix(&s[i..i + 2], 16)) - .collect() - } + #[cfg(feature = "instruments")] + println!("- Started step 2: Verify claimed polynomial"); + #[cfg(feature = "instruments")] + let timer2 = Instant::now(); - #[test] - fn test_sharp_compatibility() { - let trace = fibonacci_2_cols_shifted::compute_trace(FieldElement::one(), 4); + if !Self::step_2_verify_claimed_composition_polynomial(&air, proof, &domain, &challenges) { + error!("Composition Polynomial verification failed"); + return false; + } - let claimed_index = 3; - let claimed_value = trace.get_row(claimed_index)[0]; - let mut proof_options = ProofOptions::default_test_options(); - proof_options.blowup_factor = 4; - proof_options.coset_offset = 3; + #[cfg(feature = "instruments")] + let elapsed2 = timer2.elapsed(); + #[cfg(feature = "instruments")] + println!(" Time spent: {:?}", elapsed2); + #[cfg(feature = "instruments")] - let pub_inputs = fibonacci_2_cols_shifted::PublicInputs { - claimed_value, - claimed_index, - }; + println!("- Started step 3: Verify FRI"); + #[cfg(feature = "instruments")] + let timer3 = Instant::now(); - let transcript_init_seed = [0xca, 0xfe, 0xca, 0xfe]; + if !Self::step_3_verify_fri(proof, &domain, &challenges) { + error!("FRI verification failed"); + return false; + } - let proof = prove::>( - &trace, - &pub_inputs, - &proof_options, - StoneProverTranscript::new(&transcript_init_seed), - ) - .unwrap(); + #[cfg(feature = "instruments")] + let elapsed3 = timer3.elapsed(); + #[cfg(feature = "instruments")] + println!(" Time spent: {:?}", elapsed3); - let air = Fibonacci2ColsShifted::new(proof.trace_length, &pub_inputs, &proof_options); - let domain = Domain::new(&air); - let challenges = step_1_replay_rounds_and_recover_challenges( - &air, - &proof, - &domain, - &mut StoneProverTranscript::new(&transcript_init_seed), - ); + #[cfg(feature = "instruments")] + println!("- Started step 4: Verify deep composition polynomial"); + #[cfg(feature = "instruments")] + let timer4 = Instant::now(); - assert_eq!( - proof.lde_trace_merkle_roots[0].to_vec(), - decode_hex("0eb9dcc0fb1854572a01236753ce05139d392aa3aeafe72abff150fe21175594").unwrap() - ); + #[allow(clippy::let_and_return)] + if !Self::step_4_verify_trace_and_composition_openings(&air, proof, &challenges) { + error!("DEEP Composition Polynomial verification failed"); + return false; + } - let beta = challenges.transition_coeffs[0]; - assert_eq!( - beta, - FieldElement::from_hex_unchecked( - "86105fff7b04ed4068ecccb8dbf1ed223bd45cd26c3532d6c80a818dbd4fa7" - ), - ); - assert_eq!(challenges.transition_coeffs[1], beta.pow(2u64)); - assert_eq!(challenges.boundary_coeffs[0], beta.pow(3u64)); - assert_eq!(challenges.boundary_coeffs[1], beta.pow(4u64)); + #[cfg(feature = "instruments")] + let elapsed4 = timer4.elapsed(); + #[cfg(feature = "instruments")] + println!(" Time spent: {:?}", elapsed4); + + #[cfg(feature = "instruments")] + { + let total_time = elapsed1 + elapsed2 + elapsed3 + elapsed4; + println!( + " Fraction of verifying time per step: {:.4} {:.4} {:.4} {:.4}", + elapsed1.as_nanos() as f64 / total_time.as_nanos() as f64, + elapsed2.as_nanos() as f64 / total_time.as_nanos() as f64, + elapsed3.as_nanos() as f64 / total_time.as_nanos() as f64, + elapsed4.as_nanos() as f64 / total_time.as_nanos() as f64 + ); + } + + true } } From d2184c0ac21661c91a02bf180f24bd4c830f61d9 Mon Sep 17 00:00:00 2001 From: PatStiles <33334338+PatStiles@users.noreply.github.com> Date: Tue, 17 Oct 2023 17:08:53 -0500 Subject: [PATCH 14/18] feat(benchmarks): Refactor Field Benchmarks (#606) * add perf flamegraph and refactor bench * fmt * ci * fix xi * fix ci --------- Co-authored-by: Mariano A. Nicolini --- math/Cargo.toml | 3 +- math/benches/criterion_field.rs | 108 ++------------- math/benches/fields/mod.rs | 1 + math/benches/fields/stark252.rs | 230 ++++++++++++++++++++++++++++++++ 4 files changed, 242 insertions(+), 100 deletions(-) create mode 100644 math/benches/fields/mod.rs create mode 100644 math/benches/fields/stark252.rs diff --git a/math/Cargo.toml b/math/Cargo.toml index 4af68da852..b014501cd2 100644 --- a/math/Cargo.toml +++ b/math/Cargo.toml @@ -27,10 +27,11 @@ lambdaworks-gpu = { workspace = true, optional = true } [dev-dependencies] rand = { version = "0.8.5", default-features = false } -criterion = "0.4" +criterion = "0.5.1" const-random = "0.1.15" iai-callgrind.workspace = true proptest = "1.1.0" +pprof = { version = "0.13.0", features = ["criterion","flamegraph"] } [features] rayon = ["dep:rayon"] diff --git a/math/benches/criterion_field.rs b/math/benches/criterion_field.rs index 8db6e0d6cc..11cceaf9f4 100644 --- a/math/benches/criterion_field.rs +++ b/math/benches/criterion_field.rs @@ -1,102 +1,12 @@ -use std::hint::black_box; - use criterion::{criterion_group, criterion_main, Criterion}; -use lambdaworks_math::{ - field::fields::{ - fft_friendly::stark_252_prime_field::{ - MontgomeryConfigStark252PrimeField, Stark252PrimeField, - }, - montgomery_backed_prime_fields::IsModulus, - }, - unsigned_integer::{element::U256, montgomery::MontgomeryAlgorithms}, -}; - -mod utils; -use utils::u64_utils; - -pub fn starkfield_ops_benchmarks(c: &mut Criterion) { - let mut group = c.benchmark_group("Stark FP operations"); - let (x, y) = u64_utils::get_field_elements(); - - group.bench_with_input("add", &(x, y), |bench, (x, y)| { - bench.iter(|| x + y); - }); - - group.bench_with_input("mul", &(x, y), |bench, (x, y)| { - bench.iter(|| x * y); - }); - - group.bench_with_input("pow by 1", &x, |bench, x| { - bench.iter(|| x.pow(1_u64)); - }); - - // The non-boxed constants are intentional as they are - // normally computed at compile time. - group.bench_with_input("sos_square", &x, |bench, x| { - bench.iter(|| { - MontgomeryAlgorithms::sos_square( - black_box(x.value()), - &>::MODULUS, - &Stark252PrimeField::MU, - ) - }); - }); - - group.bench_with_input("square", &x, |bench, x| { - bench.iter(|| x.square()); - }); - - group.bench_with_input("square with pow", &x, |bench, x| { - bench.iter(|| x.pow(2_u64)); - }); - - group.bench_with_input("square with mul", &x, |bench, x| { - bench.iter(|| x * x); - }); - - group.bench_with_input("pow", &(x, 5u64), |bench, (x, y)| { - bench.iter(|| x.pow(*y)); - }); - - group.bench_with_input("sub", &(x, y), |bench, (x, y)| { - bench.iter(|| x - y); - }); - - group.bench_with_input("inv", &x, |bench, x| { - bench.iter(|| x.inv().unwrap()); - }); - - group.bench_with_input("div", &(x, y), |bench, (x, y)| { - bench.iter(|| x / y); - }); - - group.bench_with_input("eq", &(x, y), |bench, (x, y)| { - bench.iter(|| x == y); - }); - - group.bench_with_input("sqrt", &x, |bench, x| { - bench.iter(|| x.sqrt()); - }); - - group.bench_with_input("sqrt squared", &(x * x), |bench, x| { - bench.iter(|| x.sqrt()); - }); - - // Unsigned integer bitwise operations - let (x, y) = (x.value(), y.value()); - - group.bench_with_input("bitand", &(x, y), |bench, (&x, &y)| { - bench.iter(|| x & y); - }); - - group.bench_with_input("bitor", &(x, y), |bench, (&x, &y)| { - bench.iter(|| x | y); - }); +use pprof::criterion::{Output, PProfProfiler}; - group.bench_with_input("bitxor", &(x, y), |bench, (&x, &y)| { - bench.iter(|| x ^ y); - }); -} +mod fields; +use fields::stark252::starkfield_ops_benchmarks; -criterion_group!(starkfp, starkfield_ops_benchmarks); -criterion_main!(starkfp); +criterion_group!( + name = field_benches; + config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); + targets = starkfield_ops_benchmarks +); +criterion_main!(field_benches); diff --git a/math/benches/fields/mod.rs b/math/benches/fields/mod.rs new file mode 100644 index 0000000000..c1dc58a950 --- /dev/null +++ b/math/benches/fields/mod.rs @@ -0,0 +1 @@ +pub mod stark252; diff --git a/math/benches/fields/stark252.rs b/math/benches/fields/stark252.rs new file mode 100644 index 0000000000..39c4ef838a --- /dev/null +++ b/math/benches/fields/stark252.rs @@ -0,0 +1,230 @@ +use std::hint::black_box; + +use criterion::Criterion; +use lambdaworks_math::{ + field::{ + element::FieldElement, + fields::{ + fft_friendly::stark_252_prime_field::{ + MontgomeryConfigStark252PrimeField, Stark252PrimeField, + }, + montgomery_backed_prime_fields::IsModulus, + }, + }, + unsigned_integer::{ + element::{UnsignedInteger, U256}, + montgomery::MontgomeryAlgorithms, + }, +}; +use rand::random; + +pub type F = FieldElement; + +#[inline(never)] +#[no_mangle] +#[export_name = "util::rand_field_elements"] +pub fn rand_field_elements(num: usize) -> Vec<(F, F)> { + let mut result = Vec::with_capacity(num); + for _ in 0..result.capacity() { + let rand_a = UnsignedInteger { limbs: random() }; + let rand_b = UnsignedInteger { limbs: random() }; + result.push((F::new(rand_a), F::new(rand_b))); + } + result +} + +pub fn starkfield_ops_benchmarks(c: &mut Criterion) { + let input: Vec> = [1, 10, 100, 1000, 10000, 100000, 1000000] + .into_iter() + .map(rand_field_elements) + .collect::>(); + let mut group = c.benchmark_group("Stark FP operations"); + + for i in input.clone().into_iter() { + group.bench_with_input(format!("add {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(x) + black_box(y)); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("mul {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(x) * black_box(y)); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("pow by 1 {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, _) in i { + black_box(black_box(x).pow(1_u64)); + } + }); + }); + } + + // The non-boxed constants are intentional as they are + // normally computed at compile time. + for i in input.clone().into_iter() { + group.bench_with_input(format!("sos_square {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, _) in i { + MontgomeryAlgorithms::sos_square( + black_box(black_box(x.value())), + &>::MODULUS, + &Stark252PrimeField::MU, + ); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("square {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, _) in i { + black_box(black_box(x).square()); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("square with pow {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, _) in i { + black_box(black_box(x).pow(2_u64)); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("square with mul {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, _) in i { + black_box(black_box(x) * black_box(x)); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input( + format!("pow {:?}", &i.len()), + &(i, 5u64), + |bench, (i, a)| { + bench.iter(|| { + for (x, _) in i { + black_box(black_box(x).pow(*a)); + } + }); + }, + ); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("sub {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(x) - black_box(y)); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("inv {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, _) in i { + black_box(black_box(x).inv().unwrap()); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("div {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(x) / black_box(y)); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("eq {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, y) in i { + black_box(black_box(x) == black_box(y)); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("sqrt {:?}", &i.len()), &i, |bench, i| { + bench.iter(|| { + for (x, _) in i { + black_box(black_box(x).sqrt()); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("sqrt squared {:?}", &i.len()), &i, |bench, i| { + let i: Vec = i.iter().map(|(x, _)| x * x).collect(); + bench.iter(|| { + for x in &i { + black_box(black_box(x).sqrt()); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("bitand {:?}", &i.len()), &i, |bench, i| { + // Note: we should strive to have the number of limbs be generic... ideally this benchmark group itself should have a generic type that we call into from the main runner. + let i: Vec<(UnsignedInteger<4>, UnsignedInteger<4>)> = + i.iter().map(|(x, y)| (*x.value(), *y.value())).collect(); + bench.iter(|| { + for (x, y) in &i { + black_box(black_box(*x) & black_box(*y)); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("bitor {:?}", &i.len()), &i, |bench, i| { + let i: Vec<(UnsignedInteger<4>, UnsignedInteger<4>)> = + i.iter().map(|(x, y)| (*x.value(), *y.value())).collect(); + bench.iter(|| { + for (x, y) in &i { + black_box(black_box(*x) | black_box(*y)); + } + }); + }); + } + + for i in input.clone().into_iter() { + group.bench_with_input(format!("bitxor {:?}", &i.len()), &i, |bench, i| { + let i: Vec<(UnsignedInteger<4>, UnsignedInteger<4>)> = + i.iter().map(|(x, y)| (*x.value(), *y.value())).collect(); + bench.iter(|| { + for (x, y) in &i { + black_box(black_box(*x) ^ black_box(*y)); + } + }); + }); + } +} From 23154c1b2b7c1cb1620e40ee53fbb446a2923923 Mon Sep 17 00:00:00 2001 From: "Mariano A. Nicolini" Date: Wed, 18 Oct 2023 10:37:32 -0300 Subject: [PATCH 15/18] Add Table data structure and refactor code (#599) * Save work in progress * Add table module * Bug fixes * Fix more bugs * Remove test that does not make sense * Remove debugging code * Remove debugging code * Remove more debugging code * Uncomment commented tests * Uncomment commented DummyAIR * Fix tests * Polish trace module * Polish interfaces * Add debug assertion in table * Add documentation to table module * Add documentation to trace table module * Start Frame refactor * Reorder imports * Format * Add debug function to check that 1d array can be interpreted as 2d array * Remove reference to variable * Change check_2d_array_integrity to validate_2d_structure and change debug assertion to normal assertion * Polish constraint evaluations struct * Remove evaluations module * Solve remaining merge conflict * Fix tests --------- Co-authored-by: Mauro Toscano <12560266+MauroToscano@users.noreply.github.com> --- provers/cairo/src/air.rs | 84 +++---- provers/cairo/src/execution_trace.rs | 132 ++++------- provers/cairo/src/tests/integration_tests.rs | 31 ++- .../stark/src/constraints/evaluation_table.rs | 34 --- provers/stark/src/constraints/evaluator.rs | 17 +- provers/stark/src/constraints/mod.rs | 1 - provers/stark/src/debug.rs | 13 +- provers/stark/src/examples/dummy_air.rs | 2 +- .../src/examples/fibonacci_2_cols_shifted.rs | 2 +- .../stark/src/examples/fibonacci_2_columns.rs | 2 +- provers/stark/src/examples/fibonacci_rap.rs | 10 +- provers/stark/src/examples/quadratic_air.rs | 2 +- .../stark/src/examples/simple_fibonacci.rs | 2 +- provers/stark/src/frame.rs | 24 +- provers/stark/src/lib.rs | 1 + provers/stark/src/proof/options.rs | 2 +- provers/stark/src/prover.rs | 7 +- provers/stark/src/table.rs | 108 +++++++++ provers/stark/src/trace.rs | 214 ++++++++---------- provers/stark/src/verifier.rs | 10 +- 20 files changed, 354 insertions(+), 344 deletions(-) delete mode 100644 provers/stark/src/constraints/evaluation_table.rs create mode 100644 provers/stark/src/table.rs diff --git a/provers/cairo/src/air.rs b/provers/cairo/src/air.rs index 3210f6221f..88a8012722 100644 --- a/provers/cairo/src/air.rs +++ b/provers/cairo/src/air.rs @@ -21,6 +21,7 @@ use stark_platinum_prover::{ }; use crate::Felt252; +use stark_platinum_prover::table::Table; use super::{cairo_mem::CairoMemory, register_states::RegisterStates}; @@ -673,7 +674,8 @@ impl AIR for CairoAIR { transition_exemptions.push(0); // range-check builtin exemption num_transition_constraints += 1; // range-check builtin value decomposition constraint } - let num_transition_exemptions =1_usize; + let num_transition_exemptions = 1_usize; + let context = AirContext { proof_options: proof_options.clone(), trace_columns, @@ -708,19 +710,16 @@ impl AIR for CairoAIR { main_trace: &TraceTable, rap_challenges: &Self::RAPChallenges, ) -> TraceTable { - let addresses_original = main_trace - .get_cols(&[ - FRAME_PC, - FRAME_DST_ADDR, - FRAME_OP0_ADDR, - FRAME_OP1_ADDR, - EXTRA_ADDR, - ]) - .table; - - let values_original = main_trace - .get_cols(&[FRAME_INST, FRAME_DST, FRAME_OP0, FRAME_OP1, EXTRA_VAL]) - .table; + let addresses_original = main_trace.merge_columns(&[ + FRAME_PC, + FRAME_DST_ADDR, + FRAME_OP0_ADDR, + FRAME_OP1_ADDR, + EXTRA_ADDR, + ]); + + let values_original = + main_trace.merge_columns(&[FRAME_INST, FRAME_DST, FRAME_OP0, FRAME_OP1, EXTRA_VAL]); let (addresses, values) = add_pub_memory_in_public_input_section( &addresses_original, @@ -739,9 +738,8 @@ impl AIR for CairoAIR { ); // Range Check - let offsets_original = main_trace - .get_cols(&[OFF_DST, OFF_OP0, OFF_OP1, RC_HOLES]) - .table; + let offsets_original = main_trace.merge_columns(&[OFF_DST, OFF_OP0, OFF_OP1, RC_HOLES]); + let mut offsets_sorted: Vec = offsets_original .iter() .map(|x| x.representative().into()) @@ -759,34 +757,36 @@ impl AIR for CairoAIR { ); // Convert from long-format to wide-format again - let mut aux_table = Vec::new(); + let mut aux_data = Vec::new(); for i in 0..main_trace.n_rows() { - aux_table.push(offsets_sorted[4 * i]); - aux_table.push(offsets_sorted[4 * i + 1]); - aux_table.push(offsets_sorted[4 * i + 2]); - aux_table.push(offsets_sorted[4 * i + 3]); - aux_table.push(addresses[5 * i]); - aux_table.push(addresses[5 * i + 1]); - aux_table.push(addresses[5 * i + 2]); - aux_table.push(addresses[5 * i + 3]); - aux_table.push(addresses[5 * i + 4]); - aux_table.push(values[5 * i]); - aux_table.push(values[5 * i + 1]); - aux_table.push(values[5 * i + 2]); - aux_table.push(values[5 * i + 3]); - aux_table.push(values[5 * i + 4]); - aux_table.push(permutation_col[5 * i]); - aux_table.push(permutation_col[5 * i + 1]); - aux_table.push(permutation_col[5 * i + 2]); - aux_table.push(permutation_col[5 * i + 3]); - aux_table.push(permutation_col[5 * i + 4]); - aux_table.push(range_check_permutation_col[4 * i]); - aux_table.push(range_check_permutation_col[4 * i + 1]); - aux_table.push(range_check_permutation_col[4 * i + 2]); - aux_table.push(range_check_permutation_col[4 * i + 3]); + aux_data.push(offsets_sorted[4 * i]); + aux_data.push(offsets_sorted[4 * i + 1]); + aux_data.push(offsets_sorted[4 * i + 2]); + aux_data.push(offsets_sorted[4 * i + 3]); + aux_data.push(addresses[5 * i]); + aux_data.push(addresses[5 * i + 1]); + aux_data.push(addresses[5 * i + 2]); + aux_data.push(addresses[5 * i + 3]); + aux_data.push(addresses[5 * i + 4]); + aux_data.push(values[5 * i]); + aux_data.push(values[5 * i + 1]); + aux_data.push(values[5 * i + 2]); + aux_data.push(values[5 * i + 3]); + aux_data.push(values[5 * i + 4]); + aux_data.push(permutation_col[5 * i]); + aux_data.push(permutation_col[5 * i + 1]); + aux_data.push(permutation_col[5 * i + 2]); + aux_data.push(permutation_col[5 * i + 3]); + aux_data.push(permutation_col[5 * i + 4]); + aux_data.push(range_check_permutation_col[4 * i]); + aux_data.push(range_check_permutation_col[4 * i + 1]); + aux_data.push(range_check_permutation_col[4 * i + 2]); + aux_data.push(range_check_permutation_col[4 * i + 3]); } - TraceTable::new(aux_table, self.number_auxiliary_rap_columns()) + let aux_table = Table::new(&aux_data, self.number_auxiliary_rap_columns()); + + TraceTable { table: aux_table } } fn build_rap_challenges( diff --git a/provers/cairo/src/execution_trace.rs b/provers/cairo/src/execution_trace.rs index af2c291942..a611d23009 100644 --- a/provers/cairo/src/execution_trace.rs +++ b/provers/cairo/src/execution_trace.rs @@ -1,23 +1,3 @@ -use lambdaworks_math::{ - field::{ - element::FieldElement, - fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, - traits::{IsFFTField, IsPrimeField}, - }, - unsigned_integer::element::UnsignedInteger, -}; -use stark_platinum_prover::trace::TraceTable; -use std::ops::Range; - -use crate::air::{EXTRA_ADDR, RC_HOLES}; -use crate::{ - air::{ - MemorySegment, PublicInputs, FRAME_DST_ADDR, FRAME_OP0_ADDR, FRAME_OP1_ADDR, FRAME_PC, - OFF_DST, OFF_OP0, OFF_OP1, - }, - Felt252, -}; - use super::{ cairo_mem::CairoMemory, decode::{ @@ -29,6 +9,22 @@ use super::{ }, register_states::RegisterStates, }; +use crate::air::{EXTRA_ADDR, RC_HOLES}; +use crate::{ + air::{ + MemorySegment, PublicInputs, FRAME_DST_ADDR, FRAME_OP0_ADDR, FRAME_OP1_ADDR, FRAME_PC, + OFF_DST, OFF_OP0, OFF_OP1, + }, + Felt252, +}; +use lambdaworks_math::{ + field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, + unsigned_integer::element::UnsignedInteger, +}; +use stark_platinum_prover::trace::TraceTable; +use std::ops::Range; + +type CairoTraceTable = TraceTable; // MAIN TRACE LAYOUT // ----------------------------------------------------------------------------------------- @@ -52,12 +48,12 @@ pub fn build_main_trace( register_states: &RegisterStates, memory: &CairoMemory, public_input: &mut PublicInputs, -) -> TraceTable { +) -> CairoTraceTable { let mut main_trace = build_cairo_execution_trace(register_states, memory, public_input); - let mut address_cols = main_trace - .get_cols(&[FRAME_PC, FRAME_DST_ADDR, FRAME_OP0_ADDR, FRAME_OP1_ADDR]) - .table; + let mut address_cols = + main_trace.merge_columns(&[FRAME_PC, FRAME_DST_ADDR, FRAME_OP0_ADDR, FRAME_OP1_ADDR]); + address_cols.sort_by_key(|x| x.representative()); let (rc_holes, rc_min, rc_max) = get_rc_holes(&main_trace, &[OFF_DST, OFF_OP0, OFF_OP1]); @@ -66,7 +62,6 @@ pub fn build_main_trace( fill_rc_holes(&mut main_trace, &rc_holes); let memory_holes = get_memory_holes(&address_cols, public_input.codelen); - // let memory_holes = get_memory_holes(&address_cols, public_input.public_memory.len()); if !memory_holes.is_empty() { fill_memory_holes(&mut main_trace, &memory_holes); @@ -79,8 +74,8 @@ pub fn build_main_trace( ); let trace_len_next_power_of_two = main_trace.n_rows().next_power_of_two(); - let padding = trace_len_next_power_of_two - main_trace.n_rows(); - pad_with_last_row(&mut main_trace, padding); + let padding_len = trace_len_next_power_of_two - main_trace.n_rows(); + main_trace.pad_with_last_row(padding_len); main_trace } @@ -88,30 +83,15 @@ pub fn build_main_trace( /// Artificial `(0, 0)` dummy memory accesses must be added for the public memory. /// See section 9.8 of the Cairo whitepaper. fn add_pub_memory_dummy_accesses( - main_trace: &mut TraceTable, + main_trace: &mut CairoTraceTable, pub_memory_len: usize, last_memory_hole_idx: usize, ) { for i in 0..pub_memory_len { - add_to_column( - last_memory_hole_idx + i, - main_trace, - &Felt252::zero(), - EXTRA_ADDR, - ); + main_trace.set_or_extend(last_memory_hole_idx + i, EXTRA_ADDR, &Felt252::zero()); } } -fn pad_with_last_row(trace: &mut TraceTable, number_rows: usize) { - let last_row = trace.last_row().to_vec(); - let mut pad: Vec<_> = std::iter::repeat(&last_row) - .take(number_rows) - .flatten() - .cloned() - .collect(); - trace.table.append(&mut pad); -} - /// Gets holes from the range-checked columns. These holes must be filled for the /// permutation range-checks, as can be read in section 9.9 of the Cairo whitepaper. /// Receives the trace and the indexes of the range-checked columns. @@ -119,15 +99,8 @@ fn pad_with_last_row(trace: &mut TraceTable, number_rows: usiz /// values rc_min and rc_max, corresponding to the minimum and maximum values of the range. /// NOTE: These extreme values should be received as public inputs in the future and not /// calculated here. -fn get_rc_holes( - trace: &TraceTable, - columns_indices: &[usize], -) -> (Vec>, u16, u16) -where - F: IsFFTField + IsPrimeField, - u16: From, -{ - let offset_columns = trace.get_cols(columns_indices).table; +fn get_rc_holes(trace: &CairoTraceTable, columns_indices: &[usize]) -> (Vec, u16, u16) { + let offset_columns = trace.merge_columns(columns_indices); let mut sorted_offset_representatives: Vec = offset_columns .iter() @@ -135,12 +108,12 @@ where .collect(); sorted_offset_representatives.sort(); - let mut all_missing_values: Vec> = Vec::new(); + let mut all_missing_values: Vec = Vec::new(); for window in sorted_offset_representatives.windows(2) { if window[1] != window[0] { let mut missing_range: Vec<_> = ((window[0] + 1)..window[1]) - .map(|x| FieldElement::from(x as u64)) + .map(|x| Felt252::from(x as u64)) .collect(); all_missing_values.append(&mut missing_range); } @@ -148,7 +121,7 @@ where let multiple_of_three_padding = ((all_missing_values.len() + 2) / 3) * 3 - all_missing_values.len(); - let padding_element = FieldElement::from(*sorted_offset_representatives.last().unwrap() as u64); + let padding_element = Felt252::from(*sorted_offset_representatives.last().unwrap() as u64); all_missing_values.append(&mut vec![padding_element; multiple_of_three_padding]); ( @@ -159,17 +132,18 @@ where } /// Fills holes found in the range-checked columns. -fn fill_rc_holes(trace: &mut TraceTable, holes: &[Felt252]) { +fn fill_rc_holes(trace: &mut CairoTraceTable, holes: &[Felt252]) { holes.iter().enumerate().for_each(|(i, hole)| { - add_to_column(i, trace, hole, RC_HOLES); + trace.set_or_extend(i, RC_HOLES, hole); }); // Fill the rest of the RC_HOLES column to avoid inexistent zeros - let mut offsets = trace.get_cols(&[OFF_DST, OFF_OP0, OFF_OP1, RC_HOLES]).table; + let mut offsets = trace.merge_columns(&[OFF_DST, OFF_OP0, OFF_OP1, RC_HOLES]); + offsets.sort_by_key(|x| x.representative()); let greatest_offset = offsets.last().unwrap(); (holes.len()..trace.n_rows()).for_each(|i| { - add_to_column(i, trace, greatest_offset, RC_HOLES); + trace.set_or_extend(i, RC_HOLES, greatest_offset); }); } @@ -211,28 +185,12 @@ fn get_memory_holes(sorted_addrs: &[Felt252], codelen: usize) -> Vec { } /// Fill memory holes in the extra address column of the trace with the missing addresses. -fn fill_memory_holes(trace: &mut TraceTable, memory_holes: &[Felt252]) { +fn fill_memory_holes(trace: &mut CairoTraceTable, memory_holes: &[Felt252]) { memory_holes.iter().enumerate().for_each(|(i, hole)| { - add_to_column(i, trace, hole, EXTRA_ADDR); + trace.set_or_extend(i, EXTRA_ADDR, hole); }); } -fn add_to_column( - i: usize, - trace: &mut TraceTable, - value: &Felt252, - col: usize, -) { - let trace_idx = i * trace.n_cols + col; - if trace_idx >= trace.table.len() { - let mut last_row = trace.last_row().to_vec(); - last_row[col] = *value; - trace.table.append(&mut last_row); - } else { - trace.table[trace_idx] = *value; - } -} - /// Receives the raw Cairo trace and memory as outputted from the Cairo VM and returns /// the trace table used to Felt252ed the Cairo STARK prover. /// The constraints of the Cairo AIR are defined over this trace rather than the raw trace @@ -241,7 +199,7 @@ pub fn build_cairo_execution_trace( raw_trace: &RegisterStates, memory: &CairoMemory, public_inputs: &PublicInputs, -) -> TraceTable { +) -> CairoTraceTable { let n_steps = raw_trace.steps(); // Instruction flags and offsets are decoded from the raw instructions and represented @@ -334,7 +292,7 @@ pub fn build_cairo_execution_trace( add_rc_builtin_columns(&mut trace_cols, range_check_builtin_range.clone(), memory); } - TraceTable::new_from_cols(&trace_cols) + TraceTable::from_columns(&trace_cols) } // Build range-check builtin columns: rc_0, rc_1, ... , rc_7, rc_value @@ -621,6 +579,7 @@ mod test { use super::*; use lambdaworks_math::field::element::FieldElement; + use stark_platinum_prover::table::Table; #[test] fn test_rc_decompose() { @@ -661,7 +620,7 @@ mod test { FieldElement::from(7), FieldElement::from(7), ]; - let table = TraceTable::::new_from_cols(&columns); + let table = TraceTable::::from_columns(&columns); let (col, rc_min, rc_max) = get_rc_holes(&table, &[0, 1, 2]); assert_eq!(col, expected_col); @@ -673,9 +632,10 @@ mod test { fn test_add_missing_values_to_rc_holes_column() { let mut row = vec![Felt252::from(5); 36]; row[35] = Felt252::zero(); - let table = row.repeat(8); + let data = row.repeat(8); + let table = Table::new(&data, 36); - let mut main_trace = TraceTable:: { table, n_cols: 36 }; + let mut main_trace = TraceTable:: { table }; let rc_holes = vec![ Felt252::from(1), @@ -699,7 +659,7 @@ mod test { Felt252::from(6), ]; - let rc_holes_column = main_trace.cols()[35].clone(); + let rc_holes_column = main_trace.columns()[35].clone(); assert_eq!(expected_rc_holes_column, rc_holes_column); } @@ -776,12 +736,12 @@ mod test { trace_cols[FRAME_DST_ADDR][1] = Felt252::from(9); trace_cols[FRAME_OP0_ADDR][1] = Felt252::from(10); trace_cols[FRAME_OP1_ADDR][1] = Felt252::from(11); - let mut trace = TraceTable::new_from_cols(&trace_cols); + let mut trace = TraceTable::from_columns(&trace_cols); let memory_holes = vec![Felt252::from(4), Felt252::from(7), Felt252::from(8)]; fill_memory_holes(&mut trace, &memory_holes); - let extra_addr = &trace.cols()[EXTRA_ADDR]; + let extra_addr = &trace.columns()[EXTRA_ADDR]; assert_eq!(extra_addr, &memory_holes) } } diff --git a/provers/cairo/src/tests/integration_tests.rs b/provers/cairo/src/tests/integration_tests.rs index db64d01807..7dc62067ad 100644 --- a/provers/cairo/src/tests/integration_tests.rs +++ b/provers/cairo/src/tests/integration_tests.rs @@ -1,3 +1,14 @@ +use crate::{ + air::{ + generate_cairo_proof, verify_cairo_proof, CairoAIR, MemorySegment, MemorySegmentMap, + PublicInputs, FRAME_DST_ADDR, FRAME_OP0_ADDR, FRAME_OP1_ADDR, FRAME_PC, + }, + cairo_layout::CairoLayout, + execution_trace::build_main_trace, + runner::run::{generate_prover_args, run_program}, + tests::utils::{cairo0_program_path, test_prove_cairo_program}, + Felt252, +}; use lambdaworks_math::field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField; use stark_platinum_prover::{ debug::validate_trace, @@ -11,18 +22,6 @@ use stark_platinum_prover::{ transcript::StoneProverTranscript, }; -use crate::{ - air::{ - generate_cairo_proof, verify_cairo_proof, CairoAIR, MemorySegment, MemorySegmentMap, - PublicInputs, FRAME_DST_ADDR, FRAME_OP0_ADDR, FRAME_OP1_ADDR, FRAME_PC, - }, - cairo_layout::CairoLayout, - execution_trace::build_main_trace, - runner::run::{generate_prover_args, run_program}, - tests::utils::{cairo0_program_path, test_prove_cairo_program}, - Felt252, -}; - #[test_log::test] fn test_prove_cairo_simple_program() { let layout = CairoLayout::Plain; @@ -160,13 +159,13 @@ fn test_verifier_rejects_proof_with_changed_range_check_value() { let proof_options = ProofOptions::default_test_options(); - let mut malicious_trace_columns = main_trace.cols(); + let mut malicious_trace_columns = main_trace.columns(); let n_cols = malicious_trace_columns.len(); let mut last_column = malicious_trace_columns.last().unwrap().clone(); last_column[0] = malicious_rc_value; malicious_trace_columns[n_cols - 1] = last_column; - let malicious_trace = TraceTable::new_from_cols(&malicious_trace_columns); + let malicious_trace = TraceTable::from_columns(&malicious_trace_columns); let proof = generate_cairo_proof(&malicious_trace, &pub_inputs, &proof_options).unwrap(); assert!(!verify_cairo_proof(&proof, &pub_inputs, &proof_options)); } @@ -229,12 +228,12 @@ fn test_verifier_rejects_proof_with_changed_output() { let proof_options = ProofOptions::default_test_options(); - let mut malicious_trace_columns = main_trace.cols(); + let mut malicious_trace_columns = main_trace.columns(); let mut output_value_column = malicious_trace_columns[output_col_idx + 4].clone(); output_value_column[output_row_idx] = malicious_output_value; malicious_trace_columns[output_col_idx + 4] = output_value_column; - let malicious_trace = TraceTable::new_from_cols(&malicious_trace_columns); + let malicious_trace = TraceTable::from_columns(&malicious_trace_columns); let proof = generate_cairo_proof(&malicious_trace, &pub_inputs, &proof_options).unwrap(); assert!(!verify_cairo_proof(&proof, &pub_inputs, &proof_options)); } diff --git a/provers/stark/src/constraints/evaluation_table.rs b/provers/stark/src/constraints/evaluation_table.rs deleted file mode 100644 index 95d298d447..0000000000 --- a/provers/stark/src/constraints/evaluation_table.rs +++ /dev/null @@ -1,34 +0,0 @@ -use lambdaworks_math::fft::polynomial::FFTPoly; -use lambdaworks_math::{ - field::{ - element::FieldElement, - traits::{IsFFTField, IsField}, - }, - polynomial::Polynomial, -}; - -#[derive(Clone, Debug)] -pub struct ConstraintEvaluationTable { - // Accumulation of the evaluation of the constraints - pub evaluations_acc: Vec>, - pub trace_length: usize, -} - -impl ConstraintEvaluationTable { - pub fn new(_n_cols: usize, domain: &[FieldElement]) -> Self { - let evaluations_acc = Vec::with_capacity(domain.len()); - - ConstraintEvaluationTable { - evaluations_acc, - trace_length: domain.len(), - } - } - - pub fn compute_composition_poly(&self, offset: &FieldElement) -> Polynomial> - where - F: IsFFTField, - Polynomial>: FFTPoly, - { - Polynomial::interpolate_offset_fft(&self.evaluations_acc, offset).unwrap() - } -} diff --git a/provers/stark/src/constraints/evaluator.rs b/provers/stark/src/constraints/evaluator.rs index f5d699f65f..f6213a6f1d 100644 --- a/provers/stark/src/constraints/evaluator.rs +++ b/provers/stark/src/constraints/evaluator.rs @@ -11,6 +11,7 @@ use rayon::prelude::{ IndexedParallelIterator, IntoParallelIterator, IntoParallelRefIterator, ParallelIterator, }; +use super::boundary::BoundaryConstraints; #[cfg(all(debug_assertions, not(feature = "parallel")))] use crate::debug::check_boundary_polys_divisibility; use crate::domain::Domain; @@ -18,8 +19,6 @@ use crate::trace::TraceTable; use crate::traits::AIR; use crate::{frame::Frame, prover::evaluate_polynomial_on_lde_domain}; -use super::{boundary::BoundaryConstraints, evaluation_table::ConstraintEvaluationTable}; - pub struct ConstraintEvaluator { air: A, boundary_constraints: BoundaryConstraints, @@ -41,17 +40,12 @@ impl> ConstraintEvaluator { transition_coefficients: &[FieldElement], boundary_coefficients: &[FieldElement], rap_challenges: &A::RAPChallenges, - ) -> ConstraintEvaluationTable + ) -> Vec> where FieldElement: Serializable + Send + Sync, A: Send + Sync, A::RAPChallenges: Send + Sync, { - // The + 1 is for the boundary constraints column - let mut evaluation_table = ConstraintEvaluationTable::new( - self.air.context().num_transition_constraints() + 1, - &domain.lde_roots_of_unity_coset, - ); let boundary_constraints = &self.boundary_constraints; let number_of_b_constraints = boundary_constraints.constraints.len(); let boundary_zerofiers_inverse_evaluations: Vec>> = @@ -75,7 +69,7 @@ impl> ConstraintEvaluator { #[cfg(all(debug_assertions, not(feature = "parallel")))] let boundary_polys: Vec>> = Vec::new(); - let n_col = lde_trace.n_cols; + let n_col = lde_trace.n_cols(); let n_elem = domain.lde_roots_of_unity_coset.len(); let boundary_polys_evaluations = boundary_constraints .constraints @@ -84,6 +78,7 @@ impl> ConstraintEvaluator { let col = constraint.col; lde_trace .table + .data .iter() .skip(col) .step_by(n_col) @@ -226,9 +221,7 @@ impl> ConstraintEvaluator { }) .collect::>>(); - evaluation_table.evaluations_acc = evaluations_t; - - evaluation_table + evaluations_t } /// Given `evaluations` T_i(x) of the trace polynomial composed with the constraint diff --git a/provers/stark/src/constraints/mod.rs b/provers/stark/src/constraints/mod.rs index 95cea3340f..2087e3c79c 100644 --- a/provers/stark/src/constraints/mod.rs +++ b/provers/stark/src/constraints/mod.rs @@ -1,3 +1,2 @@ pub mod boundary; -pub mod evaluation_table; pub mod evaluator; diff --git a/provers/stark/src/debug.rs b/provers/stark/src/debug.rs index 9df45f97f4..33ea5f64a2 100644 --- a/provers/stark/src/debug.rs +++ b/provers/stark/src/debug.rs @@ -27,7 +27,8 @@ pub fn validate_trace>( .unwrap() }) .collect(); - let trace = TraceTable::new_from_cols(&trace_columns); + + let trace = TraceTable::from_columns(&trace_columns); // --------- VALIDATE BOUNDARY CONSTRAINTS ------------ air.boundary_constraints(rap_challenges) @@ -96,3 +97,13 @@ pub fn check_boundary_polys_divisibility( } } } + +/// Validates that the one-dimensional array `data` can be interpreted as two-dimensional +/// array, returning a true when valid and false when not. +pub fn validate_2d_structure(data: &[FieldElement], width: usize) -> bool +where + F: IsFFTField, +{ + let rows: Vec>> = data.chunks(width).map(|c| c.to_vec()).collect(); + rows.iter().all(|r| r.len() == rows[0].len()) +} diff --git a/provers/stark/src/examples/dummy_air.rs b/provers/stark/src/examples/dummy_air.rs index 1fe41f46cb..84cb8fcb65 100644 --- a/provers/stark/src/examples/dummy_air.rs +++ b/provers/stark/src/examples/dummy_air.rs @@ -118,5 +118,5 @@ pub fn dummy_trace(trace_length: usize) -> TraceTable { ret.push(ret[i - 1].clone() + ret[i - 2].clone()); } - TraceTable::new_from_cols(&[vec![FieldElement::::one(); trace_length], ret]) + TraceTable::from_columns(&[vec![FieldElement::::one(); trace_length], ret]) } diff --git a/provers/stark/src/examples/fibonacci_2_cols_shifted.rs b/provers/stark/src/examples/fibonacci_2_cols_shifted.rs index 66199d337f..4b7a7a7841 100644 --- a/provers/stark/src/examples/fibonacci_2_cols_shifted.rs +++ b/provers/stark/src/examples/fibonacci_2_cols_shifted.rs @@ -141,7 +141,7 @@ pub fn compute_trace( col1.push(y.clone()); } - TraceTable::new_from_cols(&[col0, col1]) + TraceTable::from_columns(&[col0, col1]) } #[cfg(test)] diff --git a/provers/stark/src/examples/fibonacci_2_columns.rs b/provers/stark/src/examples/fibonacci_2_columns.rs index b058f6a903..40ea61a0b5 100644 --- a/provers/stark/src/examples/fibonacci_2_columns.rs +++ b/provers/stark/src/examples/fibonacci_2_columns.rs @@ -132,5 +132,5 @@ pub fn compute_trace( ret2.push(new_val + ret2[i - 1].clone()); } - TraceTable::new_from_cols(&[ret1, ret2]) + TraceTable::from_columns(&[ret1, ret2]) } diff --git a/provers/stark/src/examples/fibonacci_rap.rs b/provers/stark/src/examples/fibonacci_rap.rs index 08db064b18..bf358a38dd 100644 --- a/provers/stark/src/examples/fibonacci_rap.rs +++ b/provers/stark/src/examples/fibonacci_rap.rs @@ -74,7 +74,7 @@ where main_trace: &TraceTable, gamma: &Self::RAPChallenges, ) -> TraceTable { - let main_segment_cols = main_trace.cols(); + let main_segment_cols = main_trace.columns(); let not_perm = &main_segment_cols[0]; let perm = &main_segment_cols[1]; @@ -92,7 +92,7 @@ where aux_col.push(z_i * n_p_term.div(p_term)); } } - TraceTable::new_from_cols(&[aux_col]) + TraceTable::from_columns(&[aux_col]) } fn build_rap_challenges( @@ -186,7 +186,7 @@ pub fn fibonacci_rap_trace( let mut trace_cols = vec![fib_seq, fib_permuted]; resize_to_next_power_of_two(&mut trace_cols); - TraceTable::new_from_cols(&trace_cols) + TraceTable::from_columns(&trace_cols) } #[cfg(test)] @@ -229,13 +229,13 @@ mod test { ]; resize_to_next_power_of_two(&mut expected_trace); - assert_eq!(trace.cols(), expected_trace); + assert_eq!(trace.columns(), expected_trace); } #[test] fn aux_col() { let trace = fibonacci_rap_trace([FE17::from(1), FE17::from(1)], 64); - let trace_cols = trace.cols(); + let trace_cols = trace.columns(); let not_perm = trace_cols[0].clone(); let perm = trace_cols[1].clone(); diff --git a/provers/stark/src/examples/quadratic_air.rs b/provers/stark/src/examples/quadratic_air.rs index d0fcc35b35..dc3797a879 100644 --- a/provers/stark/src/examples/quadratic_air.rs +++ b/provers/stark/src/examples/quadratic_air.rs @@ -125,5 +125,5 @@ pub fn quadratic_trace( ret.push(ret[i - 1].clone() * ret[i - 1].clone()); } - TraceTable::new_from_cols(&[ret]) + TraceTable::from_columns(&[ret]) } diff --git a/provers/stark/src/examples/simple_fibonacci.rs b/provers/stark/src/examples/simple_fibonacci.rs index 3a7998d5e6..6c2603da9d 100644 --- a/provers/stark/src/examples/simple_fibonacci.rs +++ b/provers/stark/src/examples/simple_fibonacci.rs @@ -129,5 +129,5 @@ pub fn fibonacci_trace( ret.push(ret[i - 1].clone() + ret[i - 2].clone()); } - TraceTable::new_from_cols(&[ret]) + TraceTable::from_columns(&[ret]) } diff --git a/provers/stark/src/frame.rs b/provers/stark/src/frame.rs index 809929be5e..55c6be874f 100644 --- a/provers/stark/src/frame.rs +++ b/provers/stark/src/frame.rs @@ -1,4 +1,5 @@ use super::trace::TraceTable; +use crate::table::Table; use lambdaworks_math::{ field::{element::FieldElement, traits::IsFFTField}, polynomial::Polynomial, @@ -6,32 +7,29 @@ use lambdaworks_math::{ #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] pub struct Frame { - // Vector of rows - data: Vec>, - row_width: usize, + table: Table, } impl Frame { pub fn new(data: Vec>, row_width: usize) -> Self { - Self { data, row_width } + let table = Table::new(&data, row_width); + Self { table } } - pub fn num_rows(&self) -> usize { - self.data.len() / self.row_width + pub fn n_rows(&self) -> usize { + self.table.height } - pub fn num_columns(&self) -> usize { - self.row_width + pub fn n_cols(&self) -> usize { + self.table.width } pub fn get_row(&self, row_idx: usize) -> &[FieldElement] { - let row_offset = row_idx * self.row_width; - &self.data[row_offset..row_offset + self.row_width] + self.table.get_row(row_idx) } pub fn get_row_mut(&mut self, row_idx: usize) -> &mut [FieldElement] { - let row_offset = row_idx * self.row_width; - &mut self.data[row_offset..row_offset + self.row_width] + self.table.get_row_mut(row_idx) } pub fn read_from_trace( @@ -52,7 +50,7 @@ impl Frame { }) .collect(); - Self::new(data, trace.n_cols) + Self::new(data, trace.table.width) } /// Given a slice of trace polynomials, an evaluation point `x`, the frame offsets diff --git a/provers/stark/src/lib.rs b/provers/stark/src/lib.rs index 5cb64a4cd4..6ea2f366a9 100644 --- a/provers/stark/src/lib.rs +++ b/provers/stark/src/lib.rs @@ -12,6 +12,7 @@ pub mod fri; pub mod grinding; pub mod proof; pub mod prover; +pub mod table; pub mod trace; pub mod traits; pub mod transcript; diff --git a/provers/stark/src/proof/options.rs b/provers/stark/src/proof/options.rs index 4a64c92bcc..105e442e27 100644 --- a/provers/stark/src/proof/options.rs +++ b/provers/stark/src/proof/options.rs @@ -143,7 +143,7 @@ impl ProofOptions { } /// Default proof options used for testing purposes. - /// These options should not be used in production. + /// These options should never be used in production. pub fn default_test_options() -> Self { Self { blowup_factor: 4, diff --git a/provers/stark/src/prover.rs b/provers/stark/src/prover.rs index e03e2238f6..4f4a702f13 100644 --- a/provers/stark/src/prover.rs +++ b/provers/stark/src/prover.rs @@ -138,7 +138,7 @@ pub trait IsStarkProver { } // Compute commitments [t_j]. - let lde_trace = TraceTable::new_from_cols(&lde_trace_permuted); + let lde_trace = TraceTable::from_columns(&lde_trace_permuted); let (lde_trace_merkle_tree, lde_trace_merkle_root) = Self::batch_commit(&lde_trace.rows()); // >>>> Send commitments: [tβ±Ό] @@ -205,7 +205,7 @@ pub trait IsStarkProver { lde_trace_merkle_roots.push(aux_merkle_root); } - let lde_trace = TraceTable::new_from_cols(&evaluations); + let lde_trace = TraceTable::from_columns(&evaluations); Ok(Round1 { trace_polys, @@ -269,7 +269,8 @@ pub trait IsStarkProver { // Get the composition poly H let composition_poly = - constraint_evaluations.compute_composition_poly(&domain.coset_offset); + Polynomial::interpolate_offset_fft(&constraint_evaluations, &domain.coset_offset) + .unwrap(); let number_of_parts = air.composition_poly_degree_bound() / air.trace_length(); let composition_poly_parts = composition_poly.break_in_parts(number_of_parts); diff --git a/provers/stark/src/table.rs b/provers/stark/src/table.rs new file mode 100644 index 0000000000..37ed7053c5 --- /dev/null +++ b/provers/stark/src/table.rs @@ -0,0 +1,108 @@ +use lambdaworks_math::field::{element::FieldElement, traits::IsFFTField}; + +/// A two-dimensional Table holding field elements, arranged in a row-major order. +/// This is the basic underlying data structure used for any two-dimensional component in the +/// the STARK protocol implementation, such as the `TraceTable` and the `EvaluationFrame`. +/// Since this struct is a representation of a two-dimensional table, all rows should have the same +/// length. +#[derive(Clone, Default, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct Table { + pub data: Vec>, + pub width: usize, + pub height: usize, +} + +impl Table { + /// Crates a new Table instance from a one-dimensional array in row major order + /// and the intended width of the table. + pub fn new(data: &[FieldElement], width: usize) -> Self { + // Check if the intented width is 0, used for creating an empty table. + if width == 0 { + return Self { + data: Vec::new(), + width, + height: 0, + }; + } + + // Check that the one-dimensional data makes sense to be interpreted as a 2D one. + assert!(crate::debug::validate_2d_structure(data, width)); + let height = data.len() / width; + + Self { + data: data.to_vec(), + width, + height, + } + } + + /// Creates a Table instance from a vector of the intended columns. + pub fn from_columns(columns: &[Vec>]) -> Self { + if columns.is_empty() { + return Self::new(&Vec::new(), 0); + } + let height = columns[0].len(); + + // Check that all columns have the same length for integrity + debug_assert!(columns.iter().all(|c| c.len() == height)); + + let width = columns.len(); + let mut data = Vec::with_capacity(width * height); + for row_idx in 0..height { + for column in columns { + data.push(column[row_idx].clone()); + } + } + + Self::new(&data, width) + } + + /// Returns a vector of vectors of field elements representing the table rows + pub fn rows(&self) -> Vec>> { + self.data.chunks(self.width).map(|r| r.to_vec()).collect() + } + + /// Given a row index, returns a reference to that row as a slice of field elements. + pub fn get_row(&self, row_idx: usize) -> &[FieldElement] { + let row_offset = row_idx * self.width; + &self.data[row_offset..row_offset + self.width] + } + + /// Given a row index, returns a mutable reference to that row as a slice of field elements. + pub fn get_row_mut(&mut self, row_idx: usize) -> &mut [FieldElement] { + let n_cols = self.width; + let row_offset = row_idx * n_cols; + &mut self.data[row_offset..row_offset + n_cols] + } + + /// Given a slice of field elements representing a row, appends it to + /// the end of the table. + pub fn append_row(&mut self, row: &[FieldElement]) { + debug_assert_eq!(row.len(), self.width); + self.data.extend_from_slice(row); + self.height += 1 + } + + /// Returns a reference to the last row of the table + pub fn last_row(&self) -> &[FieldElement] { + self.get_row(self.height - 1) + } + + /// Returns a vector of vectors of field elements representing the table + /// columns + pub fn columns(&self) -> Vec>> { + (0..self.width) + .map(|col_idx| { + (0..self.height) + .map(|row_idx| self.data[row_idx * self.width + col_idx].clone()) + .collect() + }) + .collect() + } + + /// Given row and column indexes, returns the stored field element in that position of the table. + pub fn get(&self, row: usize, col: usize) -> FieldElement { + let idx = row * self.width + col; + self.data[idx].clone() + } +} diff --git a/provers/stark/src/trace.rs b/provers/stark/src/trace.rs index 1dc6cff34d..4edff10928 100644 --- a/provers/stark/src/trace.rs +++ b/provers/stark/src/trace.rs @@ -1,3 +1,4 @@ +use crate::table::Table; use lambdaworks_math::fft::errors::FFTError; use lambdaworks_math::fft::polynomial::FFTPoly; use lambdaworks_math::{ @@ -5,104 +6,87 @@ use lambdaworks_math::{ polynomial::Polynomial, }; +/// A two-dimensional representation of an execution trace of the STARK +/// protocol. +/// +/// For the moment it is mostly a wrapper around the `Table` struct. It is a +/// layer above the raw two-dimensional table, with functionality relevant to the +/// STARK protocol. #[derive(Clone, Default, Debug, PartialEq, Eq)] pub struct TraceTable { - /// `table` is row-major trace element description - pub table: Vec>, - pub n_cols: usize, + pub table: Table, } impl TraceTable { - pub fn empty() -> Self { - Self { - table: Vec::new(), - n_cols: 0, - } + pub fn new(data: &[FieldElement], n_columns: usize) -> Self { + let table = Table::new(data, n_columns); + Self { table } } - pub fn is_empty(&self) -> bool { - self.n_cols == 0 + pub fn from_columns(columns: &[Vec>]) -> Self { + let table = Table::from_columns(columns); + Self { table } } - pub fn new(table: Vec>, n_cols: usize) -> Self { - Self { table, n_cols } + pub fn empty() -> Self { + Self::new(&Vec::new(), 0) } - pub fn get_cols(&self, columns: &[usize]) -> Self { - let mut table = Vec::new(); - for row_index in 0..self.n_rows() { - for column in columns { - table.push(self.table[row_index * self.n_cols + column].clone()); - } - } - - Self { - table, - n_cols: columns.len(), - } + pub fn is_empty(&self) -> bool { + self.table.width == 0 } - pub fn new_from_cols(cols: &[Vec>]) -> Self { - let n_rows = cols[0].len(); - debug_assert!(cols.iter().all(|c| c.len() == n_rows)); - - let n_cols = cols.len(); - - let mut table = Vec::with_capacity(n_cols * n_rows); - - for row_idx in 0..n_rows { - for col in cols { - table.push(col[row_idx].clone()); - } - } - Self { table, n_cols } + pub fn n_rows(&self) -> usize { + self.table.height } - pub fn n_rows(&self) -> usize { - if self.n_cols == 0 { - 0 - } else { - self.table.len() / self.n_cols - } + pub fn n_cols(&self) -> usize { + self.table.width } pub fn rows(&self) -> Vec>> { - let n_rows = self.n_rows(); - (0..n_rows) - .map(|row_idx| { - self.table[(row_idx * self.n_cols)..(row_idx * self.n_cols + self.n_cols)].to_vec() - }) - .collect() + self.table.rows() } pub fn get_row(&self, row_idx: usize) -> &[FieldElement] { - let row_offset = row_idx * self.n_cols; - &self.table[row_offset..row_offset + self.n_cols] + self.table.get_row(row_idx) + } + + pub fn get_row_mut(&mut self, row_idx: usize) -> &mut [FieldElement] { + self.table.get_row_mut(row_idx) } pub fn last_row(&self) -> &[FieldElement] { self.get_row(self.n_rows() - 1) } - pub fn cols(&self) -> Vec>> { - let n_rows = self.n_rows(); - (0..self.n_cols) - .map(|col_idx| { - (0..n_rows) - .map(|row_idx| self.table[row_idx * self.n_cols + col_idx].clone()) - .collect() - }) - .collect() + pub fn columns(&self) -> Vec>> { + self.table.columns() } - /// Given a step and a column index, gives stored value in that position - pub fn get(&self, step: usize, col: usize) -> FieldElement { - let idx = step * self.n_cols + col; - self.table[idx].clone() + /// Given a slice of integer numbers representing column indexes, merge these columns into + /// a one-dimensional vector. + /// + /// The particular way they are merged is not really important since this function is used to + /// aggreagate values distributed across various columns with no importance on their ordering, + /// such as to sort them. + pub fn merge_columns(&self, column_indexes: &[usize]) -> Vec> { + let mut data = Vec::with_capacity(self.n_rows() * column_indexes.len()); + for row_index in 0..self.n_rows() { + for column in column_indexes { + data.push(self.table.data[row_index * self.n_cols() + column].clone()); + } + } + data + } + + /// Given a row and a column index, gives stored value in that position + pub fn get(&self, row: usize, col: usize) -> FieldElement { + self.table.get(row, col) } pub fn compute_trace_polys(&self) -> Vec>> { - self.cols() + self.columns() .iter() .map(|col| Polynomial::interpolate_fft(col)) .collect::>>, FFTError>>() @@ -110,16 +94,49 @@ impl TraceTable { } pub fn concatenate(&self, new_cols: Vec>, n_cols: usize) -> Self { - let mut new_table = Vec::new(); + let mut data = Vec::new(); let mut i = 0; - for row_index in (0..self.table.len()).step_by(self.n_cols) { - new_table.append(&mut self.table[row_index..row_index + self.n_cols].to_vec()); - new_table.append(&mut new_cols[i..(i + n_cols)].to_vec()); + for row_index in (0..self.table.data.len()).step_by(self.table.width) { + data.append(&mut self.table.data[row_index..row_index + self.table.width].to_vec()); + data.append(&mut new_cols[i..(i + n_cols)].to_vec()); i += n_cols; } - TraceTable { - table: new_table, - n_cols: self.n_cols + n_cols, + + let table = Table::new(&data, self.n_cols() + n_cols); + Self { table } + } + + /// Given the padding length, appends the last row of the trace table + /// that many times. + /// This is useful for example when the desired trace length should be power + /// of two, and only the last row is the one that can be appended without affecting + /// the integrity of the constraints. + pub fn pad_with_last_row(&mut self, padding_len: usize) { + let last_row = self.last_row().to_vec(); + (0..padding_len).for_each(|_| { + self.table.append_row(&last_row); + }) + } + + /// Given a row index, a column index and a value, tries to set that location + /// of the trace with the given value. + /// The row_idx passed as argument may be greater than the max row index by 1. In this case, + /// last row of the trace is cloned, and the value is set in that cloned row. Then, the row is + /// appended to the end of the trace. + pub fn set_or_extend(&mut self, row_idx: usize, col_idx: usize, value: &FieldElement) { + debug_assert!(col_idx < self.n_cols()); + // NOTE: This is not very nice, but for how the function is being used at the moment, + // the passed `row_idx` should never be greater than `self.n_rows() + 1`. This is just + // an integrity check for ease in the developing process, we should think a better alternative + // in the future. + debug_assert!(row_idx <= self.n_rows() + 1); + if row_idx >= self.n_rows() { + let mut last_row = self.last_row().to_vec(); + last_row[col_idx] = value.clone(); + self.table.append_row(&last_row) + } else { + let row = self.get_row_mut(row_idx); + row[col_idx] = value.clone(); } } } @@ -135,55 +152,12 @@ mod test { let col_1 = vec![FE::from(1), FE::from(2), FE::from(5), FE::from(13)]; let col_2 = vec![FE::from(1), FE::from(3), FE::from(8), FE::from(21)]; - let trace_table = TraceTable::new_from_cols(&[col_1.clone(), col_2.clone()]); - let res_cols = trace_table.cols(); + let trace_table = TraceTable::from_columns(&[col_1.clone(), col_2.clone()]); + let res_cols = trace_table.columns(); assert_eq!(res_cols, vec![col_1, col_2]); } - #[test] - fn test_subtable_works() { - let table = vec![ - FE::new(1), - FE::new(2), - FE::new(3), - FE::new(1), - FE::new(2), - FE::new(3), - FE::new(1), - FE::new(2), - FE::new(3), - ]; - let trace_table = TraceTable { table, n_cols: 3 }; - let subtable = trace_table.get_cols(&[0, 1]); - assert_eq!( - subtable.table, - vec![ - FE::new(1), - FE::new(2), - FE::new(1), - FE::new(2), - FE::new(1), - FE::new(2) - ] - ); - assert_eq!(subtable.n_cols, 2); - let subtable = trace_table.get_cols(&[0, 2]); - assert_eq!( - subtable.table, - vec![ - FE::new(1), - FE::new(3), - FE::new(1), - FE::new(3), - FE::new(1), - FE::new(3) - ] - ); - assert_eq!(subtable.n_cols, 2); - assert_eq!(trace_table.get_cols(&[]), TraceTable::empty()); - } - #[test] fn test_concatenate_works() { let table1_columns = vec![vec![FE::new(7), FE::new(8), FE::new(9)]]; @@ -195,12 +169,12 @@ mod test { FE::new(5), FE::new(6), ]; - let expected_table = TraceTable::new_from_cols(&[ + let expected_table = TraceTable::from_columns(&[ vec![FE::new(7), FE::new(8), FE::new(9)], vec![FE::new(1), FE::new(3), FE::new(5)], vec![FE::new(2), FE::new(4), FE::new(6)], ]); - let table1 = TraceTable::new_from_cols(&table1_columns); + let table1 = TraceTable::from_columns(&table1_columns); assert_eq!(table1.concatenate(new_columns, 2), expected_table) } } diff --git a/provers/stark/src/verifier.rs b/provers/stark/src/verifier.rs index a67c116662..f36cceee93 100644 --- a/provers/stark/src/verifier.rs +++ b/provers/stark/src/verifier.rs @@ -120,8 +120,8 @@ pub trait IsStarkVerifier { ); // <<<< Receive values: tβ±Ό(zgᡏ) - for i in 0..proof.trace_ood_frame_evaluations.num_columns() { - for j in 0..proof.trace_ood_frame_evaluations.num_rows() { + for i in 0..proof.trace_ood_frame_evaluations.n_cols() { + for j in 0..proof.trace_ood_frame_evaluations.n_rows() { transcript.append_field_element(&proof.trace_ood_frame_evaluations.get_row(j)[i]); } } @@ -623,15 +623,15 @@ pub trait IsStarkVerifier { lde_trace_evaluations: &[FieldElement], lde_composition_poly_parts_evaluation: &[FieldElement], ) -> FieldElement { - let mut denoms_trace = (0..proof.trace_ood_frame_evaluations.num_rows()) + let mut denoms_trace = (0..proof.trace_ood_frame_evaluations.n_rows()) .map(|row_idx| evaluation_point - &challenges.z * primitive_root.pow(row_idx as u64)) .collect::>>(); FieldElement::inplace_batch_inverse(&mut denoms_trace).unwrap(); - let trace_term = (0..proof.trace_ood_frame_evaluations.num_columns()) + let trace_term = (0..proof.trace_ood_frame_evaluations.n_cols()) .zip(&challenges.trace_term_coeffs) .fold(FieldElement::zero(), |trace_terms, (col_idx, coeff_row)| { - let trace_i = (0..proof.trace_ood_frame_evaluations.num_rows()) + let trace_i = (0..proof.trace_ood_frame_evaluations.n_rows()) .zip(coeff_row) .fold(FieldElement::zero(), |trace_t, (row_idx, coeff)| { let poly_evaluation = (lde_trace_evaluations[col_idx].clone() From 8f7b415f56292e153cd7764a3212c14cad9aa2d2 Mon Sep 17 00:00:00 2001 From: juan518munoz <62400508+juan518munoz@users.noreply.github.com> Date: Wed, 18 Oct 2023 16:14:15 -0300 Subject: [PATCH 16/18] Cairo reorganized (#607) * initial commit * modified README * fix cairo programs dir * Update provers/cairo/README.md Co-authored-by: Mariano A. Nicolini * Update provers/cairo/README.md Co-authored-by: Mariano A. Nicolini * Fix cargo * Re organized * Remove proof * Update readme * Fmt * CLI feature * CLI Fix * Fmt --------- Co-authored-by: Jmunoz Co-authored-by: Mauro Toscano <12560266+MauroToscano@users.noreply.github.com> Co-authored-by: Mariano A. Nicolini Co-authored-by: MauroFab --- .github/workflows/ci.yaml | 4 + Cargo.toml | 2 +- README.md | 1 - provers/cairo-prover-cli/Cargo.toml | 17 -- provers/cairo-prover-cli/Makefile | 43 ------ provers/cairo-prover-cli/README.md | 107 ------------- .../cairo-prover-cli/cairo_compile.Dockerfile | 11 -- provers/cairo/Cargo.toml | 14 +- provers/cairo/Makefile | 42 +++-- provers/cairo/README.md | 146 ++++++++++++------ provers/cairo/benches/criterion_prover.rs | 6 +- provers/cairo/benches/criterion_prover_70k.rs | 4 +- provers/cairo/benches/criterion_verifier.rs | 2 +- .../cairo/benches/criterion_verifier_70k.rs | 2 +- provers/cairo/benches/functions/stark.rs | 2 +- .../cairo-prover-lib}/requirements.txt | 0 .../{ => cairo-prover-lib}/tests/wasm.rs | 4 +- .../{cairo-prover-cli => cairo}/src/main.rs | 6 +- 18 files changed, 151 insertions(+), 262 deletions(-) delete mode 100644 provers/cairo-prover-cli/Cargo.toml delete mode 100644 provers/cairo-prover-cli/Makefile delete mode 100644 provers/cairo-prover-cli/README.md delete mode 100644 provers/cairo-prover-cli/cairo_compile.Dockerfile rename provers/{cairo-prover-cli => cairo/cairo-prover-lib}/requirements.txt (100%) rename provers/cairo/{ => cairo-prover-lib}/tests/wasm.rs (99%) rename provers/{cairo-prover-cli => cairo}/src/main.rs (96%) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 853051e48b..e2acafd4e2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -30,6 +30,10 @@ jobs: - name: Run cargo check run: cargo check + - name: Run cargo check cli + run: | + cargo check --features cli + - name: Run cargo check for math with no-std run: cargo check --package lambdaworks-math --no-default-features diff --git a/Cargo.toml b/Cargo.toml index 59fc41ff65..9037d23288 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["math", "crypto", "gpu", "benches", "provers/plonk", "provers/stark", "provers/cairo", "provers/cairo-prover-cli"] +members = ["math", "crypto", "gpu", "benches", "provers/plonk", "provers/stark", "provers/cairo", "provers/cairo"] exclude = ["ensure-no_std"] resolver = "2" diff --git a/README.md b/README.md index f6f0ceb120..b537177053 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,6 @@ So, we decided to build our library, focusing on performance, with clear documen - [Crypto primitives](https://github.com/lambdaclass/lambdaworks/tree/main/crypto) - [Plonk Prover](https://github.com/lambdaclass/lambdaworks/tree/main/provers/plonk) - [Cairo Prover](https://github.com/lambdaclass/lambdaworks/tree/main/provers/cairo) -- [Cairo Prover CLI](https://github.com/lambdaclass/lambdaworks/tree/main/provers/cairo-prover-cli) If you are interested in proving Cairo programs, use the Cairo Prover CLI. diff --git a/provers/cairo-prover-cli/Cargo.toml b/provers/cairo-prover-cli/Cargo.toml deleted file mode 100644 index 75ab6fcbcf..0000000000 --- a/provers/cairo-prover-cli/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "cairo-platinum-prover-cli" -version.workspace = true -edition.workspace = true -license.workspace = true -repository.workspace = true - -[[bin]] -name = "cairo-platinum-prover-cli" -path = "src/main.rs" - -[dependencies] -serde_cbor = { version = "0.11.1"} -lambdaworks-math = { workspace = true , features = ["lambdaworks-serde"] } -stark-platinum-prover = { workspace = true, features = ["wasm"] } -cairo-platinum-prover = { workspace = true} -clap = { version = "4.4.6", features = ["derive"] } diff --git a/provers/cairo-prover-cli/Makefile b/provers/cairo-prover-cli/Makefile deleted file mode 100644 index 39a94d79ba..0000000000 --- a/provers/cairo-prover-cli/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -.PHONY: test coverage clippy clean - -ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) - -# Variable to give compiled Cairo programas a proper name. It extracts the file extension and adds -# the .json extension to it. -COMPILED_PROGRAM=$(basename $(PROGRAM_PATH)).json - -build: - cargo build --release - -docker_build_cairo_compiler: - docker build -f cairo_compile.Dockerfile -t cairo . - -compile: - cairo-compile --proof_mode $(PROGRAM_PATH) > $(COMPILED_PROGRAM) 2>/dev/null || \ - docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM_PATH) > $(COMPILED_PROGRAM) - -prove: - cargo run --quiet --release prove $(PROGRAM_PATH) $(PROOF_PATH) - -verify: - cargo run --quiet --release verify $(PROOF_PATH) - -run_all: - cargo run --quiet --release prove-and-verify $(PROGRAM_PATH) - -compile_and_prove: - @cairo-compile --proof_mode $(PROGRAM_PATH) > $(COMPILED_PROGRAM) 2>/dev/null || \ - docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM_PATH) > $(COMPILED_PROGRAM) - @echo "Compiling done \n" - @cargo run --quiet --release prove $(COMPILED_PROGRAM) $(PROOF_PATH) - @rm $(COMPILED_PROGRAM) - -compile_and_run_all: - @cairo-compile --proof_mode $(PROGRAM_PATH) > $(COMPILED_PROGRAM) 2>/dev/null || \ - docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM_PATH) > $(COMPILED_PROGRAM) - @echo "Compiling done \n" - @cargo run --quiet --release prove-and-verify $(COMPILED_PROGRAM) $(PROOF_PATH) - @rm $(COMPILED_PROGRAM) - -clippy: - cargo clippy --workspace --all-targets -- -D warnings diff --git a/provers/cairo-prover-cli/README.md b/provers/cairo-prover-cli/README.md deleted file mode 100644 index b6155e5ed1..0000000000 --- a/provers/cairo-prover-cli/README.md +++ /dev/null @@ -1,107 +0,0 @@ -
- -# Lambdaworks Cairo Platinum Prover CLI - -
- -## ⚠️ Disclaimer - -This prover is still in development and may contain bugs. It is not intended to be used in production yet. - -Please check issues under security label, and wait for them to be resolved if they are relevant your project. - -Output builtin is finished, and range check is supported but it's not sound yet. - -CLI currently runs with 100 bits of conjecturable security - -## [Cairo Platinum Prover Docs](<[lambdaclass.github.io/lambdaworks/](https://github.com/lambdaclass/lambdaworks/blob/main/provers/cairo/README.md)>) - -### Usage: - -To prove programs Cairo has to be compiled. For compilation you need to have `cairo-lang` or `docker` installed. - -When using Docker, start by creating the container image with: - -```**bash** - make docker_build_cairo_compiler -``` - -Examples of Cairo 0 programs can be found [here](https://github.com/lambdaclass/lambdaworks/tree/main/provers/cairo/cairo_programs/cairo0) - - -**To compile and generate a proof you can use:** - -```bash -make compile_and_prove PROGRAM_PATH= PROOF_PATH= -``` - -For example: - -```bash -make compile_and_prove PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.cairo PROOF_PATH=cairo_programs/cairo0/fibonacci_5.proof -``` - - -**To verify a proof you can use:** - -```bash -make verify PROOF_PATH= -``` - -For example: - -```bash -make verify PROOF_PATH=fibonacci_5.proof -``` - -**To compile Cairo:** - -```bash -make compile PROGRAM_PATH= -``` - -For example: - -```bash -make compile PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.cairo -``` - -**To prove a compiled program:** - -```bash -make prove PROGRAM_PATH= PROOF_PATH= -``` - -For example: - -```bash -make prove PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.json PROOF_PATH=program_proof.proof -``` - - - -**To prove and verify with a single command you can use:** - -```bash -make run_all PROGRAM_PATH= -``` - -For example: - -```bash -make run_all PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.json -``` - - - -**To compile, proof, prove and verify at the same time you can use:** - -```bash -make compile_and_run_all PROGRAM_PATH= -``` - -For example: - -```bash -make compile_and_run_all PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.cairo -``` \ No newline at end of file diff --git a/provers/cairo-prover-cli/cairo_compile.Dockerfile b/provers/cairo-prover-cli/cairo_compile.Dockerfile deleted file mode 100644 index 369f6db844..0000000000 --- a/provers/cairo-prover-cli/cairo_compile.Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM python:3.9-slim - -WORKDIR /app - -RUN apt-get update && apt-get install -y --no-install-recommends g++ libgmp3-dev - -COPY requirements.txt / - -RUN pip install -r /requirements.txt - -ENTRYPOINT ["cairo-compile"] diff --git a/provers/cairo/Cargo.toml b/provers/cairo/Cargo.toml index 0ccd0960bf..e292b5af4c 100644 --- a/provers/cairo/Cargo.toml +++ b/provers/cairo/Cargo.toml @@ -1,4 +1,3 @@ - [package] name = "cairo-platinum-prover" rust-version = "1.66" @@ -6,7 +5,13 @@ version.workspace = true edition.workspace = true license.workspace = true +[[bin]] +name = "platinum-prover" +path = "src/main.rs" +required-features = ["cli"] + [lib] +name = "platinum_prover" crate-type = ["cdylib", "rlib"] [dependencies] @@ -25,7 +30,9 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" num-integer = "0.1.45" itertools = "0.11.0" - +serde_cbor = { version = "0.11.1" } +# For cli +clap = { version = "4.4.6", features = ["derive"], optional = true } # Parallelization crates rayon = { version = "1.7.0", optional = true } @@ -33,7 +40,6 @@ rayon = { version = "1.7.0", optional = true } wasm-bindgen = { version = "0.2", optional = true } serde-wasm-bindgen = { version = "0.5", optional = true } web-sys = { version = "0.3.64", features = ['console'], optional = true } -serde_cbor = { version = "0.11.1"} [dev-dependencies] hex = "0.4.3" @@ -51,7 +57,7 @@ instruments = [] # This enables timing prints in prover and ve metal = ["lambdaworks-math/metal"] parallel = ["dep:rayon"] wasm = ["dep:wasm-bindgen", "dep:serde-wasm-bindgen", "dep:web-sys"] - +cli = ["dep:clap"] [target.'cfg(not(all(target_arch = "wasm32", target_os = "unknown")))'.dev-dependencies] proptest = "1.2.0" diff --git a/provers/cairo/Makefile b/provers/cairo/Makefile index 3a22a15e8f..66f9547fed 100644 --- a/provers/cairo/Makefile +++ b/provers/cairo/Makefile @@ -27,10 +27,37 @@ test: $(COMPILED_CAIRO0_PROGRAMS) test_metal: $(COMPILED_CAIRO0_PROGRAMS) cargo test -F metal - + +docker_build_cairo_compiler: + docker build -f cairo_compile.Dockerfile -t cairo . + +docker_compile_cairo: + docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM) > $(COMPILED_PROGRAM) + +compile: + cairo-compile --proof_mode $(PROGRAM_PATH) > $(COMPILED_PROGRAM) 2>/dev/null || \ + docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM_PATH) > $(COMPILED_PROGRAM) + +prove: + cargo run --quiet --release prove $(PROGRAM_PATH) $(PROOF_PATH) + +verify: + cargo run --quiet --release verify $(PROOF_PATH) + +run_all: + cargo run --quiet --release prove-and-verify $(PROGRAM_PATH) + +compile_and_run_all: + @cairo-compile --proof_mode $(PROGRAM_PATH) > $(COMPILED_PROGRAM) 2>/dev/null || \ + docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM_PATH) > $(COMPILED_PROGRAM) + @echo "Compiling done \n" + @cargo run --quiet --release prove-and-verify $(COMPILED_PROGRAM) $(PROOF_PATH) + @rm $(COMPILED_PROGRAM) + clippy: cargo clippy --workspace --all-targets -- -D warnings + benchmarks_sequential: $(COMPILED_CAIRO0_PROGRAMS) cargo bench @@ -44,12 +71,6 @@ benchmarks_parallel_all: $(COMPILED_CAIRO0_PROGRAMS) build_metal: cargo b --features metal --release -docker_build_cairo_compiler: - docker build -f cairo_compile.Dockerfile -t cairo . - -docker_compile_cairo: - docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM) > $(COMPILED_PROGRAM) - target/release/cairo-platinum-prover: cargo build --bin cairo-platinum-prover --release --features instruments @@ -67,13 +88,6 @@ docker_compile_and_prove: target/release/cairo-platinum-prover @cargo run --bin cairo-platinum-prover --features instruments --quiet --release prove $(COMPILED_PROGRAM) $(PROOF_PATH) @rm $(COMPILED_PROGRAM) -compile_and_run_all: target/release/cairo-platinum-prover - @echo "Compiling program with cairo-compile" - @cairo-compile --proof_mode $(PROGRAM) > $(COMPILED_PROGRAM) - @echo "Compiling done \n" - @cargo run --bin cairo-platinum-prover --features instruments --quiet --release prove_and_verify $(COMPILED_PROGRAM) - @rm $(COMPILED_PROGRAM) - compile_and_prove: target/release/cairo-platinum-prover @echo "Compiling program with cairo-compile" @cairo-compile --proof_mode $(PROGRAM) --output $(COMPILED_PROGRAM) diff --git a/provers/cairo/README.md b/provers/cairo/README.md index 2700f463b4..57a51a5a77 100644 --- a/provers/cairo/README.md +++ b/provers/cairo/README.md @@ -1,75 +1,109 @@
-# 🌟 Lambdaworks Cairo Platinum Prover 🌟 +# Lambdaworks Cairo Platinum Prover CLI -drawing +
-## An open-source Cairo prover +## ⚠️ Disclaimer - +This prover is still in development and may contain bugs. It is not intended to be used in production yet. -[![Telegram Chat][tg-badge]][tg-url] +Please check issues under security label, and wait for them to be resolved if they are relevant to your project. -[tg-badge]: https://img.shields.io/static/v1?color=green&logo=telegram&label=chat&style=flat&message=join -[tg-url]: https://t.me/+98Whlzql7Hs0MDZh +Output builtin is finished, and range check is supported but it's not sound yet. +CLI currently runs with 100 bits of conjecturable security -## ⚠️ Disclaimer +## [Cairo Platinum Prover Docs](<[lambdaclass.github.io/lambdaworks/](https://github.com/lambdaclass/lambdaworks/blob/main/provers/cairo/README.md)>) -This prover is still in development and may contain bugs. It is not intended to be used in production yet. +### Usage: -Please check issues under security label, and wait for them to be resolved if they are relevant your project. +To prove Cairo programs, they first need to be compiled. For compilation you need to have `cairo-lang` or `docker` installed. -Output builtin is finished, and range check is supported but it's not sound yet. +When using Docker, start by creating the container image with: -We expect to have something working in a good state by mid August 2023. +```**bash** + make docker_build_cairo_compiler +``` -## [Documentation]([lambdaclass.github.io/lambdaworks/](https://lambdaclass.github.io/lambdaworks/starks/cairo.html)) +Examples of Cairo 0 programs can be found [here](https://github.com/lambdaclass/lambdaworks/tree/main/provers/cairo/cairo-prover-lib/cairo_programs/cairo0) -## Table of Contents -- [🌟 Lambdaworks Cairo Platinum Prover 🌟](#-lambdaworks-cairo-platinum-prover-) - - [An open-source Cairo prover](#an-open-source-cairo-prover) - - [⚠️ Disclaimer](#️-disclaimer) - - [Documentation](#documentation) - - [Table of Contents](#table-of-contents) - - [To be added](#to-be-added) - - [Requirements](#requirements) - - [How to try it](#how-to-try-it) - - [πŸš€ Prove and verify](#-prove-and-verify) - - [Using WASM verifier](#using-wasm-verifier) - - [Running tests](#running-tests) - - [Running fuzzers](#running-fuzzers) - - [πŸ“š References](#-references) - - [🌞 Related Projects](#-related-projects) +**To compile and generate a proof you can use:** -## To be added +```bash +make compile_and_prove PROGRAM_PATH= PROOF_PATH= +``` -To be added: -- CLI Improvements -- Add parameters for proving and verifying in the CLI / (Public inputs should be serialized and deserialized) -- Add Cairo compilation inside Rust, to prove and verify Cairo1/Cairo2 from the .cairo file, instead of the .casm file -- Add last constraint of Range Check Built In -- Add more parallelization -- Benchmarks and optimizations for Graviton -- Bitwise Builtin -- Cairo Verifier - - Batch verifier / For trees and N proofs -- Chiplet support -- Different layouts -- Pedersen Builtin -- Pick hash configuration with ProofOptions -- Poseidon Builtin +For example: -## Requirements +```bash +make compile_and_prove PROGRAM_PATH=cairo-prover-lib/cairo_programs/cairo0/fibonacci_5.cairo PROOF_PATH=cairo-prover-lib/cairo_programs/cairo0/fibonacci_5.proof +``` -- Cargo 1.69+ - -## How to try it -### πŸš€ Prove and verify +**To verify a proof you can use:** + +```bash +make verify PROOF_PATH= +``` + +For example: + +```bash +make verify PROOF_PATH=fibonacci_5.proof +``` + +**To compile Cairo:** + +```bash +make compile PROGRAM_PATH= +``` + +For example: + +```bash +make compile PROGRAM_PATH=cairo-prover-lib/cairo_programs/cairo0/fibonacci_5.cairo +``` + +**To prove a compiled program:** + +```bash +make prove PROGRAM_PATH= PROOF_PATH= +``` + +For example: + +```bash +make prove PROGRAM_PATH=cairo-prover-lib/cairo_programs/cairo0/fibonacci_5.json PROOF_PATH=program_proof.proof +``` + + + +**To prove and verify with a single command you can use:** + +```bash +make run_all PROGRAM_PATH= +``` + +For example: + +```bash +make run_all PROGRAM_PATH=cairo-prover-lib/cairo_programs/cairo0/fibonacci_5.json +``` + +**To compile, proof, prove and verify at the same time you can use:** + +```bash +make compile_and_run_all PROGRAM_PATH= +``` + +For example: + +```bash +make compile_and_run_all PROGRAM_PATH=cairo-prover-lib/cairo_programs/cairo0/fibonacci_5.cairo +``` -To prove and verify a program through the CLI, refer to the [CLI documentation](https://lambdaclass.github.io/lambdaworks/tree/main/provers/cairo-prover-cli/README.md). ### Using WASM verifier To use the verifier in WASM, generate a npm package using `wasm-pack` @@ -103,6 +137,17 @@ if you donΒ΄t have the tools for fuzzing installed use make fuzzer_tools ``` +## To be added +- Stone compatibility +- Add program as a public input +- Add Cairo compilation inside Rust, to prove and verify Cairo1/Cairo2 from the .cairo file, instead of the .casm file +- Add more Layouts / Builtins +- Improve parallelization +- Benchmarks and optimizations for Graviton +- Cairo Verifier + - Batch verifier / For trees and N proofs +- Pick hash configuration with ProofOptions + ## πŸ“š References The following links, repos and projects have been important in the development of this library and we want to thank and acknowledge them. @@ -138,7 +183,6 @@ The following links, repos and projects have been important in the development o - [CAIRO VM - Rust](https://github.com/lambdaclass/cairo-vm) - [CAIRO VM - Go](https://github.com/lambdaclass/cairo_vm.go) -- [Lambdaworks](https://github.com/lambdaclass/lambdaworks) - [CAIRO native](https://github.com/lambdaclass/cairo_native/) - [StarkNet in Rust](https://github.com/lambdaclass/starknet_in_rust) - [StarkNet Stack](https://github.com/lambdaclass/starknet_stack) diff --git a/provers/cairo/benches/criterion_prover.rs b/provers/cairo/benches/criterion_prover.rs index 9b025da674..451b4cef79 100644 --- a/provers/cairo/benches/criterion_prover.rs +++ b/provers/cairo/benches/criterion_prover.rs @@ -1,9 +1,9 @@ -use cairo_platinum_prover::{ - air::generate_cairo_proof, cairo_layout::CairoLayout, runner::run::generate_prover_args, -}; use criterion::{ black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, }; +use platinum_prover::{ + air::generate_cairo_proof, cairo_layout::CairoLayout, runner::run::generate_prover_args, +}; use stark_platinum_prover::proof::options::{ProofOptions, SecurityLevel}; pub mod functions; diff --git a/provers/cairo/benches/criterion_prover_70k.rs b/provers/cairo/benches/criterion_prover_70k.rs index 160cdd6298..ff04b8ec1b 100644 --- a/provers/cairo/benches/criterion_prover_70k.rs +++ b/provers/cairo/benches/criterion_prover_70k.rs @@ -1,9 +1,9 @@ -use cairo_platinum_prover::cairo_layout::CairoLayout; -use cairo_platinum_prover::{air::generate_cairo_proof, runner::run::generate_prover_args}; use criterion::{ black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, SamplingMode, }; +use platinum_prover::cairo_layout::CairoLayout; +use platinum_prover::{air::generate_cairo_proof, runner::run::generate_prover_args}; use stark_platinum_prover::proof::options::{ProofOptions, SecurityLevel}; pub mod functions; diff --git a/provers/cairo/benches/criterion_verifier.rs b/provers/cairo/benches/criterion_verifier.rs index 999b3ced46..50fefcd17e 100644 --- a/provers/cairo/benches/criterion_verifier.rs +++ b/provers/cairo/benches/criterion_verifier.rs @@ -1,10 +1,10 @@ -use cairo_platinum_prover::air::{verify_cairo_proof, PublicInputs}; use criterion::{ black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, }; use lambdaworks_math::{ field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, traits::Deserializable, }; +use platinum_prover::air::{verify_cairo_proof, PublicInputs}; use stark_platinum_prover::proof::{ options::{ProofOptions, SecurityLevel}, stark::StarkProof, diff --git a/provers/cairo/benches/criterion_verifier_70k.rs b/provers/cairo/benches/criterion_verifier_70k.rs index 8a279da19f..ab2cc6e69a 100644 --- a/provers/cairo/benches/criterion_verifier_70k.rs +++ b/provers/cairo/benches/criterion_verifier_70k.rs @@ -1,4 +1,3 @@ -use cairo_platinum_prover::air::{verify_cairo_proof, PublicInputs}; use criterion::{ black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, SamplingMode, @@ -6,6 +5,7 @@ use criterion::{ use lambdaworks_math::{ field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, traits::Deserializable, }; +use platinum_prover::air::{verify_cairo_proof, PublicInputs}; use stark_platinum_prover::proof::{ options::{ProofOptions, SecurityLevel}, stark::StarkProof, diff --git a/provers/cairo/benches/functions/stark.rs b/provers/cairo/benches/functions/stark.rs index 15f4611483..ab08338ee8 100644 --- a/provers/cairo/benches/functions/stark.rs +++ b/provers/cairo/benches/functions/stark.rs @@ -1,4 +1,4 @@ -use cairo_platinum_prover::{cairo_mem::CairoMemory, register_states::RegisterStates}; +use platinum_prover::{cairo_mem::CairoMemory, register_states::RegisterStates}; pub fn generate_cairo_trace(filename: &str) -> (RegisterStates, CairoMemory) { let base_dir = env!("CARGO_MANIFEST_DIR").to_string() + "/src/cairo_vm/test_data/"; diff --git a/provers/cairo-prover-cli/requirements.txt b/provers/cairo/cairo-prover-lib/requirements.txt similarity index 100% rename from provers/cairo-prover-cli/requirements.txt rename to provers/cairo/cairo-prover-lib/requirements.txt diff --git a/provers/cairo/tests/wasm.rs b/provers/cairo/cairo-prover-lib/tests/wasm.rs similarity index 99% rename from provers/cairo/tests/wasm.rs rename to provers/cairo/cairo-prover-lib/tests/wasm.rs index 04223cdb55..32c6b34d88 100644 --- a/provers/cairo/tests/wasm.rs +++ b/provers/cairo/cairo-prover-lib/tests/wasm.rs @@ -1,7 +1,7 @@ #[cfg(feature = "wasm")] -use cairo_platinum_prover::wasm_wrappers::deserialize_proof_wasm; +use platinum_prover::wasm_wrappers::deserialize_proof_wasm; #[cfg(feature = "wasm")] -use cairo_platinum_prover::wasm_wrappers::verify_cairo_proof_wasm; +use platinum_prover::wasm_wrappers::verify_cairo_proof_wasm; #[cfg(feature = "wasm")] use stark_platinum_prover::proof::options::ProofOptions; diff --git a/provers/cairo-prover-cli/src/main.rs b/provers/cairo/src/main.rs similarity index 96% rename from provers/cairo-prover-cli/src/main.rs rename to provers/cairo/src/main.rs index 14273700ca..8d1f362736 100644 --- a/provers/cairo-prover-cli/src/main.rs +++ b/provers/cairo/src/main.rs @@ -1,8 +1,8 @@ -use cairo_platinum_prover::air::{generate_cairo_proof, verify_cairo_proof, PublicInputs}; -use cairo_platinum_prover::cairo_layout::CairoLayout; -use cairo_platinum_prover::runner::run::generate_prover_args; use lambdaworks_math::field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField; use lambdaworks_math::traits::{Deserializable, Serializable}; +use platinum_prover::air::{generate_cairo_proof, verify_cairo_proof, PublicInputs}; +use platinum_prover::cairo_layout::CairoLayout; +use platinum_prover::runner::run::generate_prover_args; use stark_platinum_prover::proof::options::{ProofOptions, SecurityLevel}; use stark_platinum_prover::proof::stark::StarkProof; From 6d686d3005c025a9a2da47c90ef4dc75228967ac Mon Sep 17 00:00:00 2001 From: juan518munoz <62400508+juan518munoz@users.noreply.github.com> Date: Fri, 20 Oct 2023 15:06:45 -0300 Subject: [PATCH 17/18] CLI improvements - followup (#603) * migrate cli to extern crate * add clap4 for cli handling * cargo fmt * readme changes * Add disclaimer readme * Remove bit security text from cairo prover crate * add compile option to makefile * add compile and run all to makefile * add example to readme * cargo fmt * add compile and prove to makefile * better readme * add quiet flag to makefile binaries * reorganized readme * initial commit * add remove after compile to docker run * externalize commands * Update README * cargo fmt * update README * err handling for non existing files * moved prints to err handler * Update provers/cairo-prover-cli/src/main.rs Co-authored-by: Mariano A. Nicolini * stark curve, pedersen hash, precalculated points (#597) * stark curve, pedersen hash, precalculated points * lint * lint + array index fixes * cargo fmt * clippy * fmt * ref to starknet-rs * reviews * constant points moved to another file * move 'from_affine_hex_string' to starkcurve * make add_points a private fn * docs for pedersen * rename add_points -> lookup_and_accumulate --------- Co-authored-by: Mariano A. Nicolini * Addition fuzzer for Stark Field (#601) * Add fuzzer * Remove artifacts --------- Co-authored-by: Mariano A. Nicolini * update README * Update Makefile * update README bin * changed println for eprintln * fix README * rmv fuzz and wasm from README --------- Co-authored-by: Jmunoz Co-authored-by: Mariano A. Nicolini Co-authored-by: MauroFab Co-authored-by: irfan Co-authored-by: Mauro Toscano <12560266+MauroToscano@users.noreply.github.com> --- provers/cairo/Makefile | 45 ---------- provers/cairo/README.md | 60 +++++++------ provers/cairo/src/commands.rs | 56 ++++++++++++ provers/cairo/src/main.rs | 162 +++++++++++++++++++++++++++------- 4 files changed, 216 insertions(+), 107 deletions(-) create mode 100644 provers/cairo/src/commands.rs diff --git a/provers/cairo/Makefile b/provers/cairo/Makefile index 66f9547fed..0eee3e465e 100644 --- a/provers/cairo/Makefile +++ b/provers/cairo/Makefile @@ -34,30 +34,9 @@ docker_build_cairo_compiler: docker_compile_cairo: docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM) > $(COMPILED_PROGRAM) -compile: - cairo-compile --proof_mode $(PROGRAM_PATH) > $(COMPILED_PROGRAM) 2>/dev/null || \ - docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM_PATH) > $(COMPILED_PROGRAM) - -prove: - cargo run --quiet --release prove $(PROGRAM_PATH) $(PROOF_PATH) - -verify: - cargo run --quiet --release verify $(PROOF_PATH) - -run_all: - cargo run --quiet --release prove-and-verify $(PROGRAM_PATH) - -compile_and_run_all: - @cairo-compile --proof_mode $(PROGRAM_PATH) > $(COMPILED_PROGRAM) 2>/dev/null || \ - docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM_PATH) > $(COMPILED_PROGRAM) - @echo "Compiling done \n" - @cargo run --quiet --release prove-and-verify $(COMPILED_PROGRAM) $(PROOF_PATH) - @rm $(COMPILED_PROGRAM) - clippy: cargo clippy --workspace --all-targets -- -D warnings - benchmarks_sequential: $(COMPILED_CAIRO0_PROGRAMS) cargo bench @@ -70,31 +49,7 @@ benchmarks_parallel_all: $(COMPILED_CAIRO0_PROGRAMS) build_metal: cargo b --features metal --release - -target/release/cairo-platinum-prover: - cargo build --bin cairo-platinum-prover --release --features instruments -docker_compile_and_run_all: target/release/cairo-platinum-prover - @echo "Compiling program with docker" - docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM) > $(COMPILED_PROGRAM) - @echo "Compiling done \n" - @cargo run --bin cairo-platinum-prover --features instruments --quiet --release prove_and_verify $(COMPILED_PROGRAM) - @rm $(COMPILED_PROGRAM) - -docker_compile_and_prove: target/release/cairo-platinum-prover - @echo "Compiling program with docker" - @docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM) > $(COMPILED_PROGRAM) - @echo "Compiling done \n" - @cargo run --bin cairo-platinum-prover --features instruments --quiet --release prove $(COMPILED_PROGRAM) $(PROOF_PATH) - @rm $(COMPILED_PROGRAM) - -compile_and_prove: target/release/cairo-platinum-prover - @echo "Compiling program with cairo-compile" - @cairo-compile --proof_mode $(PROGRAM) --output $(COMPILED_PROGRAM) - @echo "Compiling done \n" - @cargo run --bin cairo-platinum-prover --features instruments --quiet --release prove $(COMPILED_PROGRAM) $(PROOF_PATH) - @rm $(COMPILED_PROGRAM) - clean: rm -f $(CAIRO0_PROGRAMS_DIR)/*.json rm -f $(CAIRO0_PROGRAMS_DIR)/*.trace diff --git a/provers/cairo/README.md b/provers/cairo/README.md index 57a51a5a77..3383e83a1c 100644 --- a/provers/cairo/README.md +++ b/provers/cairo/README.md @@ -32,50 +32,50 @@ Examples of Cairo 0 programs can be found [here](https://github.com/lambdaclass/ **To compile and generate a proof you can use:** ```bash -make compile_and_prove PROGRAM_PATH= PROOF_PATH= +cargo run --release --features="cli" compile-and-prove ``` For example: ```bash -make compile_and_prove PROGRAM_PATH=cairo-prover-lib/cairo_programs/cairo0/fibonacci_5.cairo PROOF_PATH=cairo-prover-lib/cairo_programs/cairo0/fibonacci_5.proof +cargo run --release --features="cli" compile-and-prove cairo_programs/cairo0/fibonacci_5.cairo cairo_programs/cairo0/fibonacci_5.proof ``` **To verify a proof you can use:** ```bash -make verify PROOF_PATH= +cargo run --release --features="cli" verify ``` For example: ```bash -make verify PROOF_PATH=fibonacci_5.proof +cargo run --release --features="cli" verify fibonacci_5.proof ``` **To compile Cairo:** ```bash -make compile PROGRAM_PATH= +cargo run --release --features="cli" compile ``` For example: ```bash -make compile PROGRAM_PATH=cairo-prover-lib/cairo_programs/cairo0/fibonacci_5.cairo +cargo run --release --features="cli" compile cairo_programs/cairo0/fibonacci_5.cairo ``` **To prove a compiled program:** ```bash -make prove PROGRAM_PATH= PROOF_PATH= +cargo run --release --features="cli" prove ``` For example: ```bash -make prove PROGRAM_PATH=cairo-prover-lib/cairo_programs/cairo0/fibonacci_5.json PROOF_PATH=program_proof.proof +cargo run --release --features="cli" prove cairo_programs/cairo0/fibonacci_5.json program_proof.proof ``` @@ -83,33 +83,48 @@ make prove PROGRAM_PATH=cairo-prover-lib/cairo_programs/cairo0/fibonacci_5.json **To prove and verify with a single command you can use:** ```bash -make run_all PROGRAM_PATH= +cargo run --release --features="cli" run_all ``` For example: ```bash -make run_all PROGRAM_PATH=cairo-prover-lib/cairo_programs/cairo0/fibonacci_5.json +cargo run --release --features="cli" run_all cairo_programs/cairo0/fibonacci_5.json ``` + + **To compile, proof, prove and verify at the same time you can use:** ```bash -make compile_and_run_all PROGRAM_PATH= +cargo run --release --features="cli" compile_and_run_all ``` For example: ```bash -make compile_and_run_all PROGRAM_PATH=cairo-prover-lib/cairo_programs/cairo0/fibonacci_5.cairo +cargo run --release --features="cli" compile_and_run_all cairo_programs/cairo0/fibonacci_5.cairo +``` + +### Run CLI as a binary + +**To install as a binary run the command on the root directory of the CLI:** +```bash +cargo install --features="cli" --path . ``` -### Using WASM verifier +To run the CLI as a binary instead of using cargo replace `cargo run --release --features="cli"` with `platinum-prover`. -To use the verifier in WASM, generate a npm package using `wasm-pack` +for example: +```bash +platinum-prover cairo_programs/cairo0/fibonacci_5.cairo cairo_programs/cairo0/fibonacci_5.proof +``` + +**You can uninstall the binary with:** +```bash +cargo uninstall +``` -As a shortcut, you can call -`make build_wasm` ## Running tests To run tests, simply use ``` @@ -124,19 +139,6 @@ Be sure to build the docker image if you don't want to install the `cairo-lang` make docker_build_cairo_compiler ``` -## Running fuzzers -To run a fuzzer, simply use - -``` -make fuzzer -``` - -if you donΒ΄t have the tools for fuzzing installed use - -``` -make fuzzer_tools -``` - ## To be added - Stone compatibility - Add program as a public input diff --git a/provers/cairo/src/commands.rs b/provers/cairo/src/commands.rs new file mode 100644 index 0000000000..866862643b --- /dev/null +++ b/provers/cairo/src/commands.rs @@ -0,0 +1,56 @@ +use clap::{Args, Parser, Subcommand}; + +#[derive(Parser, Debug)] +#[command(author = "Lambdaworks", version, about)] +pub struct ProverArgs { + #[clap(subcommand)] + pub entity: ProverEntity, +} + +#[derive(Subcommand, Debug)] +pub enum ProverEntity { + #[clap(about = "Compile a given cairo program")] + Compile(CompileArgs), + #[clap(about = "Generate a proof for a given compiled cairo program")] + Prove(ProveArgs), + #[clap(about = "Verify a proof for a given compiled cairo program")] + Verify(VerifyArgs), + #[clap(about = "Generate and verify a proof for a given compiled cairo program")] + ProveAndVerify(ProveAndVerifyArgs), + #[clap(about = "Compile and prove a given cairo program")] + CompileAndProve(CompileAndProveArgs), + #[clap(about = "Compile, prove and verify a given cairo program")] + CompileAndRunAll(CompileAndRunAllArgs), +} + +#[derive(Args, Debug)] +pub struct CompileArgs { + pub program_path: String, +} + +#[derive(Args, Debug)] +pub struct ProveArgs { + pub program_path: String, + pub proof_path: String, +} + +#[derive(Args, Debug)] +pub struct VerifyArgs { + pub proof_path: String, +} + +#[derive(Args, Debug)] +pub struct ProveAndVerifyArgs { + pub program_path: String, +} + +#[derive(Args, Debug)] +pub struct CompileAndProveArgs { + pub program_path: String, + pub proof_path: String, +} + +#[derive(Args, Debug)] +pub struct CompileAndRunAllArgs { + pub program_path: String, +} diff --git a/provers/cairo/src/main.rs b/provers/cairo/src/main.rs index 8d1f362736..e04ac67796 100644 --- a/provers/cairo/src/main.rs +++ b/provers/cairo/src/main.rs @@ -5,42 +5,104 @@ use platinum_prover::cairo_layout::CairoLayout; use platinum_prover::runner::run::generate_prover_args; use stark_platinum_prover::proof::options::{ProofOptions, SecurityLevel}; use stark_platinum_prover::proof::stark::StarkProof; +mod commands; +use clap::Parser; +use std::env; +use std::fs::File; +use std::io::{Error, ErrorKind}; +use std::process::{Command, Stdio}; use std::time::Instant; -use clap::{Args, Parser, Subcommand}; +/// Get current directory and return it as a String +fn get_root_dir() -> Result { + let path_buf = env::current_dir()?.canonicalize()?; + if let Some(path) = path_buf.to_str() { + return Ok(path.to_string()); + } -#[derive(Parser, Debug)] -#[command(author = "Lambdaworks", version, about)] -struct ProverArgs { - #[clap(subcommand)] - entity: ProverEntity, + Err(Error::new(ErrorKind::NotFound, "not found")) } -#[derive(Subcommand, Debug)] -enum ProverEntity { - #[clap(about = "Generate a proof for a given compiled cairo program")] - Prove(ProveArgs), - #[clap(about = "Verify a proof for a given compiled cairo program")] - Verify(VerifyArgs), - #[clap(about = "Generate and verify a proof for a given compiled cairo program")] - ProveAndVerify(ProveAndVerifyArgs), -} +/// Attemps to compile the Cairo program with `cairo-compile` +/// and then save it to the desired path. +/// Returns `Ok` on success else returns `Error` +fn cairo_compile(program_path: &String, out_file_path: &String) -> Result<(), Error> { + let out_file = File::create(out_file_path)?; -#[derive(Args, Debug)] -struct ProveArgs { - program_path: String, - proof_path: String, + match Command::new("cairo-compile") + .arg("--proof_mode") + .arg(program_path) + .stderr(Stdio::null()) + .stdout(out_file) + .spawn() + { + Ok(mut child) => { + // wait for spawned proccess to finish + match child.wait() { + Ok(_) => Ok(()), + Err(err) => Err(err), + } + } + Err(err) => Err(err), + } } -#[derive(Args, Debug)] -struct VerifyArgs { - proof_path: String, +/// Attemps to compile the Cairo program with `docker` +/// and then save it to the desired path. +/// Returns `Ok` on success else returns `Error` +fn docker_compile(program_path: &String, out_file_path: &String) -> Result<(), Error> { + let out_file = File::create(out_file_path)?; + let root_dir = get_root_dir()?; + match Command::new("docker") + .arg("run") + .arg("--rm") + .arg("-v") + .arg(format!("{}/:/pwd", root_dir)) + .arg("cairo") + .arg("--proof_mode") + .arg(format!("/pwd/{}", program_path)) + .stderr(Stdio::null()) + .stdout(out_file) + .spawn() + { + Ok(mut child) => { + // wait for spawned proccess to finish + match child.wait() { + Ok(status) => match status.code() { + Some(0) => Ok(()), // exit success + _ => Err(Error::new( + ErrorKind::Other, + "File provided is not a Cairo uncompiled", + )), + }, + Err(err) => Err(err), + } + } + Err(err) => Err(err), + } } -#[derive(Args, Debug)] -struct ProveAndVerifyArgs { - program_path: String, +/// Attemps to compile the Cairo program +/// with either `cairo-compile` or `docker`` +fn try_compile(program_path: &String, out_file_path: &String) -> Result<(), Error> { + if !program_path.contains(".cairo") { + return Err(Error::new( + ErrorKind::Other, + "Provided file is not a Cairo source file", + )); + } + + if cairo_compile(program_path, out_file_path).is_ok() + || docker_compile(program_path, out_file_path).is_ok() + { + Ok(()) + } else { + Err(Error::new( + ErrorKind::Other, + "Failed to compile cairo program, neither cairo-compile nor docker found", + )) + } } fn generate_proof( @@ -68,13 +130,13 @@ fn generate_proof( println!("Making proof ..."); let proof = match generate_cairo_proof(&main_trace, &pub_inputs, proof_options) { Ok(p) => p, - Err(e) => { - println!("Error generating proof: {:?}", e); + Err(err) => { + eprintln!("Error generating proof: {:?}", err); return None; } }; - println!("Time spent in proving: {:?} \n", timer.elapsed()); + println!(" Time spent in proving: {:?} \n", timer.elapsed()); Some((proof, pub_inputs)) } @@ -88,7 +150,7 @@ fn verify_proof( println!("Verifying ..."); let proof_verified = verify_cairo_proof(&proof, &pub_inputs, proof_options); - println!("Time spent in verifying: {:?} \n", timer.elapsed()); + println!(" Time spent in verifying: {:?} \n", timer.elapsed()); if proof_verified { println!("Verification succeded"); @@ -102,9 +164,17 @@ fn verify_proof( fn main() { let proof_options = ProofOptions::new_secure(SecurityLevel::Conjecturable100Bits, 3); - let args: ProverArgs = ProverArgs::parse(); + let args: commands::ProverArgs = commands::ProverArgs::parse(); match args.entity { - ProverEntity::Prove(args) => { + commands::ProverEntity::Compile(args) => { + let out_file_path = args.program_path.replace(".cairo", ".json"); + if let Err(err) = try_compile(&args.program_path, &out_file_path) { + println!("{}", err); + } else { + println!("Compiled cairo program"); + } + } + commands::ProverEntity::Prove(args) => { // verify input file is .cairo if args.program_path.contains(".cairo") { println!("\nYou are trying to prove a non compiled Cairo program. Please compile it before sending it to the prover.\n"); @@ -128,7 +198,7 @@ fn main() { }; println!("Proof written to {}", args.proof_path); } - ProverEntity::Verify(args) => { + commands::ProverEntity::Verify(args) => { let Ok(program_content) = std::fs::read(&args.proof_path) else { println!("Error opening {} file", args.proof_path); return; @@ -158,12 +228,38 @@ fn main() { verify_proof(proof, pub_inputs, &proof_options); } - ProverEntity::ProveAndVerify(args) => { + commands::ProverEntity::ProveAndVerify(args) => { let Some((proof, pub_inputs)) = generate_proof(&args.program_path, &proof_options) else { return; }; verify_proof(proof, pub_inputs, &proof_options); } + commands::ProverEntity::CompileAndProve(args) => { + let out_file_path = args.program_path.replace(".cairo", ".json"); + match try_compile(&args.program_path, &out_file_path) { + Ok(_) => { + generate_proof(&out_file_path, &proof_options); + } + Err(err) => { + eprintln!("{}", err) + } + } + } + commands::ProverEntity::CompileAndRunAll(args) => { + let out_file_path = args.program_path.replace(".cairo", ".json"); + match try_compile(&args.program_path, &out_file_path) { + Ok(_) => { + let Some((proof, pub_inputs)) = generate_proof(&out_file_path, &proof_options) + else { + return; + }; + verify_proof(proof, pub_inputs, &proof_options); + } + Err(err) => { + eprintln!("{}", err) + } + } + } } } From 94790afba6421a09ce5c90b09b6e794dfb994f53 Mon Sep 17 00:00:00 2001 From: "Mariano A. Nicolini" Date: Mon, 23 Oct 2023 11:25:02 -0300 Subject: [PATCH 18/18] fix: polish some CLI details (#620) * Polish CLI * Fix README * Polish some README details * Change compile-and-run-all to compile-prove-and-verify --- provers/cairo/README.md | 12 ++++---- provers/cairo/src/commands.rs | 2 +- provers/cairo/src/main.rs | 58 +++++++++++++++++++++++------------ 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/provers/cairo/README.md b/provers/cairo/README.md index 3383e83a1c..d0ec274b7c 100644 --- a/provers/cairo/README.md +++ b/provers/cairo/README.md @@ -83,13 +83,13 @@ cargo run --release --features="cli" prove cairo_programs/cairo0/fibonacci_5.jso **To prove and verify with a single command you can use:** ```bash -cargo run --release --features="cli" run_all +cargo run --release --features="cli" prove-and-verify ``` For example: ```bash -cargo run --release --features="cli" run_all cairo_programs/cairo0/fibonacci_5.json +cargo run --release --features="cli" prove-and-verify cairo_programs/cairo0/fibonacci_5.json ``` @@ -97,13 +97,13 @@ cargo run --release --features="cli" run_all cairo_programs/cairo0/fibonacci_5.j **To compile, proof, prove and verify at the same time you can use:** ```bash -cargo run --release --features="cli" compile_and_run_all +cargo run --release --features="cli" compile-prove-and-verify ``` For example: ```bash -cargo run --release --features="cli" compile_and_run_all cairo_programs/cairo0/fibonacci_5.cairo +cargo run --release --features="cli" compile-prove-and-verify cairo_programs/cairo0/fibonacci_5.cairo ``` ### Run CLI as a binary @@ -115,9 +115,9 @@ cargo install --features="cli" --path . To run the CLI as a binary instead of using cargo replace `cargo run --release --features="cli"` with `platinum-prover`. -for example: +for example, the command to generate a proof becomes: ```bash -platinum-prover cairo_programs/cairo0/fibonacci_5.cairo cairo_programs/cairo0/fibonacci_5.proof +platinum-prover prove cairo_programs/cairo0/fibonacci_5.json cairo_programs/cairo0/fibonacci_5.proof ``` **You can uninstall the binary with:** diff --git a/provers/cairo/src/commands.rs b/provers/cairo/src/commands.rs index 866862643b..a8895563a0 100644 --- a/provers/cairo/src/commands.rs +++ b/provers/cairo/src/commands.rs @@ -20,7 +20,7 @@ pub enum ProverEntity { #[clap(about = "Compile and prove a given cairo program")] CompileAndProve(CompileAndProveArgs), #[clap(about = "Compile, prove and verify a given cairo program")] - CompileAndRunAll(CompileAndRunAllArgs), + CompileProveAndVerify(CompileAndRunAllArgs), } #[derive(Args, Debug)] diff --git a/provers/cairo/src/main.rs b/provers/cairo/src/main.rs index e04ac67796..e944fa3a01 100644 --- a/provers/cairo/src/main.rs +++ b/provers/cairo/src/main.rs @@ -112,7 +112,7 @@ fn generate_proof( let timer = Instant::now(); let Ok(program_content) = std::fs::read(input_path) else { - println!("Error opening {input_path} file"); + eprintln!("Error opening {input_path} file"); return None; }; @@ -120,7 +120,7 @@ fn generate_proof( let layout = CairoLayout::Plain; let Ok((main_trace, pub_inputs)) = generate_prover_args(&program_content, &None, layout) else { - println!("Error generating prover args"); + eprintln!("Error generating prover args"); return None; }; @@ -161,6 +161,24 @@ fn verify_proof( proof_verified } +fn write_proof( + proof: StarkProof, + pub_inputs: PublicInputs, + proof_path: String, +) { + let mut bytes = vec![]; + let proof_bytes: Vec = serde_cbor::to_vec(&proof).unwrap(); + bytes.extend(proof_bytes.len().to_be_bytes()); + bytes.extend(proof_bytes); + bytes.extend(pub_inputs.serialize()); + + let Ok(()) = std::fs::write(&proof_path, bytes) else { + eprintln!("Error writing proof to file: {}", &proof_path); + return; + }; + println!("Proof written to {}", &proof_path); +} + fn main() { let proof_options = ProofOptions::new_secure(SecurityLevel::Conjecturable100Bits, 3); @@ -169,7 +187,7 @@ fn main() { commands::ProverEntity::Compile(args) => { let out_file_path = args.program_path.replace(".cairo", ".json"); if let Err(err) = try_compile(&args.program_path, &out_file_path) { - println!("{}", err); + eprintln!("{}", err); } else { println!("Compiled cairo program"); } @@ -177,7 +195,7 @@ fn main() { commands::ProverEntity::Prove(args) => { // verify input file is .cairo if args.program_path.contains(".cairo") { - println!("\nYou are trying to prove a non compiled Cairo program. Please compile it before sending it to the prover.\n"); + eprintln!("\nYou are trying to prove a non compiled Cairo program. Please compile it before sending it to the prover.\n"); return; } @@ -186,33 +204,23 @@ fn main() { return; }; - let mut bytes = vec![]; - let proof_bytes: Vec = serde_cbor::to_vec(&proof).unwrap(); - bytes.extend(proof_bytes.len().to_be_bytes()); - bytes.extend(proof_bytes); - bytes.extend(pub_inputs.serialize()); - - let Ok(()) = std::fs::write(&args.proof_path, bytes) else { - println!("Error writing proof to file: {}", args.proof_path); - return; - }; - println!("Proof written to {}", args.proof_path); + write_proof(proof, pub_inputs, args.proof_path); } commands::ProverEntity::Verify(args) => { let Ok(program_content) = std::fs::read(&args.proof_path) else { - println!("Error opening {} file", args.proof_path); + eprintln!("Error opening {} file", args.proof_path); return; }; let mut bytes = program_content.as_slice(); if bytes.len() < 8 { - println!("Error reading proof from file: {}", args.proof_path); + eprintln!("Error reading proof from file: {}", args.proof_path); return; } let proof_len = usize::from_be_bytes(bytes[0..8].try_into().unwrap()); bytes = &bytes[8..]; if bytes.len() < proof_len { - println!("Error reading proof from file: {}", args.proof_path); + eprintln!("Error reading proof from file: {}", args.proof_path); return; } let Ok(proof) = serde_cbor::from_slice(&bytes[0..proof_len]) else { @@ -229,6 +237,11 @@ fn main() { verify_proof(proof, pub_inputs, &proof_options); } commands::ProverEntity::ProveAndVerify(args) => { + if args.program_path.contains(".cairo") { + eprintln!("\nYou are trying to prove a non compiled Cairo program. Please compile it before sending it to the prover.\n"); + return; + } + let Some((proof, pub_inputs)) = generate_proof(&args.program_path, &proof_options) else { return; @@ -239,14 +252,19 @@ fn main() { let out_file_path = args.program_path.replace(".cairo", ".json"); match try_compile(&args.program_path, &out_file_path) { Ok(_) => { - generate_proof(&out_file_path, &proof_options); + let Some((proof, pub_inputs)) = generate_proof(&out_file_path, &proof_options) + else { + return; + }; + + write_proof(proof, pub_inputs, args.proof_path); } Err(err) => { eprintln!("{}", err) } } } - commands::ProverEntity::CompileAndRunAll(args) => { + commands::ProverEntity::CompileProveAndVerify(args) => { let out_file_path = args.program_path.replace(".cairo", ".json"); match try_compile(&args.program_path, &out_file_path) { Ok(_) => {