From ab1da40461da56c57cdb38635ddec20c0b7b7483 Mon Sep 17 00:00:00 2001 From: M Alghazwi Date: Thu, 22 May 2025 14:10:16 +0200 Subject: [PATCH] add bn254 wrapper --- codex-plonky2-circuits/Cargo.toml | 3 + .../src/bn254_wrapper/bn254_fr.rs | 7 + .../src/bn254_wrapper/config.rs | 238 ++ .../src/bn254_wrapper/mod.rs | 5 + .../src/bn254_wrapper/poseidon_bn254.rs | 268 +++ .../bn254_wrapper/poseidon_bn254_constants.rs | 2087 +++++++++++++++++ .../src/bn254_wrapper/wrap.rs | 223 ++ codex-plonky2-circuits/src/lib.rs | 1 + codex-plonky2-circuits/src/recursion/leaf.rs | 2 +- codex-plonky2-circuits/src/recursion/node.rs | 4 +- codex-plonky2-circuits/src/recursion/tree.rs | 2 +- codex-plonky2-circuits/src/recursion/utils.rs | 3 +- 12 files changed, 2837 insertions(+), 6 deletions(-) create mode 100644 codex-plonky2-circuits/src/bn254_wrapper/bn254_fr.rs create mode 100644 codex-plonky2-circuits/src/bn254_wrapper/config.rs create mode 100644 codex-plonky2-circuits/src/bn254_wrapper/mod.rs create mode 100644 codex-plonky2-circuits/src/bn254_wrapper/poseidon_bn254.rs create mode 100644 codex-plonky2-circuits/src/bn254_wrapper/poseidon_bn254_constants.rs create mode 100644 codex-plonky2-circuits/src/bn254_wrapper/wrap.rs diff --git a/codex-plonky2-circuits/Cargo.toml b/codex-plonky2-circuits/Cargo.toml index 3fd80ac..66ee1e4 100644 --- a/codex-plonky2-circuits/Cargo.toml +++ b/codex-plonky2-circuits/Cargo.toml @@ -18,6 +18,9 @@ plonky2_poseidon2 = { path = "../plonky2_poseidon2" } itertools = { workspace = true } plonky2_maybe_rayon = { workspace = true } hashbrown = "0.14.5" +ff = { package = "ff", version = "0.13", features = ["derive"] } +num = "0.4.3" +lazy_static = "1.5.0" [dev-dependencies] criterion = { version = "0.5.1", default-features = false } diff --git a/codex-plonky2-circuits/src/bn254_wrapper/bn254_fr.rs b/codex-plonky2-circuits/src/bn254_wrapper/bn254_fr.rs new file mode 100644 index 0000000..535403f --- /dev/null +++ b/codex-plonky2-circuits/src/bn254_wrapper/bn254_fr.rs @@ -0,0 +1,7 @@ +use ff::PrimeField; + +#[derive(PrimeField)] +#[PrimeFieldModulus = "21888242871839275222246405745257275088548364400416034343698204186575808495617"] +#[PrimeFieldGenerator = "7"] +#[PrimeFieldReprEndianness = "little"] +pub struct Fr([u64; 4]); diff --git a/codex-plonky2-circuits/src/bn254_wrapper/config.rs b/codex-plonky2-circuits/src/bn254_wrapper/config.rs new file mode 100644 index 0000000..974087c --- /dev/null +++ b/codex-plonky2-circuits/src/bn254_wrapper/config.rs @@ -0,0 +1,238 @@ +use core::fmt; +use std::error::Error; +use std::marker::PhantomData; + +use ff::{Field as ff_Field, PrimeField}; +use num::BigUint; +use plonky2::field::extension::quadratic::QuadraticExtension; +use plonky2::field::goldilocks_field::GoldilocksField; +use plonky2::field::types::Field; +use plonky2::hash::hash_types::RichField; +use plonky2::hash::poseidon::{PoseidonHash, PoseidonPermutation}; +use plonky2::plonk::config::{GenericConfig, GenericHashOut, Hasher}; +use serde::de::Visitor; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +use crate::bn254_wrapper::poseidon_bn254::{permution, GOLDILOCKS_ELEMENTS, RATE}; +use crate::bn254_wrapper::bn254_fr::{Fr, FrRepr}; + +/// Configuration using Poseidon BN254 over the Goldilocks field. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize)] +pub struct PoseidonBN254GoldilocksConfig; +impl GenericConfig<2> for PoseidonBN254GoldilocksConfig { + type F = GoldilocksField; + type FE = QuadraticExtension; + type Hasher = PoseidonBN254Hash; + type InnerHasher = PoseidonHash; +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct PoseidonBN254HashOut { + pub value: Fr, + _phantom: PhantomData, +} + +fn hash_out_to_bytes(hash: PoseidonBN254HashOut) -> Vec { + let binding = hash.value.to_repr(); + let limbs = binding.as_ref(); + limbs.to_vec() +} + +impl GenericHashOut for PoseidonBN254HashOut { + fn to_bytes(&self) -> Vec { + hash_out_to_bytes(*self) + } + + fn from_bytes(bytes: &[u8]) -> Self { + let sized_bytes: [u8; 32] = bytes.try_into().unwrap(); + let fr_repr = FrRepr(sized_bytes); + let fr = Fr::from_repr(fr_repr).unwrap(); + + Self { + value: fr, + _phantom: PhantomData, + } + } + + fn to_vec(&self) -> Vec { + let bytes = hash_out_to_bytes(*self); + bytes + // Chunks of 7 bytes since 8 bytes would allow collisions. + .chunks(7) + .map(|bytes| { + let mut arr = [0; 8]; + arr[..bytes.len()].copy_from_slice(bytes); + F::from_canonical_u64(u64::from_le_bytes(arr)) + }) + .collect() + } +} + +impl Serialize for PoseidonBN254HashOut { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + // Output the hash as a bigint string. + let binding = self.value.to_repr(); + let limbs = binding.as_ref(); + + let big_int = BigUint::from_bytes_le(limbs); + serializer.serialize_str(big_int.to_str_radix(10).as_str()) + } +} + +impl<'de, F: RichField> Deserialize<'de> for PoseidonBN254HashOut { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct PoseidonBN254HashOutVisitor; + + impl<'a> Visitor<'a> for PoseidonBN254HashOutVisitor { + type Value = String; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string with integer value within BN254 scalar field") + } + + fn visit_str(self, v: &str) -> Result + where + E: Error, + { + Ok(v.to_string()) + } + } + + let deserialized_str = deserializer + .deserialize_str(PoseidonBN254HashOutVisitor) + .unwrap(); + let big_int = BigUint::parse_bytes(deserialized_str.as_bytes(), 10).unwrap(); + + let mut bytes = big_int.to_bytes_le(); + for _i in bytes.len()..32 { + bytes.push(0); + } + + let sized_bytes: [u8; 32] = bytes.try_into().unwrap(); + let fr_repr = FrRepr(sized_bytes); + let fr = Fr::from_repr(fr_repr).unwrap(); + + Ok(Self { + value: fr, + _phantom: PhantomData, + }) + } +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct PoseidonBN254Hash; +impl Hasher for PoseidonBN254Hash { + const HASH_SIZE: usize = 32; // Hash output is 4 limbs of u64 + type Hash = PoseidonBN254HashOut; + type Permutation = PoseidonPermutation; + + fn hash_no_pad(input: &[F]) -> Self::Hash { + let mut state = [Fr::ZERO; 4]; + + state[0] = Fr::ZERO; + for rate_chunk in input.chunks(RATE * 3) { + for (j, bn254_chunk) in rate_chunk.chunks(3).enumerate() { + let mut bytes = bn254_chunk[0].to_canonical_u64().to_le_bytes().to_vec(); + + for gl_element in bn254_chunk.iter().skip(1) { + let chunk_bytes = gl_element.to_canonical_u64().to_le_bytes(); + bytes.extend_from_slice(&chunk_bytes); + } + + for _i in bytes.len()..32 { + bytes.push(0); + } + + let sized_bytes: [u8; 32] = bytes.try_into().unwrap(); + let fr_repr = FrRepr(sized_bytes); + state[j + 1] = Fr::from_repr(fr_repr).unwrap(); + } + permution(&mut state); + } + + PoseidonBN254HashOut { + value: state[0], + _phantom: PhantomData, + } + } + + fn hash_pad(input: &[F]) -> Self::Hash { + let mut padded_input = input.to_vec(); + padded_input.push(F::ONE); + while (padded_input.len() + 1) % (RATE * GOLDILOCKS_ELEMENTS) != 0 { + padded_input.push(F::ZERO); + } + padded_input.push(F::ONE); + Self::hash_no_pad(&padded_input) + } + + fn hash_or_noop(inputs: &[F]) -> Self::Hash { + if inputs.len() * 8 <= GOLDILOCKS_ELEMENTS * 8 { + let mut inputs_bytes = vec![0u8; 32]; + for i in 0..inputs.len() { + inputs_bytes[i * 8..(i + 1) * 8] + .copy_from_slice(&inputs[i].to_canonical_u64().to_le_bytes()); + } + Self::Hash::from_bytes(&inputs_bytes) + } else { + Self::hash_no_pad(inputs) + } + } + + fn two_to_one(left: Self::Hash, right: Self::Hash) -> Self::Hash { + let mut state = [Fr::ZERO, Fr::ZERO, left.value, right.value]; + permution(&mut state); + + PoseidonBN254HashOut { + value: state[0], + _phantom: PhantomData, + } + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + + #[test] + fn test_byte_methods() { + type F = GoldilocksField; + + let fr = Fr::from_str_vartime( + "11575173631114898451293296430061690731976535592475236587664058405912382527658", + ) + .unwrap(); + let hash = PoseidonBN254HashOut:: { + value: fr, + _phantom: PhantomData, + }; + + let bytes = hash.to_bytes(); + + let hash_from_bytes = PoseidonBN254HashOut::::from_bytes(&bytes); + assert_eq!(hash, hash_from_bytes); + } + + #[test] + fn test_serialization() { + let fr = Fr::from_str_vartime( + "11575173631114898451293296430061690731976535592475236587664058405912382527658", + ) + .unwrap(); + let hash = PoseidonBN254HashOut:: { + value: fr, + _phantom: PhantomData, + }; + + let serialized = serde_json::to_string(&hash).unwrap(); + let deserialized: PoseidonBN254HashOut = + serde_json::from_str(&serialized).unwrap(); + assert_eq!(hash, deserialized); + } +} diff --git a/codex-plonky2-circuits/src/bn254_wrapper/mod.rs b/codex-plonky2-circuits/src/bn254_wrapper/mod.rs new file mode 100644 index 0000000..7338944 --- /dev/null +++ b/codex-plonky2-circuits/src/bn254_wrapper/mod.rs @@ -0,0 +1,5 @@ +pub mod config; +pub mod bn254_fr; +pub mod poseidon_bn254_constants; +pub mod poseidon_bn254; +pub mod wrap; \ No newline at end of file diff --git a/codex-plonky2-circuits/src/bn254_wrapper/poseidon_bn254.rs b/codex-plonky2-circuits/src/bn254_wrapper/poseidon_bn254.rs new file mode 100644 index 0000000..024c32a --- /dev/null +++ b/codex-plonky2-circuits/src/bn254_wrapper/poseidon_bn254.rs @@ -0,0 +1,268 @@ +use std::ops::{AddAssign, MulAssign}; + +use ff::Field; + +use crate::bn254_wrapper::poseidon_bn254_constants::{ + C_CONSTANTS, M_MATRIX, P_MATRIX, S_CONSTANTS, +}; +use crate::bn254_wrapper::bn254_fr::Fr; + +pub const RATE: usize = 3; +pub const WIDTH: usize = 4; +pub const FULL_ROUNDS: usize = 8; +pub const PARTIAL_ROUNDS: usize = 56; +pub const GOLDILOCKS_ELEMENTS: usize = 3; + +pub type PoseidonState = [Fr; WIDTH]; + +// This poseidon BN254 implementation is based on the following implementation: +// https://github.com/iden3/go-iden3-crypto/blob/e5cf066b8be3da9a3df9544c65818df189fdbebe/poseidon/poseidon.go +pub fn permution(state: &mut PoseidonState) { + ark(state, 0); + full_rounds(state, true); + partial_rounds(state); + full_rounds(state, false); +} + +fn ark(state: &mut PoseidonState, it: usize) { + for i in 0..WIDTH { + state[i].add_assign(&C_CONSTANTS[it + i]); + } +} + +fn exp5(mut x: Fr) -> Fr { + let aux = x; + x = x.square(); + x = x.square(); + x.mul_assign(&aux); + + x +} + +fn exp5_state(state: &mut PoseidonState) { + for state_element in state.iter_mut().take(WIDTH) { + *state_element = exp5(*state_element); + } +} + +fn full_rounds(state: &mut PoseidonState, first: bool) { + for i in 0..FULL_ROUNDS / 2 - 1 { + exp5_state(state); + if first { + ark(state, (i + 1) * WIDTH); + } else { + ark( + state, + (FULL_ROUNDS / 2 + 1) * WIDTH + PARTIAL_ROUNDS + i * WIDTH, + ); + } + mix(state, &M_MATRIX); + } + + exp5_state(state); + if first { + ark(state, (FULL_ROUNDS / 2) * WIDTH); + mix(state, &P_MATRIX); + } else { + mix(state, &M_MATRIX); + } +} + +fn partial_rounds(state: &mut PoseidonState) { + for i in 0..PARTIAL_ROUNDS { + state[0] = exp5(state[0]); + state[0].add_assign(&C_CONSTANTS[(FULL_ROUNDS / 2 + 1) * WIDTH + i]); + + let mut mul; + let mut new_state0 = Fr::ZERO; + for j in 0..WIDTH { + mul = Fr::ZERO; + mul.add_assign(&S_CONSTANTS[(WIDTH * 2 - 1) * i + j]); + mul.mul_assign(&state[j]); + new_state0.add_assign(&mul); + } + + for k in 1..WIDTH { + mul = Fr::ZERO; + mul.add_assign(&state[0]); + mul.mul_assign(&S_CONSTANTS[(WIDTH * 2 - 1) * i + WIDTH + k - 1]); + state[k].add_assign(&mul); + } + + state[0] = new_state0; + } +} + +fn mix(state: &mut PoseidonState, constant_matrix: &[Vec]) { + let mut result: PoseidonState = [Fr::ZERO; WIDTH]; + + let mut mul; + for (i, result_element) in result.iter_mut().enumerate().take(WIDTH) { + for j in 0..WIDTH { + mul = Fr::ZERO; + mul.add_assign(&constant_matrix[j][i]); + mul.mul_assign(&state[j]); + result_element.add_assign(&mul); + } + } + + state[..WIDTH].copy_from_slice(&result[..WIDTH]); +} + +#[cfg(test)] +mod permutation_tests { + use anyhow::Ok; + use ff::{Field, PrimeField}; + + use super::{permution, WIDTH}; + use crate::bn254_wrapper::bn254_fr::Fr; + + #[test] + fn test_permuation() -> Result<(), anyhow::Error> { + // Test inputs are: + // 1. all zeros + // 2. range 0..WIDTH + // 3. all max BN254 values + // 4. random elements of BN254. + // Expected output calculated from this poseidon implementation: https://github.com/iden3/go-iden3-crypto/blob/master/poseidon/poseidon.go#L65 + + let max_value: Fr = Fr::from_str_vartime( + "21888242871839275222246405745257275088548364400416034343698204186575808495616", + ) + .unwrap(); + + let test_vectors: Vec<([Fr; 4], [Fr; 4])> = vec![ + ( + [Fr::ZERO; 4], + [ + Fr::from_str_vartime("5317387130258456662214331362918410991734007599705406860481038345552731150762").unwrap(), + Fr::from_str_vartime("17768273200467269691696191901389126520069745877826494955630904743826040320364").unwrap(), + Fr::from_str_vartime("19413739268543925182080121099097652227979760828059217876810647045303340666757").unwrap(), + Fr::from_str_vartime("3717738800218482999400886888123026296874264026760636028937972004600663725187").unwrap(), + ] + ), + ( + [ + Fr::from_str_vartime("0").unwrap(), + Fr::from_str_vartime("1").unwrap(), + Fr::from_str_vartime("2").unwrap(), + Fr::from_str_vartime("3").unwrap(), + ], + [ + Fr::from_str_vartime("6542985608222806190361240322586112750744169038454362455181422643027100751666").unwrap(), + Fr::from_str_vartime("3478427836468552423396868478117894008061261013954248157992395910462939736589").unwrap(), + Fr::from_str_vartime("1904980799580062506738911865015687096398867595589699208837816975692422464009").unwrap(), + Fr::from_str_vartime("11971464497515232077059236682405357499403220967704831154657374522418385384151").unwrap(), + ] + ), + ( + [max_value; 4], + [ + Fr::from_str_vartime("13055670547682322550638362580666986963569035646873545133474324633020685301274").unwrap(), + Fr::from_str_vartime("19087936485076376314486368416882351797015004625427655501762827988254486144933").unwrap(), + Fr::from_str_vartime("10391468779200270580383536396630001155994223659670674913170907401637624483385").unwrap(), + Fr::from_str_vartime("17202557688472898583549180366140168198092766974201433936205272956998081177816").unwrap(), + ] + ), + ( + [ + Fr::from_str_vartime("6542985608222806190361240322586112750744169038454362455181422643027100751666").unwrap(), + Fr::from_str_vartime("3478427836468552423396868478117894008061261013954248157992395910462939736589").unwrap(), + Fr::from_str_vartime("1904980799580062506738911865015687096398867595589699208837816975692422464009").unwrap(), + Fr::from_str_vartime("11971464497515232077059236682405357499403220967704831154657374522418385384151").unwrap(), + ], + [ + Fr::from_str_vartime("21792249080447013894140672594027696524030291802493510986509431008224624594361").unwrap(), + Fr::from_str_vartime("3536096706123550619294332177231935214243656967137545251021848527424156573335").unwrap(), + Fr::from_str_vartime("14869351042206255711434675256184369368509719143073814271302931417334356905217").unwrap(), + Fr::from_str_vartime("5027523131326906886284185656868809493297314443444919363729302983434650240523").unwrap(), + ] + ), + ]; + + for (mut input, expected_output) in test_vectors.into_iter() { + permution(&mut input); + for i in 0..WIDTH { + assert_eq!(input[i], expected_output[i]); + } + } + + Ok(()) + } +} + +#[cfg(test)] +mod merkle_tree_tests { + use anyhow::Result; + use plonky2::field::extension::Extendable; + use plonky2::hash::hash_types::RichField; + use plonky2::hash::merkle_proofs::verify_merkle_proof_to_cap; + use plonky2::hash::merkle_tree::MerkleTree; + use plonky2::plonk::config::GenericConfig; + + use crate::bn254_wrapper::config::PoseidonBN254GoldilocksConfig; + + fn random_data(n: usize, k: usize) -> Vec> { + (0..n).map(|_| F::rand_vec(k)).collect() + } + + fn verify_all_leaves< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + leaves: Vec>, + cap_height: usize, + ) -> Result<()> { + let tree = MerkleTree::::new(leaves.clone(), cap_height); + for (i, leaf) in leaves.into_iter().enumerate() { + let proof = tree.prove(i); + verify_merkle_proof_to_cap(leaf, i, &tree.cap, &proof)?; + } + Ok(()) + } + + #[test] + #[should_panic] + fn test_cap_height_too_big() { + const D: usize = 2; + type C = PoseidonBN254GoldilocksConfig; + type F = >::F; + + let log_n = 8; + let cap_height = log_n + 1; // Should panic if `cap_height > len_n`. + + let leaves = random_data::(1 << log_n, 7); + let _ = MerkleTree::>::Hasher>::new(leaves, cap_height); + } + + #[test] + fn test_cap_height_eq_log2_len() -> Result<()> { + const D: usize = 2; + type C = PoseidonBN254GoldilocksConfig; + type F = >::F; + + let log_n = 8; + let n = 1 << log_n; + let leaves = random_data::(n, 7); + + verify_all_leaves::(leaves, log_n)?; + + Ok(()) + } + + #[test] + fn test_merkle_trees() -> Result<()> { + const D: usize = 2; + type C = PoseidonBN254GoldilocksConfig; + type F = >::F; + + let log_n = 8; + let n = 1 << log_n; + let leaves = random_data::(n, 7); + + verify_all_leaves::(leaves, 1)?; + + Ok(()) + } +} diff --git a/codex-plonky2-circuits/src/bn254_wrapper/poseidon_bn254_constants.rs b/codex-plonky2-circuits/src/bn254_wrapper/poseidon_bn254_constants.rs new file mode 100644 index 0000000..3379eba --- /dev/null +++ b/codex-plonky2-circuits/src/bn254_wrapper/poseidon_bn254_constants.rs @@ -0,0 +1,2087 @@ +use ff::{Field, PrimeField}; +use lazy_static::lazy_static; + +use crate::bn254_wrapper::bn254_fr::Fr; + +lazy_static! { + pub static ref C_CONSTANTS: Vec = load_c_constants(); + pub static ref S_CONSTANTS: Vec = load_s_constants(); + pub static ref M_MATRIX: Vec> = load_m_matrix(); + pub static ref P_MATRIX: Vec> = load_p_matrix(); +} + +fn load_c_constants() -> Vec { + let mut c_constants = vec![Fr::ZERO; 88]; + + c_constants[0] = Fr::from_str_vartime( + "11633431549750490989983886834189948010834808234699737327785600195936805266405", + ) + .unwrap(); + c_constants[1] = Fr::from_str_vartime( + "17353750182810071758476407404624088842693631054828301270920107619055744005334", + ) + .unwrap(); + c_constants[2] = Fr::from_str_vartime( + "11575173631114898451293296430061690731976535592475236587664058405912382527658", + ) + .unwrap(); + c_constants[3] = Fr::from_str_vartime( + "9724643380371653925020965751082872123058642683375812487991079305063678725624", + ) + .unwrap(); + c_constants[4] = Fr::from_str_vartime( + "12239673881776349871068957838196514517245834187939809998544709168112271341816", + ) + .unwrap(); + c_constants[5] = Fr::from_str_vartime( + "8213756851595907076282161124887805623974269954849888814703174589291971114278", + ) + .unwrap(); + c_constants[6] = Fr::from_str_vartime( + "10700856158409047630150108954036764855084229282872224809993001752389888794123", + ) + .unwrap(); + c_constants[7] = Fr::from_str_vartime( + "4309412763160017434705250214903006191171337994199861518317363388963372067759", + ) + .unwrap(); + c_constants[8] = Fr::from_str_vartime( + "13621360205860636764861614843016050680668828136032459556937427803817198955108", + ) + .unwrap(); + c_constants[9] = Fr::from_str_vartime( + "18132744072298259781740650630118713682311962872833394850644922000343506947506", + ) + .unwrap(); + c_constants[10] = Fr::from_str_vartime( + "10497941627597965031241580959233976924443640728463059894693130666064841012508", + ) + .unwrap(); + c_constants[11] = Fr::from_str_vartime( + "6417221626367515719470057497947343409306030587855174225463612195298058047522", + ) + .unwrap(); + c_constants[12] = Fr::from_str_vartime( + "4674983908670004491400354631773389862914788156614497726528237310334040582090", + ) + .unwrap(); + c_constants[13] = Fr::from_str_vartime( + "873340198155297459771531732108476825755499970277106398541966195153210717293", + ) + .unwrap(); + c_constants[14] = Fr::from_str_vartime( + "9133482302270339304679323394649165596260136537041379860642176850815828132593", + ) + .unwrap(); + c_constants[15] = Fr::from_str_vartime( + "19667464340426349564507575767837635537801536066735594705258884488718315050710", + ) + .unwrap(); + c_constants[16] = Fr::from_str_vartime( + "331000697881161076911287227440410522823531125482651243929873545789686252480", + ) + .unwrap(); + c_constants[17] = Fr::from_str_vartime( + "2272743329483520819389104778389979623160875907321267447635586085241433137026", + ) + .unwrap(); + c_constants[18] = Fr::from_str_vartime( + "20056061746422267419826865443608176291944892343638717421077672390127627926748", + ) + .unwrap(); + c_constants[19] = Fr::from_str_vartime( + "21689171326367195475219251979604515804697103534428737460300868676042327355863", + ) + .unwrap(); + c_constants[20] = Fr::from_str_vartime( + "7810259695400914964411387917274296266504340291833964145271847716091273468172", + ) + .unwrap(); + c_constants[21] = Fr::from_str_vartime( + "14020998353215410538067420885522582505027736982810754116099481711825941220642", + ) + .unwrap(); + c_constants[22] = Fr::from_str_vartime( + "9245012796693900213810598954108273676196337302084957472786966340245263275743", + ) + .unwrap(); + c_constants[23] = Fr::from_str_vartime( + "8962981905074764319938168719738488892057352527537684271935935864821273084600", + ) + .unwrap(); + c_constants[24] = Fr::from_str_vartime( + "17332843516965697478516240137711403804881134130964557790940490781033584077729", + ) + .unwrap(); + c_constants[25] = Fr::from_str_vartime( + "2962481512633005781617177153208165597038681617596047875933934580338169170271", + ) + .unwrap(); + c_constants[26] = Fr::from_str_vartime( + "3545583524837641414415308887998349399894575957283448040799889114001300580510", + ) + .unwrap(); + c_constants[27] = Fr::from_str_vartime( + "9825748584719861837046057557518727684444343953070352817632834283853645430055", + ) + .unwrap(); + c_constants[28] = Fr::from_str_vartime( + "17858606226144476516342911398749600850253621768390773635294560290497927852949", + ) + .unwrap(); + c_constants[29] = Fr::from_str_vartime( + "19407543101519936976076786599565778993379293656069417288311522496519916759844", + ) + .unwrap(); + c_constants[30] = Fr::from_str_vartime( + "21548305854518815463471937514130615108218483277778620473090880308362072806993", + ) + .unwrap(); + c_constants[31] = Fr::from_str_vartime( + "5027201548230124209007202023859059041801516590630988556095211824751904956552", + ) + .unwrap(); + c_constants[32] = Fr::from_str_vartime( + "1278320788183053034261211126815207721315633476390581364649595040979423239088", + ) + .unwrap(); + c_constants[33] = Fr::from_str_vartime( + "21021340095589643000573495115924922630807303076545481383969066202975724043976", + ) + .unwrap(); + c_constants[34] = Fr::from_str_vartime( + "918385069628188207001966014851379853961258262104472252966637722307728618311", + ) + .unwrap(); + c_constants[35] = Fr::from_str_vartime( + "7965072539100037475925090906281896901763370093075915840665305317760262942154", + ) + .unwrap(); + c_constants[36] = Fr::from_str_vartime( + "7378267415483811789102866201206786220747449921553565182362543937740633252433", + ) + .unwrap(); + c_constants[37] = Fr::from_str_vartime( + "21420063039401631492872969377050715448026482027341082733718950945529081119315", + ) + .unwrap(); + c_constants[38] = Fr::from_str_vartime( + "6984186848935723943941543006673172228872682933412337752165652636767411415446", + ) + .unwrap(); + c_constants[39] = Fr::from_str_vartime( + "12107134736452640457370020100579770521541376434013671407419563526253119375027", + ) + .unwrap(); + c_constants[40] = Fr::from_str_vartime( + "8454625495310558663140928634608422027208548557279385097066005785045755903417", + ) + .unwrap(); + c_constants[41] = Fr::from_str_vartime( + "8017631723660250252193376543593224884977313136061388836952991492888330231080", + ) + .unwrap(); + c_constants[42] = Fr::from_str_vartime( + "19995498935394919030796805510514577077319475365066948284951310616396837691603", + ) + .unwrap(); + c_constants[43] = Fr::from_str_vartime( + "10247653874740427181312035102426523630476005333120089103526343619029364327967", + ) + .unwrap(); + c_constants[44] = Fr::from_str_vartime( + "13160967777591563201117493157286130579932067039961943416358165521611018318814", + ) + .unwrap(); + c_constants[45] = Fr::from_str_vartime( + "5676293694146750080963041160092533338992482128392885932218516813947476623756", + ) + .unwrap(); + c_constants[46] = Fr::from_str_vartime( + "11945330020489343984352429388118756789915736454422495317728221749575540363130", + ) + .unwrap(); + c_constants[47] = Fr::from_str_vartime( + "16575755931296600565681989782918578103656201270919325693721999523168590365097", + ) + .unwrap(); + c_constants[48] = Fr::from_str_vartime( + "6507448101913175376269537672277524478400652962306200709943614250998845221975", + ) + .unwrap(); + c_constants[49] = Fr::from_str_vartime( + "20000756050339437189232666465591830538666897533492662864197332257508545696504", + ) + .unwrap(); + c_constants[50] = Fr::from_str_vartime( + "2538139500492919467696560596150779916859394629326537877502980743087004819534", + ) + .unwrap(); + c_constants[51] = Fr::from_str_vartime( + "7871037999774788273525866585990542333245923983722339125599991222477852815605", + ) + .unwrap(); + c_constants[52] = Fr::from_str_vartime( + "8368558409504001796987467259514778517606739110778427183378433173780120985763", + ) + .unwrap(); + c_constants[53] = Fr::from_str_vartime( + "10459885623117973980697126416757555084518174957115744579590957904857119054380", + ) + .unwrap(); + c_constants[54] = Fr::from_str_vartime( + "3384626976854176329065296334831532874977246373363627584425356985964639685936", + ) + .unwrap(); + c_constants[55] = Fr::from_str_vartime( + "14737139139809423972873213065253246598075451131478157534053817909649707346105", + ) + .unwrap(); + c_constants[56] = Fr::from_str_vartime( + "5793030407008346395600962336988545239125310160053522248574303463872647020425", + ) + .unwrap(); + c_constants[57] = Fr::from_str_vartime( + "161797721038773165886882501305032811420344793568022002686671602943345085701", + ) + .unwrap(); + c_constants[58] = Fr::from_str_vartime( + "16804762399165090393770239542398927686244163302041099831597167085216405440289", + ) + .unwrap(); + c_constants[59] = Fr::from_str_vartime( + "15440431301017924367171251352865716677435047477418739126248587843926419339250", + ) + .unwrap(); + c_constants[60] = Fr::from_str_vartime( + "15570353803062363582500010627498291625214012654155408601153435169223922455380", + ) + .unwrap(); + c_constants[61] = Fr::from_str_vartime( + "15115601269705628455987152258857868396524812969878723314685224929600383566277", + ) + .unwrap(); + c_constants[62] = Fr::from_str_vartime( + "6356053248039389904799735666848118481514593163165587256076018940751965212118", + ) + .unwrap(); + c_constants[63] = Fr::from_str_vartime( + "16309790196305846370580640353745827882351273732480869449701807093685497609128", + ) + .unwrap(); + c_constants[64] = Fr::from_str_vartime( + "18447296906230039277288210321788736138216936478488032824595044533456671231353", + ) + .unwrap(); + c_constants[65] = Fr::from_str_vartime( + "6105351805879633605209308509080121925171118411225835503106175078539279138153", + ) + .unwrap(); + c_constants[66] = Fr::from_str_vartime( + "19852645406205681222287243787651048897744424465454177194550461625744671602479", + ) + .unwrap(); + c_constants[67] = Fr::from_str_vartime( + "9007786282651237028773725177593860474523832555275407287854317958939412791659", + ) + .unwrap(); + c_constants[68] = Fr::from_str_vartime( + "18947127426470143546676956069733014228119216644326548862881450999285087652129", + ) + .unwrap(); + c_constants[69] = Fr::from_str_vartime( + "4006307826238987763983990462011007258305618881936961734589789440938853470615", + ) + .unwrap(); + c_constants[70] = Fr::from_str_vartime( + "6924385845051163089352800210788743599810236082363643773698057309137019167115", + ) + .unwrap(); + c_constants[71] = Fr::from_str_vartime( + "2561599182344380405085465588284140808385687895597384476955417835636116225821", + ) + .unwrap(); + c_constants[72] = Fr::from_str_vartime( + "18225048309586676741223646736155757525087799474840323150729701492173705507839", + ) + .unwrap(); + c_constants[73] = Fr::from_str_vartime( + "16007480414415489869989133828107467718966566156219711380836971295459227141818", + ) + .unwrap(); + c_constants[74] = Fr::from_str_vartime( + "1248906006044888441798838825685606393060257012284188943868730340563960780866", + ) + .unwrap(); + c_constants[75] = Fr::from_str_vartime( + "20912864018050627133842158245163422113261374878008212512322853267715626252916", + ) + .unwrap(); + c_constants[76] = Fr::from_str_vartime( + "13216486202690474504584820948167785518004498504229717602814280132903612841969", + ) + .unwrap(); + c_constants[77] = Fr::from_str_vartime( + "17416264900059210810716133407170753459272974595675494034944092509584936747655", + ) + .unwrap(); + c_constants[78] = Fr::from_str_vartime( + "15395940772659312642272628762657023074462358708226101085466723152641135097674", + ) + .unwrap(); + c_constants[79] = Fr::from_str_vartime( + "4690442806047481777095177614992497363041188209965731514747362442612318535595", + ) + .unwrap(); + c_constants[80] = Fr::from_str_vartime( + "12980185426778583997022610696582563821013078583440402121868121411086576741088", + ) + .unwrap(); + c_constants[81] = Fr::from_str_vartime( + "19436953581443472871973830882428624449045305494959438365629984120779166561614", + ) + .unwrap(); + c_constants[82] = Fr::from_str_vartime( + "7021128259021787032633332177524933222338330182720924079777325144523649322812", + ) + .unwrap(); + c_constants[83] = Fr::from_str_vartime( + "18561291417991436986590120557027289864572049192245689357046574683519049533637", + ) + .unwrap(); + c_constants[84] = Fr::from_str_vartime( + "12019749240411640852887001467406069824508276240179427493437313074459156379732", + ) + .unwrap(); + c_constants[85] = Fr::from_str_vartime( + "19007581091212404202795325684108744075320879284650517772195719617120941682734", + ) + .unwrap(); + c_constants[86] = Fr::from_str_vartime( + "8172766643075822491744127151779052248074930479661223662192995838879026989201", + ) + .unwrap(); + c_constants[87] = Fr::from_str_vartime( + "1885998770792872998306340529689960371653339961062025442813774917754800650781", + ) + .unwrap(); + + c_constants +} + +fn load_s_constants() -> Vec { + let mut s_constants = vec![Fr::ZERO; 392]; + + s_constants[0] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[1] = Fr::from_str_vartime( + "20198106103550706280267600199190750325504745188750640438654177959939538483777", + ) + .unwrap(); + s_constants[2] = Fr::from_str_vartime( + "20760367756622597472566835313508896628444391801225538453375145392828630013190", + ) + .unwrap(); + s_constants[3] = Fr::from_str_vartime( + "4560321026325826558577463029506577497226940849420215249948019116691014248443", + ) + .unwrap(); + s_constants[4] = Fr::from_str_vartime( + "14542348742554217629977259301175635295381723358917389768274600005636270665372", + ) + .unwrap(); + s_constants[5] = Fr::from_str_vartime( + "15896375770890915929312334597144922470201903000282577832977222171710825960733", + ) + .unwrap(); + s_constants[6] = Fr::from_str_vartime( + "12252597347102015743878803847985560878912969150828000392862427919235870760323", + ) + .unwrap(); + s_constants[7] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[8] = Fr::from_str_vartime( + "7179342059755701265188463641990689102412444920238824560515276276968272417627", + ) + .unwrap(); + s_constants[9] = Fr::from_str_vartime( + "4291630597779640477035256747339007105528129889017831542003293220100844273045", + ) + .unwrap(); + s_constants[10] = Fr::from_str_vartime( + "7155591457893668398581213488670279080694237456746471479962759104308162960346", + ) + .unwrap(); + s_constants[11] = Fr::from_str_vartime( + "18018059843853960571576693455761079306078638316240126846230125992269221919628", + ) + .unwrap(); + s_constants[12] = Fr::from_str_vartime( + "17192953047291854075450899126062621814148699654417386994738494022353693631044", + ) + .unwrap(); + s_constants[13] = Fr::from_str_vartime( + "21569358698233938087179836388127293183598397710122666685148766859224500701833", + ) + .unwrap(); + s_constants[14] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[15] = Fr::from_str_vartime( + "767999929530270249383649002937499906068820748885293476546946323828660462871", + ) + .unwrap(); + s_constants[16] = Fr::from_str_vartime( + "5621566033978712522450054985133362876999740181849707666504220417128301048308", + ) + .unwrap(); + s_constants[17] = Fr::from_str_vartime( + "7047587043137472855909285569331719962122602952080655968507950635506526200417", + ) + .unwrap(); + s_constants[18] = Fr::from_str_vartime( + "4106788926932251085789923064963212794107963499320782851030491954062548275037", + ) + .unwrap(); + s_constants[19] = Fr::from_str_vartime( + "4545465201904739898734767265726940896371623586331600641370124254775978068067", + ) + .unwrap(); + s_constants[20] = Fr::from_str_vartime( + "10998902844068831181439895790460185435489188976722435541316954293463196661627", + ) + .unwrap(); + s_constants[21] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[22] = Fr::from_str_vartime( + "4376836298206152573581217002448306554373223213053980459591637689821900483336", + ) + .unwrap(); + s_constants[23] = Fr::from_str_vartime( + "5063873841797552329477290331693185729765297320248590815860571737190009344755", + ) + .unwrap(); + s_constants[24] = Fr::from_str_vartime( + "17220054068062949177158788546035218460663984286240089601095376499170326046885", + ) + .unwrap(); + s_constants[25] = Fr::from_str_vartime( + "6096091793679274146365056037005290512891839764898244154356695047489211507312", + ) + .unwrap(); + s_constants[26] = Fr::from_str_vartime( + "20208154436430351332345105187219062318903703844357504892008088901754085119783", + ) + .unwrap(); + s_constants[27] = Fr::from_str_vartime( + "20838511199557042422189066592494164230774524176144133560311285338373104325885", + ) + .unwrap(); + s_constants[28] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[29] = Fr::from_str_vartime( + "16227720862704770803579874423899491820268073980006154670796744520986650305964", + ) + .unwrap(); + s_constants[30] = Fr::from_str_vartime( + "3929921339874032224077598341189960169422821598221170533707987779964278253429", + ) + .unwrap(); + s_constants[31] = Fr::from_str_vartime( + "11676522033799786037262769984406232796495555956069794755879715792396951198318", + ) + .unwrap(); + s_constants[32] = Fr::from_str_vartime( + "7762519209385193303450585425818218327021377088446472105589371562364474259645", + ) + .unwrap(); + s_constants[33] = Fr::from_str_vartime( + "12228816136730871104506419752649367119045148103237539623130531869347941136043", + ) + .unwrap(); + s_constants[34] = Fr::from_str_vartime( + "5506740114091186508725306313701186842841118936086047703119202768266996591645", + ) + .unwrap(); + s_constants[35] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[36] = Fr::from_str_vartime( + "14813919600103919291484875851986720548476220511386386518354061356196294952105", + ) + .unwrap(); + s_constants[37] = Fr::from_str_vartime( + "19412665928425989269357649645392922518929142728556361947563991549129986237680", + ) + .unwrap(); + s_constants[38] = Fr::from_str_vartime( + "7745252322635388376641759428229975035032852732127464661605110457073217385072", + ) + .unwrap(); + s_constants[39] = Fr::from_str_vartime( + "12066184602104703003390387343585316865507822321930012054206126015745471356816", + ) + .unwrap(); + s_constants[40] = Fr::from_str_vartime( + "12620273762884289038844321186080149434615909817652953074992148689167338466281", + ) + .unwrap(); + s_constants[41] = Fr::from_str_vartime( + "11751773042154924867322926561716263630089863992083485679779160826117120630730", + ) + .unwrap(); + s_constants[42] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[43] = Fr::from_str_vartime( + "5787863126296931978637454491180421506307265052288386136386997720537089333357", + ) + .unwrap(); + s_constants[44] = Fr::from_str_vartime( + "4359270971608384879625804007684881130504862820820494966964908818477035866962", + ) + .unwrap(); + s_constants[45] = Fr::from_str_vartime( + "19213956561377299828591097862016633994148464565683346498602915228516385038972", + ) + .unwrap(); + s_constants[46] = Fr::from_str_vartime( + "10661554072824488477243358897537934080796136449622029441506710580786939692047", + ) + .unwrap(); + s_constants[47] = Fr::from_str_vartime( + "3607791084285905641943446462342879718459787316113396877697968017015606720718", + ) + .unwrap(); + s_constants[48] = Fr::from_str_vartime( + "21380267103954285713588504655257961830793460465329761560308765483331070823566", + ) + .unwrap(); + s_constants[49] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[50] = Fr::from_str_vartime( + "16335017324810170896233622441986531365208293021101073775522004006769586788569", + ) + .unwrap(); + s_constants[51] = Fr::from_str_vartime( + "8596452296160802102282257210844234154821630615259613589128211738647312221536", + ) + .unwrap(); + s_constants[52] = Fr::from_str_vartime( + "16301372420970040998092568156060757300799008373690279794165397142889066306513", + ) + .unwrap(); + s_constants[53] = Fr::from_str_vartime( + "11903327405072234929619206491534763321300297227799575111355508350177812704304", + ) + .unwrap(); + s_constants[54] = Fr::from_str_vartime( + "14821948344368180716550312221723948572649473361813001292505502225087596775887", + ) + .unwrap(); + s_constants[55] = Fr::from_str_vartime( + "5285692778454746827266147532131677990565304365953070750869571432820529495914", + ) + .unwrap(); + s_constants[56] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[57] = Fr::from_str_vartime( + "10012872528823706988605864950067342792516562023507005612462537243496467566252", + ) + .unwrap(); + s_constants[58] = Fr::from_str_vartime( + "21446538914812609684138720355481253195782233393805940184895189253411195275222", + ) + .unwrap(); + s_constants[59] = Fr::from_str_vartime( + "6967738095634646257690113616580876555259467406702097184326306034350680240041", + ) + .unwrap(); + s_constants[60] = Fr::from_str_vartime( + "4106908293164276270299730590107104728631886925545072356564726466348010934176", + ) + .unwrap(); + s_constants[61] = Fr::from_str_vartime( + "20927688665665429774877287472467937369033546230576320387423016374665584172634", + ) + .unwrap(); + s_constants[62] = Fr::from_str_vartime( + "9961827048684904093454156105462119035870307939873087416648411282423867596401", + ) + .unwrap(); + s_constants[63] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[64] = Fr::from_str_vartime( + "17625964999746898246984332334222740240090489215775011285534890391099108738991", + ) + .unwrap(); + s_constants[65] = Fr::from_str_vartime( + "6756403122817134101960922940971569987994537470470008333055210502063290961967", + ) + .unwrap(); + s_constants[66] = Fr::from_str_vartime( + "18209952059360034384023720860507712662310034604843833483955548867331649086618", + ) + .unwrap(); + s_constants[67] = Fr::from_str_vartime( + "8749953392298305294875888962184156769810429880914465959429873281709868501522", + ) + .unwrap(); + s_constants[68] = Fr::from_str_vartime( + "13903906876414887303860424108888965657645488675119946001291096608021846549241", + ) + .unwrap(); + s_constants[69] = Fr::from_str_vartime( + "8884215530056835002390372161442569149992192407996136723184495322116314590715", + ) + .unwrap(); + s_constants[70] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[71] = Fr::from_str_vartime( + "15368493359884894356742361670810465111377869951487306983186672135817808040059", + ) + .unwrap(); + s_constants[72] = Fr::from_str_vartime( + "16469301592941427332568429408115015498659452810956369922459344407975076653255", + ) + .unwrap(); + s_constants[73] = Fr::from_str_vartime( + "11953776125042477689669753843214783238996317490452913722906886945106240528752", + ) + .unwrap(); + s_constants[74] = Fr::from_str_vartime( + "4850027575321262255650746466350338325012270813222547784484958365303358175196", + ) + .unwrap(); + s_constants[75] = Fr::from_str_vartime( + "7167191208528939112939986630484202425436947674819310704476597678688297314160", + ) + .unwrap(); + s_constants[76] = Fr::from_str_vartime( + "14743993805036761996537001252852408745345655735519736268834200732992754437162", + ) + .unwrap(); + s_constants[77] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[78] = Fr::from_str_vartime( + "2193200656642352685118935602989839715339339245164998181015765438900681320425", + ) + .unwrap(); + s_constants[79] = Fr::from_str_vartime( + "4952431971730605970338760580694476897050208114543185599136664869372496356437", + ) + .unwrap(); + s_constants[80] = Fr::from_str_vartime( + "11345335340256434787038072013242069397625261572269911025596723263652849081076", + ) + .unwrap(); + s_constants[81] = Fr::from_str_vartime( + "19160419866562146325212161338497565927215049171520418417356683157217751672139", + ) + .unwrap(); + s_constants[82] = Fr::from_str_vartime( + "1906154907657701464044944280274832161539842850674948965456024456273947429115", + ) + .unwrap(); + s_constants[83] = Fr::from_str_vartime( + "16149082223365808325093364716798557120316343643236068373217398223890421952409", + ) + .unwrap(); + s_constants[84] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[85] = Fr::from_str_vartime( + "15043765472887378252850447725400426753906560153686308918666838116627815818554", + ) + .unwrap(); + s_constants[86] = Fr::from_str_vartime( + "12358170975909062301667468450513761096746838254885629802196667786117625700681", + ) + .unwrap(); + s_constants[87] = Fr::from_str_vartime( + "8976079215643004959353142348700280485976874920070539486194110584442767827768", + ) + .unwrap(); + s_constants[88] = Fr::from_str_vartime( + "16076674040958582640238476383964669465698501606063044308184974525408139269248", + ) + .unwrap(); + s_constants[89] = Fr::from_str_vartime( + "21647594485928619120181355125322770225837180985764869124047447620451714635371", + ) + .unwrap(); + s_constants[90] = Fr::from_str_vartime( + "21615565593822404396628787247811190031843657706885317097074400292994831686718", + ) + .unwrap(); + s_constants[91] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[92] = Fr::from_str_vartime( + "7285489402319904168831455790041657959272324796876172356990227907987038622155", + ) + .unwrap(); + s_constants[93] = Fr::from_str_vartime( + "8211470967679835460786450636871651606756811185450731546421075600179331665168", + ) + .unwrap(); + s_constants[94] = Fr::from_str_vartime( + "13120324752637151731834041425113532499273467426551390593296677993139082244188", + ) + .unwrap(); + s_constants[95] = Fr::from_str_vartime( + "6490061383110696131545774076292741528427005211177990719476969041145673265422", + ) + .unwrap(); + s_constants[96] = Fr::from_str_vartime( + "21671644951532628690769713999772810624944081525303128765668379478511313095702", + ) + .unwrap(); + s_constants[97] = Fr::from_str_vartime( + "17491948871201042934988514071862478178478080786921680019735540941776855947714", + ) + .unwrap(); + s_constants[98] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[99] = Fr::from_str_vartime( + "20875198681143976093301585336441600786893116178926266185909922467347281090330", + ) + .unwrap(); + s_constants[100] = Fr::from_str_vartime( + "3598136009866557326049002438338730052625336381410025235713569185700458778346", + ) + .unwrap(); + s_constants[101] = Fr::from_str_vartime( + "10257854050179821094359263633511835293496268374135163743255999829573090463793", + ) + .unwrap(); + s_constants[102] = Fr::from_str_vartime( + "8709186608235401140998284233255708538357614560705220346211132868280137795418", + ) + .unwrap(); + s_constants[103] = Fr::from_str_vartime( + "1259589977644258611864841556278758814462356863769029941139050408715640323060", + ) + .unwrap(); + s_constants[104] = Fr::from_str_vartime( + "4938787097541166466238757186525276546940957932147842294635573194784914432374", + ) + .unwrap(); + s_constants[105] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[106] = Fr::from_str_vartime( + "16717728254520320964463545682641729805489575123710417403982868570393738171908", + ) + .unwrap(); + s_constants[107] = Fr::from_str_vartime( + "9748879216547249587937312403683718221531596047715540576918379577191876140829", + ) + .unwrap(); + s_constants[108] = Fr::from_str_vartime( + "14944874834710321794079457580123143945012638912293883509561999360499542827539", + ) + .unwrap(); + s_constants[109] = Fr::from_str_vartime( + "18031584503513589779232867929321541667009512801047020067337884181460183159789", + ) + .unwrap(); + s_constants[110] = Fr::from_str_vartime( + "18414164542389736964053830253126595155017280572430646030445262089460883013232", + ) + .unwrap(); + s_constants[111] = Fr::from_str_vartime( + "2610402018952962996318994974332047870945223376199918653423836750745739531230", + ) + .unwrap(); + s_constants[112] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[113] = Fr::from_str_vartime( + "14009467204580838343058201541088761048498359505808795311724314678689480323211", + ) + .unwrap(); + s_constants[114] = Fr::from_str_vartime( + "21469776223413224601890303218554639233147301494161934252153679844173746974667", + ) + .unwrap(); + s_constants[115] = Fr::from_str_vartime( + "20647680658876691843280356403387803136370174824153696476894283712779784940833", + ) + .unwrap(); + s_constants[116] = Fr::from_str_vartime( + "7936850548423967572066326867280341951424312865893525326890769023431047320991", + ) + .unwrap(); + s_constants[117] = Fr::from_str_vartime( + "12722969395702657985023075505830677750286440950878333627607092139722193056708", + ) + .unwrap(); + s_constants[118] = Fr::from_str_vartime( + "11321152935530907374770739017822060871862163756958501641453518139130228537202", + ) + .unwrap(); + s_constants[119] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[120] = Fr::from_str_vartime( + "4094512680835093637766266255807831961532213986166871807693377951477711786051", + ) + .unwrap(); + s_constants[121] = Fr::from_str_vartime( + "18178389385096689665303225717280896610765865274508135228632006790574677752293", + ) + .unwrap(); + s_constants[122] = Fr::from_str_vartime( + "5003815887613767774717115773943502417144707145760897577207221259749678760892", + ) + .unwrap(); + s_constants[123] = Fr::from_str_vartime( + "11395014411676120154590806918236444089801092874462769558428488274754488682814", + ) + .unwrap(); + s_constants[124] = Fr::from_str_vartime( + "5043626533165824802355651303240938472427342475587368271803664178703751133184", + ) + .unwrap(); + s_constants[125] = Fr::from_str_vartime( + "20737661798231456194286427103806996346683878567029159134024210934417745289241", + ) + .unwrap(); + s_constants[126] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[127] = Fr::from_str_vartime( + "17885807983183478128547293344015669882824716934567927629992464147210758449961", + ) + .unwrap(); + s_constants[128] = Fr::from_str_vartime( + "4491530859611985170204284394599169523531547745924230349900720023555385570566", + ) + .unwrap(); + s_constants[129] = Fr::from_str_vartime( + "10590405810993997824904026910850308084431468206425947323744908163083992870845", + ) + .unwrap(); + s_constants[130] = Fr::from_str_vartime( + "14773696309507449928652967351151268377421083281901294044684766706170272145134", + ) + .unwrap(); + s_constants[131] = Fr::from_str_vartime( + "8012817909803347753036095373079065441540540870790316296905616948358031128489", + ) + .unwrap(); + s_constants[132] = Fr::from_str_vartime( + "15953294845538540694147122390548121234862217402440162841644474763770065752954", + ) + .unwrap(); + s_constants[133] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[134] = Fr::from_str_vartime( + "19330308615634016202275470394593918283291746889176278663184951919223544096896", + ) + .unwrap(); + s_constants[135] = Fr::from_str_vartime( + "15105179537685942573078046208371583063999793255578601214915887961329652398190", + ) + .unwrap(); + s_constants[136] = Fr::from_str_vartime( + "21709064542465141520669973714950919003335169451362947708974082912187480247791", + ) + .unwrap(); + s_constants[137] = Fr::from_str_vartime( + "460683998482756280912187509737431365362650506162063605585420395591986395093", + ) + .unwrap(); + s_constants[138] = Fr::from_str_vartime( + "8528936230636059063848306774318500923209521695610089597282351580188192653610", + ) + .unwrap(); + s_constants[139] = Fr::from_str_vartime( + "8893687738651874055934077641258880070065696892648906132887857010931807062812", + ) + .unwrap(); + s_constants[140] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[141] = Fr::from_str_vartime( + "9353521397201520020163669559110959732855095088196767785130221250369398534266", + ) + .unwrap(); + s_constants[142] = Fr::from_str_vartime( + "16613542657585137487151470980837461302153210762614545024991732555481490683814", + ) + .unwrap(); + s_constants[143] = Fr::from_str_vartime( + "2204502375207887950205548277458704596225935813112150868324282564135082293291", + ) + .unwrap(); + s_constants[144] = Fr::from_str_vartime( + "21254675318867619388160936117044327276221059873039333971338260709002243972836", + ) + .unwrap(); + s_constants[145] = Fr::from_str_vartime( + "16665573707712654499163134682677891418056405526644611110898762937899356502949", + ) + .unwrap(); + s_constants[146] = Fr::from_str_vartime( + "14267552583056171982269630733147008270458243455399509417719716681547925602990", + ) + .unwrap(); + s_constants[147] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[148] = Fr::from_str_vartime( + "16367942369253394098422648739247412041658904846897825274155468251740735622582", + ) + .unwrap(); + s_constants[149] = Fr::from_str_vartime( + "3109601755423487827090460933116495844768178403907542635843078881599579349417", + ) + .unwrap(); + s_constants[150] = Fr::from_str_vartime( + "13070881723095523414228674713428974685755915412664044005891151350338033029052", + ) + .unwrap(); + s_constants[151] = Fr::from_str_vartime( + "10259475086157775344414603146661739080464638100961174958014154428063344142346", + ) + .unwrap(); + s_constants[152] = Fr::from_str_vartime( + "14392919515768311705876085292469557682647137722466492884286386263408604670613", + ) + .unwrap(); + s_constants[153] = Fr::from_str_vartime( + "517834877649467900881483483632287988070398657044896986690867428743067995638", + ) + .unwrap(); + s_constants[154] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[155] = Fr::from_str_vartime( + "19776116368291396730046653100175352607868202157614878715709943043429632352654", + ) + .unwrap(); + s_constants[156] = Fr::from_str_vartime( + "5905125865653916927083238886025287246947738553282644091380121061742003257962", + ) + .unwrap(); + s_constants[157] = Fr::from_str_vartime( + "21028910015562338297173802587144293023870505593218986935232089708700866548848", + ) + .unwrap(); + s_constants[158] = Fr::from_str_vartime( + "13395944831564259671405922878791909538223635993323846275946092882663526594615", + ) + .unwrap(); + s_constants[159] = Fr::from_str_vartime( + "7995249236543262914206397633444491535498682241246319919218592002459454218505", + ) + .unwrap(); + s_constants[160] = Fr::from_str_vartime( + "20437702676708041916002540544749140197744801315911882559568865094949905456106", + ) + .unwrap(); + s_constants[161] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[162] = Fr::from_str_vartime( + "18122990859780045886774524690965061785055534365091244948379358057402402367696", + ) + .unwrap(); + s_constants[163] = Fr::from_str_vartime( + "7828598613589603783167146853068200035787559469554903457639957531866407371355", + ) + .unwrap(); + s_constants[164] = Fr::from_str_vartime( + "9332650099915404377420203417011695963084742503430897569811042552155208487972", + ) + .unwrap(); + s_constants[165] = Fr::from_str_vartime( + "10307617695590426797520999316292503894130404130453293663650538793774250723792", + ) + .unwrap(); + s_constants[166] = Fr::from_str_vartime( + "8835502107624355497501451075768318888448783969087607217992442118675676473235", + ) + .unwrap(); + s_constants[167] = Fr::from_str_vartime( + "19120067314041132936628146578356142975011085061134316893491148167766430272263", + ) + .unwrap(); + s_constants[168] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[169] = Fr::from_str_vartime( + "14131158550284047904306566770309132813679338145017696511713416041803712831947", + ) + .unwrap(); + s_constants[170] = Fr::from_str_vartime( + "18278505503803771900469477275449664281120609236542416293497549235136781566441", + ) + .unwrap(); + s_constants[171] = Fr::from_str_vartime( + "17153958308999151990078644296244213778962356073179462336659818419962234105847", + ) + .unwrap(); + s_constants[172] = Fr::from_str_vartime( + "16626758607046130451896378742113613353140534310327816824141377148817543345317", + ) + .unwrap(); + s_constants[173] = Fr::from_str_vartime( + "3253978674468876751813289588828587424582893573659628257653601068985274811195", + ) + .unwrap(); + s_constants[174] = Fr::from_str_vartime( + "15124684821333452470068683925631859150599113099371600515189799092190905862045", + ) + .unwrap(); + s_constants[175] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[176] = Fr::from_str_vartime( + "17554798861971373266763024346102515996719053781651720018946226608652696029966", + ) + .unwrap(); + s_constants[177] = Fr::from_str_vartime( + "4673377481212178482442054929782481181148885179378220577674849430151263814812", + ) + .unwrap(); + s_constants[178] = Fr::from_str_vartime( + "12802184117569856558550257245216015988375556783492060695287038701794605413493", + ) + .unwrap(); + s_constants[179] = Fr::from_str_vartime( + "9519514614359898302883682133832551410294990399516042521409471023087274168403", + ) + .unwrap(); + s_constants[180] = Fr::from_str_vartime( + "16836659443451056297630548550595506972721716824013972318987309735084892491057", + ) + .unwrap(); + s_constants[181] = Fr::from_str_vartime( + "7395214083924359580241425985340483333597901523044123868756997584036793198254", + ) + .unwrap(); + s_constants[182] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[183] = Fr::from_str_vartime( + "14399322858803900772257678181955451734179272552912056546775770413858440530384", + ) + .unwrap(); + s_constants[184] = Fr::from_str_vartime( + "1909978450171978853529623580362647076357052571231552147289256161279685882392", + ) + .unwrap(); + s_constants[185] = Fr::from_str_vartime( + "13281885756205124109513999931355079980393369422935519271174043924199138273390", + ) + .unwrap(); + s_constants[186] = Fr::from_str_vartime( + "164209740719129725777909013206421786172977937257506729867551471718043494039", + ) + .unwrap(); + s_constants[187] = Fr::from_str_vartime( + "16705691420580567376788433299746618119784690539139871305988345805972046012457", + ) + .unwrap(); + s_constants[188] = Fr::from_str_vartime( + "5826800399196629549123275187565614318381497389323145097682684583838285855788", + ) + .unwrap(); + s_constants[189] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[190] = Fr::from_str_vartime( + "8745700306539329869259196731866071878870577472742983713396535761464344570296", + ) + .unwrap(); + s_constants[191] = Fr::from_str_vartime( + "508475125028636547085017721909144447367158867634347790363605834249994548305", + ) + .unwrap(); + s_constants[192] = Fr::from_str_vartime( + "13308065070657129846765808536411368840800238227915085241160671109842614736069", + ) + .unwrap(); + s_constants[193] = Fr::from_str_vartime( + "10019712566526881174916627302365233202635409302600998712624311257405295555967", + ) + .unwrap(); + s_constants[194] = Fr::from_str_vartime( + "14948048658262145603596652021141019702423717894287496732011428902097682702613", + ) + .unwrap(); + s_constants[195] = Fr::from_str_vartime( + "15039086326216274046991605161343057988750627388067276180888219462568845064229", + ) + .unwrap(); + s_constants[196] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[197] = Fr::from_str_vartime( + "21096491705236217573638753819195066035854753372393176304524423503032224425998", + ) + .unwrap(); + s_constants[198] = Fr::from_str_vartime( + "20540136431631199250453995588480387143164544354370046506703506396812372935282", + ) + .unwrap(); + s_constants[199] = Fr::from_str_vartime( + "21186849459525281586750729801174049327027230971997759985511944731378352524720", + ) + .unwrap(); + s_constants[200] = Fr::from_str_vartime( + "6848121885117228161216817594905430814981258429233967407187604355908721328558", + ) + .unwrap(); + s_constants[201] = Fr::from_str_vartime( + "13037575047232910005715065472416622419305037510557664085418549453156900385456", + ) + .unwrap(); + s_constants[202] = Fr::from_str_vartime( + "17833625863119365031315208055152981164942897924758710427636399886811449556740", + ) + .unwrap(); + s_constants[203] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[204] = Fr::from_str_vartime( + "647623368236351122220409431799139859876095524525221664162752495435482065515", + ) + .unwrap(); + s_constants[205] = Fr::from_str_vartime( + "12974365649211231492520765559798270821958589291536737829547558404742935791527", + ) + .unwrap(); + s_constants[206] = Fr::from_str_vartime( + "15547534600512764170410743968922508315745715132682752278457116429781298799438", + ) + .unwrap(); + s_constants[207] = Fr::from_str_vartime( + "20584726236425418677723102941610547182735385166462720350906478152233407640408", + ) + .unwrap(); + s_constants[208] = Fr::from_str_vartime( + "14300225354615797067692544691787701642123233971394030871903066287215191118747", + ) + .unwrap(); + s_constants[209] = Fr::from_str_vartime( + "16295678001265781880580526410222599033811623386008655132827551618100838695276", + ) + .unwrap(); + s_constants[210] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[211] = Fr::from_str_vartime( + "20381043379079252254800770843787089884660790822955671220847236480297529336205", + ) + .unwrap(); + s_constants[212] = Fr::from_str_vartime( + "9108894275082870067933192903079574663897324502580109505768620424181024287163", + ) + .unwrap(); + s_constants[213] = Fr::from_str_vartime( + "5680820607864330888516377287072858105818590744368374152569440046457757684320", + ) + .unwrap(); + s_constants[214] = Fr::from_str_vartime( + "11053473350105919249170169199500210854013326531260083017794490958609880379672", + ) + .unwrap(); + s_constants[215] = Fr::from_str_vartime( + "12769075511883530146865321202033588214490414269703513464106497906236932124198", + ) + .unwrap(); + s_constants[216] = Fr::from_str_vartime( + "18759973693942567196361351599844723429910867650807109887961315229008339652628", + ) + .unwrap(); + s_constants[217] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[218] = Fr::from_str_vartime( + "16425700741812211675363235647687005029399366301071410733155116166884856887679", + ) + .unwrap(); + s_constants[219] = Fr::from_str_vartime( + "19869702808216677847758761872487163621387473209265033304520824036210441934818", + ) + .unwrap(); + s_constants[220] = Fr::from_str_vartime( + "14073988039965881048079447010526118226047246598254103612590470558684258186244", + ) + .unwrap(); + s_constants[221] = Fr::from_str_vartime( + "886202035735213563046862324816018035210995137716997070920200120700003967134", + ) + .unwrap(); + s_constants[222] = Fr::from_str_vartime( + "12027565694895224474791802234109034039772984880014776210441706322417559146489", + ) + .unwrap(); + s_constants[223] = Fr::from_str_vartime( + "11972498202326440163586176809543524758264680802074662372615568024949824595702", + ) + .unwrap(); + s_constants[224] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[225] = Fr::from_str_vartime( + "1348630117144789003644452314839072329750068133934739562703659359268389747985", + ) + .unwrap(); + s_constants[226] = Fr::from_str_vartime( + "1396107425439796908939750972938223221605778648225762567016308314789520339962", + ) + .unwrap(); + s_constants[227] = Fr::from_str_vartime( + "6173001858003427802042546706782122098835769939275305980271183297728965316942", + ) + .unwrap(); + s_constants[228] = Fr::from_str_vartime( + "16943717877001499284920880255048707490719574351604140426529143119277836403129", + ) + .unwrap(); + s_constants[229] = Fr::from_str_vartime( + "14254637476176032842487152448677962929592936990526843481247886860454775633326", + ) + .unwrap(); + s_constants[230] = Fr::from_str_vartime( + "20112551263640702643495202387764478482489841288043250651308711396213637765954", + ) + .unwrap(); + s_constants[231] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[232] = Fr::from_str_vartime( + "14580210729080456657697439135745213807214996922877431278225104041221322283144", + ) + .unwrap(); + s_constants[233] = Fr::from_str_vartime( + "17944065522218783686971981171223808953317623885825040885897493399216933397441", + ) + .unwrap(); + s_constants[234] = Fr::from_str_vartime( + "21672476111949246523929453701335722206799241314728447223788259504904156987147", + ) + .unwrap(); + s_constants[235] = Fr::from_str_vartime( + "16427849329831493218262402566840933522542577642557896988530799384419530862522", + ) + .unwrap(); + s_constants[236] = Fr::from_str_vartime( + "10752733058291453323011452726707429118120906743416692984681703374550581513882", + ) + .unwrap(); + s_constants[237] = Fr::from_str_vartime( + "1120153114481280927826334009363750761062539786064908406397864613779304433308", + ) + .unwrap(); + s_constants[238] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[239] = Fr::from_str_vartime( + "6657045611436002337943867733574742655960423094099745811786819937865742754593", + ) + .unwrap(); + s_constants[240] = Fr::from_str_vartime( + "4548688566209049346950516871294343401334051071109430534058854346117866744739", + ) + .unwrap(); + s_constants[241] = Fr::from_str_vartime( + "12004873649650240122663793814044887628092046288070805572287428956807094282568", + ) + .unwrap(); + s_constants[242] = Fr::from_str_vartime( + "10376720357183386406622952185756280165877227546938927619561389051210153106592", + ) + .unwrap(); + s_constants[243] = Fr::from_str_vartime( + "17932525558731721856340352992169746291760530992792261472641282908501604446811", + ) + .unwrap(); + s_constants[244] = Fr::from_str_vartime( + "17590757077464321402178239743669088074723578712251925458853962272816312109152", + ) + .unwrap(); + s_constants[245] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[246] = Fr::from_str_vartime( + "3209081991282167870383195969354868449640899668458993044016055038297543518657", + ) + .unwrap(); + s_constants[247] = Fr::from_str_vartime( + "5864786650128394026837230220022650012182783025931675255391916679281913080366", + ) + .unwrap(); + s_constants[248] = Fr::from_str_vartime( + "12439377586247860055183624555830288546667346442629775929405362799390541279515", + ) + .unwrap(); + s_constants[249] = Fr::from_str_vartime( + "20249169533694211243074917072193953326307543430194777911574824077740409867889", + ) + .unwrap(); + s_constants[250] = Fr::from_str_vartime( + "11955292991025510476129504480910338468553857092582960824101774602100105865508", + ) + .unwrap(); + s_constants[251] = Fr::from_str_vartime( + "21233753658809258463246874948160331522087646774375604829374717282611108497353", + ) + .unwrap(); + s_constants[252] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[253] = Fr::from_str_vartime( + "5299619631018824922731916064083443097684549422797706633258895684420281864108", + ) + .unwrap(); + s_constants[254] = Fr::from_str_vartime( + "16213823392220550809755333072267867447553466481133861809088541225502993792933", + ) + .unwrap(); + s_constants[255] = Fr::from_str_vartime( + "21774021022385158712853171484065240472428767308361650780051834129571232443113", + ) + .unwrap(); + s_constants[256] = Fr::from_str_vartime( + "19519712983460247626783700627305949599146930344376818640048505866722051236075", + ) + .unwrap(); + s_constants[257] = Fr::from_str_vartime( + "19201631020677948940033345574241839698570728570677190746232685184366085684755", + ) + .unwrap(); + s_constants[258] = Fr::from_str_vartime( + "16950719963293537936274035069294977251884656006132028465274842882566872316866", + ) + .unwrap(); + s_constants[259] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[260] = Fr::from_str_vartime( + "19155409025424437690664522806909434551970754598652921692474864449826455337216", + ) + .unwrap(); + s_constants[261] = Fr::from_str_vartime( + "7680332789706498740282955823359712103361665361365018131178757219206780037124", + ) + .unwrap(); + s_constants[262] = Fr::from_str_vartime( + "21076561076080209150759527181245666654056099483239360146471339739637030537201", + ) + .unwrap(); + s_constants[263] = Fr::from_str_vartime( + "497501917138640900716963445320097032971939272734057482481699619406679852072", + ) + .unwrap(); + s_constants[264] = Fr::from_str_vartime( + "219804352410528064548663406794875692377819157777555527292379890517994310898", + ) + .unwrap(); + s_constants[265] = Fr::from_str_vartime( + "20650062109272119754567889432541551183228545711882667368558930819623066285550", + ) + .unwrap(); + s_constants[266] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[267] = Fr::from_str_vartime( + "11946781549111733342374437686417901919881339755720725189559112628795817706603", + ) + .unwrap(); + s_constants[268] = Fr::from_str_vartime( + "2484460820642436269798549252737235980435448156526237726927772714161779556117", + ) + .unwrap(); + s_constants[269] = Fr::from_str_vartime( + "9131896045016416748829978568219748930005109068654516264093181558753767987250", + ) + .unwrap(); + s_constants[270] = Fr::from_str_vartime( + "17539690836656056361902215257263592451628414553660709391600001441653830206065", + ) + .unwrap(); + s_constants[271] = Fr::from_str_vartime( + "18680327085533119384849399232368527875194911756927197995064579410845089235626", + ) + .unwrap(); + s_constants[272] = Fr::from_str_vartime( + "3733704884118300721043768874060062456481930803626613247865795986430463043840", + ) + .unwrap(); + s_constants[273] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[274] = Fr::from_str_vartime( + "10869324612517034722196547288387911568763853980957190569709459262556333259802", + ) + .unwrap(); + s_constants[275] = Fr::from_str_vartime( + "13541129633400691168270375425224652251629428845905913714872674429516061703834", + ) + .unwrap(); + s_constants[276] = Fr::from_str_vartime( + "19566585716231282658157065399746041623123586124594568018338142400023247847175", + ) + .unwrap(); + s_constants[277] = Fr::from_str_vartime( + "11129427786234676461186088751699468257665219195861018218716326589482169235738", + ) + .unwrap(); + s_constants[278] = Fr::from_str_vartime( + "12587809912397784737743829505557561200040529463438352967575388905004140998345", + ) + .unwrap(); + s_constants[279] = Fr::from_str_vartime( + "19808473521007223175388701036440740142351657866781216113100022591252318502799", + ) + .unwrap(); + s_constants[280] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[281] = Fr::from_str_vartime( + "5873853271511157388891218086625116841039294307138994311967890057520246823262", + ) + .unwrap(); + s_constants[282] = Fr::from_str_vartime( + "13003486326245606952057355171036271201855738149044785151305974666902939676968", + ) + .unwrap(); + s_constants[283] = Fr::from_str_vartime( + "317822617317373237216981618014479686465697065761329030109475447686164721451", + ) + .unwrap(); + s_constants[284] = Fr::from_str_vartime( + "10813741057848680550002438472132336318708520104631920434881565279665858338767", + ) + .unwrap(); + s_constants[285] = Fr::from_str_vartime( + "1407947600055243217568670010193019554033099296398850283939346444151815545565", + ) + .unwrap(); + s_constants[286] = Fr::from_str_vartime( + "10748165363652029592490593406190797442361550791106744394554436667603982640562", + ) + .unwrap(); + s_constants[287] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[288] = Fr::from_str_vartime( + "3799831132390157900444549796610450353874750090914089848349537541361771448668", + ) + .unwrap(); + s_constants[289] = Fr::from_str_vartime( + "1236474870532132985977600728058617189131963342170879994970972386547660462416", + ) + .unwrap(); + s_constants[290] = Fr::from_str_vartime( + "12129114991304316197801712028291571747667685822200300686411158807713612068935", + ) + .unwrap(); + s_constants[291] = Fr::from_str_vartime( + "12452782504819389866332384374641397209636135503933026692197899235338769218420", + ) + .unwrap(); + s_constants[292] = Fr::from_str_vartime( + "17177375615846222421363183777625422826542711334348976790999247784204226247153", + ) + .unwrap(); + s_constants[293] = Fr::from_str_vartime( + "14724993254182752446999797852163908134432351958415665363281656992462126774682", + ) + .unwrap(); + s_constants[294] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[295] = Fr::from_str_vartime( + "5334385037080506459192079464304402035717161708938461991741391759156701759962", + ) + .unwrap(); + s_constants[296] = Fr::from_str_vartime( + "5839603057106324284245920895643629522252067410986057849259994788753287208289", + ) + .unwrap(); + s_constants[297] = Fr::from_str_vartime( + "14326608902192980988016963288619186073396385273801977982209424374836032185437", + ) + .unwrap(); + s_constants[298] = Fr::from_str_vartime( + "3833013442414862082598619907743002206819313202476167703686360031484342083849", + ) + .unwrap(); + s_constants[299] = Fr::from_str_vartime( + "5782627886836397242604493658841762433123584410931373681442076300374639175204", + ) + .unwrap(); + s_constants[300] = Fr::from_str_vartime( + "19713051315944380534324352563108780835417447391745041989823306798607010582122", + ) + .unwrap(); + s_constants[301] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[302] = Fr::from_str_vartime( + "18432899792379962331910523191119990280606783016109716227581834102469679493864", + ) + .unwrap(); + s_constants[303] = Fr::from_str_vartime( + "10114179315138932736747722408239325460537042542506605453447755151962569740761", + ) + .unwrap(); + s_constants[304] = Fr::from_str_vartime( + "5821210875734924302116104693653963583724566141160222647210211530317113743846", + ) + .unwrap(); + s_constants[305] = Fr::from_str_vartime( + "7272434816631750120284299385293876240257916908609412315349255596053274406936", + ) + .unwrap(); + s_constants[306] = Fr::from_str_vartime( + "4212296281436173015983236952207520516627835095278776445938770899997037368424", + ) + .unwrap(); + s_constants[307] = Fr::from_str_vartime( + "6955140567497387214231321978484207887660637811874868846921238176118501620416", + ) + .unwrap(); + s_constants[308] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[309] = Fr::from_str_vartime( + "16897957031536287824842741409118604269531477953952068130977839056875990315078", + ) + .unwrap(); + s_constants[310] = Fr::from_str_vartime( + "13928891481908488754724298520914059676632551457225054691072093686516662594704", + ) + .unwrap(); + s_constants[311] = Fr::from_str_vartime( + "18609207589312797911981956932131451830029990404869237009695385065926468947990", + ) + .unwrap(); + s_constants[312] = Fr::from_str_vartime( + "5536380863513150280191401661180648941427892275212253324640352848339521760494", + ) + .unwrap(); + s_constants[313] = Fr::from_str_vartime( + "5599225957062546984064803248700291456577900100660883438352062938121375670876", + ) + .unwrap(); + s_constants[314] = Fr::from_str_vartime( + "12727467597196655197125834858597394259624613129696376281662301390743901689826", + ) + .unwrap(); + s_constants[315] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[316] = Fr::from_str_vartime( + "19163832296523160821274196616772872907137958231822436470531902352232904941115", + ) + .unwrap(); + s_constants[317] = Fr::from_str_vartime( + "10312950311908120735753698174433012744274520178660214256070764297181492311529", + ) + .unwrap(); + s_constants[318] = Fr::from_str_vartime( + "20378282857854630279466471430783739929226973027333858163427244408490964366943", + ) + .unwrap(); + s_constants[319] = Fr::from_str_vartime( + "10377180064239448654317729091272064413356995963412409612959212677629982453181", + ) + .unwrap(); + s_constants[320] = Fr::from_str_vartime( + "2933414924716564156600257176308187931324021696634706744075039747567264729208", + ) + .unwrap(); + s_constants[321] = Fr::from_str_vartime( + "8493086687568016258498608482327521077256426060613869678446606139457160557731", + ) + .unwrap(); + s_constants[322] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[323] = Fr::from_str_vartime( + "19381450024835411599145851239904096365633900646004460102189421850759351066697", + ) + .unwrap(); + s_constants[324] = Fr::from_str_vartime( + "11953019744947469552190875928518181787128546459454153390773097887154577772396", + ) + .unwrap(); + s_constants[325] = Fr::from_str_vartime( + "13376491371023193271031127665379748375688991534278974638471913598784726444357", + ) + .unwrap(); + s_constants[326] = Fr::from_str_vartime( + "7542871725069391080270213343389444722683777408103033554143042828340526643887", + ) + .unwrap(); + s_constants[327] = Fr::from_str_vartime( + "9502363618190826927264503377951186073033660324604374823531489866751694300021", + ) + .unwrap(); + s_constants[328] = Fr::from_str_vartime( + "8942475100033900568271185100922618012810524607209352225513012701802010622336", + ) + .unwrap(); + s_constants[329] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[330] = Fr::from_str_vartime( + "21672484879307704998081070986668301291593477229230485880081317733634466423656", + ) + .unwrap(); + s_constants[331] = Fr::from_str_vartime( + "12560411374852110641761658167591216057124945743772728716943960683160724056822", + ) + .unwrap(); + s_constants[332] = Fr::from_str_vartime( + "3722997355103511782752507300407310792223403249171458092438045493962181025019", + ) + .unwrap(); + s_constants[333] = Fr::from_str_vartime( + "14433522510308019912373989177241241296955315520711007204668297246004835289367", + ) + .unwrap(); + s_constants[334] = Fr::from_str_vartime( + "21074332145955362315628041254977693445345960799533333435986322886475303250112", + ) + .unwrap(); + s_constants[335] = Fr::from_str_vartime( + "11688037814420019994761430124416432916208455640936309232737398596294520128684", + ) + .unwrap(); + s_constants[336] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[337] = Fr::from_str_vartime( + "8413591227751150541157599965184931267423827079669402000298235589329872211968", + ) + .unwrap(); + s_constants[338] = Fr::from_str_vartime( + "17650123658569960265162949890832225475263279247059954604797491790529432356321", + ) + .unwrap(); + s_constants[339] = Fr::from_str_vartime( + "7032368326020336746840339437615845824739080336621780283569419873917360702928", + ) + .unwrap(); + s_constants[340] = Fr::from_str_vartime( + "7385147306527643945794759599270778258162448657029306136967713046400437047254", + ) + .unwrap(); + s_constants[341] = Fr::from_str_vartime( + "9164511581583407790134635624183479582650863721435788581639986518157210097971", + ) + .unwrap(); + s_constants[342] = Fr::from_str_vartime( + "21232697956642675538653913718380508229639927919821094050264990131998515480363", + ) + .unwrap(); + s_constants[343] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[344] = Fr::from_str_vartime( + "18766563503966172098056598342132389632908065386663557822565991028183540018003", + ) + .unwrap(); + s_constants[345] = Fr::from_str_vartime( + "19588227650050881742478712753831458567447756852853785637599026881217455808917", + ) + .unwrap(); + s_constants[346] = Fr::from_str_vartime( + "1397562335684000327360763239099474090628194083907387149001776134346855210172", + ) + .unwrap(); + s_constants[347] = Fr::from_str_vartime( + "10198846647447159506242448434572704392281982267842998844531477628631237977793", + ) + .unwrap(); + s_constants[348] = Fr::from_str_vartime( + "4082126476185956308289516001173247963427942564076732012191115788827109604670", + ) + .unwrap(); + s_constants[349] = Fr::from_str_vartime( + "1259882007354573001457197686554861546488356012943826286439775962762529569759", + ) + .unwrap(); + s_constants[350] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[351] = Fr::from_str_vartime( + "7716815769035341534093079824074304698185682494514188549310576878173077130022", + ) + .unwrap(); + s_constants[352] = Fr::from_str_vartime( + "2044076383384167496824768664485547753134864604656664348421025061131743608977", + ) + .unwrap(); + s_constants[353] = Fr::from_str_vartime( + "7774223140652128981941948651155326068745393941932597512012824767919719875428", + ) + .unwrap(); + s_constants[354] = Fr::from_str_vartime( + "6679985805196174386295848216686508579276442390463151307353623646770660788584", + ) + .unwrap(); + s_constants[355] = Fr::from_str_vartime( + "6774793209384233535964197412993868564894958211307656732015443437790617825766", + ) + .unwrap(); + s_constants[356] = Fr::from_str_vartime( + "17867078843395024616403441485600115396944676013587205981831608189485186004136", + ) + .unwrap(); + s_constants[357] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[358] = Fr::from_str_vartime( + "6918083713687670289412597323877415882006094844653186686554461196053948517650", + ) + .unwrap(); + s_constants[359] = Fr::from_str_vartime( + "14794244995142016109988120927552904368673513765173156992855465350554201454520", + ) + .unwrap(); + s_constants[360] = Fr::from_str_vartime( + "9469895491505210921132335959822444547950761948532088884408658386318765611458", + ) + .unwrap(); + s_constants[361] = Fr::from_str_vartime( + "12410499443680346161671381257661336704947211959564338473797332912666796028788", + ) + .unwrap(); + s_constants[362] = Fr::from_str_vartime( + "7926578664199378339557308917160770386201454695092254922901982085502190339711", + ) + .unwrap(); + s_constants[363] = Fr::from_str_vartime( + "1074389802911575405482398726791994815320889352331411931514923735327800497648", + ) + .unwrap(); + s_constants[364] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[365] = Fr::from_str_vartime( + "12660721219055881159942064421460786460560697520809352389013840987393603997135", + ) + .unwrap(); + s_constants[366] = Fr::from_str_vartime( + "4257759001257681685309102971805195284424999843809187868418076529498991787195", + ) + .unwrap(); + s_constants[367] = Fr::from_str_vartime( + "8970798405382398224814171740357247330369162836256360293947332566119181156885", + ) + .unwrap(); + s_constants[368] = Fr::from_str_vartime( + "17958544420119383745643163073564878224834088412686597346123856987725643531187", + ) + .unwrap(); + s_constants[369] = Fr::from_str_vartime( + "17738189036503307406862818984242172707709553320980438963253190315183389070671", + ) + .unwrap(); + s_constants[370] = Fr::from_str_vartime( + "14287766641051399433873731520879849723607926081596701974021064214044740995654", + ) + .unwrap(); + s_constants[371] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[372] = Fr::from_str_vartime( + "21558827418411379216994978187086694912014548431326761389965315489378942066021", + ) + .unwrap(); + s_constants[373] = Fr::from_str_vartime( + "7136882485367499209618511242521887384194879969153189708025876500490677483273", + ) + .unwrap(); + s_constants[374] = Fr::from_str_vartime( + "17220467566610801825959292161481147144970669500227722755203417787632930011521", + ) + .unwrap(); + s_constants[375] = Fr::from_str_vartime( + "15644351871844947578414272909094033689340289967910075614127700893758848906931", + ) + .unwrap(); + s_constants[376] = Fr::from_str_vartime( + "21741724266010931381264164854372691714176988715532516896804407315923532276434", + ) + .unwrap(); + s_constants[377] = Fr::from_str_vartime( + "2419785684404332928492315984637322970326738862445167379156610994774664059995", + ) + .unwrap(); + s_constants[378] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[379] = Fr::from_str_vartime( + "10339805366850086548361875185109456315271528882904249869004576409152632926693", + ) + .unwrap(); + s_constants[380] = Fr::from_str_vartime( + "19066576437237017989921605377017982206044010175904765960860923934443601514592", + ) + .unwrap(); + s_constants[381] = Fr::from_str_vartime( + "13822379132369217064164395859669265238386142106084498781870935216496751999075", + ) + .unwrap(); + s_constants[382] = Fr::from_str_vartime( + "21216485273531618687167053274106121432450196094331038082541464436433083018343", + ) + .unwrap(); + s_constants[383] = Fr::from_str_vartime( + "1540326880060266517508750499666125605454874001382251434794459985013783734049", + ) + .unwrap(); + s_constants[384] = Fr::from_str_vartime( + "10979571635040509905158742852019305039752888804051338348133671756054719250675", + ) + .unwrap(); + s_constants[385] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + s_constants[386] = Fr::from_str_vartime( + "17817950236968355275450565661453279500832679749582869473068209804712565393928", + ) + .unwrap(); + s_constants[387] = Fr::from_str_vartime( + "4057227004326267443894866444790295439173752231112985308059870347643133047427", + ) + .unwrap(); + s_constants[388] = Fr::from_str_vartime( + "9481547255077304194865834384522710415757401332737060279379100936057225542025", + ) + .unwrap(); + s_constants[389] = Fr::from_str_vartime( + "19204974983793400699898444372535256207646557857575315905278218870961389967884", + ) + .unwrap(); + s_constants[390] = Fr::from_str_vartime( + "14672613178263529785795301930884172260797190868602674472542654261498546023746", + ) + .unwrap(); + s_constants[391] = Fr::from_str_vartime( + "21407770160218607278833379114951608489910182969042472165261557405353704846967", + ) + .unwrap(); + + s_constants +} + +fn load_m_matrix() -> Vec> { + let mut m_matrix = vec![vec![Fr::ZERO; 4]; 4]; + + m_matrix[0][0] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + m_matrix[0][1] = Fr::from_str_vartime( + "19204974983793400699898444372535256207646557857575315905278218870961389967884", + ) + .unwrap(); + m_matrix[0][2] = Fr::from_str_vartime( + "14672613178263529785795301930884172260797190868602674472542654261498546023746", + ) + .unwrap(); + m_matrix[0][3] = Fr::from_str_vartime( + "21407770160218607278833379114951608489910182969042472165261557405353704846967", + ) + .unwrap(); + m_matrix[1][0] = Fr::from_str_vartime( + "17849615858846139011678879517964683507928512741474025695659909954675835121177", + ) + .unwrap(); + m_matrix[1][1] = Fr::from_str_vartime( + "3722304780857845144568029505892077496425786544014166938942516810831732569870", + ) + .unwrap(); + m_matrix[1][2] = Fr::from_str_vartime( + "20850178060552184587113773087797340350525370429749200838012809627359404457643", + ) + .unwrap(); + m_matrix[1][3] = Fr::from_str_vartime( + "16058955581309173858487265533260133430557379878452348481750737813742488209262", + ) + .unwrap(); + m_matrix[2][0] = Fr::from_str_vartime( + "1013663139540921998616312712475594638459213772728467613870351821911056489570", + ) + .unwrap(); + m_matrix[2][1] = Fr::from_str_vartime( + "11920634922168932145084219049241528148129057802067880076377897257847125830511", + ) + .unwrap(); + m_matrix[2][2] = Fr::from_str_vartime( + "7082289538076771741936674361200789891432311337766695368327626572220036527624", + ) + .unwrap(); + m_matrix[2][3] = Fr::from_str_vartime( + "593311177550138061601452020934455734040559402531605836278498327468203888086", + ) + .unwrap(); + m_matrix[3][0] = Fr::from_str_vartime( + "13211800058103802189838759488224684841774731021206389709687693993627918500545", + ) + .unwrap(); + m_matrix[3][1] = Fr::from_str_vartime( + "6085682566123812000257211683010755099394491689511511633947011263229442977967", + ) + .unwrap(); + m_matrix[3][2] = Fr::from_str_vartime( + "1787876543469562003404632310460227730887431311758627706450615128255538398187", + ) + .unwrap(); + m_matrix[3][3] = Fr::from_str_vartime( + "341662423637860635938968460722645910313598807845686354625820505885069260074", + ) + .unwrap(); + + m_matrix +} + +fn load_p_matrix() -> Vec> { + let mut p_matrix = vec![vec![Fr::ZERO; 4]; 4]; + + p_matrix[0][0] = Fr::from_str_vartime( + "16023668707004248971294664614290028914393192768609916554276071736843535714477", + ) + .unwrap(); + p_matrix[0][1] = Fr::from_str_vartime( + "1219730950550419355108306775069417768387360853368230473071077119306046675572", + ) + .unwrap(); + p_matrix[0][2] = Fr::from_str_vartime( + "15510244717642334318966561950951002886323209693558586261457615423770062424603", + ) + .unwrap(); + p_matrix[0][3] = Fr::from_str_vartime( + "11219946567517274434615160614700308041943360069146893241486574665265822013129", + ) + .unwrap(); + p_matrix[1][0] = Fr::from_str_vartime( + "17849615858846139011678879517964683507928512741474025695659909954675835121177", + ) + .unwrap(); + p_matrix[1][1] = Fr::from_str_vartime( + "17895496371927328657913965415733510282704230821151428152183928968046205671575", + ) + .unwrap(); + p_matrix[1][2] = Fr::from_str_vartime( + "12435993608134323226059776526130103965669300982573338632451717852485169465950", + ) + .unwrap(); + p_matrix[1][3] = Fr::from_str_vartime( + "19939917978926080723093316474977996505935743392066675936804030819065420290084", + ) + .unwrap(); + p_matrix[2][0] = Fr::from_str_vartime( + "1013663139540921998616312712475594638459213772728467613870351821911056489570", + ) + .unwrap(); + p_matrix[2][1] = Fr::from_str_vartime( + "1028374094780216331619466080637054051304375033009771928288419347940821888279", + ) + .unwrap(); + p_matrix[2][2] = Fr::from_str_vartime( + "5643605551164490740833629634586387123466682387363311974272188018328439695366", + ) + .unwrap(); + p_matrix[2][3] = Fr::from_str_vartime( + "3961412593815053600853163531157674011892719679065160984658051723455387746952", + ) + .unwrap(); + p_matrix[3][0] = Fr::from_str_vartime( + "13211800058103802189838759488224684841774731021206389709687693993627918500545", + ) + .unwrap(); + p_matrix[3][1] = Fr::from_str_vartime( + "16436452107226347557423995353975118393704571960279031780622882419612847031696", + ) + .unwrap(); + p_matrix[3][2] = Fr::from_str_vartime( + "11841890240732656097844244837012648335708695431011214021127380678644769978309", + ) + .unwrap(); + p_matrix[3][3] = Fr::from_str_vartime( + "10936049757440664316304266313740303505981633272820388610540392640560764966725", + ) + .unwrap(); + + p_matrix +} diff --git a/codex-plonky2-circuits/src/bn254_wrapper/wrap.rs b/codex-plonky2-circuits/src/bn254_wrapper/wrap.rs new file mode 100644 index 0000000..c985cf6 --- /dev/null +++ b/codex-plonky2-circuits/src/bn254_wrapper/wrap.rs @@ -0,0 +1,223 @@ +use std::fs::{self, File}; +use std::marker::PhantomData; +use std::path::Path; +use plonky2::hash::hash_types::RichField; +use plonky2::iop::witness::{PartialWitness, WitnessWrite}; +use plonky2::plonk::circuit_builder::CircuitBuilder; +use plonky2::plonk::circuit_data::{CommonCircuitData, VerifierCircuitData, VerifierOnlyCircuitData}; +use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; +use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; +use plonky2_field::extension::Extendable; +use serde::Serialize; +use plonky2_poseidon2::Poseidon2; +use crate::circuit_helper::Plonky2Circuit; +use crate::error::CircuitError; + +/// Wrap circuit - wraps the plonky2 proof with +/// InnerParameters: Config params for the inner proof - this is the default config +/// OuterParameters: Config params for the outer proof - this is the bn254 config +#[derive(Debug)] +pub struct WrapCircuit< + F: RichField + Extendable + Poseidon2, + const D: usize, + InnerParameters: GenericConfig, + OuterParameters: GenericConfig, +> { + inner_verifier_data: VerifierCircuitData, + phantom_data: PhantomData +} + +#[derive(Clone, Debug)] +pub struct WrapTargets< + const D: usize, +>{ + pub inner_proof: ProofWithPublicInputsTarget, +} + +#[derive(Clone, Debug)] +pub struct WrapInput< + F: RichField + Extendable + Poseidon2, + const D: usize, + InnerParameters: GenericConfig, +>{ + pub inner_proof: ProofWithPublicInputs +} + +impl< + F: RichField + Extendable + Poseidon2, + const D: usize, + InnerParameters: GenericConfig, + OuterParameters: GenericConfig, + > Plonky2Circuit for WrapCircuit + where + >::Hasher: AlgebraicHasher +{ + type Targets = WrapTargets; + type Input = WrapInput; + + fn add_targets(&self, builder: &mut CircuitBuilder, register_pi: bool) -> crate::Result { + let inner_common = self.inner_verifier_data.common.clone(); + + // the proof virtual targets + let vir_proof = builder.add_virtual_proof_with_pis(&inner_common); + // make inner public input into outer public input + if register_pi { + builder.register_public_inputs(&vir_proof.public_inputs); + } + + // constant target for the verifier data + let const_verifier_data = builder.constant_verifier_data(&self.inner_verifier_data.verifier_only); + + // verify the proofs in-circuit + builder.verify_proof::(&vir_proof, &const_verifier_data, &inner_common); + + Ok( + WrapTargets{ + inner_proof:vir_proof, + } + ) + } + + fn assign_targets(&self, pw: &mut PartialWitness, targets: &Self::Targets, input: &Self::Input) -> crate::Result<()> where + >::Hasher: AlgebraicHasher { + // assign the proof + pw.set_proof_with_pis_target(&targets.inner_proof, &input.inner_proof) + .map_err(|e| { + CircuitError::ProofTargetAssignmentError("inner-proof".to_string(), e.to_string()) + })?; + + Ok(()) + } +} + +impl< + F: RichField + Extendable + Poseidon2, + const D: usize, + InnerParameters: GenericConfig, + OuterParameters: GenericConfig, +> WrapCircuit +{ + pub fn new( + inner_verifier_data: VerifierCircuitData, + ) -> Self { + Self{ + inner_verifier_data, + phantom_data: Default::default(), + } + } +} + +#[derive(Debug)] +pub struct WrappedOutput< + F: RichField + Extendable + Poseidon2, + C: GenericConfig, + const D: usize +> { + pub proof: ProofWithPublicInputs, + pub common_data: CommonCircuitData, + pub verifier_data: VerifierOnlyCircuitData, +} + +impl< + F: RichField + Extendable + Poseidon2, + C: GenericConfig, + const D: usize +> WrappedOutput { + pub fn save>(&self, path: P) -> anyhow::Result<()> + where + C: Serialize, + { + if !path.as_ref().exists() { + fs::create_dir_all(&path)?; + } + let common_data_file = File::create(path.as_ref().join("common_circuit_data.json"))?; + serde_json::to_writer(&common_data_file, &self.common_data)?; + println!("Succesfully wrote common circuit data to common_circuit_data.json"); + + let verifier_data_file = + File::create(path.as_ref().join("verifier_only_circuit_data.json"))?; + serde_json::to_writer(&verifier_data_file, &self.verifier_data)?; + println!("Succesfully wrote verifier data to verifier_only_circuit_data.json"); + + let proof_file = File::create(path.as_ref().join("proof_with_public_inputs.json"))?; + serde_json::to_writer(&proof_file, &self.proof)?; + println!("Succesfully wrote proof to proof_with_public_inputs.json"); + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use plonky2::field::goldilocks_field::GoldilocksField; + use plonky2::field::types::Field; + use plonky2::gates::noop::NoopGate; + use plonky2::plonk::circuit_builder::CircuitBuilder; + use plonky2::plonk::circuit_data::CircuitConfig; + use plonky2::plonk::config::PoseidonGoldilocksConfig; + use crate::bn254_wrapper::config::PoseidonBN254GoldilocksConfig; + use super::*; + + #[test] + fn test_full_wrap() -> anyhow::Result<()>{ + const D: usize = 2; + + type F = GoldilocksField; + type InnerParameters = PoseidonGoldilocksConfig; + type OuterParameters = PoseidonBN254GoldilocksConfig; + + let build_path = "./verifier_data".to_string(); + let test_path = format!("{}/test_small/", build_path); + + let conf = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(conf); + + // let a = builder.add_virtual_public_input(); + // let b = builder.add_virtual_public_input(); + // let c = builder.add(a,b); + // builder.register_public_input(c); + for _ in 0..(4096+10) { + builder.add_gate(NoopGate, vec![]); + } + // Add one virtual public input so that the circuit has minimal structure. + let t = builder.add_virtual_public_input(); + + // Set up the dummy circuit and wrapper. + let dummy_circuit = builder.build::(); + let mut pw = PartialWitness::new(); + // pw.set_target(a, GoldilocksField::from_canonical_u64(1))?; + // pw.set_target(b, GoldilocksField::from_canonical_u64(2))?; + pw.set_target(t, F::ZERO).expect("faulty assign"); + println!( + "dummy circuit degree: {}", + dummy_circuit.common.degree_bits() + ); + let dummy_inner_proof = dummy_circuit.prove(pw).unwrap(); + assert!(dummy_circuit.verify(dummy_inner_proof.clone()).is_ok()); + println!("Verified dummy_circuit"); + + // wrap this in the outer circuit. + let wrapper = WrapCircuit::::new(dummy_circuit.verifier_data()); + let (targ, data) = wrapper.build_with_standard_config().unwrap(); + println!( + "wrapper circuit degree: {}", + data.common.degree_bits() + ); + let verifier_data = data.verifier_data(); + let prover_data = data.prover_data(); + let wrap_input = WrapInput{ + inner_proof: dummy_inner_proof, + }; + let proof = wrapper.prove(&targ, &wrap_input,&prover_data).unwrap(); + + let wrap_circ = WrappedOutput::{ + proof, + common_data: prover_data.common, + verifier_data: verifier_data.verifier_only, + }; + + wrap_circ.save(test_path).unwrap(); + println!("Saved test wrapped circuit"); + Ok(()) + } +} diff --git a/codex-plonky2-circuits/src/lib.rs b/codex-plonky2-circuits/src/lib.rs index e0dffed..4994186 100644 --- a/codex-plonky2-circuits/src/lib.rs +++ b/codex-plonky2-circuits/src/lib.rs @@ -3,5 +3,6 @@ pub mod recursion; pub mod error; pub mod circuit_helper; mod bundle; +pub mod bn254_wrapper; pub type Result = core::result::Result; diff --git a/codex-plonky2-circuits/src/recursion/leaf.rs b/codex-plonky2-circuits/src/recursion/leaf.rs index 738fd91..2887f5c 100644 --- a/codex-plonky2-circuits/src/recursion/leaf.rs +++ b/codex-plonky2-circuits/src/recursion/leaf.rs @@ -180,7 +180,7 @@ mod tests { use plonky2::plonk::config::GenericConfig; use plonky2_field::types::PrimeField64; use plonky2::plonk::circuit_data::{CircuitConfig, CommonCircuitData}; - use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash}; + use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2Hash; // For our tests, we define: const D: usize = 2; diff --git a/codex-plonky2-circuits/src/recursion/node.rs b/codex-plonky2-circuits/src/recursion/node.rs index 04b7009..6c3531b 100644 --- a/codex-plonky2-circuits/src/recursion/node.rs +++ b/codex-plonky2-circuits/src/recursion/node.rs @@ -260,7 +260,7 @@ mod tests { use plonky2::plonk::config::GenericConfig; use plonky2_field::types::{Field, PrimeField64}; use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData}; - use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash}; + use plonky2_poseidon2::poseidon2_hash::poseidon2:: Poseidon2Hash; use crate::recursion::leaf::BUCKET_SIZE; @@ -276,7 +276,7 @@ mod tests { let config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(config); let mut pub_input = vec![]; - for i in 0..9+B { + for _i in 0..9+B { pub_input.push(builder.add_virtual_public_input()); } let data = builder.build::(); diff --git a/codex-plonky2-circuits/src/recursion/tree.rs b/codex-plonky2-circuits/src/recursion/tree.rs index 91a785d..a49c0c5 100644 --- a/codex-plonky2-circuits/src/recursion/tree.rs +++ b/codex-plonky2-circuits/src/recursion/tree.rs @@ -307,7 +307,7 @@ mod tests { use plonky2::plonk::config::GenericConfig; use plonky2_field::types::Field; use plonky2::plonk::circuit_data::CircuitConfig; - use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash}; + use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2Hash; use plonky2::iop::witness::WitnessWrite; const D: usize = 2; diff --git a/codex-plonky2-circuits/src/recursion/utils.rs b/codex-plonky2-circuits/src/recursion/utils.rs index e090b4b..a55bef1 100644 --- a/codex-plonky2-circuits/src/recursion/utils.rs +++ b/codex-plonky2-circuits/src/recursion/utils.rs @@ -166,14 +166,13 @@ mod tests { use plonky2::plonk::config::GenericConfig; use plonky2_field::types::{Field, PrimeField64}; use plonky2::plonk::circuit_data::CircuitConfig; - use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash}; + // use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; use plonky2::iop::witness::PartialWitness; // For our tests, we define: const D: usize = 2; type C = PoseidonGoldilocksConfig; type F = >::F; - type H = Poseidon2Hash; // Helper: Build, prove, and return public inputs --- fn build_and_prove(builder: CircuitBuilder) -> Vec {