From 11d971fed893a3456b9fda61edbdd341fd95c7b3 Mon Sep 17 00:00:00 2001 From: topanisto Date: Thu, 15 Aug 2024 19:27:33 +0200 Subject: [PATCH 01/17] plonky3 changes --- plonky3/Cargo.toml | 9 +- plonky3/src/baby_bear.rs | 121 +++++++++++ plonky3/src/circuit_builder.rs | 56 ++--- plonky3/src/goldilocks.rs | 110 ++++++++++ plonky3/src/lib.rs | 3 + plonky3/src/params.rs | 126 +++-------- plonky3/src/stark.rs | 49 +++-- plonky3/src/stark_babybear.rs | 377 +++++++++++++++++++++++++++++++++ 8 files changed, 704 insertions(+), 147 deletions(-) create mode 100644 plonky3/src/baby_bear.rs create mode 100644 plonky3/src/goldilocks.rs create mode 100644 plonky3/src/stark_babybear.rs diff --git a/plonky3/Cargo.toml b/plonky3/Cargo.toml index 24a8cdca44..e60ce3976a 100644 --- a/plonky3/Cargo.toml +++ b/plonky3/Cargo.toml @@ -17,15 +17,20 @@ p3-air = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-star p3-matrix = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed" } p3-field = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed" } p3-uni-stark = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed" } -p3-commit = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed", features = ["test-utils"] } +p3-commit = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed", features = [ + "test-utils", +] } p3-poseidon2 = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed" } p3-poseidon = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed" } p3-fri = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed" } # We don't use p3-maybe-rayon directly, but it is a dependency of p3-uni-stark. # Activating the "parallel" feature gives us parallelism in the prover. -p3-maybe-rayon = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed", features = ["parallel"] } +p3-maybe-rayon = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed", features = [ + "parallel", +] } p3-mds = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed" } p3-merkle-tree = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed" } +p3-baby-bear = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed" } p3-goldilocks = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed" } p3-symmetric = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed" } p3-dft = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed" } diff --git a/plonky3/src/baby_bear.rs b/plonky3/src/baby_bear.rs new file mode 100644 index 0000000000..36537cae18 --- /dev/null +++ b/plonky3/src/baby_bear.rs @@ -0,0 +1,121 @@ +//! The concrete parameters used in the prover +//! Inspired from [this example](https://github.com/Plonky3/Plonky3/blob/6a1b0710fdf85136d0fdd645b92933615867740a/keccak-air/examples/prove_goldilocks_keccak.rs#L57) + +use lazy_static::lazy_static; + +use crate::params::FieldElementMap; +use p3_baby_bear::{BabyBear, DiffusionMatrixBabyBear, MdsMatrixBabyBear}; +use p3_challenger::DuplexChallenger; +use p3_commit::ExtensionMmcs; +use p3_dft::Radix2DitParallel; +use p3_field::{extension::BinomialExtensionField, Field}; +use p3_fri::{FriConfig, TwoAdicFriPcs}; +use p3_merkle_tree::FieldMerkleTreeMmcs; +use p3_poseidon2::{Poseidon2, Poseidon2ExternalMatrixGeneral}; +use p3_symmetric::{PaddingFreeSponge, TruncatedPermutation}; +use p3_uni_stark::StarkConfig; + +use rand::{distributions::Standard, Rng, SeedableRng}; + +use powdr_number::{BabyBearField, FieldElement}; + +const DEGREE: usize = 2; +type Challenge = BinomialExtensionField; + +const WIDTH: usize = 16; +const D: u64 = 7; +type Perm = Poseidon2; + +// const ROUNDS_F: usize = poseidon2_round_numbers_128::(WIDTH, D).0; +// const ROUNDS_P: usize = poseidon2_round_numbers_128::(WIDTH, D).1; + +// params directly taken from plonky3's poseidon2_round_numbers_128 function +// to guarentee 128-bit security. + +const ROUNDS_F: usize = 8; +const ROUNDS_P: usize = 13; + +const RATE: usize = 8; +const OUT: usize = 8; +type Hash = PaddingFreeSponge; + +const N: usize = 2; +const CHUNK: usize = 8; +type Compress = TruncatedPermutation; + +const DIGEST_ELEMS: usize = 8; +type ValMmcs = FieldMerkleTreeMmcs< + ::Packing, + ::Packing, + Hash, + Compress, + DIGEST_ELEMS, +>; + +pub type Val = BabyBear; + +pub type Challenger = DuplexChallenger; +type ChallengeMmcs = ExtensionMmcs, ValMmcs>; +type Dft = Radix2DitParallel; +type MyPcs = TwoAdicFriPcs, ChallengeMmcs>; +pub type Config = StarkConfig, Challenge, Challenger>; + +const FRI_LOG_BLOWUP: usize = 1; +const FRI_NUM_QUERIES: usize = 100; +const FRI_PROOF_OF_WORK_BITS: usize = 16; + +const RNG_SEED: u64 = 42; + +lazy_static! { + static ref PERM_BB: Perm = Perm::new( + ROUNDS_F, + rand_chacha::ChaCha8Rng::seed_from_u64(RNG_SEED) + .sample_iter(Standard) + .take(ROUNDS_F) + .collect::>(), + Poseidon2ExternalMatrixGeneral, + ROUNDS_P, + rand_chacha::ChaCha8Rng::seed_from_u64(RNG_SEED) + .sample_iter(Standard) + .take(ROUNDS_P) + .collect(), + DiffusionMatrixBabyBear::default() + ); +} + +impl FieldElementMap for BabyBearField { + type P3Field = BabyBear; + type MdsMatrix = MdsMatrixBabyBear; + + fn to_p3_field(&self) -> Self::P3Field { + BabyBear::from_canonical_u32(self.to_integer().try_into_u32().unwrap()) + } +} + +pub(crate) fn get_challenger_baby_bear() -> Challenger { + Challenger::new(PERM_BB.clone()) +} + +pub(crate) fn get_config_baby_bear( +) -> StarkConfig, Challenge, Challenger> { + let hash = Hash::::new(PERM_BB.clone()); + + let compress = Compress::::new(PERM_BB.clone()); + + let val_mmcs = ValMmcs::::new(hash, compress); + + let challenge_mmcs = ChallengeMmcs::::new(val_mmcs.clone()); + + let dft = Dft {}; + + let fri_config = FriConfig { + log_blowup: FRI_LOG_BLOWUP, + num_queries: FRI_NUM_QUERIES, + proof_of_work_bits: FRI_PROOF_OF_WORK_BITS, + mmcs: challenge_mmcs, + }; + + let pcs = MyPcs::::new(dft, val_mmcs, fri_config); + + Config::new(pcs) +} diff --git a/plonky3/src/circuit_builder.rs b/plonky3/src/circuit_builder.rs index 84ec64a38d..e4724b7375 100644 --- a/plonky3/src/circuit_builder.rs +++ b/plonky3/src/circuit_builder.rs @@ -6,22 +6,24 @@ //! everywhere save for at row j is constructed to constrain s * (pub - x) on //! every row. -use std::{any::TypeId, collections::BTreeMap}; +use std::collections::BTreeMap; +use crate::params::FieldElementMap; use p3_air::{Air, AirBuilder, AirBuilderWithPublicValues, BaseAir, PairBuilder}; -use p3_field::AbstractField; -use p3_goldilocks::Goldilocks; +// use p3_baby_bear::BabyBear; +// use p3_field::{extension::ComplexExtendable, AbstractField, PrimeField}; +// use p3_goldilocks::Goldilocks; use p3_matrix::{dense::RowMajorMatrix, Matrix}; +// use p3_mds::MdsPermutation; use powdr_ast::analyzed::{ AlgebraicBinaryOperation, AlgebraicBinaryOperator, AlgebraicExpression, AlgebraicUnaryOperation, AlgebraicUnaryOperator, Analyzed, IdentityKind, PolynomialType, }; use powdr_executor::witgen::WitgenCallback; -use powdr_number::{FieldElement, GoldilocksField, LargeInt}; +// use powdr_number::{BabyBearField, FieldElement, GoldilocksField, LargeInt}; +use powdr_number::FieldElement; -pub type Val = p3_goldilocks::Goldilocks; - -pub(crate) struct PowdrCircuit<'a, T> { +pub(crate) struct PowdrCircuit<'a, T: FieldElementMap> { /// The analyzed PIL analyzed: &'a Analyzed, /// The value of the witness columns, if set @@ -30,11 +32,11 @@ pub(crate) struct PowdrCircuit<'a, T> { _witgen_callback: Option>, /// The matrix of preprocessed values, used in debug mode to check the constraints before proving #[cfg(debug_assertions)] - preprocessed: Option>, + preprocessed: Option::P3Field>>, } -impl<'a, T: FieldElement> PowdrCircuit<'a, T> { - pub fn generate_trace_rows(&self) -> RowMajorMatrix { +impl<'a, T: FieldElement + FieldElementMap + Sync> PowdrCircuit<'a, T> { + pub fn generate_trace_rows(&self) -> RowMajorMatrix<::P3Field> { // an iterator over all columns, committed then fixed let witness = self.witness().iter(); let degrees = self.analyzed.degrees(); @@ -48,7 +50,7 @@ impl<'a, T: FieldElement> PowdrCircuit<'a, T> { // witness values witness.clone().map(move |(_, v)| v[i as usize]) }) - .map(cast_to_goldilocks) + .map(|f| f.to_p3_field()) .collect() } 0 => { @@ -62,12 +64,7 @@ impl<'a, T: FieldElement> PowdrCircuit<'a, T> { } } -pub fn cast_to_goldilocks(v: T) -> Val { - assert_eq!(TypeId::of::(), TypeId::of::()); - Val::from_canonical_u64(v.to_integer().try_into_u64().unwrap()) -} - -impl<'a, T: FieldElement> PowdrCircuit<'a, T> { +impl<'a, T: FieldElement + FieldElementMap> PowdrCircuit<'a, T> { pub(crate) fn new(analyzed: &'a Analyzed) -> Self { if analyzed .definitions @@ -91,7 +88,7 @@ impl<'a, T: FieldElement> PowdrCircuit<'a, T> { } /// Calculates public values from generated witness values. - pub(crate) fn get_public_values(&self) -> Vec { + pub(crate) fn get_public_values(&self) -> Vec<::P3Field> { let witness = self .witness .as_ref() @@ -105,7 +102,7 @@ impl<'a, T: FieldElement> PowdrCircuit<'a, T> { .iter() .map(|(col_name, _, idx)| { let vals = *witness.get(&col_name).unwrap(); - cast_to_goldilocks(vals[*idx]) + vals[*idx].to_p3_field() }) .collect() } @@ -128,14 +125,16 @@ impl<'a, T: FieldElement> PowdrCircuit<'a, T> { #[cfg(debug_assertions)] pub(crate) fn with_preprocessed( mut self, - preprocessed_matrix: RowMajorMatrix, + preprocessed_matrix: RowMajorMatrix<::P3Field>, ) -> Self { self.preprocessed = Some(preprocessed_matrix); self } /// Conversion to plonky3 expression - fn to_plonky3_expr + AirBuilderWithPublicValues>( + fn to_plonky3_expr< + AB: AirBuilder::P3Field> + AirBuilderWithPublicValues, + >( &self, e: &AlgebraicExpression, main: &AB::M, @@ -172,7 +171,7 @@ impl<'a, T: FieldElement> PowdrCircuit<'a, T> { .get(id) .expect("Referenced public value does not exist")) .into(), - AlgebraicExpression::Number(n) => AB::Expr::from(cast_to_goldilocks(*n)), + AlgebraicExpression::Number(n) => AB::Expr::from(n.to_p3_field()), AlgebraicExpression::BinaryOperation(AlgebraicBinaryOperation { left, op, right }) => { let left = self.to_plonky3_expr::(left, main, fixed, publics); let right = self.to_plonky3_expr::(right, main, fixed, publics); @@ -204,7 +203,9 @@ impl<'a, T: FieldElement> PowdrCircuit<'a, T> { /// An extension of [Air] allowing access to the number of fixed columns -impl<'a, T: FieldElement> BaseAir for PowdrCircuit<'a, T> { +impl<'a, T: FieldElement + FieldElementMap> BaseAir<::P3Field> + for PowdrCircuit<'a, T> +{ fn width(&self) -> usize { self.analyzed.commitment_count() } @@ -213,7 +214,7 @@ impl<'a, T: FieldElement> BaseAir for PowdrCircuit<'a, T> { self.analyzed.constant_count() + self.analyzed.publics_count() } - fn preprocessed_trace(&self) -> Option> { + fn preprocessed_trace(&self) -> Option::P3Field>> { #[cfg(debug_assertions)] { self.preprocessed.clone() @@ -223,8 +224,11 @@ impl<'a, T: FieldElement> BaseAir for PowdrCircuit<'a, T> { } } -impl<'a, T: FieldElement, AB: AirBuilderWithPublicValues + PairBuilder> Air - for PowdrCircuit<'a, T> +impl< + 'a, + T: FieldElement + FieldElementMap, + AB: AirBuilderWithPublicValues::P3Field> + PairBuilder, + > Air for PowdrCircuit<'a, T> { fn eval(&self, builder: &mut AB) { let main = builder.main(); diff --git a/plonky3/src/goldilocks.rs b/plonky3/src/goldilocks.rs new file mode 100644 index 0000000000..c39fad111f --- /dev/null +++ b/plonky3/src/goldilocks.rs @@ -0,0 +1,110 @@ +//! The concrete parameters used in the prover +//! Inspired from [this example](https://github.com/Plonky3/Plonky3/blob/6a1b0710fdf85136d0fdd645b92933615867740a/keccak-air/examples/prove_goldilocks_keccak.rs#L57) + +use lazy_static::lazy_static; + +use crate::params::FieldElementMap; +use p3_challenger::DuplexChallenger; +use p3_commit::ExtensionMmcs; +use p3_dft::Radix2DitParallel; +use p3_field::{extension::BinomialExtensionField, Field}; +use p3_fri::{FriConfig, TwoAdicFriPcs}; +use p3_goldilocks::{Goldilocks, MdsMatrixGoldilocks}; +use p3_merkle_tree::FieldMerkleTreeMmcs; +use p3_poseidon::Poseidon; +use p3_symmetric::{PaddingFreeSponge, TruncatedPermutation}; +use p3_uni_stark::StarkConfig; +use powdr_number::{FieldElement, GoldilocksField, LargeInt}; +use rand::distributions::Standard; + +const DEGREE: usize = 2; +type Challenge = BinomialExtensionField; + +const WIDTH: usize = 8; +const ALPHA: u64 = 7; + +type Perm = Poseidon; + +const RATE: usize = 4; +const OUT: usize = 4; +type Hash = PaddingFreeSponge, WIDTH, RATE, OUT>; + +const N: usize = 2; +const CHUNK: usize = 4; +type Compress = TruncatedPermutation, N, CHUNK, WIDTH>; + +const DIGEST_ELEMS: usize = 4; +type ValMmcs = FieldMerkleTreeMmcs< + ::Packing, + ::Packing, + Hash, + Compress, + DIGEST_ELEMS, +>; + +pub type Challenger = DuplexChallenger, WIDTH, RATE>; +type ChallengeMmcs = ExtensionMmcs, ValMmcs>; +type Dft = Radix2DitParallel; +type MyPcs = TwoAdicFriPcs, ChallengeMmcs>; +pub type Config = StarkConfig, Challenge, Challenger>; + +const HALF_NUM_FULL_ROUNDS: usize = 4; +const NUM_PARTIAL_ROUNDS: usize = 22; + +const FRI_LOG_BLOWUP: usize = 1; +const FRI_NUM_QUERIES: usize = 100; +const FRI_PROOF_OF_WORK_BITS: usize = 16; + +const NUM_ROUNDS: usize = 2 * HALF_NUM_FULL_ROUNDS + NUM_PARTIAL_ROUNDS; +const NUM_CONSTANTS: usize = WIDTH * NUM_ROUNDS; + +const RNG_SEED: u64 = 42; + +lazy_static! { + static ref PERM_GL: Perm = Perm::new( + HALF_NUM_FULL_ROUNDS, + NUM_PARTIAL_ROUNDS, + rand_chacha::ChaCha8Rng::seed_from_u64(RNG_SEED) + .sample_iter(Standard) + .take(NUM_CONSTANTS) + .collect(), + MdsMatrixGoldilocks, + ); +} + +impl FieldElementMap for GoldilocksField { + type P3Field = Goldilocks; + type MdsMatrix = MdsMatrixGoldilocks; + + fn to_p3_field(&self) -> Self::P3Field { + Goldilocks::from_canonical_u64(self.to_integer().try_into_u64().unwrap()) + } +} + +pub fn get_challenger_goldilocks() -> Challenger { + Challenger::new(PERM_GL.clone()) +} + +pub fn get_config_goldilocks( +) -> StarkConfig, Challenge, Challenger> { + let hash = Hash::::new(PERM_GL.clone()); + + let compress = Compress::::new(PERM_GL.clone()); + + let val_mmcs = ValMmcs::::new(hash, compress); + + let challenge_mmcs = ChallengeMmcs::::new(val_mmcs.clone()); + + let dft = Dft {}; + + let fri_config = FriConfig { + log_blowup: FRI_LOG_BLOWUP, + num_queries: FRI_NUM_QUERIES, + proof_of_work_bits: FRI_PROOF_OF_WORK_BITS, + mmcs: challenge_mmcs, + }; + + let pcs = MyPcs::::new(dft, val_mmcs, fri_config); + + Config::new(pcs) +} diff --git a/plonky3/src/lib.rs b/plonky3/src/lib.rs index 4bcb981bcf..424de35f90 100644 --- a/plonky3/src/lib.rs +++ b/plonky3/src/lib.rs @@ -1,5 +1,8 @@ +mod baby_bear; mod circuit_builder; +mod goldilocks; mod params; mod stark; +mod stark_babybear; pub use stark::Plonky3Prover; diff --git a/plonky3/src/params.rs b/plonky3/src/params.rs index 7b4171a9f3..5817178f45 100644 --- a/plonky3/src/params.rs +++ b/plonky3/src/params.rs @@ -1,98 +1,32 @@ -//! The concrete parameters used in the prover -//! Inspired from [this example](https://github.com/Plonky3/Plonky3/blob/6a1b0710fdf85136d0fdd645b92933615867740a/keccak-air/examples/prove_goldilocks_keccak.rs#L57) - -use lazy_static::lazy_static; - -use p3_challenger::DuplexChallenger; -use p3_commit::ExtensionMmcs; -use p3_dft::Radix2DitParallel; -use p3_field::{extension::BinomialExtensionField, Field}; -use p3_fri::{FriConfig, TwoAdicFriPcs}; -use p3_goldilocks::MdsMatrixGoldilocks; -use p3_merkle_tree::FieldMerkleTreeMmcs; -use p3_poseidon::Poseidon; -use p3_symmetric::{PaddingFreeSponge, TruncatedPermutation}; -use p3_uni_stark::StarkConfig; - -use rand::{distributions::Standard, Rng, SeedableRng}; - -use crate::circuit_builder::Val; - -const D: usize = 2; -type Challenge = BinomialExtensionField; -const WIDTH: usize = 8; -const ALPHA: u64 = 7; -type Perm = Poseidon; - -const RATE: usize = 4; -const OUT: usize = 4; -type Hash = PaddingFreeSponge; - -const N: usize = 2; -const CHUNK: usize = 4; -type Compress = TruncatedPermutation; - -const DIGEST_ELEMS: usize = 4; -type ValMmcs = FieldMerkleTreeMmcs< - ::Packing, - ::Packing, - Hash, - Compress, - DIGEST_ELEMS, ->; -pub type Challenger = DuplexChallenger; -type ChallengeMmcs = ExtensionMmcs; -type Dft = Radix2DitParallel; -type MyPcs = TwoAdicFriPcs; -pub type Config = StarkConfig; - -const HALF_NUM_FULL_ROUNDS: usize = 4; -const NUM_PARTIAL_ROUNDS: usize = 22; - -const FRI_LOG_BLOWUP: usize = 1; -const FRI_NUM_QUERIES: usize = 100; -const FRI_PROOF_OF_WORK_BITS: usize = 16; - -const NUM_ROUNDS: usize = 2 * HALF_NUM_FULL_ROUNDS + NUM_PARTIAL_ROUNDS; -const NUM_CONSTANTS: usize = WIDTH * NUM_ROUNDS; - -const RNG_SEED: u64 = 42; - -lazy_static! { - static ref PERM: Perm = Perm::new( - HALF_NUM_FULL_ROUNDS, - NUM_PARTIAL_ROUNDS, - rand_chacha::ChaCha8Rng::seed_from_u64(RNG_SEED) - .sample_iter(Standard) - .take(NUM_CONSTANTS) - .collect(), - MdsMatrixGoldilocks, - ); -} - -pub fn get_challenger() -> Challenger { - Challenger::new(PERM.clone()) +// use lazy_static::lazy_static; + +// use p3_baby_bear::MdsMatrixBabyBear; +// use p3_challenger::DuplexChallenger; +// use p3_commit::ExtensionMmcs; +// use p3_dft::Radix2DitParallel; +use p3_field::PrimeField; +// use p3_fri::{FriConfig, TwoAdicFriPcs}; +// use p3_goldilocks::{Goldilocks, MdsMatrixGoldilocks}; +// use p3_merkle_tree::FieldMerkleTreeMmcs; +// use p3_poseidon::Poseidon; +// use p3_symmetric::{PaddingFreeSponge, TruncatedPermutation}; +// use p3_uni_stark::StarkConfig; + +// use rand::{distributions::Standard, Rng, SeedableRng}; + +// use crate::data_traits::FieldElementMap; +// use powdr_number::{BabyBearField, GoldilocksField}; + +pub trait FieldElementMap: Clone + Send + Sync { + type P3Field: PrimeField; + type MdsMatrix; + + fn to_p3_field(&self) -> Self::P3Field; } +// pub trait Permutation { +// fn get_challenger() -> Challenger; +// } -pub fn get_config() -> StarkConfig { - let hash = Hash::new(PERM.clone()); - - let compress = Compress::new(PERM.clone()); - - let val_mmcs = ValMmcs::new(hash, compress); - - let challenge_mmcs = ChallengeMmcs::new(val_mmcs.clone()); - - let dft = Dft {}; - - let fri_config = FriConfig { - log_blowup: FRI_LOG_BLOWUP, - num_queries: FRI_NUM_QUERIES, - proof_of_work_bits: FRI_PROOF_OF_WORK_BITS, - mmcs: challenge_mmcs, - }; - - let pcs = MyPcs::new(dft, val_mmcs, fri_config); - - Config::new(pcs) -} +// pub trait Configure { +// pub fn get_config() -> StarkConfig, Challenge, Challenger>; +// } diff --git a/plonky3/src/stark.rs b/plonky3/src/stark.rs index d5ff6de73c..f13e000172 100644 --- a/plonky3/src/stark.rs +++ b/plonky3/src/stark.rs @@ -1,12 +1,12 @@ //! A plonky3 prover using FRI and Poseidon +use p3_baby_bear::BabyBear; use p3_goldilocks::Goldilocks; use p3_matrix::dense::RowMajorMatrix; use core::fmt; use std::sync::Arc; -use crate::params::Challenger; use powdr_ast::analyzed::Analyzed; use powdr_executor::witgen::WitgenCallback; @@ -16,19 +16,19 @@ use p3_uni_stark::{ }; use powdr_number::{FieldElement, KnownField}; -use crate::circuit_builder::{cast_to_goldilocks, PowdrCircuit}; +use crate::{circuit_builder::PowdrCircuit, params::FieldElementMap}; -use crate::params::{get_challenger, get_config, Config}; +use crate::goldilocks::{get_challenger_goldilocks, get_config_goldilocks, Challenger, Config}; -pub struct Plonky3Prover { +pub struct Plonky3Prover { /// The analyzed PIL analyzed: Arc>, /// The value of the fixed columns fixed: Arc)>>, /// Proving key - proving_key: Option>, + proving_key: Option>>, /// Verifying key - verifying_key: Option>, + verifying_key: Option>>, } pub enum VerificationKeyExportError { @@ -43,7 +43,7 @@ impl fmt::Display for VerificationKeyExportError { } } -impl Plonky3Prover { +impl Plonky3Prover { pub fn new(analyzed: Arc>, fixed: Arc)>>) -> Self { Self { analyzed, @@ -68,7 +68,7 @@ impl Plonky3Prover { /// Returns preprocessed matrix based on the fixed inputs [`Plonky3Prover`]. /// This is used when running the setup phase - pub fn get_preprocessed_matrix(&self) -> RowMajorMatrix { + pub fn get_preprocessed_matrix(&self) -> RowMajorMatrix { let publics = self .analyzed .get_publics() @@ -82,18 +82,18 @@ impl Plonky3Prover { .collect::)>>(); match self.fixed.len() + publics.len() { - 0 => RowMajorMatrix::new(Vec::::new(), 0), + 0 => RowMajorMatrix::new(Vec::::new(), 0), _ => RowMajorMatrix::new( // write fixed row by row (0..self.analyzed.degree()) .flat_map(|i| { self.fixed .iter() - .map(move |(_, values)| cast_to_goldilocks(values[i as usize])) + .map(move |(_, values)| values[i as usize].to_p3_field()) .chain( publics .iter() - .map(move |(_, values)| cast_to_goldilocks(values[i as usize])), + .map(move |(_, values)| values[i as usize].to_p3_field()), ) }) .collect(), @@ -103,7 +103,7 @@ impl Plonky3Prover { } } -impl Plonky3Prover { +impl Plonky3Prover { pub fn setup(&mut self) { // get fixed columns let fixed = &self.fixed; @@ -126,11 +126,11 @@ impl Plonky3Prover { } // get the config - let config = get_config(); + let config = get_config_goldilocks(); // commit to the fixed columns let pcs = config.pcs(); - let domain = <_ as p3_commit::Pcs<_, Challenger>>::natural_domain_for_degree( + let domain = <_ as p3_commit::Pcs<_, Challenger>>::natural_domain_for_degree( pcs, self.analyzed.degree() as usize, ); @@ -141,7 +141,7 @@ impl Plonky3Prover { fixed .iter() .chain(publics.iter()) - .map(move |(_, values)| cast_to_goldilocks(values[i as usize])) + .map(move |(_, values)| values[i as usize].to_p3_field()) }) .collect(), self.fixed.len() + publics.len(), @@ -151,7 +151,7 @@ impl Plonky3Prover { // commit to the evaluations let (fixed_commit, fixed_data) = - <_ as p3_commit::Pcs<_, Challenger>>::commit(pcs, evaluations); + <_ as p3_commit::Pcs<_, Challenger>>::commit(pcs, evaluations); let proving_key = StarkProvingKey { preprocessed_commit: fixed_commit, @@ -170,7 +170,10 @@ impl Plonky3Prover { witness: &[(String, Vec)], witgen_callback: WitgenCallback, ) -> Result, String> { - assert_eq!(T::known_field(), Some(KnownField::GoldilocksField)); + assert!( + T::known_field() == Some(KnownField::GoldilocksField) + || T::known_field() == Some(KnownField::BabyBearField) + ); let circuit = PowdrCircuit::new(&self.analyzed) .with_witgen_callback(witgen_callback) @@ -183,9 +186,9 @@ impl Plonky3Prover { let trace = circuit.generate_trace_rows(); - let config = get_config(); + let config = get_config_goldilocks(); - let mut challenger = get_challenger(); + let mut challenger = get_challenger_goldilocks(); let proving_key = self.proving_key.as_ref(); @@ -198,7 +201,7 @@ impl Plonky3Prover { &publics, ); - let mut challenger = get_challenger(); + let mut challenger = get_challenger_goldilocks(); let verifying_key = self.verifying_key.as_ref(); @@ -220,12 +223,12 @@ impl Plonky3Prover { let publics = instances .iter() .flatten() - .map(|v| cast_to_goldilocks(*v)) + .map(|v| v.to_p3_field()) .collect(); - let config = get_config(); + let config = get_config_goldilocks(); - let mut challenger = get_challenger(); + let mut challenger = get_challenger_goldilocks(); let verifying_key = self.verifying_key.as_ref(); diff --git a/plonky3/src/stark_babybear.rs b/plonky3/src/stark_babybear.rs new file mode 100644 index 0000000000..3a9bf029c7 --- /dev/null +++ b/plonky3/src/stark_babybear.rs @@ -0,0 +1,377 @@ +//! A plonky3 prover using FRI and Poseidon + +use p3_baby_bear::BabyBear; +use p3_matrix::dense::RowMajorMatrix; + +use core::fmt; +use std::sync::Arc; + +use powdr_ast::analyzed::Analyzed; + +use powdr_executor::witgen::WitgenCallback; + +use p3_uni_stark::{ + prove_with_key, verify_with_key, Proof, StarkGenericConfig, StarkProvingKey, StarkVerifyingKey, +}; +use powdr_number::{FieldElement, KnownField}; + +use crate::{circuit_builder::PowdrCircuit, params::FieldElementMap}; + +use crate::baby_bear::{get_challenger_baby_bear, get_config_baby_bear, Challenger, Config}; + +pub struct Plonky3ProverBabyBear { + /// The analyzed PIL + analyzed: Arc>, + /// The value of the fixed columns + fixed: Arc)>>, + /// Proving key + proving_key: Option>>, + /// Verifying key + verifying_key: Option>>, +} + +pub enum VerificationKeyExportError { + NoVerificationKey, +} + +impl fmt::Display for VerificationKeyExportError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::NoVerificationKey => write!(f, "No verification key set"), + } + } +} + +impl Plonky3ProverBabyBear { + pub fn new(analyzed: Arc>, fixed: Arc)>>) -> Self { + Self { + analyzed, + fixed, + proving_key: None, + verifying_key: None, + } + } + + pub fn set_verifying_key(&mut self, rdr: &mut dyn std::io::Read) { + self.verifying_key = Some(bincode::deserialize_from(rdr).unwrap()); + } + + pub fn export_verifying_key(&self) -> Result, VerificationKeyExportError> { + Ok(bincode::serialize( + self.verifying_key + .as_ref() + .ok_or(VerificationKeyExportError::NoVerificationKey)?, + ) + .unwrap()) + } + + /// Returns preprocessed matrix based on the fixed inputs [`Plonky3Prover`]. + /// This is used when running the setup phase + pub fn get_preprocessed_matrix(&self) -> RowMajorMatrix { + let publics = self + .analyzed + .get_publics() + .into_iter() + .map(|(name, _, row_id)| { + let selector = (0..self.analyzed.degree()) + .map(move |i| T::from(i == row_id as u64)) + .collect::>(); + (name, selector) + }) + .collect::)>>(); + + match self.fixed.len() + publics.len() { + 0 => RowMajorMatrix::new(Vec::::new(), 0), + _ => RowMajorMatrix::new( + // write fixed row by row + (0..self.analyzed.degree()) + .flat_map(|i| { + self.fixed + .iter() + .map(move |(_, values)| values[i as usize].to_p3_field()) + .chain( + publics + .iter() + .map(move |(_, values)| values[i as usize].to_p3_field()), + ) + }) + .collect(), + self.fixed.len() + publics.len(), + ), + } + } +} + +impl Plonky3ProverBabyBear { + pub fn setup(&mut self) { + // get fixed columns + let fixed = &self.fixed; + + // get selector columns for public values + let publics = self + .analyzed + .get_publics() + .into_iter() + .map(|(name, _, row_id)| { + let selector = (0..self.analyzed.degree()) + .map(move |i| T::from(i == row_id as u64)) + .collect::>(); + (name, selector) + }) + .collect::)>>(); + + if fixed.is_empty() && publics.is_empty() { + return; + } + + // get the config + let config = get_config_baby_bear(); + + // commit to the fixed columns + let pcs = config.pcs(); + let domain = <_ as p3_commit::Pcs<_, Challenger>>::natural_domain_for_degree( + pcs, + self.analyzed.degree() as usize, + ); + // write fixed into matrix row by row + let matrix = RowMajorMatrix::new( + (0..self.analyzed.degree()) + .flat_map(|i| { + fixed + .iter() + .chain(publics.iter()) + .map(move |(_, values)| values[i as usize].to_p3_field()) + }) + .collect(), + self.fixed.len() + publics.len(), + ); + + let evaluations = vec![(domain, matrix)]; + + // commit to the evaluations + let (fixed_commit, fixed_data) = + <_ as p3_commit::Pcs<_, Challenger>>::commit(pcs, evaluations); + + let proving_key = StarkProvingKey { + preprocessed_commit: fixed_commit, + preprocessed_data: fixed_data, + }; + let verifying_key = StarkVerifyingKey { + preprocessed_commit: fixed_commit, + }; + + self.proving_key = Some(proving_key); + self.verifying_key = Some(verifying_key); + } + + pub fn prove( + &self, + witness: &[(String, Vec)], + witgen_callback: WitgenCallback, + ) -> Result, String> { + assert!( + T::known_field() == Some(KnownField::GoldilocksField) + || T::known_field() == Some(KnownField::BabyBearField) + ); + + let circuit = PowdrCircuit::new(&self.analyzed) + .with_witgen_callback(witgen_callback) + .with_witness(witness); + + #[cfg(debug_assertions)] + let circuit = circuit.with_preprocessed(self.get_preprocessed_matrix()); + + let publics = circuit.get_public_values(); + + let trace = circuit.generate_trace_rows(); + + let config = get_config_baby_bear(); + + let mut challenger = get_challenger_baby_bear(); + + let proving_key = self.proving_key.as_ref(); + + let proof = prove_with_key( + &config, + proving_key, + &circuit, + &mut challenger, + trace, + &publics, + ); + + let mut challenger = get_challenger_baby_bear(); + + let verifying_key = self.verifying_key.as_ref(); + + verify_with_key( + &config, + verifying_key, + &circuit, + &mut challenger, + &proof, + &publics, + ) + .unwrap(); + Ok(bincode::serialize(&proof).unwrap()) + } + + pub fn verify(&self, proof: &[u8], instances: &[Vec]) -> Result<(), String> { + let proof: Proof<_> = + bincode::deserialize(proof).map_err(|e| format!("Failed to deserialize proof: {e}"))?; + let publics = instances + .iter() + .flatten() + .map(|v| v.to_p3_field()) + .collect(); + + let config = get_config_baby_bear(); + + let mut challenger = get_challenger_baby_bear(); + + let verifying_key = self.verifying_key.as_ref(); + + verify_with_key( + &config, + verifying_key, + &PowdrCircuit::new(&self.analyzed), + &mut challenger, + &proof, + &publics, + ) + .map_err(|e| format!("Failed to verify proof: {e:?}")) + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use powdr_executor::constant_evaluator::get_uniquely_sized_cloned; + use powdr_number::BabyBearField; + use powdr_pipeline::Pipeline; + use test_log::test; + + use crate::Plonky3Prover; + + /// Prove and verify execution + fn run_test_baby_bear(pil: &str) { + run_test_baby_bear_publics(pil, None) + } + + fn run_test_baby_bear_publics(pil: &str, malicious_publics: Option>) { + let mut pipeline = Pipeline::::default().from_pil_string(pil.to_string()); + + let pil = pipeline.compute_optimized_pil().unwrap(); + let witness_callback = pipeline.witgen_callback().unwrap(); + let witness = pipeline.compute_witness().unwrap(); + let fixed = pipeline.compute_fixed_cols().unwrap(); + let fixed = Arc::new(get_uniquely_sized_cloned(&fixed).unwrap()); + + let mut prover = Plonky3Prover::new(pil, fixed); + prover.setup(); + let proof = prover.prove(&witness, witness_callback); + + assert!(proof.is_ok()); + + if let Some(publics) = malicious_publics { + prover.verify(&proof.unwrap(), &[publics]).unwrap() + } + } + + #[test] + fn public_values() { + let content = "namespace Global(8); pol witness x; x * (x - 1) = 0; public out = x(7);"; + run_test_baby_bear(content); + } + + #[test] + #[should_panic = "not implemented: Unexpected expression: :oldstate"] + fn public_reference() { + let content = r#" + namespace Global(8); + col witness x; + col witness y; + public oldstate = x(0); + x = 0; + y = 1 + :oldstate; + "#; + run_test_baby_bear(content); + } + + #[test] + #[should_panic = "fri err: InvalidPowWitness"] + fn public_inputs_malicious() { + let content = r#" + namespace Add(8); + col witness x; + col witness y; + col witness z; + y - 1 = 0; + x = 0; + x + y = z; + + public outz = z(7); + "#; + let malicious_publics = Some(vec![BabyBearField::from(0)]); + run_test_baby_bear_publics(content, malicious_publics); + } + + #[test] + #[should_panic = "assertion `left == right` failed: Not a power of two: 0\n left: 0\n right: 1"] + fn empty() { + let content = "namespace Global(8);"; + run_test_baby_bear(content); + } + + #[test] + fn add() { + let content = r#" + namespace Add(8); + col witness x; + col witness y; + col witness z; + x + y = z; + "#; + run_test_baby_bear(content); + } + + #[test] + fn fixed() { + let content = r#" + namespace Add(8); + col witness x; + col fixed y = [1, 0]*; + x * y = y; + "#; + run_test_baby_bear(content); + } + + #[test] + #[should_panic = "not implemented"] + fn challenge() { + let content = r#" + let N: int = 8; + + namespace Global(N); + let beta: expr = std::prelude::challenge(0, 42); + col witness stage(0) x; + col witness stage(1) y; + x = y + beta; + "#; + run_test_baby_bear(content); + } + + #[test] + fn polynomial_identity() { + let content = "namespace Global(8); pol fixed z = [1, 2]*; pol witness a; a = z + 1;"; + run_test_baby_bear(content); + } + + #[test] + #[should_panic = "not implemented"] + fn lookup() { + let content = "namespace Global(8); pol fixed z = [0, 1]*; pol witness a; [a] in [z];"; + run_test_baby_bear(content); + } +} From e310a7e31eb1a49b7921b4563dc3bf44993db859 Mon Sep 17 00:00:00 2001 From: topanisto Date: Fri, 16 Aug 2024 13:27:21 +0200 Subject: [PATCH 02/17] associated types for FieldElementMap --- plonky3/src/baby_bear.rs | 132 ++++++++++++++++++--------------------- plonky3/src/params.rs | 59 ++++++++++------- 2 files changed, 96 insertions(+), 95 deletions(-) diff --git a/plonky3/src/baby_bear.rs b/plonky3/src/baby_bear.rs index 36537cae18..1716d20cad 100644 --- a/plonky3/src/baby_bear.rs +++ b/plonky3/src/baby_bear.rs @@ -19,65 +19,46 @@ use rand::{distributions::Standard, Rng, SeedableRng}; use powdr_number::{BabyBearField, FieldElement}; -const DEGREE: usize = 2; -type Challenge = BinomialExtensionField; - -const WIDTH: usize = 16; -const D: u64 = 7; -type Perm = Poseidon2; - -// const ROUNDS_F: usize = poseidon2_round_numbers_128::(WIDTH, D).0; -// const ROUNDS_P: usize = poseidon2_round_numbers_128::(WIDTH, D).1; - -// params directly taken from plonky3's poseidon2_round_numbers_128 function -// to guarentee 128-bit security. - -const ROUNDS_F: usize = 8; -const ROUNDS_P: usize = 13; - -const RATE: usize = 8; -const OUT: usize = 8; -type Hash = PaddingFreeSponge; - -const N: usize = 2; -const CHUNK: usize = 8; -type Compress = TruncatedPermutation; - -const DIGEST_ELEMS: usize = 8; -type ValMmcs = FieldMerkleTreeMmcs< - ::Packing, - ::Packing, - Hash, - Compress, - DIGEST_ELEMS, ->; - -pub type Val = BabyBear; - -pub type Challenger = DuplexChallenger; -type ChallengeMmcs = ExtensionMmcs, ValMmcs>; -type Dft = Radix2DitParallel; -type MyPcs = TwoAdicFriPcs, ChallengeMmcs>; -pub type Config = StarkConfig, Challenge, Challenger>; +pub trait Poseidon2Compatible { + const D: u64; + const ROUNDS_F: usize; + const ROUNDS_P: usize; + const PERM_WIDTH: usize; + const RNG_SEED: u64 = 42; + + type Poseidon2Perm: Poseidon2< + BabyBear, + Poseidon2ExternalMatrixGeneral, + DiffusionMatrixBabyBear, + WIDTH, + D, + >; +} -const FRI_LOG_BLOWUP: usize = 1; -const FRI_NUM_QUERIES: usize = 100; -const FRI_PROOF_OF_WORK_BITS: usize = 16; +impl Poseidon2Compatible for BabyBearField { + const D: u64 = 7; + // params directly taken from plonky3's poseidon2_round_numbers_128 function + // to guarentee 128-bit security. + const ROUNDS_F: usize = 8; + const ROUNDS_P: usize = 13; + const PERM_WIDTH: usize = 16; -const RNG_SEED: u64 = 42; + type Poseidon2Perm = + Poseidon2; +} lazy_static! { - static ref PERM_BB: Perm = Perm::new( - ROUNDS_F, - rand_chacha::ChaCha8Rng::seed_from_u64(RNG_SEED) + static ref PERM_BB: Poseidon2Compatible::Perm = BabyBearField::Poseidon2Perm::new( + BabyBearField::ROUNDS_F, + rand_chacha::ChaCha8Rng::seed_from_u64(BabyBearField::RNG_SEED) .sample_iter(Standard) - .take(ROUNDS_F) - .collect::>(), + .take(BabyBearField::ROUNDS_F) + .collect::>(), Poseidon2ExternalMatrixGeneral, - ROUNDS_P, - rand_chacha::ChaCha8Rng::seed_from_u64(RNG_SEED) + BabyBearField::ROUNDS_P, + rand_chacha::ChaCha8Rng::seed_from_u64(BabyBearField::RNG_SEED) .sample_iter(Standard) - .take(ROUNDS_P) + .take(BabyBearField::ROUNDS_P) .collect(), DiffusionMatrixBabyBear::default() ); @@ -87,35 +68,44 @@ impl FieldElementMap for BabyBearField { type P3Field = BabyBear; type MdsMatrix = MdsMatrixBabyBear; + const DEGREE: usize = 2; + const WIDTH: usize = BabyBearField::PERM_WIDTH; + const RATE: usize = 8; + const OUT: usize = 8; + const N: usize = 2; + const CHUNK: usize = 8; + const DIGEST_ELEMS: usize = 8; + + type Perm = BabyBearField::Poseidon2Perm; + fn to_p3_field(&self) -> Self::P3Field { BabyBear::from_canonical_u32(self.to_integer().try_into_u32().unwrap()) } -} -pub(crate) fn get_challenger_baby_bear() -> Challenger { - Challenger::new(PERM_BB.clone()) -} + fn get_challenger() -> Challenger { + Challenger::new(PERM_BB.clone()) + } -pub(crate) fn get_config_baby_bear( -) -> StarkConfig, Challenge, Challenger> { - let hash = Hash::::new(PERM_BB.clone()); + fn get_config() -> Config { + let hash = Hash::new(PERM_BB.clone()); - let compress = Compress::::new(PERM_BB.clone()); + let compress = Compress::new(PERM_BB.clone()); - let val_mmcs = ValMmcs::::new(hash, compress); + let val_mmcs = ValMmcs::new(hash, compress); - let challenge_mmcs = ChallengeMmcs::::new(val_mmcs.clone()); + let challenge_mmcs = ChallengeMmcs::new(val_mmcs.clone()); - let dft = Dft {}; + let dft = Dft {}; - let fri_config = FriConfig { - log_blowup: FRI_LOG_BLOWUP, - num_queries: FRI_NUM_QUERIES, - proof_of_work_bits: FRI_PROOF_OF_WORK_BITS, - mmcs: challenge_mmcs, - }; + let fri_config = FriConfig { + log_blowup: FRI_LOG_BLOWUP, + num_queries: FRI_NUM_QUERIES, + proof_of_work_bits: FRI_PROOF_OF_WORK_BITS, + mmcs: challenge_mmcs, + }; - let pcs = MyPcs::::new(dft, val_mmcs, fri_config); + let pcs = MyPcs::new(dft, val_mmcs, fri_config); - Config::new(pcs) + Config::new(pcs) + } } diff --git a/plonky3/src/params.rs b/plonky3/src/params.rs index 5817178f45..65d7eae034 100644 --- a/plonky3/src/params.rs +++ b/plonky3/src/params.rs @@ -1,32 +1,43 @@ // use lazy_static::lazy_static; -// use p3_baby_bear::MdsMatrixBabyBear; -// use p3_challenger::DuplexChallenger; -// use p3_commit::ExtensionMmcs; -// use p3_dft::Radix2DitParallel; -use p3_field::PrimeField; -// use p3_fri::{FriConfig, TwoAdicFriPcs}; -// use p3_goldilocks::{Goldilocks, MdsMatrixGoldilocks}; -// use p3_merkle_tree::FieldMerkleTreeMmcs; -// use p3_poseidon::Poseidon; -// use p3_symmetric::{PaddingFreeSponge, TruncatedPermutation}; -// use p3_uni_stark::StarkConfig; - -// use rand::{distributions::Standard, Rng, SeedableRng}; - -// use crate::data_traits::FieldElementMap; -// use powdr_number::{BabyBearField, GoldilocksField}; +use p3_challenger::DuplexChallenger; +use p3_commit::ExtensionMmcs; +use p3_dft::Radix2DitParallel; +use p3_field::{extension::BinomialExtensionField, AbstractField, PrimeField}; +use p3_fri::{FriConfig, TwoAdicFriPcs}; +use p3_symmetric::{compression::TruncatedPermutation, CryptographicPermutation, Permutation}; +use p3_uni_stark::StarkConfig; + +type Dft = Radix2DitParallel; pub trait FieldElementMap: Clone + Send + Sync { type P3Field: PrimeField; type MdsMatrix; + type Perm: Permutation<[AbstractField; WIDTH]> + + CryptographicPermutation<[AbstractField; WIDTH]>; - fn to_p3_field(&self) -> Self::P3Field; -} -// pub trait Permutation { -// fn get_challenger() -> Challenger; -// } + type Hash = PaddingFreeSponge; + type Compress = TruncatedPermutation; + type Challenge = BinomialExtensionField; + type Challenger = DuplexChallenger; + type ChallengeMmcs = ExtensionMmcs; + type MyPcs = TwoAdicFriPcs; + type Config = StarkConfig; + + const DEGREE: usize; + const WIDTH: usize; + const RATE: usize; + const OUT: usize; + const N: usize; + const CHUNK: usize; + const DIGEST_ELEMS: usize; + const FRI_LOG_BLOWUP: usize = 1; + const FRI_NUM_QUERIES: usize = 100; + const FRI_PROOF_OF_WORK_BITS: usize = 16; -// pub trait Configure { -// pub fn get_config() -> StarkConfig, Challenge, Challenger>; -// } + pub(crate) fn to_p3_field(&self) -> Self::P3Field; + + pub(crate) fn get_challenger() -> Challenger; + + pub(crate) fn get_config() -> Config; +} From 07e2dca72777dcf21f74b01c871b70988de32bdb Mon Sep 17 00:00:00 2001 From: topanisto Date: Fri, 16 Aug 2024 13:52:33 +0200 Subject: [PATCH 03/17] traits implemented --- plonky3/src/baby_bear.rs | 14 ++--- plonky3/src/goldilocks.rs | 121 ++++++++++++++++++-------------------- plonky3/src/params.rs | 4 +- 3 files changed, 65 insertions(+), 74 deletions(-) diff --git a/plonky3/src/baby_bear.rs b/plonky3/src/baby_bear.rs index 1716d20cad..c3c308a1d7 100644 --- a/plonky3/src/baby_bear.rs +++ b/plonky3/src/baby_bear.rs @@ -8,10 +8,10 @@ use p3_baby_bear::{BabyBear, DiffusionMatrixBabyBear, MdsMatrixBabyBear}; use p3_challenger::DuplexChallenger; use p3_commit::ExtensionMmcs; use p3_dft::Radix2DitParallel; -use p3_field::{extension::BinomialExtensionField, Field}; +use p3_field::{extension::BinomialExtensionField, Field}, AbstractField; use p3_fri::{FriConfig, TwoAdicFriPcs}; use p3_merkle_tree::FieldMerkleTreeMmcs; -use p3_poseidon2::{Poseidon2, Poseidon2ExternalMatrixGeneral}; +use p3_poseidon2::{DiffusionPermutation, Poseidon2, Poseidon2ExternalMatrixGeneral}; use p3_symmetric::{PaddingFreeSponge, TruncatedPermutation}; use p3_uni_stark::StarkConfig; @@ -27,10 +27,10 @@ pub trait Poseidon2Compatible { const RNG_SEED: u64 = 42; type Poseidon2Perm: Poseidon2< - BabyBear, + PrimeField, Poseidon2ExternalMatrixGeneral, - DiffusionMatrixBabyBear, - WIDTH, + DiffusionPermutation, + PERM_WIDTH, D, >; } @@ -44,11 +44,11 @@ impl Poseidon2Compatible for BabyBearField { const PERM_WIDTH: usize = 16; type Poseidon2Perm = - Poseidon2; + Poseidon2; } lazy_static! { - static ref PERM_BB: Poseidon2Compatible::Perm = BabyBearField::Poseidon2Perm::new( + static ref PERM_BB: Poseidon2Compatible::Poseidon2Perm = BabyBearField::Poseidon2Perm::new( BabyBearField::ROUNDS_F, rand_chacha::ChaCha8Rng::seed_from_u64(BabyBearField::RNG_SEED) .sample_iter(Standard) diff --git a/plonky3/src/goldilocks.rs b/plonky3/src/goldilocks.rs index c39fad111f..3a4a098488 100644 --- a/plonky3/src/goldilocks.rs +++ b/plonky3/src/goldilocks.rs @@ -7,7 +7,7 @@ use crate::params::FieldElementMap; use p3_challenger::DuplexChallenger; use p3_commit::ExtensionMmcs; use p3_dft::Radix2DitParallel; -use p3_field::{extension::BinomialExtensionField, Field}; +use p3_field::{extension::BinomialExtensionField, AbstractField, Field}; use p3_fri::{FriConfig, TwoAdicFriPcs}; use p3_goldilocks::{Goldilocks, MdsMatrixGoldilocks}; use p3_merkle_tree::FieldMerkleTreeMmcs; @@ -17,56 +17,39 @@ use p3_uni_stark::StarkConfig; use powdr_number::{FieldElement, GoldilocksField, LargeInt}; use rand::distributions::Standard; -const DEGREE: usize = 2; -type Challenge = BinomialExtensionField; - -const WIDTH: usize = 8; -const ALPHA: u64 = 7; - -type Perm = Poseidon; - -const RATE: usize = 4; -const OUT: usize = 4; -type Hash = PaddingFreeSponge, WIDTH, RATE, OUT>; - -const N: usize = 2; -const CHUNK: usize = 4; -type Compress = TruncatedPermutation, N, CHUNK, WIDTH>; - -const DIGEST_ELEMS: usize = 4; -type ValMmcs = FieldMerkleTreeMmcs< - ::Packing, - ::Packing, - Hash, - Compress, - DIGEST_ELEMS, ->; - -pub type Challenger = DuplexChallenger, WIDTH, RATE>; -type ChallengeMmcs = ExtensionMmcs, ValMmcs>; -type Dft = Radix2DitParallel; -type MyPcs = TwoAdicFriPcs, ChallengeMmcs>; -pub type Config = StarkConfig, Challenge, Challenger>; - -const HALF_NUM_FULL_ROUNDS: usize = 4; -const NUM_PARTIAL_ROUNDS: usize = 22; - -const FRI_LOG_BLOWUP: usize = 1; -const FRI_NUM_QUERIES: usize = 100; -const FRI_PROOF_OF_WORK_BITS: usize = 16; +pub trait PoseidonCompatible { + const PERM_WIDTH: usize; + const ALPHA: u64; + const HALF_NUM_FULL_ROUNDS: usize; + const NUM_PARTIAL_ROUNDS: usize; + const NUM_ROUNDS: usize = 2 * HALF_NUM_FULL_ROUNDS + NUM_PARTIAL_ROUNDS; + const NUM_CONSTANTS: usize = WIDTH * NUM_ROUNDS; + const RNG_SEED: u64 = 42; + + type PoseidonPerm: Poseidon< + PrimeField, + MdsPermutation, + PERM_WIDTH, + ALPHA, + >; +} -const NUM_ROUNDS: usize = 2 * HALF_NUM_FULL_ROUNDS + NUM_PARTIAL_ROUNDS; -const NUM_CONSTANTS: usize = WIDTH * NUM_ROUNDS; +impl PoseidonCompatible for GoldilocksField { + const PERM_WIDTH: usize = 8; + const ALPHA: u64 = 7; + const HALF_NUM_FULL_ROUNDS: usize = 4; + const NUM_PARTIAL_ROUNDS: usize = 22; -const RNG_SEED: u64 = 42; + type PoseidonPerm = Poseidon; +} lazy_static! { - static ref PERM_GL: Perm = Perm::new( - HALF_NUM_FULL_ROUNDS, - NUM_PARTIAL_ROUNDS, - rand_chacha::ChaCha8Rng::seed_from_u64(RNG_SEED) + static ref PERM_GL: PoseidonCompatible::PoseidonPerm = GoldilocksField::PoseidonPerm::new( + GoldilocksField::HALF_NUM_FULL_ROUNDS, + GoldilocksField::NUM_PARTIAL_ROUNDS, + rand_chacha::ChaCha8Rng::seed_from_u64(GoldilocksField::RNG_SEED) .sample_iter(Standard) - .take(NUM_CONSTANTS) + .take(GoldilocksField::NUM_CONSTANTS) .collect(), MdsMatrixGoldilocks, ); @@ -75,36 +58,44 @@ lazy_static! { impl FieldElementMap for GoldilocksField { type P3Field = Goldilocks; type MdsMatrix = MdsMatrixGoldilocks; + type Perm = GoldilocksField::PoseidonPerm; + + const DEGREE: usize = 2; + const WIDTH: usize = GoldilocksField::PERM_WIDTH; + const RATE: usize = 4; + const OUT: usize = 4; + const N: usize = 2; + const CHUNK: usize = 4; + const DIGEST_ELEMS: usize = 4; fn to_p3_field(&self) -> Self::P3Field { Goldilocks::from_canonical_u64(self.to_integer().try_into_u64().unwrap()) } -} -pub fn get_challenger_goldilocks() -> Challenger { - Challenger::new(PERM_GL.clone()) -} + fn get_challenger() -> Challenger { + Challenger::new(PERM_GL.clone()) + } -pub fn get_config_goldilocks( -) -> StarkConfig, Challenge, Challenger> { - let hash = Hash::::new(PERM_GL.clone()); + fn get_config() -> Config { + let hash = Hash::new(PERM_GL.clone()); - let compress = Compress::::new(PERM_GL.clone()); + let compress = Compress::new(PERM_GL.clone()); - let val_mmcs = ValMmcs::::new(hash, compress); + let val_mmcs = ValMmcs::new(hash, compress); - let challenge_mmcs = ChallengeMmcs::::new(val_mmcs.clone()); + let challenge_mmcs = ChallengeMmcs::new(val_mmcs.clone()); - let dft = Dft {}; + let dft = Dft {}; - let fri_config = FriConfig { - log_blowup: FRI_LOG_BLOWUP, - num_queries: FRI_NUM_QUERIES, - proof_of_work_bits: FRI_PROOF_OF_WORK_BITS, - mmcs: challenge_mmcs, - }; + let fri_config = FriConfig { + log_blowup: FRI_LOG_BLOWUP, + num_queries: FRI_NUM_QUERIES, + proof_of_work_bits: FRI_PROOF_OF_WORK_BITS, + mmcs: challenge_mmcs, + }; - let pcs = MyPcs::::new(dft, val_mmcs, fri_config); + let pcs = MyPcs::new(dft, val_mmcs, fri_config); - Config::new(pcs) + Config::new(pcs) + } } diff --git a/plonky3/src/params.rs b/plonky3/src/params.rs index 65d7eae034..88a3d3d54a 100644 --- a/plonky3/src/params.rs +++ b/plonky3/src/params.rs @@ -8,8 +8,6 @@ use p3_fri::{FriConfig, TwoAdicFriPcs}; use p3_symmetric::{compression::TruncatedPermutation, CryptographicPermutation, Permutation}; use p3_uni_stark::StarkConfig; -type Dft = Radix2DitParallel; - pub trait FieldElementMap: Clone + Send + Sync { type P3Field: PrimeField; type MdsMatrix; @@ -21,6 +19,7 @@ pub trait FieldElementMap: Clone + Send + Sync { type Challenge = BinomialExtensionField; type Challenger = DuplexChallenger; type ChallengeMmcs = ExtensionMmcs; + type Dft = Radix2DitParallel; type MyPcs = TwoAdicFriPcs; type Config = StarkConfig; @@ -31,6 +30,7 @@ pub trait FieldElementMap: Clone + Send + Sync { const N: usize; const CHUNK: usize; const DIGEST_ELEMS: usize; + const FRI_LOG_BLOWUP: usize = 1; const FRI_NUM_QUERIES: usize = 100; const FRI_PROOF_OF_WORK_BITS: usize = 16; From 7fee9d382e46112cccac14c5c4606478a70f068c Mon Sep 17 00:00:00 2001 From: topanisto Date: Mon, 19 Aug 2024 13:10:38 +0200 Subject: [PATCH 04/17] baby bear and goldilocks impl done --- plonky3/src/baby_bear.rs | 9 ++++++--- plonky3/src/goldilocks.rs | 5 ++++- plonky3/src/params.rs | 9 +++------ plonky3/src/stark.rs | 4 +--- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/plonky3/src/baby_bear.rs b/plonky3/src/baby_bear.rs index bfb4dfc48c..d1d2d9374a 100644 --- a/plonky3/src/baby_bear.rs +++ b/plonky3/src/baby_bear.rs @@ -17,7 +17,7 @@ use p3_uni_stark::StarkConfig; use rand::{distributions::Standard, Rng, SeedableRng}; -use powdr_number::{BabyBearField, FieldElement}; +use powdr_number::{BabyBearField, FieldElement, LargeInt}; pub trait Poseidon2Compatible { const D: u64; @@ -26,6 +26,7 @@ pub trait Poseidon2Compatible { const PERM_WIDTH: usize; const RNG_SEED: u64 = 42; + type PermObject; type Poseidon2Perm; } @@ -37,6 +38,7 @@ impl Poseidon2Compatible for BabyBearField { const ROUNDS_P: usize = 13; const PERM_WIDTH: usize = 16; + type PermObject = [BabyBear; Self::PERM_WIDTH]; type Poseidon2Perm = Poseidon2< BabyBear, Poseidon2ExternalMatrixGeneral, @@ -48,7 +50,7 @@ impl Poseidon2Compatible for BabyBearField { lazy_static! { static ref PERM_BB: ::Poseidon2Perm = - BabyBearField::Poseidon2Perm::new( + ::Poseidon2Perm::new( BabyBearField::ROUNDS_F, rand_chacha::ChaCha8Rng::seed_from_u64(BabyBearField::RNG_SEED) .sample_iter(Standard) @@ -67,6 +69,7 @@ lazy_static! { impl FieldElementMap for BabyBearField { type P3Field = BabyBear; type MdsMatrix = MdsMatrixBabyBear; + type PermObject = ::PermObject; type Perm = ::Poseidon2Perm; type Hash = PaddingFreeSponge; @@ -85,7 +88,7 @@ impl FieldElementMap for BabyBearField { type MyPcs = TwoAdicFriPcs; type Config = StarkConfig; - const DEGREE: usize = 2; + const DEGREE: usize = 4; const WIDTH: usize = BabyBearField::PERM_WIDTH; const RATE: usize = 8; const OUT: usize = 8; diff --git a/plonky3/src/goldilocks.rs b/plonky3/src/goldilocks.rs index 89df3cfdc5..c73d040044 100644 --- a/plonky3/src/goldilocks.rs +++ b/plonky3/src/goldilocks.rs @@ -23,9 +23,10 @@ pub trait PoseidonCompatible { const HALF_NUM_FULL_ROUNDS: usize; const NUM_PARTIAL_ROUNDS: usize; const NUM_ROUNDS: usize = 2 * Self::HALF_NUM_FULL_ROUNDS + Self::NUM_PARTIAL_ROUNDS; - const NUM_CONSTANTS: usize = Self::WIDTH * Self::NUM_ROUNDS; + const NUM_CONSTANTS: usize = Self::PERM_WIDTH * Self::NUM_ROUNDS; const RNG_SEED: u64 = 42; + type PermObject; type PoseidonPerm; } @@ -35,6 +36,7 @@ impl PoseidonCompatible for GoldilocksField { const HALF_NUM_FULL_ROUNDS: usize = 4; const NUM_PARTIAL_ROUNDS: usize = 22; + type PermObject = [Goldilocks; Self::PERM_WIDTH]; type PoseidonPerm = Poseidon; } @@ -55,6 +57,7 @@ lazy_static! { impl FieldElementMap for GoldilocksField { type P3Field = Goldilocks; type MdsMatrix = MdsMatrixGoldilocks; + type PermObject = ::PermObject; type Perm = ::PoseidonPerm; type Hash = PaddingFreeSponge; diff --git a/plonky3/src/params.rs b/plonky3/src/params.rs index 2fabc50975..7d4cca3f5b 100644 --- a/plonky3/src/params.rs +++ b/plonky3/src/params.rs @@ -1,9 +1,6 @@ -use p3_baby_bear::BabyBearParameters; -use p3_field::{AbstractField, PrimeField}; -use p3_fri::{FriConfig, TwoAdicFriPcs}; -use p3_goldilocks::Goldilocks; +use p3_field::PrimeField; use p3_symmetric::{CryptographicPermutation, Permutation}; -use p3_uni_stark::StarkConfig; +use p3_uni_stark::StarkGenericConfig; use powdr_number::FieldElement; pub(crate) trait FieldElementMap: Clone + Send + Sync { @@ -19,7 +16,7 @@ pub(crate) trait FieldElementMap: Clone + Send + Sync { type ValMmcs; type ChallengeMmcs; type MyPcs; - type Config; + type Config: StarkGenericConfig; const DEGREE: usize; const WIDTH: usize; diff --git a/plonky3/src/stark.rs b/plonky3/src/stark.rs index 3bca477ee1..889e557ffb 100644 --- a/plonky3/src/stark.rs +++ b/plonky3/src/stark.rs @@ -14,12 +14,10 @@ use powdr_executor::witgen::WitgenCallback; use p3_uni_stark::{ prove_with_key, verify_with_key, Proof, StarkGenericConfig, StarkProvingKey, StarkVerifyingKey, }; -use powdr_number::{FieldElement, KnownField}; +use powdr_number::{BabyBearField, FieldElement, GoldilocksField, KnownField}; use crate::{circuit_builder::PowdrCircuit, params::FieldElementMap}; -use crate::goldilocks::{get_challenger_goldilocks, get_config_goldilocks, Challenger, Config}; - pub struct Plonky3Prover { /// The analyzed PIL analyzed: Arc>, From d210602438563b74d2a85a905b1feb15e389ed0d Mon Sep 17 00:00:00 2001 From: topanisto Date: Mon, 19 Aug 2024 13:22:58 +0200 Subject: [PATCH 05/17] baby bear and goldilocks impl done --- plonky3/src/circuit_builder.rs | 2 +- plonky3/src/params.rs | 4 ++-- plonky3/src/stark.rs | 20 +++++++++----------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/plonky3/src/circuit_builder.rs b/plonky3/src/circuit_builder.rs index e4724b7375..5049a40972 100644 --- a/plonky3/src/circuit_builder.rs +++ b/plonky3/src/circuit_builder.rs @@ -50,7 +50,7 @@ impl<'a, T: FieldElement + FieldElementMap + Sync> PowdrCircuit<'a, T> { // witness values witness.clone().map(move |(_, v)| v[i as usize]) }) - .map(|f| f.to_p3_field()) + .map(|f| T::to_p3_field(f)) .collect() } 0 => { diff --git a/plonky3/src/params.rs b/plonky3/src/params.rs index 7d4cca3f5b..2dbe19a0f5 100644 --- a/plonky3/src/params.rs +++ b/plonky3/src/params.rs @@ -3,7 +3,7 @@ use p3_symmetric::{CryptographicPermutation, Permutation}; use p3_uni_stark::StarkGenericConfig; use powdr_number::FieldElement; -pub(crate) trait FieldElementMap: Clone + Send + Sync { +pub(crate) trait FieldElementMap: FieldElement { type P3Field: PrimeField; type MdsMatrix; type PermObject: Clone; @@ -30,7 +30,7 @@ pub(crate) trait FieldElementMap: Clone + Send + Sync { const FRI_NUM_QUERIES: usize = 100; const FRI_PROOF_OF_WORK_BITS: usize = 16; - fn to_p3_field(elt: T) -> Self::P3Field; + fn to_p3_field(self) -> Self::P3Field; fn get_challenger() -> Self::Challenger; diff --git a/plonky3/src/stark.rs b/plonky3/src/stark.rs index 889e557ffb..0d7d017532 100644 --- a/plonky3/src/stark.rs +++ b/plonky3/src/stark.rs @@ -11,22 +11,20 @@ use powdr_ast::analyzed::Analyzed; use powdr_executor::witgen::WitgenCallback; -use p3_uni_stark::{ - prove_with_key, verify_with_key, Proof, StarkGenericConfig, StarkProvingKey, StarkVerifyingKey, -}; +use p3_uni_stark::{prove_with_key, verify_with_key, Proof, StarkProvingKey, StarkVerifyingKey}; use powdr_number::{BabyBearField, FieldElement, GoldilocksField, KnownField}; use crate::{circuit_builder::PowdrCircuit, params::FieldElementMap}; -pub struct Plonky3Prover { +pub struct Plonky3Prover { /// The analyzed PIL analyzed: Arc>, /// The value of the fixed columns fixed: Arc)>>, /// Proving key - proving_key: Option>, + proving_key: Option>, /// Verifying key - verifying_key: Option>, + verifying_key: Option>, } pub enum VerificationKeyExportError { @@ -41,7 +39,7 @@ impl fmt::Display for VerificationKeyExportError { } } -impl Plonky3Prover { +impl Plonky3Prover { pub fn new(analyzed: Arc>, fixed: Arc)>>) -> Self { Self { analyzed, @@ -66,7 +64,7 @@ impl Plonky3Prover { /// Returns preprocessed matrix based on the fixed inputs [`Plonky3Prover`]. /// This is used when running the setup phase - pub fn get_preprocessed_matrix(&self) -> RowMajorMatrix { + pub fn get_preprocessed_matrix(&self) -> RowMajorMatrix { let publics = self .analyzed .get_publics() @@ -80,18 +78,18 @@ impl Plonky3Prover { .collect::)>>(); match self.fixed.len() + publics.len() { - 0 => RowMajorMatrix::new(Vec::::new(), 0), + 0 => RowMajorMatrix::new(Vec::::new(), 0), _ => RowMajorMatrix::new( // write fixed row by row (0..self.analyzed.degree()) .flat_map(|i| { self.fixed .iter() - .map(move |(_, values)| F::to_p3_field(values[i as usize])) + .map(move |(_, values)| T::to_p3_field(values[i as usize])) .chain( publics .iter() - .map(move |(_, values)| F::to_p3_field(values[i as usize])), + .map(move |(_, values)| T::to_p3_field(values[i as usize])), ) }) .collect(), From 615bcf653b831731726cf0a6f4db592b79c4bc79 Mon Sep 17 00:00:00 2001 From: topanisto Date: Tue, 20 Aug 2024 16:35:43 +0200 Subject: [PATCH 06/17] wip --- plonky3/src/baby_bear.rs | 22 ++++++++-------- plonky3/src/circuit_builder.rs | 37 +++++++++++++-------------- plonky3/src/goldilocks.rs | 26 +++++++++---------- plonky3/src/params.rs | 25 ++++++++++++------ plonky3/src/stark.rs | 46 +++++++++++++++++----------------- 5 files changed, 80 insertions(+), 76 deletions(-) diff --git a/plonky3/src/baby_bear.rs b/plonky3/src/baby_bear.rs index d1d2d9374a..eba0d0e62e 100644 --- a/plonky3/src/baby_bear.rs +++ b/plonky3/src/baby_bear.rs @@ -26,7 +26,6 @@ pub trait Poseidon2Compatible { const PERM_WIDTH: usize; const RNG_SEED: u64 = 42; - type PermObject; type Poseidon2Perm; } @@ -38,7 +37,6 @@ impl Poseidon2Compatible for BabyBearField { const ROUNDS_P: usize = 13; const PERM_WIDTH: usize = 16; - type PermObject = [BabyBear; Self::PERM_WIDTH]; type Poseidon2Perm = Poseidon2< BabyBear, Poseidon2ExternalMatrixGeneral, @@ -69,9 +67,17 @@ lazy_static! { impl FieldElementMap for BabyBearField { type P3Field = BabyBear; type MdsMatrix = MdsMatrixBabyBear; - type PermObject = ::PermObject; + type PermObject = [BabyBear; Self::PERM_WIDTH]; type Perm = ::Poseidon2Perm; + const DEGREE: usize = 4; + const WIDTH: usize = BabyBearField::PERM_WIDTH; + const RATE: usize = 8; + const OUT: usize = 8; + const N: usize = 2; + const CHUNK: usize = 8; + const DIGEST_ELEMS: usize = 8; + type Hash = PaddingFreeSponge; type Compress = TruncatedPermutation; type Challenge = BinomialExtensionField; @@ -88,14 +94,6 @@ impl FieldElementMap for BabyBearField { type MyPcs = TwoAdicFriPcs; type Config = StarkConfig; - const DEGREE: usize = 4; - const WIDTH: usize = BabyBearField::PERM_WIDTH; - const RATE: usize = 8; - const OUT: usize = 8; - const N: usize = 2; - const CHUNK: usize = 8; - const DIGEST_ELEMS: usize = 8; - fn to_p3_field(elt: T) -> Self::P3Field { BabyBear::from_canonical_u32(elt.to_integer().try_into_u32().unwrap()) } @@ -104,7 +102,7 @@ impl FieldElementMap for BabyBearField { Self::Challenger::new(PERM_BB.clone()) } - fn get_config() -> Self::Config { + fn get_config() -> StarkConfig { let hash = Self::Hash::new(PERM_BB.clone()); let compress = Self::Compress::new(PERM_BB.clone()); diff --git a/plonky3/src/circuit_builder.rs b/plonky3/src/circuit_builder.rs index 5049a40972..72c28faf92 100644 --- a/plonky3/src/circuit_builder.rs +++ b/plonky3/src/circuit_builder.rs @@ -23,7 +23,7 @@ use powdr_executor::witgen::WitgenCallback; // use powdr_number::{BabyBearField, FieldElement, GoldilocksField, LargeInt}; use powdr_number::FieldElement; -pub(crate) struct PowdrCircuit<'a, T: FieldElementMap> { +pub(crate) struct PowdrCircuit<'a, T: FieldElement, F: FieldElementMap> { /// The analyzed PIL analyzed: &'a Analyzed, /// The value of the witness columns, if set @@ -32,11 +32,11 @@ pub(crate) struct PowdrCircuit<'a, T: FieldElementMap> { _witgen_callback: Option>, /// The matrix of preprocessed values, used in debug mode to check the constraints before proving #[cfg(debug_assertions)] - preprocessed: Option::P3Field>>, + preprocessed: Option>, } -impl<'a, T: FieldElement + FieldElementMap + Sync> PowdrCircuit<'a, T> { - pub fn generate_trace_rows(&self) -> RowMajorMatrix<::P3Field> { +impl<'a, T: FieldElement + Sync, F: FieldElementMap + Sync> PowdrCircuit<'a, T, F> { + pub fn generate_trace_rows(&self) -> RowMajorMatrix { // an iterator over all columns, committed then fixed let witness = self.witness().iter(); let degrees = self.analyzed.degrees(); @@ -50,7 +50,7 @@ impl<'a, T: FieldElement + FieldElementMap + Sync> PowdrCircuit<'a, T> { // witness values witness.clone().map(move |(_, v)| v[i as usize]) }) - .map(|f| T::to_p3_field(f)) + .map(|f| F::to_p3_field(f)) .collect() } 0 => { @@ -64,7 +64,7 @@ impl<'a, T: FieldElement + FieldElementMap + Sync> PowdrCircuit<'a, T> { } } -impl<'a, T: FieldElement + FieldElementMap> PowdrCircuit<'a, T> { +impl<'a, T: FieldElement, F: FieldElementMap> PowdrCircuit<'a, T, F> { pub(crate) fn new(analyzed: &'a Analyzed) -> Self { if analyzed .definitions @@ -88,7 +88,7 @@ impl<'a, T: FieldElement + FieldElementMap> PowdrCircuit<'a, T> { } /// Calculates public values from generated witness values. - pub(crate) fn get_public_values(&self) -> Vec<::P3Field> { + pub(crate) fn get_public_values(&self) -> Vec { let witness = self .witness .as_ref() @@ -102,7 +102,7 @@ impl<'a, T: FieldElement + FieldElementMap> PowdrCircuit<'a, T> { .iter() .map(|(col_name, _, idx)| { let vals = *witness.get(&col_name).unwrap(); - vals[*idx].to_p3_field() + F::to_p3_field(vals[*idx]) }) .collect() } @@ -125,16 +125,14 @@ impl<'a, T: FieldElement + FieldElementMap> PowdrCircuit<'a, T> { #[cfg(debug_assertions)] pub(crate) fn with_preprocessed( mut self, - preprocessed_matrix: RowMajorMatrix<::P3Field>, + preprocessed_matrix: RowMajorMatrix, ) -> Self { self.preprocessed = Some(preprocessed_matrix); self } /// Conversion to plonky3 expression - fn to_plonky3_expr< - AB: AirBuilder::P3Field> + AirBuilderWithPublicValues, - >( + fn to_plonky3_expr + AirBuilderWithPublicValues>( &self, e: &AlgebraicExpression, main: &AB::M, @@ -171,7 +169,7 @@ impl<'a, T: FieldElement + FieldElementMap> PowdrCircuit<'a, T> { .get(id) .expect("Referenced public value does not exist")) .into(), - AlgebraicExpression::Number(n) => AB::Expr::from(n.to_p3_field()), + AlgebraicExpression::Number(n) => AB::Expr::from(F::to_p3_field(n.clone())), AlgebraicExpression::BinaryOperation(AlgebraicBinaryOperation { left, op, right }) => { let left = self.to_plonky3_expr::(left, main, fixed, publics); let right = self.to_plonky3_expr::(right, main, fixed, publics); @@ -203,9 +201,7 @@ impl<'a, T: FieldElement + FieldElementMap> PowdrCircuit<'a, T> { /// An extension of [Air] allowing access to the number of fixed columns -impl<'a, T: FieldElement + FieldElementMap> BaseAir<::P3Field> - for PowdrCircuit<'a, T> -{ +impl<'a, T: FieldElement, F: FieldElementMap> BaseAir for PowdrCircuit<'a, T, F> { fn width(&self) -> usize { self.analyzed.commitment_count() } @@ -214,7 +210,7 @@ impl<'a, T: FieldElement + FieldElementMap> BaseAir<::P3Fi self.analyzed.constant_count() + self.analyzed.publics_count() } - fn preprocessed_trace(&self) -> Option::P3Field>> { + fn preprocessed_trace(&self) -> Option> { #[cfg(debug_assertions)] { self.preprocessed.clone() @@ -226,9 +222,10 @@ impl<'a, T: FieldElement + FieldElementMap> BaseAir<::P3Fi impl< 'a, - T: FieldElement + FieldElementMap, - AB: AirBuilderWithPublicValues::P3Field> + PairBuilder, - > Air for PowdrCircuit<'a, T> + T: FieldElement, + F: FieldElementMap, + AB: AirBuilderWithPublicValues + PairBuilder, + > Air for PowdrCircuit<'a, T, F> { fn eval(&self, builder: &mut AB) { let main = builder.main(); diff --git a/plonky3/src/goldilocks.rs b/plonky3/src/goldilocks.rs index c73d040044..14ff9cf9be 100644 --- a/plonky3/src/goldilocks.rs +++ b/plonky3/src/goldilocks.rs @@ -15,7 +15,7 @@ use p3_poseidon::Poseidon; use p3_symmetric::{PaddingFreeSponge, TruncatedPermutation}; use p3_uni_stark::StarkConfig; use powdr_number::{FieldElement, GoldilocksField, LargeInt}; -use rand::distributions::Standard; +use rand::{distributions::Standard, Rng, SeedableRng}; pub trait PoseidonCompatible { const PERM_WIDTH: usize; @@ -26,7 +26,6 @@ pub trait PoseidonCompatible { const NUM_CONSTANTS: usize = Self::PERM_WIDTH * Self::NUM_ROUNDS; const RNG_SEED: u64 = 42; - type PermObject; type PoseidonPerm; } @@ -36,14 +35,13 @@ impl PoseidonCompatible for GoldilocksField { const HALF_NUM_FULL_ROUNDS: usize = 4; const NUM_PARTIAL_ROUNDS: usize = 22; - type PermObject = [Goldilocks; Self::PERM_WIDTH]; type PoseidonPerm = Poseidon; } lazy_static! { static ref PERM_GL: ::PoseidonPerm = - GoldilocksField::PoseidonPerm::new( + ::PoseidonPerm::new( GoldilocksField::HALF_NUM_FULL_ROUNDS, GoldilocksField::NUM_PARTIAL_ROUNDS, rand_chacha::ChaCha8Rng::seed_from_u64(GoldilocksField::RNG_SEED) @@ -57,9 +55,17 @@ lazy_static! { impl FieldElementMap for GoldilocksField { type P3Field = Goldilocks; type MdsMatrix = MdsMatrixGoldilocks; - type PermObject = ::PermObject; + type PermObject = [Goldilocks; Self::WIDTH]; type Perm = ::PoseidonPerm; + const DEGREE: usize = 2; + const WIDTH: usize = GoldilocksField::PERM_WIDTH; + const RATE: usize = 4; + const OUT: usize = 4; + const N: usize = 2; + const CHUNK: usize = 4; + const DIGEST_ELEMS: usize = 4; + type Hash = PaddingFreeSponge; type Compress = TruncatedPermutation; type Challenge = BinomialExtensionField; @@ -76,14 +82,6 @@ impl FieldElementMap for GoldilocksField { type MyPcs = TwoAdicFriPcs; type Config = StarkConfig; - const DEGREE: usize = 2; - const WIDTH: usize = GoldilocksField::PERM_WIDTH; - const RATE: usize = 4; - const OUT: usize = 4; - const N: usize = 2; - const CHUNK: usize = 4; - const DIGEST_ELEMS: usize = 4; - fn to_p3_field(elt: T) -> Self::P3Field { Goldilocks::from_canonical_u64(elt.to_integer().try_into_u64().unwrap()) } @@ -92,7 +90,7 @@ impl FieldElementMap for GoldilocksField { Self::Challenger::new(PERM_GL.clone()) } - fn get_config() -> Self::Config { + fn get_config() -> StarkConfig { let hash = Self::Hash::new(PERM_GL.clone()); let compress = Self::Compress::new(PERM_GL.clone()); diff --git a/plonky3/src/params.rs b/plonky3/src/params.rs index 2dbe19a0f5..c965aff2d8 100644 --- a/plonky3/src/params.rs +++ b/plonky3/src/params.rs @@ -1,6 +1,8 @@ -use p3_field::PrimeField; +use p3_challenger::{CanObserve, CanSample, FieldChallenger}; +use p3_commit::{Pcs, Val}; +use p3_field::{ExtensionField, PrimeField}; use p3_symmetric::{CryptographicPermutation, Permutation}; -use p3_uni_stark::StarkGenericConfig; +use p3_uni_stark::{StarkConfig, StarkGenericConfig}; use powdr_number::FieldElement; pub(crate) trait FieldElementMap: FieldElement { @@ -10,14 +12,23 @@ pub(crate) trait FieldElementMap: FieldElement { type Perm: Permutation + CryptographicPermutation; type Hash; type Compress; - type Challenge; - type Challenger; + type Challenge: ExtensionField< + Val<>::Domain>, + >; type Dft; type ValMmcs; type ChallengeMmcs; - type MyPcs; + type MyPcs: Pcs; type Config: StarkGenericConfig; + type Challenger: FieldChallenger<< + <::Challenger, + >>::Domain as p3_commit::PolynomialSpace>::Val>; + // FieldChallenger + // + CanObserve<>::Commitment> + // + CanSample; const DEGREE: usize; const WIDTH: usize; const RATE: usize; @@ -30,9 +41,9 @@ pub(crate) trait FieldElementMap: FieldElement { const FRI_NUM_QUERIES: usize = 100; const FRI_PROOF_OF_WORK_BITS: usize = 16; - fn to_p3_field(self) -> Self::P3Field; + fn to_p3_field(elt: T) -> Self::P3Field; fn get_challenger() -> Self::Challenger; - fn get_config() -> Self::Config; + fn get_config() -> StarkConfig; } diff --git a/plonky3/src/stark.rs b/plonky3/src/stark.rs index 0d7d017532..a12f0c1377 100644 --- a/plonky3/src/stark.rs +++ b/plonky3/src/stark.rs @@ -1,7 +1,5 @@ //! A plonky3 prover using FRI and Poseidon -use p3_baby_bear::BabyBear; -use p3_goldilocks::Goldilocks; use p3_matrix::dense::RowMajorMatrix; use core::fmt; @@ -11,20 +9,22 @@ use powdr_ast::analyzed::Analyzed; use powdr_executor::witgen::WitgenCallback; -use p3_uni_stark::{prove_with_key, verify_with_key, Proof, StarkProvingKey, StarkVerifyingKey}; +use p3_uni_stark::{ + prove_with_key, verify_with_key, Proof, StarkGenericConfig, StarkProvingKey, StarkVerifyingKey, +}; use powdr_number::{BabyBearField, FieldElement, GoldilocksField, KnownField}; use crate::{circuit_builder::PowdrCircuit, params::FieldElementMap}; -pub struct Plonky3Prover { +pub struct Plonky3Prover { /// The analyzed PIL analyzed: Arc>, /// The value of the fixed columns fixed: Arc)>>, /// Proving key - proving_key: Option>, + proving_key: Option>, /// Verifying key - verifying_key: Option>, + verifying_key: Option>, } pub enum VerificationKeyExportError { @@ -39,7 +39,7 @@ impl fmt::Display for VerificationKeyExportError { } } -impl Plonky3Prover { +impl Plonky3Prover { pub fn new(analyzed: Arc>, fixed: Arc)>>) -> Self { Self { analyzed, @@ -64,7 +64,7 @@ impl Plonky3Prover { /// Returns preprocessed matrix based on the fixed inputs [`Plonky3Prover`]. /// This is used when running the setup phase - pub fn get_preprocessed_matrix(&self) -> RowMajorMatrix { + pub fn get_preprocessed_matrix(&self) -> RowMajorMatrix { let publics = self .analyzed .get_publics() @@ -78,18 +78,18 @@ impl Plonky3Prover { .collect::)>>(); match self.fixed.len() + publics.len() { - 0 => RowMajorMatrix::new(Vec::::new(), 0), + 0 => RowMajorMatrix::new(Vec::::new(), 0), _ => RowMajorMatrix::new( // write fixed row by row (0..self.analyzed.degree()) .flat_map(|i| { self.fixed .iter() - .map(move |(_, values)| T::to_p3_field(values[i as usize])) + .map(move |(_, values)| F::to_p3_field(values[i as usize])) .chain( publics .iter() - .map(move |(_, values)| T::to_p3_field(values[i as usize])), + .map(move |(_, values)| F::to_p3_field(values[i as usize])), ) }) .collect(), @@ -122,11 +122,11 @@ impl Plonky3Prover { } // get the config - let config = get_config_goldilocks(); + let config = F::get_config(); // commit to the fixed columns let pcs = config.pcs(); - let domain = <_ as p3_commit::Pcs<_, Challenger>>::natural_domain_for_degree( + let domain = <_ as p3_commit::Pcs<_, F::Challenger>>::natural_domain_for_degree( pcs, self.analyzed.degree() as usize, ); @@ -147,7 +147,7 @@ impl Plonky3Prover { // commit to the evaluations let (fixed_commit, fixed_data) = - <_ as p3_commit::Pcs<_, Challenger>>::commit(pcs, evaluations); + <_ as p3_commit::Pcs<_, F::Challenger>>::commit(pcs, evaluations); let proving_key = StarkProvingKey { preprocessed_commit: fixed_commit, @@ -167,11 +167,11 @@ impl Plonky3Prover { witgen_callback: WitgenCallback, ) -> Result, String> { assert!( - T::known_field() == Some(KnownField::GoldilocksField) - || T::known_field() == Some(KnownField::BabyBearField) + F::known_field() == Some(KnownField::GoldilocksField) + || F::known_field() == Some(KnownField::BabyBearField) ); - let circuit = PowdrCircuit::new(&self.analyzed) + let circuit: PowdrCircuit = PowdrCircuit::new(&self.analyzed) .with_witgen_callback(witgen_callback) .with_witness(witness); @@ -182,9 +182,9 @@ impl Plonky3Prover { let trace = circuit.generate_trace_rows(); - let config = get_config_goldilocks(); + let config = F::get_config(); - let mut challenger = get_challenger_goldilocks(); + let mut challenger = F::get_challenger(); let proving_key = self.proving_key.as_ref(); @@ -197,7 +197,7 @@ impl Plonky3Prover { &publics, ); - let mut challenger = get_challenger_goldilocks(); + let mut challenger = F::get_challenger(); let verifying_key = self.verifying_key.as_ref(); @@ -219,12 +219,12 @@ impl Plonky3Prover { let publics = instances .iter() .flatten() - .map(|v| F::to_p3_field(v)) + .map(|v| F::to_p3_field(*v)) .collect(); - let config = get_config_goldilocks(); + let config = F::get_config(); - let mut challenger = get_challenger_goldilocks(); + let mut challenger = F::get_challenger(); let verifying_key = self.verifying_key.as_ref(); From 819c0909afd7b3928aee66f5279efb17526d7bc7 Mon Sep 17 00:00:00 2001 From: topanisto Date: Tue, 20 Aug 2024 16:52:21 +0200 Subject: [PATCH 07/17] revert to challenger state --- plonky3/src/params.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/plonky3/src/params.rs b/plonky3/src/params.rs index c965aff2d8..4f8b63b0d4 100644 --- a/plonky3/src/params.rs +++ b/plonky3/src/params.rs @@ -20,15 +20,9 @@ pub(crate) trait FieldElementMap: FieldElement { type ChallengeMmcs; type MyPcs: Pcs; type Config: StarkGenericConfig; - type Challenger: FieldChallenger<< - <::Challenger, - >>::Domain as p3_commit::PolynomialSpace>::Val>; - - // FieldChallenger - // + CanObserve<>::Commitment> - // + CanSample; + type Challenger: FieldChallenger + + CanObserve<>::Commitment> + + CanSample; const DEGREE: usize; const WIDTH: usize; const RATE: usize; From 67986191423e4d3a7ed2485da8308dce91150f4f Mon Sep 17 00:00:00 2001 From: topanisto Date: Wed, 21 Aug 2024 12:35:25 +0200 Subject: [PATCH 08/17] compiles --- plonky3/src/circuit_builder.rs | 38 +++++++++++-------------- plonky3/src/lib.rs | 2 -- plonky3/src/params.rs | 46 +++++++++++++++++------------- plonky3/src/stark.rs | 52 ++++++++++++++++------------------ 4 files changed, 69 insertions(+), 69 deletions(-) diff --git a/plonky3/src/circuit_builder.rs b/plonky3/src/circuit_builder.rs index 72c28faf92..d148803b22 100644 --- a/plonky3/src/circuit_builder.rs +++ b/plonky3/src/circuit_builder.rs @@ -8,7 +8,7 @@ use std::collections::BTreeMap; -use crate::params::FieldElementMap; +use crate::params::{FieldElementMap, Plonky3Field}; use p3_air::{Air, AirBuilder, AirBuilderWithPublicValues, BaseAir, PairBuilder}; // use p3_baby_bear::BabyBear; // use p3_field::{extension::ComplexExtendable, AbstractField, PrimeField}; @@ -21,9 +21,9 @@ use powdr_ast::analyzed::{ }; use powdr_executor::witgen::WitgenCallback; // use powdr_number::{BabyBearField, FieldElement, GoldilocksField, LargeInt}; -use powdr_number::FieldElement; +// use powdr_number::FieldElement; -pub(crate) struct PowdrCircuit<'a, T: FieldElement, F: FieldElementMap> { +pub(crate) struct PowdrCircuit<'a, T: FieldElementMap> { /// The analyzed PIL analyzed: &'a Analyzed, /// The value of the witness columns, if set @@ -32,11 +32,11 @@ pub(crate) struct PowdrCircuit<'a, T: FieldElement, F: FieldElementMap> { _witgen_callback: Option>, /// The matrix of preprocessed values, used in debug mode to check the constraints before proving #[cfg(debug_assertions)] - preprocessed: Option>, + preprocessed: Option>>, } -impl<'a, T: FieldElement + Sync, F: FieldElementMap + Sync> PowdrCircuit<'a, T, F> { - pub fn generate_trace_rows(&self) -> RowMajorMatrix { +impl<'a, T: FieldElementMap + Sync> PowdrCircuit<'a, T> { + pub fn generate_trace_rows(&self) -> RowMajorMatrix> { // an iterator over all columns, committed then fixed let witness = self.witness().iter(); let degrees = self.analyzed.degrees(); @@ -50,7 +50,7 @@ impl<'a, T: FieldElement + Sync, F: FieldElementMap + Sync> PowdrCircuit<'a, T, // witness values witness.clone().map(move |(_, v)| v[i as usize]) }) - .map(|f| F::to_p3_field(f)) + .map(|f| f.to_p3_field()) .collect() } 0 => { @@ -64,7 +64,7 @@ impl<'a, T: FieldElement + Sync, F: FieldElementMap + Sync> PowdrCircuit<'a, T, } } -impl<'a, T: FieldElement, F: FieldElementMap> PowdrCircuit<'a, T, F> { +impl<'a, T: FieldElementMap> PowdrCircuit<'a, T> { pub(crate) fn new(analyzed: &'a Analyzed) -> Self { if analyzed .definitions @@ -88,7 +88,7 @@ impl<'a, T: FieldElement, F: FieldElementMap> PowdrCircuit<'a, T, F> { } /// Calculates public values from generated witness values. - pub(crate) fn get_public_values(&self) -> Vec { + pub(crate) fn get_public_values(&self) -> Vec> { let witness = self .witness .as_ref() @@ -102,7 +102,7 @@ impl<'a, T: FieldElement, F: FieldElementMap> PowdrCircuit<'a, T, F> { .iter() .map(|(col_name, _, idx)| { let vals = *witness.get(&col_name).unwrap(); - F::to_p3_field(vals[*idx]) + vals[*idx].to_p3_field() }) .collect() } @@ -125,14 +125,14 @@ impl<'a, T: FieldElement, F: FieldElementMap> PowdrCircuit<'a, T, F> { #[cfg(debug_assertions)] pub(crate) fn with_preprocessed( mut self, - preprocessed_matrix: RowMajorMatrix, + preprocessed_matrix: RowMajorMatrix>, ) -> Self { self.preprocessed = Some(preprocessed_matrix); self } /// Conversion to plonky3 expression - fn to_plonky3_expr + AirBuilderWithPublicValues>( + fn to_plonky3_expr> + AirBuilderWithPublicValues>( &self, e: &AlgebraicExpression, main: &AB::M, @@ -169,7 +169,7 @@ impl<'a, T: FieldElement, F: FieldElementMap> PowdrCircuit<'a, T, F> { .get(id) .expect("Referenced public value does not exist")) .into(), - AlgebraicExpression::Number(n) => AB::Expr::from(F::to_p3_field(n.clone())), + AlgebraicExpression::Number(n) => AB::Expr::from(n.to_p3_field()), AlgebraicExpression::BinaryOperation(AlgebraicBinaryOperation { left, op, right }) => { let left = self.to_plonky3_expr::(left, main, fixed, publics); let right = self.to_plonky3_expr::(right, main, fixed, publics); @@ -201,7 +201,7 @@ impl<'a, T: FieldElement, F: FieldElementMap> PowdrCircuit<'a, T, F> { /// An extension of [Air] allowing access to the number of fixed columns -impl<'a, T: FieldElement, F: FieldElementMap> BaseAir for PowdrCircuit<'a, T, F> { +impl<'a, T: FieldElementMap> BaseAir> for PowdrCircuit<'a, T> { fn width(&self) -> usize { self.analyzed.commitment_count() } @@ -210,7 +210,7 @@ impl<'a, T: FieldElement, F: FieldElementMap> BaseAir for PowdrCircu self.analyzed.constant_count() + self.analyzed.publics_count() } - fn preprocessed_trace(&self) -> Option> { + fn preprocessed_trace(&self) -> Option>> { #[cfg(debug_assertions)] { self.preprocessed.clone() @@ -220,12 +220,8 @@ impl<'a, T: FieldElement, F: FieldElementMap> BaseAir for PowdrCircu } } -impl< - 'a, - T: FieldElement, - F: FieldElementMap, - AB: AirBuilderWithPublicValues + PairBuilder, - > Air for PowdrCircuit<'a, T, F> +impl<'a, T: FieldElementMap, AB: AirBuilderWithPublicValues> + PairBuilder> + Air for PowdrCircuit<'a, T> { fn eval(&self, builder: &mut AB) { let main = builder.main(); diff --git a/plonky3/src/lib.rs b/plonky3/src/lib.rs index 0d1c304a72..4bcb981bcf 100644 --- a/plonky3/src/lib.rs +++ b/plonky3/src/lib.rs @@ -1,6 +1,4 @@ -mod baby_bear; mod circuit_builder; -mod goldilocks; mod params; mod stark; diff --git a/plonky3/src/params.rs b/plonky3/src/params.rs index 4f8b63b0d4..af9a5b149b 100644 --- a/plonky3/src/params.rs +++ b/plonky3/src/params.rs @@ -1,28 +1,36 @@ use p3_challenger::{CanObserve, CanSample, FieldChallenger}; -use p3_commit::{Pcs, Val}; +use p3_commit::{Pcs, PolynomialSpace, Val}; use p3_field::{ExtensionField, PrimeField}; use p3_symmetric::{CryptographicPermutation, Permutation}; use p3_uni_stark::{StarkConfig, StarkGenericConfig}; use powdr_number::FieldElement; +pub type Plonky3Field = + < as Pcs, Challenger>>::Domain as PolynomialSpace>::Val; +pub type MyPcs = <::Config as StarkGenericConfig>::Pcs; +pub type Challenge = <::Config as StarkGenericConfig>::Challenge; +pub type Challenger = <::Config as StarkGenericConfig>::Challenger; + pub(crate) trait FieldElementMap: FieldElement { type P3Field: PrimeField; - type MdsMatrix; - type PermObject: Clone; - type Perm: Permutation + CryptographicPermutation; - type Hash; - type Compress; - type Challenge: ExtensionField< - Val<>::Domain>, - >; - type Dft; - type ValMmcs; - type ChallengeMmcs; - type MyPcs: Pcs; + // type MdsMatrix; + // type PermObject: Clone; + // type Perm: Permutation + CryptographicPermutation; + // // type Hash; + // // type Compress; + // type Challenge: ExtensionField< + // Val<>::Domain>, + // >; + // // type Dft; + // // type ValMmcs; + // // type ChallengeMmcs; + // type MyPcs: Pcs; type Config: StarkGenericConfig; - type Challenger: FieldChallenger - + CanObserve<>::Commitment> - + CanSample; + + // :FieldChallenger + // + CanObserve<>::Commitment> + // + CanSample; + const DEGREE: usize; const WIDTH: usize; const RATE: usize; @@ -35,9 +43,9 @@ pub(crate) trait FieldElementMap: FieldElement { const FRI_NUM_QUERIES: usize = 100; const FRI_PROOF_OF_WORK_BITS: usize = 16; - fn to_p3_field(elt: T) -> Self::P3Field; + fn to_p3_field(&self) -> Plonky3Field; - fn get_challenger() -> Self::Challenger; + fn get_challenger() -> Challenger; - fn get_config() -> StarkConfig; + fn get_config() -> Self::Config; } diff --git a/plonky3/src/stark.rs b/plonky3/src/stark.rs index a12f0c1377..8c426e6db7 100644 --- a/plonky3/src/stark.rs +++ b/plonky3/src/stark.rs @@ -14,17 +14,20 @@ use p3_uni_stark::{ }; use powdr_number::{BabyBearField, FieldElement, GoldilocksField, KnownField}; -use crate::{circuit_builder::PowdrCircuit, params::FieldElementMap}; +use crate::{ + circuit_builder::PowdrCircuit, + params::{Challenge, Challenger, FieldElementMap, Plonky3Field}, +}; -pub struct Plonky3Prover { +pub struct Plonky3Prover { /// The analyzed PIL analyzed: Arc>, /// The value of the fixed columns fixed: Arc)>>, /// Proving key - proving_key: Option>, + proving_key: Option>, /// Verifying key - verifying_key: Option>, + verifying_key: Option>, } pub enum VerificationKeyExportError { @@ -39,7 +42,7 @@ impl fmt::Display for VerificationKeyExportError { } } -impl Plonky3Prover { +impl Plonky3Prover { pub fn new(analyzed: Arc>, fixed: Arc)>>) -> Self { Self { analyzed, @@ -64,7 +67,7 @@ impl Plonky3Prover { /// Returns preprocessed matrix based on the fixed inputs [`Plonky3Prover`]. /// This is used when running the setup phase - pub fn get_preprocessed_matrix(&self) -> RowMajorMatrix { + pub fn get_preprocessed_matrix(&self) -> RowMajorMatrix> { let publics = self .analyzed .get_publics() @@ -78,18 +81,18 @@ impl Plonky3Prover { .collect::)>>(); match self.fixed.len() + publics.len() { - 0 => RowMajorMatrix::new(Vec::::new(), 0), + 0 => RowMajorMatrix::new(Vec::>::new(), 0), _ => RowMajorMatrix::new( // write fixed row by row (0..self.analyzed.degree()) .flat_map(|i| { self.fixed .iter() - .map(move |(_, values)| F::to_p3_field(values[i as usize])) + .map(move |(_, values)| values[i as usize].to_p3_field()) .chain( publics .iter() - .map(move |(_, values)| F::to_p3_field(values[i as usize])), + .map(move |(_, values)| values[i as usize].to_p3_field()), ) }) .collect(), @@ -99,7 +102,7 @@ impl Plonky3Prover { } } -impl Plonky3Prover { +impl Plonky3Prover { pub fn setup(&mut self) { // get fixed columns let fixed = &self.fixed; @@ -122,11 +125,11 @@ impl Plonky3Prover { } // get the config - let config = F::get_config(); + let config = T::get_config(); // commit to the fixed columns let pcs = config.pcs(); - let domain = <_ as p3_commit::Pcs<_, F::Challenger>>::natural_domain_for_degree( + let domain = <_ as p3_commit::Pcs<_, Challenger>>::natural_domain_for_degree( pcs, self.analyzed.degree() as usize, ); @@ -137,7 +140,7 @@ impl Plonky3Prover { fixed .iter() .chain(publics.iter()) - .map(move |(_, values)| F::to_p3_field(values[i as usize])) + .map(move |(_, values)| values[i as usize].to_p3_field()) }) .collect(), self.fixed.len() + publics.len(), @@ -147,10 +150,10 @@ impl Plonky3Prover { // commit to the evaluations let (fixed_commit, fixed_data) = - <_ as p3_commit::Pcs<_, F::Challenger>>::commit(pcs, evaluations); + <_ as p3_commit::Pcs<_, Challenger>>::commit(pcs, evaluations); let proving_key = StarkProvingKey { - preprocessed_commit: fixed_commit, + preprocessed_commit: fixed_commit.clone(), preprocessed_data: fixed_data, }; let verifying_key = StarkVerifyingKey { @@ -166,12 +169,7 @@ impl Plonky3Prover { witness: &[(String, Vec)], witgen_callback: WitgenCallback, ) -> Result, String> { - assert!( - F::known_field() == Some(KnownField::GoldilocksField) - || F::known_field() == Some(KnownField::BabyBearField) - ); - - let circuit: PowdrCircuit = PowdrCircuit::new(&self.analyzed) + let circuit: PowdrCircuit = PowdrCircuit::new(&self.analyzed) .with_witgen_callback(witgen_callback) .with_witness(witness); @@ -182,9 +180,9 @@ impl Plonky3Prover { let trace = circuit.generate_trace_rows(); - let config = F::get_config(); + let config = T::get_config(); - let mut challenger = F::get_challenger(); + let mut challenger = T::get_challenger(); let proving_key = self.proving_key.as_ref(); @@ -197,7 +195,7 @@ impl Plonky3Prover { &publics, ); - let mut challenger = F::get_challenger(); + let mut challenger = T::get_challenger(); let verifying_key = self.verifying_key.as_ref(); @@ -219,12 +217,12 @@ impl Plonky3Prover { let publics = instances .iter() .flatten() - .map(|v| F::to_p3_field(*v)) + .map(|v| v.to_p3_field()) .collect(); - let config = F::get_config(); + let config = T::get_config(); - let mut challenger = F::get_challenger(); + let mut challenger = T::get_challenger(); let verifying_key = self.verifying_key.as_ref(); From 97347040fcd29077d36c8edf8e51ca8e9b343fbc Mon Sep 17 00:00:00 2001 From: topanisto Date: Wed, 21 Aug 2024 14:04:48 +0200 Subject: [PATCH 09/17] working tests --- plonky3/src/baby_bear.rs | 154 +++++++++++++++++--------------------- plonky3/src/goldilocks.rs | 134 +++++++++++++++------------------ plonky3/src/lib.rs | 3 +- plonky3/src/params.rs | 40 +--------- plonky3/src/stark.rs | 56 ++++++++++++-- 5 files changed, 187 insertions(+), 200 deletions(-) diff --git a/plonky3/src/baby_bear.rs b/plonky3/src/baby_bear.rs index eba0d0e62e..6cf11bb6f9 100644 --- a/plonky3/src/baby_bear.rs +++ b/plonky3/src/baby_bear.rs @@ -3,8 +3,8 @@ use lazy_static::lazy_static; -use crate::params::FieldElementMap; -use p3_baby_bear::{BabyBear, DiffusionMatrixBabyBear, MdsMatrixBabyBear}; +use crate::params::{Challenger, FieldElementMap, Plonky3Field}; +use p3_baby_bear::{BabyBear, DiffusionMatrixBabyBear}; use p3_challenger::DuplexChallenger; use p3_commit::ExtensionMmcs; use p3_dft::Radix2DitParallel; @@ -19,108 +19,90 @@ use rand::{distributions::Standard, Rng, SeedableRng}; use powdr_number::{BabyBearField, FieldElement, LargeInt}; -pub trait Poseidon2Compatible { - const D: u64; - const ROUNDS_F: usize; - const ROUNDS_P: usize; - const PERM_WIDTH: usize; - const RNG_SEED: u64 = 42; - - type Poseidon2Perm; -} - -impl Poseidon2Compatible for BabyBearField { - const D: u64 = 7; - // params directly taken from plonky3's poseidon2_round_numbers_128 function - // to guarentee 128-bit security. - const ROUNDS_F: usize = 8; - const ROUNDS_P: usize = 13; - const PERM_WIDTH: usize = 16; - - type Poseidon2Perm = Poseidon2< - BabyBear, - Poseidon2ExternalMatrixGeneral, - DiffusionMatrixBabyBear, - { Self::PERM_WIDTH }, - { Self::D }, - >; -} +const D: u64 = 7; +// params directly taken from plonky3's poseidon2_round_numbers_128 function +// to guarentee 128-bit security. +const ROUNDS_F: usize = 8; +const ROUNDS_P: usize = 13; +const WIDTH: usize = 16; +type Perm = Poseidon2; + +const DEGREE: usize = 4; +type FriChallenge = BinomialExtensionField; + +const RATE: usize = 8; +const OUT: usize = 8; +type FriChallenger = DuplexChallenger; +type Hash = PaddingFreeSponge; + +const N: usize = 2; +const CHUNK: usize = 8; +type Compress = TruncatedPermutation; +const DIGEST_ELEMS: usize = 8; +type ValMmcs = FieldMerkleTreeMmcs< + ::Packing, + ::Packing, + Hash, + Compress, + DIGEST_ELEMS, +>; + +type ChallengeMmcs = ExtensionMmcs; +type Dft = Radix2DitParallel; +type MyPcs = TwoAdicFriPcs; + +const FRI_LOG_BLOWUP: usize = 1; +const FRI_NUM_QUERIES: usize = 100; +const FRI_PROOF_OF_WORK_BITS: usize = 16; + +const RNG_SEED: u64 = 42; lazy_static! { - static ref PERM_BB: ::Poseidon2Perm = - ::Poseidon2Perm::new( - BabyBearField::ROUNDS_F, - rand_chacha::ChaCha8Rng::seed_from_u64(BabyBearField::RNG_SEED) - .sample_iter(Standard) - .take(BabyBearField::ROUNDS_F) - .collect::>(), - Poseidon2ExternalMatrixGeneral, - BabyBearField::ROUNDS_P, - rand_chacha::ChaCha8Rng::seed_from_u64(BabyBearField::RNG_SEED) - .sample_iter(Standard) - .take(BabyBearField::ROUNDS_P) - .collect(), - DiffusionMatrixBabyBear::default() - ); + static ref PERM_BB: Perm = Perm::new( + ROUNDS_F, + rand_chacha::ChaCha8Rng::seed_from_u64(RNG_SEED) + .sample_iter(Standard) + .take(ROUNDS_F) + .collect::>(), + Poseidon2ExternalMatrixGeneral, + ROUNDS_P, + rand_chacha::ChaCha8Rng::seed_from_u64(RNG_SEED) + .sample_iter(Standard) + .take(ROUNDS_P) + .collect(), + DiffusionMatrixBabyBear::default() + ); } impl FieldElementMap for BabyBearField { - type P3Field = BabyBear; - type MdsMatrix = MdsMatrixBabyBear; - type PermObject = [BabyBear; Self::PERM_WIDTH]; - type Perm = ::Poseidon2Perm; - - const DEGREE: usize = 4; - const WIDTH: usize = BabyBearField::PERM_WIDTH; - const RATE: usize = 8; - const OUT: usize = 8; - const N: usize = 2; - const CHUNK: usize = 8; - const DIGEST_ELEMS: usize = 8; - - type Hash = PaddingFreeSponge; - type Compress = TruncatedPermutation; - type Challenge = BinomialExtensionField; - type Challenger = DuplexChallenger; - type Dft = Radix2DitParallel; - type ValMmcs = FieldMerkleTreeMmcs< - ::Packing, - ::Packing, - Self::Hash, - Self::Compress, - { Self::DIGEST_ELEMS }, - >; - type ChallengeMmcs = ExtensionMmcs; - type MyPcs = TwoAdicFriPcs; - type Config = StarkConfig; - - fn to_p3_field(elt: T) -> Self::P3Field { - BabyBear::from_canonical_u32(elt.to_integer().try_into_u32().unwrap()) + type Config = StarkConfig; + fn to_p3_field(&self) -> Plonky3Field { + BabyBear::from_canonical_u32(self.to_integer().try_into_u32().unwrap()) } - fn get_challenger() -> Self::Challenger { - Self::Challenger::new(PERM_BB.clone()) + fn get_challenger() -> Challenger { + FriChallenger::new(PERM_BB.clone()) } - fn get_config() -> StarkConfig { - let hash = Self::Hash::new(PERM_BB.clone()); + fn get_config() -> Self::Config { + let hash = Hash::new(PERM_BB.clone()); - let compress = Self::Compress::new(PERM_BB.clone()); + let compress = Compress::new(PERM_BB.clone()); - let val_mmcs = Self::ValMmcs::new(hash, compress); + let val_mmcs = ValMmcs::new(hash, compress); - let challenge_mmcs = Self::ChallengeMmcs::new(val_mmcs.clone()); + let challenge_mmcs = ChallengeMmcs::new(val_mmcs.clone()); - let dft = Self::Dft {}; + let dft = Dft {}; let fri_config = FriConfig { - log_blowup: Self::FRI_LOG_BLOWUP, - num_queries: Self::FRI_NUM_QUERIES, - proof_of_work_bits: Self::FRI_PROOF_OF_WORK_BITS, + log_blowup: FRI_LOG_BLOWUP, + num_queries: FRI_NUM_QUERIES, + proof_of_work_bits: FRI_PROOF_OF_WORK_BITS, mmcs: challenge_mmcs, }; - let pcs = Self::MyPcs::new(dft, val_mmcs, fri_config); + let pcs = MyPcs::new(dft, val_mmcs, fri_config); Self::Config::new(pcs) } diff --git a/plonky3/src/goldilocks.rs b/plonky3/src/goldilocks.rs index 14ff9cf9be..17070d5b69 100644 --- a/plonky3/src/goldilocks.rs +++ b/plonky3/src/goldilocks.rs @@ -3,7 +3,7 @@ use lazy_static::lazy_static; -use crate::params::FieldElementMap; +use crate::params::{Challenger, FieldElementMap, Plonky3Field}; use p3_challenger::DuplexChallenger; use p3_commit::ExtensionMmcs; use p3_dft::Radix2DitParallel; @@ -17,98 +17,88 @@ use p3_uni_stark::StarkConfig; use powdr_number::{FieldElement, GoldilocksField, LargeInt}; use rand::{distributions::Standard, Rng, SeedableRng}; -pub trait PoseidonCompatible { - const PERM_WIDTH: usize; - const ALPHA: u64; - const HALF_NUM_FULL_ROUNDS: usize; - const NUM_PARTIAL_ROUNDS: usize; - const NUM_ROUNDS: usize = 2 * Self::HALF_NUM_FULL_ROUNDS + Self::NUM_PARTIAL_ROUNDS; - const NUM_CONSTANTS: usize = Self::PERM_WIDTH * Self::NUM_ROUNDS; - const RNG_SEED: u64 = 42; +const DEGREE: usize = 2; +type FriChallenge = BinomialExtensionField; +const WIDTH: usize = 8; +const ALPHA: u64 = 7; +type Perm = Poseidon; - type PoseidonPerm; -} +const RATE: usize = 4; +const OUT: usize = 4; +type Hash = PaddingFreeSponge; -impl PoseidonCompatible for GoldilocksField { - const PERM_WIDTH: usize = 8; - const ALPHA: u64 = 7; - const HALF_NUM_FULL_ROUNDS: usize = 4; - const NUM_PARTIAL_ROUNDS: usize = 22; +const N: usize = 2; +const CHUNK: usize = 4; +type Compress = TruncatedPermutation; - type PoseidonPerm = - Poseidon; -} +const DIGEST_ELEMS: usize = 4; +type ValMmcs = FieldMerkleTreeMmcs< + ::Packing, + ::Packing, + Hash, + Compress, + DIGEST_ELEMS, +>; + +pub type FriChallenger = DuplexChallenger; +type ChallengeMmcs = ExtensionMmcs; +type Dft = Radix2DitParallel; +type MyPcs = TwoAdicFriPcs; + +const HALF_NUM_FULL_ROUNDS: usize = 4; +const NUM_PARTIAL_ROUNDS: usize = 22; + +const FRI_LOG_BLOWUP: usize = 1; +const FRI_NUM_QUERIES: usize = 100; +const FRI_PROOF_OF_WORK_BITS: usize = 16; + +const NUM_ROUNDS: usize = 2 * HALF_NUM_FULL_ROUNDS + NUM_PARTIAL_ROUNDS; +const NUM_CONSTANTS: usize = WIDTH * NUM_ROUNDS; + +const RNG_SEED: u64 = 42; lazy_static! { - static ref PERM_GL: ::PoseidonPerm = - ::PoseidonPerm::new( - GoldilocksField::HALF_NUM_FULL_ROUNDS, - GoldilocksField::NUM_PARTIAL_ROUNDS, - rand_chacha::ChaCha8Rng::seed_from_u64(GoldilocksField::RNG_SEED) - .sample_iter(Standard) - .take(GoldilocksField::NUM_CONSTANTS) - .collect(), - MdsMatrixGoldilocks, - ); + static ref PERM_GL: Perm = Perm::new( + HALF_NUM_FULL_ROUNDS, + NUM_PARTIAL_ROUNDS, + rand_chacha::ChaCha8Rng::seed_from_u64(RNG_SEED) + .sample_iter(Standard) + .take(NUM_CONSTANTS) + .collect(), + MdsMatrixGoldilocks, + ); } impl FieldElementMap for GoldilocksField { - type P3Field = Goldilocks; - type MdsMatrix = MdsMatrixGoldilocks; - type PermObject = [Goldilocks; Self::WIDTH]; - type Perm = ::PoseidonPerm; - - const DEGREE: usize = 2; - const WIDTH: usize = GoldilocksField::PERM_WIDTH; - const RATE: usize = 4; - const OUT: usize = 4; - const N: usize = 2; - const CHUNK: usize = 4; - const DIGEST_ELEMS: usize = 4; - - type Hash = PaddingFreeSponge; - type Compress = TruncatedPermutation; - type Challenge = BinomialExtensionField; - type Challenger = DuplexChallenger; - type Dft = Radix2DitParallel; - type ValMmcs = FieldMerkleTreeMmcs< - ::Packing, - ::Packing, - Self::Hash, - Self::Compress, - { Self::DIGEST_ELEMS }, - >; - type ChallengeMmcs = ExtensionMmcs; - type MyPcs = TwoAdicFriPcs; - type Config = StarkConfig; - - fn to_p3_field(elt: T) -> Self::P3Field { - Goldilocks::from_canonical_u64(elt.to_integer().try_into_u64().unwrap()) + type Config = StarkConfig; + + fn to_p3_field(&self) -> Plonky3Field { + Goldilocks::from_canonical_u64(self.to_integer().try_into_u64().unwrap()) } - fn get_challenger() -> Self::Challenger { - Self::Challenger::new(PERM_GL.clone()) + fn get_challenger() -> Challenger { + FriChallenger::new(PERM_GL.clone()) } - fn get_config() -> StarkConfig { - let hash = Self::Hash::new(PERM_GL.clone()); + fn get_config() -> Self::Config { + let hash = Hash::new(PERM_GL.clone()); - let compress = Self::Compress::new(PERM_GL.clone()); + let compress = Compress::new(PERM_GL.clone()); - let val_mmcs = Self::ValMmcs::new(hash, compress); + let val_mmcs = ValMmcs::new(hash, compress); - let challenge_mmcs = Self::ChallengeMmcs::new(val_mmcs.clone()); + let challenge_mmcs = ChallengeMmcs::new(val_mmcs.clone()); - let dft = Self::Dft {}; + let dft = Dft {}; let fri_config = FriConfig { - log_blowup: Self::FRI_LOG_BLOWUP, - num_queries: Self::FRI_NUM_QUERIES, - proof_of_work_bits: Self::FRI_PROOF_OF_WORK_BITS, + log_blowup: FRI_LOG_BLOWUP, + num_queries: FRI_NUM_QUERIES, + proof_of_work_bits: FRI_PROOF_OF_WORK_BITS, mmcs: challenge_mmcs, }; - let pcs = Self::MyPcs::new(dft, val_mmcs, fri_config); + let pcs = MyPcs::new(dft, val_mmcs, fri_config); Self::Config::new(pcs) } diff --git a/plonky3/src/lib.rs b/plonky3/src/lib.rs index 4bcb981bcf..bb652e0156 100644 --- a/plonky3/src/lib.rs +++ b/plonky3/src/lib.rs @@ -1,5 +1,6 @@ +mod baby_bear; mod circuit_builder; +mod goldilocks; mod params; mod stark; - pub use stark::Plonky3Prover; diff --git a/plonky3/src/params.rs b/plonky3/src/params.rs index af9a5b149b..7c1da90e16 100644 --- a/plonky3/src/params.rs +++ b/plonky3/src/params.rs @@ -1,8 +1,5 @@ -use p3_challenger::{CanObserve, CanSample, FieldChallenger}; -use p3_commit::{Pcs, PolynomialSpace, Val}; -use p3_field::{ExtensionField, PrimeField}; -use p3_symmetric::{CryptographicPermutation, Permutation}; -use p3_uni_stark::{StarkConfig, StarkGenericConfig}; +use p3_commit::{Pcs, PolynomialSpace}; +use p3_uni_stark::StarkGenericConfig; use powdr_number::FieldElement; pub type Plonky3Field = @@ -11,37 +8,8 @@ pub type MyPcs = <::Config as StarkGenericConfig>::Pcs; pub type Challenge = <::Config as StarkGenericConfig>::Challenge; pub type Challenger = <::Config as StarkGenericConfig>::Challenger; -pub(crate) trait FieldElementMap: FieldElement { - type P3Field: PrimeField; - // type MdsMatrix; - // type PermObject: Clone; - // type Perm: Permutation + CryptographicPermutation; - // // type Hash; - // // type Compress; - // type Challenge: ExtensionField< - // Val<>::Domain>, - // >; - // // type Dft; - // // type ValMmcs; - // // type ChallengeMmcs; - // type MyPcs: Pcs; - type Config: StarkGenericConfig; - - // :FieldChallenger - // + CanObserve<>::Commitment> - // + CanSample; - - const DEGREE: usize; - const WIDTH: usize; - const RATE: usize; - const OUT: usize; - const N: usize; - const CHUNK: usize; - const DIGEST_ELEMS: usize; - - const FRI_LOG_BLOWUP: usize = 1; - const FRI_NUM_QUERIES: usize = 100; - const FRI_PROOF_OF_WORK_BITS: usize = 16; +pub trait FieldElementMap: FieldElement { + type Config: StarkGenericConfig + Sync; fn to_p3_field(&self) -> Plonky3Field; diff --git a/plonky3/src/stark.rs b/plonky3/src/stark.rs index 8c426e6db7..d48ddf6445 100644 --- a/plonky3/src/stark.rs +++ b/plonky3/src/stark.rs @@ -12,11 +12,10 @@ use powdr_executor::witgen::WitgenCallback; use p3_uni_stark::{ prove_with_key, verify_with_key, Proof, StarkGenericConfig, StarkProvingKey, StarkVerifyingKey, }; -use powdr_number::{BabyBearField, FieldElement, GoldilocksField, KnownField}; use crate::{ circuit_builder::PowdrCircuit, - params::{Challenge, Challenger, FieldElementMap, Plonky3Field}, + params::{Challenger, FieldElementMap, Plonky3Field}, }; pub struct Plonky3Prover { @@ -243,7 +242,7 @@ mod tests { use std::sync::Arc; use powdr_executor::constant_evaluator::get_uniquely_sized_cloned; - use powdr_number::GoldilocksField; + use powdr_number::{BabyBearField, GoldilocksField}; use powdr_pipeline::Pipeline; use test_log::test; @@ -274,10 +273,47 @@ mod tests { } } + fn run_test_baby_bear(pil: &str) { + run_test_baby_bear_publics(pil, None) + } + + fn run_test_baby_bear_publics(pil: &str, malicious_publics: Option>) { + let mut pipeline = Pipeline::::default().from_pil_string(pil.to_string()); + + let pil = pipeline.compute_optimized_pil().unwrap(); + let witness_callback = pipeline.witgen_callback().unwrap(); + let witness = pipeline.compute_witness().unwrap(); + let fixed = pipeline.compute_fixed_cols().unwrap(); + let fixed = Arc::new(get_uniquely_sized_cloned(&fixed).unwrap()); + + let mut prover = Plonky3Prover::new(pil, fixed); + prover.setup(); + let proof = prover.prove(&witness, witness_callback); + + assert!(proof.is_ok()); + + if let Some(publics) = malicious_publics { + prover.verify(&proof.unwrap(), &[publics]).unwrap() + } + } + + #[test] + fn add_baby_bear() { + let content = r#" + namespace Add(8); + col witness x; + col witness y; + col witness z; + x + y = z; + "#; + run_test_baby_bear(content); + } + #[test] fn public_values() { let content = "namespace Global(8); pol witness x; x * (x - 1) = 0; public out = x(7);"; run_test_goldilocks(content); + run_test_baby_bear(content); } #[test] @@ -292,6 +328,7 @@ mod tests { y = 1 + :oldstate; "#; run_test_goldilocks(content); + run_test_baby_bear(content); } #[test] @@ -308,8 +345,11 @@ mod tests { public outz = z(7); "#; - let malicious_publics = Some(vec![GoldilocksField::from(0)]); - run_test_goldilocks_publics(content, malicious_publics); + let gl_malicious_publics = Some(vec![GoldilocksField::from(0)]); + run_test_goldilocks_publics(content, gl_malicious_publics); + + let bb_malicious_publics = Some(vec![BabyBearField::from(0)]); + run_test_baby_bear_publics(content, bb_malicious_publics); } #[test] @@ -317,6 +357,7 @@ mod tests { fn empty() { let content = "namespace Global(8);"; run_test_goldilocks(content); + run_test_baby_bear(content); } #[test] @@ -329,6 +370,7 @@ mod tests { x + y = z; "#; run_test_goldilocks(content); + run_test_baby_bear(content); } #[test] @@ -340,6 +382,7 @@ mod tests { x * y = y; "#; run_test_goldilocks(content); + run_test_baby_bear(content); } #[test] @@ -355,12 +398,14 @@ mod tests { x = y + beta; "#; run_test_goldilocks(content); + run_test_baby_bear(content); } #[test] fn polynomial_identity() { let content = "namespace Global(8); pol fixed z = [1, 2]*; pol witness a; a = z + 1;"; run_test_goldilocks(content); + run_test_baby_bear(content); } #[test] @@ -368,5 +413,6 @@ mod tests { fn lookup() { let content = "namespace Global(8); pol fixed z = [0, 1]*; pol witness a; [a] in [z];"; run_test_goldilocks(content); + run_test_baby_bear(content); } } From 2b8a401a46493fbe150ba43d17687fc39a35dab3 Mon Sep 17 00:00:00 2001 From: topanisto Date: Wed, 21 Aug 2024 14:16:16 +0200 Subject: [PATCH 10/17] builds for backend --- backend/src/plonky3/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/plonky3/mod.rs b/backend/src/plonky3/mod.rs index 32a22e7383..b451a0254c 100644 --- a/backend/src/plonky3/mod.rs +++ b/backend/src/plonky3/mod.rs @@ -53,7 +53,7 @@ impl BackendFactory for Factory { } } -impl Backend for Plonky3Prover { +impl Backend for Plonky3Prover { fn verify(&self, proof: &[u8], instances: &[Vec]) -> Result<(), Error> { Ok(self.verify(proof, instances)?) } From 928317f3b07a25f4e83b728412303bfa0f15c6a7 Mon Sep 17 00:00:00 2001 From: topanisto Date: Wed, 21 Aug 2024 15:15:33 +0200 Subject: [PATCH 11/17] backend edits --- backend/src/plonky3/mod.rs | 2 +- plonky3/src/lib.rs | 1 + plonky3/src/params.rs | 3 ++- plonky3/src/stark.rs | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/backend/src/plonky3/mod.rs b/backend/src/plonky3/mod.rs index b451a0254c..60324374cd 100644 --- a/backend/src/plonky3/mod.rs +++ b/backend/src/plonky3/mod.rs @@ -6,7 +6,7 @@ use powdr_executor::{ witgen::WitgenCallback, }; use powdr_number::{FieldElement, GoldilocksField, LargeInt}; -use powdr_plonky3::Plonky3Prover; +use powdr_plonky3::{FieldElementMap, Plonky3Prover}; use crate::{Backend, BackendFactory, BackendOptions, Error, Proof}; diff --git a/plonky3/src/lib.rs b/plonky3/src/lib.rs index bb652e0156..ea1f3a8679 100644 --- a/plonky3/src/lib.rs +++ b/plonky3/src/lib.rs @@ -3,4 +3,5 @@ mod circuit_builder; mod goldilocks; mod params; mod stark; +pub use params::FieldElementMap; pub use stark::Plonky3Prover; diff --git a/plonky3/src/params.rs b/plonky3/src/params.rs index 7c1da90e16..301dbb006b 100644 --- a/plonky3/src/params.rs +++ b/plonky3/src/params.rs @@ -1,4 +1,5 @@ use p3_commit::{Pcs, PolynomialSpace}; +use p3_symmetric::CompressionFunction; use p3_uni_stark::StarkGenericConfig; use powdr_number::FieldElement; @@ -9,7 +10,7 @@ pub type Challenge = <::Config as StarkGenericConfig>:: pub type Challenger = <::Config as StarkGenericConfig>::Challenger; pub trait FieldElementMap: FieldElement { - type Config: StarkGenericConfig + Sync; + type Config: StarkGenericConfig + Send; fn to_p3_field(&self) -> Plonky3Field; diff --git a/plonky3/src/stark.rs b/plonky3/src/stark.rs index d48ddf6445..7c8a50ea71 100644 --- a/plonky3/src/stark.rs +++ b/plonky3/src/stark.rs @@ -152,7 +152,7 @@ impl Plonky3Prover { <_ as p3_commit::Pcs<_, Challenger>>::commit(pcs, evaluations); let proving_key = StarkProvingKey { - preprocessed_commit: fixed_commit.clone(), + preprocessed_commit: fixed_commit, preprocessed_data: fixed_data, }; let verifying_key = StarkVerifyingKey { From 50c563676c61fa1cbe4ba6ba1d477e16fc57850e Mon Sep 17 00:00:00 2001 From: Thibaut Schaeffer Date: Mon, 26 Aug 2024 11:22:51 +0200 Subject: [PATCH 12/17] Babybear assoc type bounds (#1719) --- backend/src/plonky3/mod.rs | 14 +++++++++++--- plonky3/src/circuit_builder.rs | 29 ++++++++++++++++++++++++----- plonky3/src/lib.rs | 2 +- plonky3/src/params.rs | 18 ++++++++++++------ plonky3/src/stark.rs | 22 +++++++++++++++++----- 5 files changed, 65 insertions(+), 20 deletions(-) diff --git a/backend/src/plonky3/mod.rs b/backend/src/plonky3/mod.rs index 60324374cd..8b3577edf6 100644 --- a/backend/src/plonky3/mod.rs +++ b/backend/src/plonky3/mod.rs @@ -6,13 +6,17 @@ use powdr_executor::{ witgen::WitgenCallback, }; use powdr_number::{FieldElement, GoldilocksField, LargeInt}; -use powdr_plonky3::{FieldElementMap, Plonky3Prover}; +use powdr_plonky3::{Commitment, FieldElementMap, Plonky3Prover, ProverData}; use crate::{Backend, BackendFactory, BackendOptions, Error, Proof}; pub(crate) struct Factory; -impl BackendFactory for Factory { +impl BackendFactory for Factory +where + ProverData: Send, + Commitment: Send, +{ fn create( &self, pil: Arc>, @@ -53,7 +57,11 @@ impl BackendFactory for Factory { } } -impl Backend for Plonky3Prover { +impl Backend for Plonky3Prover +where + ProverData: Send, + Commitment: Send, +{ fn verify(&self, proof: &[u8], instances: &[Vec]) -> Result<(), Error> { Ok(self.verify(proof, instances)?) } diff --git a/plonky3/src/circuit_builder.rs b/plonky3/src/circuit_builder.rs index d148803b22..8387be2501 100644 --- a/plonky3/src/circuit_builder.rs +++ b/plonky3/src/circuit_builder.rs @@ -8,7 +8,7 @@ use std::collections::BTreeMap; -use crate::params::{FieldElementMap, Plonky3Field}; +use crate::params::{Commitment, FieldElementMap, Plonky3Field, ProverData}; use p3_air::{Air, AirBuilder, AirBuilderWithPublicValues, BaseAir, PairBuilder}; // use p3_baby_bear::BabyBear; // use p3_field::{extension::ComplexExtendable, AbstractField, PrimeField}; @@ -23,7 +23,11 @@ use powdr_executor::witgen::WitgenCallback; // use powdr_number::{BabyBearField, FieldElement, GoldilocksField, LargeInt}; // use powdr_number::FieldElement; -pub(crate) struct PowdrCircuit<'a, T: FieldElementMap> { +pub(crate) struct PowdrCircuit<'a, T: FieldElementMap> +where + ProverData: Send, + Commitment: Send, +{ /// The analyzed PIL analyzed: &'a Analyzed, /// The value of the witness columns, if set @@ -35,7 +39,11 @@ pub(crate) struct PowdrCircuit<'a, T: FieldElementMap> { preprocessed: Option>>, } -impl<'a, T: FieldElementMap + Sync> PowdrCircuit<'a, T> { +impl<'a, T: FieldElementMap> PowdrCircuit<'a, T> +where + ProverData: Send, + Commitment: Send, +{ pub fn generate_trace_rows(&self) -> RowMajorMatrix> { // an iterator over all columns, committed then fixed let witness = self.witness().iter(); @@ -64,7 +72,11 @@ impl<'a, T: FieldElementMap + Sync> PowdrCircuit<'a, T> { } } -impl<'a, T: FieldElementMap> PowdrCircuit<'a, T> { +impl<'a, T: FieldElementMap> PowdrCircuit<'a, T> +where + ProverData: Send, + Commitment: Send, +{ pub(crate) fn new(analyzed: &'a Analyzed) -> Self { if analyzed .definitions @@ -201,7 +213,11 @@ impl<'a, T: FieldElementMap> PowdrCircuit<'a, T> { /// An extension of [Air] allowing access to the number of fixed columns -impl<'a, T: FieldElementMap> BaseAir> for PowdrCircuit<'a, T> { +impl<'a, T: FieldElementMap> BaseAir> for PowdrCircuit<'a, T> +where + ProverData: Send, + Commitment: Send, +{ fn width(&self) -> usize { self.analyzed.commitment_count() } @@ -222,6 +238,9 @@ impl<'a, T: FieldElementMap> BaseAir> for PowdrCircuit<'a, T> { impl<'a, T: FieldElementMap, AB: AirBuilderWithPublicValues> + PairBuilder> Air for PowdrCircuit<'a, T> +where + ProverData: Send, + Commitment: Send, { fn eval(&self, builder: &mut AB) { let main = builder.main(); diff --git a/plonky3/src/lib.rs b/plonky3/src/lib.rs index ea1f3a8679..364e741b91 100644 --- a/plonky3/src/lib.rs +++ b/plonky3/src/lib.rs @@ -3,5 +3,5 @@ mod circuit_builder; mod goldilocks; mod params; mod stark; -pub use params::FieldElementMap; +pub use params::{Commitment, FieldElementMap, ProverData}; pub use stark::Plonky3Prover; diff --git a/plonky3/src/params.rs b/plonky3/src/params.rs index 301dbb006b..366316004a 100644 --- a/plonky3/src/params.rs +++ b/plonky3/src/params.rs @@ -1,16 +1,22 @@ -use p3_commit::{Pcs, PolynomialSpace}; -use p3_symmetric::CompressionFunction; +use p3_commit::PolynomialSpace; use p3_uni_stark::StarkGenericConfig; use powdr_number::FieldElement; pub type Plonky3Field = - < as Pcs, Challenger>>::Domain as PolynomialSpace>::Val; -pub type MyPcs = <::Config as StarkGenericConfig>::Pcs; + < as p3_commit::Pcs, Challenger>>::Domain as PolynomialSpace>::Val; +pub type Pcs = <::Config as StarkGenericConfig>::Pcs; pub type Challenge = <::Config as StarkGenericConfig>::Challenge; pub type Challenger = <::Config as StarkGenericConfig>::Challenger; -pub trait FieldElementMap: FieldElement { - type Config: StarkGenericConfig + Send; +pub type ProverData = as p3_commit::Pcs, Challenger>>::ProverData; +pub type Commitment = as p3_commit::Pcs, Challenger>>::Commitment; + +pub trait FieldElementMap: FieldElement +where + ProverData: Send, + Commitment: Send, +{ + type Config: StarkGenericConfig; fn to_p3_field(&self) -> Plonky3Field; diff --git a/plonky3/src/stark.rs b/plonky3/src/stark.rs index 7c8a50ea71..24a7a70ddf 100644 --- a/plonky3/src/stark.rs +++ b/plonky3/src/stark.rs @@ -15,10 +15,14 @@ use p3_uni_stark::{ use crate::{ circuit_builder::PowdrCircuit, - params::{Challenger, FieldElementMap, Plonky3Field}, + params::{Challenger, Commitment, FieldElementMap, Plonky3Field, ProverData}, }; -pub struct Plonky3Prover { +pub struct Plonky3Prover +where + ProverData: Send, + Commitment: Send, +{ /// The analyzed PIL analyzed: Arc>, /// The value of the fixed columns @@ -41,7 +45,11 @@ impl fmt::Display for VerificationKeyExportError { } } -impl Plonky3Prover { +impl Plonky3Prover +where + ProverData: Send, + Commitment: Send, +{ pub fn new(analyzed: Arc>, fixed: Arc)>>) -> Self { Self { analyzed, @@ -101,7 +109,11 @@ impl Plonky3Prover { } } -impl Plonky3Prover { +impl Plonky3Prover +where + ProverData: Send, + Commitment: Send, +{ pub fn setup(&mut self) { // get fixed columns let fixed = &self.fixed; @@ -152,7 +164,7 @@ impl Plonky3Prover { <_ as p3_commit::Pcs<_, Challenger>>::commit(pcs, evaluations); let proving_key = StarkProvingKey { - preprocessed_commit: fixed_commit, + preprocessed_commit: fixed_commit.clone(), preprocessed_data: fixed_data, }; let verifying_key = StarkVerifyingKey { From 8a01c8f8f61f019d667f7c0f83c5bb655ce07db1 Mon Sep 17 00:00:00 2001 From: Lucas Clemente Vella Date: Fri, 6 Sep 2024 08:14:35 +0100 Subject: [PATCH 13/17] Allowing construction of Plonky3 backend for BabyBear and Goldilocks. (#1721) Unfortunately this requires unsafe, but a pretty tame one. --------- Co-authored-by: schaeff --- backend/src/plonky3/mod.rs | 75 ++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 19 deletions(-) diff --git a/backend/src/plonky3/mod.rs b/backend/src/plonky3/mod.rs index 8b3577edf6..a3fff30243 100644 --- a/backend/src/plonky3/mod.rs +++ b/backend/src/plonky3/mod.rs @@ -1,36 +1,70 @@ -use std::{io, path::PathBuf, sync::Arc}; +use std::{ + any::{Any, TypeId}, + io, + path::PathBuf, + sync::Arc, +}; use powdr_ast::analyzed::Analyzed; use powdr_executor::{ constant_evaluator::{get_uniquely_sized_cloned, VariablySizedColumn}, witgen::WitgenCallback, }; -use powdr_number::{FieldElement, GoldilocksField, LargeInt}; +use powdr_number::{BabyBearField, FieldElement, GoldilocksField}; use powdr_plonky3::{Commitment, FieldElementMap, Plonky3Prover, ProverData}; use crate::{Backend, BackendFactory, BackendOptions, Error, Proof}; pub(crate) struct Factory; -impl BackendFactory for Factory +fn try_create( + pil: &Arc>, + fixed: &Arc)>>, + verification_key: &mut Option<&mut dyn io::Read>, +) -> Option>> where - ProverData: Send, - Commitment: Send, + ProverData: Send, + Commitment: Send, { + // We ensure that FInner and FOuter are the same type, so we can even safely + // transmute between them. + if TypeId::of::() != TypeId::of::() { + return None; + } + + let pil = (pil as &dyn Any) + .downcast_ref::>>() + .unwrap(); + let fixed = (fixed as &dyn Any) + .downcast_ref::)>>>() + .unwrap(); + + let mut p3 = Box::new(Plonky3Prover::new(pil.clone(), fixed.clone())); + + if let Some(verification_key) = verification_key { + p3.set_verifying_key(*verification_key); + } else { + p3.setup(); + } + + let p3: Box> = p3; + let p3 = Box::into_raw(p3); + + // This is safe because we know that FInner == FOuter. + Some(unsafe { Box::from_raw(p3 as *mut dyn Backend) }) +} + +impl BackendFactory for Factory { fn create( &self, pil: Arc>, fixed: Arc)>>, _output_dir: Option, setup: Option<&mut dyn io::Read>, - verification_key: Option<&mut dyn io::Read>, + mut verification_key: Option<&mut dyn io::Read>, verification_app_key: Option<&mut dyn io::Read>, _: BackendOptions, ) -> Result>, Error> { - if T::modulus().to_arbitrary_integer() != GoldilocksField::modulus().to_arbitrary_integer() - { - unimplemented!("plonky3 is only implemented for the Goldilocks field"); - } if setup.is_some() { return Err(Error::NoSetupAvailable); } @@ -45,15 +79,18 @@ where get_uniquely_sized_cloned(&fixed).map_err(|_| Error::NoVariableDegreeAvailable)?, ); - let mut p3 = Box::new(Plonky3Prover::new(pil, fixed)); - - if let Some(verification_key) = verification_key { - p3.set_verifying_key(verification_key); - } else { - p3.setup(); - } - - Ok(p3) + Ok( + if let Some(p3) = try_create::(&pil, &fixed, &mut verification_key) + { + p3 + } else if let Some(p3) = + try_create::(&pil, &fixed, &mut verification_key) + { + p3 + } else { + unimplemented!("unsupported field type: {:?}", TypeId::of::()) + }, + ) } } From b942b9eca5e23d769757797f40a54bf95cc7880f Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Fri, 6 Sep 2024 11:40:42 +0200 Subject: [PATCH 14/17] use p3 bb in some tests --- pipeline/src/test_util.rs | 16 +++++----------- pipeline/tests/asm.rs | 6 +++++- pipeline/tests/pil.rs | 12 ++++++++++-- pipeline/tests/powdr_std.rs | 8 ++++---- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/pipeline/src/test_util.rs b/pipeline/src/test_util.rs index 90aa523ef7..78f8091b77 100644 --- a/pipeline/src/test_util.rs +++ b/pipeline/src/test_util.rs @@ -77,12 +77,6 @@ pub fn regular_test(file_name: &str, inputs: &[i32]) { pipeline_bb.compute_witness().unwrap(); } -pub fn regular_test_only_babybear(file_name: &str, inputs: &[i32]) { - let inputs_bb = inputs.iter().map(|x| BabyBearField::from(*x)).collect(); - let mut pipeline_bb = make_prepared_pipeline(file_name, inputs_bb, vec![]); - pipeline_bb.compute_witness().unwrap(); -} - pub fn regular_test_without_babybear(file_name: &str, inputs: &[i32]) { let inputs_gl = inputs.iter().map(|x| GoldilocksField::from(*x)).collect(); let pipeline_gl = make_prepared_pipeline(file_name, inputs_gl, vec![]); @@ -296,9 +290,9 @@ pub fn gen_halo2_proof(pipeline: Pipeline, backend: BackendVariant) pub fn gen_halo2_proof(_pipeline: Pipeline, _backend: BackendVariant) {} #[cfg(feature = "plonky3")] -pub fn test_plonky3_with_backend_variant( +pub fn test_plonky3_with_backend_variant( file_name: &str, - inputs: Vec, + inputs: Vec, backend: BackendVariant, ) { let backend = match backend { @@ -314,7 +308,7 @@ pub fn test_plonky3_with_backend_variant( // Generate a proof let proof = pipeline.compute_proof().cloned().unwrap(); - let publics: Vec = pipeline + let publics: Vec = pipeline .publics() .clone() .unwrap() @@ -341,10 +335,10 @@ pub fn test_plonky3_with_backend_variant( } #[cfg(not(feature = "plonky3"))] -pub fn test_plonky3_with_backend_variant(_: &str, _: Vec, _: BackendVariant) {} +pub fn test_plonky3_with_backend_variant(_: &str, _: Vec, _: BackendVariant) {} #[cfg(not(feature = "plonky3"))] -pub fn gen_plonky3_proof(_: &str, _: Vec) {} +pub fn gen_plonky3_proof(_: &str, _: Vec) {} /// Returns the analyzed PIL containing only the std library. pub fn std_analyzed() -> Analyzed { diff --git a/pipeline/tests/asm.rs b/pipeline/tests/asm.rs index 6ff2c8068c..d8efe23181 100644 --- a/pipeline/tests/asm.rs +++ b/pipeline/tests/asm.rs @@ -39,7 +39,11 @@ fn simple_sum_asm() { let f = "asm/simple_sum.asm"; let i = [16, 4, 1, 2, 8, 5]; regular_test(f, &i); - test_plonky3_with_backend_variant(f, slice_to_vec(&i), BackendVariant::Composite); + test_plonky3_with_backend_variant::( + f, + slice_to_vec(&i), + BackendVariant::Composite, + ); } #[test] diff --git a/pipeline/tests/pil.rs b/pipeline/tests/pil.rs index c21c93df51..3c50a0c0d6 100644 --- a/pipeline/tests/pil.rs +++ b/pipeline/tests/pil.rs @@ -87,7 +87,11 @@ fn permutation_with_selector() { fn fibonacci() { let f = "pil/fibonacci.pil"; regular_test(f, Default::default()); - test_plonky3_with_backend_variant(f, Default::default(), BackendVariant::Monolithic); + test_plonky3_with_backend_variant::( + f, + Default::default(), + BackendVariant::Monolithic, + ); } #[test] @@ -241,7 +245,11 @@ fn halo_without_lookup() { #[test] fn add() { let f = "pil/add.pil"; - test_plonky3_with_backend_variant(f, Default::default(), BackendVariant::Monolithic); + test_plonky3_with_backend_variant::( + f, + Default::default(), + BackendVariant::Monolithic, + ); } #[test] diff --git a/pipeline/tests/powdr_std.rs b/pipeline/tests/powdr_std.rs index c367899ccd..e77771cc59 100644 --- a/pipeline/tests/powdr_std.rs +++ b/pipeline/tests/powdr_std.rs @@ -6,8 +6,8 @@ use powdr_pil_analyzer::evaluator::Value; use powdr_pipeline::{ test_util::{ evaluate_function, evaluate_integer_function, execute_test_file, gen_estark_proof, - gen_halo2_proof, make_simple_prepared_pipeline, regular_test, regular_test_only_babybear, - std_analyzed, test_halo2, test_pilcom, BackendVariant, + gen_halo2_proof, make_simple_prepared_pipeline, regular_test, std_analyzed, test_halo2, + test_pilcom, test_plonky3_with_backend_variant, BackendVariant, }, Pipeline, }; @@ -186,14 +186,14 @@ fn binary_test() { #[ignore = "Too slow"] fn binary_bb_8_test() { let f = "std/binary_bb_test_8.asm"; - regular_test_only_babybear(f, &[]); + test_plonky3_with_backend_variant::(f, vec![], BackendVariant::Composite); } #[test] #[ignore = "Too slow"] fn binary_bb_16_test() { let f = "std/binary_bb_test_16.asm"; - regular_test_only_babybear(f, &[]); + test_plonky3_with_backend_variant::(f, vec![], BackendVariant::Composite); } #[test] From 19dbac8024bf0dbf49cccb00b318ea46aaec798a Mon Sep 17 00:00:00 2001 From: schaeff Date: Fri, 6 Sep 2024 13:36:19 +0200 Subject: [PATCH 15/17] self fix self review --- plonky3/src/baby_bear.rs | 2 +- plonky3/src/circuit_builder.rs | 10 +++------- plonky3/src/goldilocks.rs | 2 +- plonky3/src/params.rs | 2 +- plonky3/src/stark.rs | 8 ++++---- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/plonky3/src/baby_bear.rs b/plonky3/src/baby_bear.rs index 6cf11bb6f9..ce95080f59 100644 --- a/plonky3/src/baby_bear.rs +++ b/plonky3/src/baby_bear.rs @@ -76,7 +76,7 @@ lazy_static! { impl FieldElementMap for BabyBearField { type Config = StarkConfig; - fn to_p3_field(&self) -> Plonky3Field { + fn into_p3_field(self) -> Plonky3Field { BabyBear::from_canonical_u32(self.to_integer().try_into_u32().unwrap()) } diff --git a/plonky3/src/circuit_builder.rs b/plonky3/src/circuit_builder.rs index 2f7b23ccc6..5e9e7480f7 100644 --- a/plonky3/src/circuit_builder.rs +++ b/plonky3/src/circuit_builder.rs @@ -10,11 +10,7 @@ use std::collections::{BTreeMap, HashSet}; use crate::params::{Commitment, FieldElementMap, Plonky3Field, ProverData}; use p3_air::{Air, AirBuilder, AirBuilderWithPublicValues, BaseAir, PairBuilder}; -// use p3_baby_bear::BabyBear; -// use p3_field::{extension::ComplexExtendable, AbstractField, PrimeField}; -// use p3_goldilocks::Goldilocks; use p3_matrix::{dense::RowMajorMatrix, Matrix}; -// use p3_mds::MdsPermutation; use powdr_ast::analyzed::{ AlgebraicBinaryOperation, AlgebraicBinaryOperator, AlgebraicExpression, AlgebraicUnaryOperation, AlgebraicUnaryOperator, Analyzed, Identity, IdentityKind, @@ -86,7 +82,7 @@ where // witness values witness.clone().map(move |(_, v)| v[i as usize]) }) - .map(|f| f.to_p3_field()) + .map(|f| f.into_p3_field()) .collect() } 0 => { @@ -142,7 +138,7 @@ where .iter() .map(|(col_name, _, idx)| { let vals = *witness.get(&col_name).unwrap(); - vals[*idx].to_p3_field() + vals[*idx].into_p3_field() }) .collect() } @@ -209,7 +205,7 @@ where .get(id) .expect("Referenced public value does not exist")) .into(), - AlgebraicExpression::Number(n) => AB::Expr::from(n.to_p3_field()), + AlgebraicExpression::Number(n) => AB::Expr::from(n.into_p3_field()), AlgebraicExpression::BinaryOperation(AlgebraicBinaryOperation { left, op, right }) => { let left = self.to_plonky3_expr::(left, main, fixed, publics); let right = self.to_plonky3_expr::(right, main, fixed, publics); diff --git a/plonky3/src/goldilocks.rs b/plonky3/src/goldilocks.rs index 17070d5b69..70bc98ad01 100644 --- a/plonky3/src/goldilocks.rs +++ b/plonky3/src/goldilocks.rs @@ -72,7 +72,7 @@ lazy_static! { impl FieldElementMap for GoldilocksField { type Config = StarkConfig; - fn to_p3_field(&self) -> Plonky3Field { + fn into_p3_field(self) -> Plonky3Field { Goldilocks::from_canonical_u64(self.to_integer().try_into_u64().unwrap()) } diff --git a/plonky3/src/params.rs b/plonky3/src/params.rs index 6e7770f8db..ee34b80961 100644 --- a/plonky3/src/params.rs +++ b/plonky3/src/params.rs @@ -21,7 +21,7 @@ where { type Config: StarkGenericConfig; - fn to_p3_field(&self) -> Plonky3Field; + fn into_p3_field(self) -> Plonky3Field; fn get_challenger() -> Challenger; diff --git a/plonky3/src/stark.rs b/plonky3/src/stark.rs index 24a7a70ddf..aa760aaf16 100644 --- a/plonky3/src/stark.rs +++ b/plonky3/src/stark.rs @@ -95,11 +95,11 @@ where .flat_map(|i| { self.fixed .iter() - .map(move |(_, values)| values[i as usize].to_p3_field()) + .map(move |(_, values)| values[i as usize].into_p3_field()) .chain( publics .iter() - .map(move |(_, values)| values[i as usize].to_p3_field()), + .map(move |(_, values)| values[i as usize].into_p3_field()), ) }) .collect(), @@ -151,7 +151,7 @@ where fixed .iter() .chain(publics.iter()) - .map(move |(_, values)| values[i as usize].to_p3_field()) + .map(move |(_, values)| values[i as usize].into_p3_field()) }) .collect(), self.fixed.len() + publics.len(), @@ -228,7 +228,7 @@ where let publics = instances .iter() .flatten() - .map(|v| v.to_p3_field()) + .map(|v| v.into_p3_field()) .collect(); let config = T::get_config(); From 7d1ae5eca5745a084bc087e49d284bd59486ddfc Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Fri, 6 Sep 2024 14:18:27 +0200 Subject: [PATCH 16/17] fix convert --- number/Cargo.toml | 4 ++-- number/src/baby_bear.rs | 2 +- plonky3/src/baby_bear.rs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/number/Cargo.toml b/number/Cargo.toml index ce848f5fd2..7f74cf36b8 100644 --- a/number/Cargo.toml +++ b/number/Cargo.toml @@ -13,8 +13,8 @@ ark-bn254 = { version = "0.4.0", default-features = false, features = [ ] } ark-ff = "0.4.2" ark-serialize = "0.4.2" -p3-baby-bear = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed" } -p3-field = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "uni-stark-with-fixed" } +p3-baby-bear = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "main" } +p3-field = { git = "https://github.com/powdr-labs/Plonky3.git", branch = "main" } num-bigint = { version = "0.4.3", features = ["serde"] } num-traits = "0.2.15" csv = "1.3" diff --git a/number/src/baby_bear.rs b/number/src/baby_bear.rs index d1c4852869..b571cb7ac0 100644 --- a/number/src/baby_bear.rs +++ b/number/src/baby_bear.rs @@ -32,7 +32,7 @@ use p3_field::{AbstractField, Field, PrimeField32}; Deserialize, derive_more::Display, )] -pub struct BabyBearField(BabyBear); +pub struct BabyBearField(pub BabyBear); const P: u32 = 0x78000001; diff --git a/plonky3/src/baby_bear.rs b/plonky3/src/baby_bear.rs index ce95080f59..6e149b6b80 100644 --- a/plonky3/src/baby_bear.rs +++ b/plonky3/src/baby_bear.rs @@ -8,7 +8,7 @@ use p3_baby_bear::{BabyBear, DiffusionMatrixBabyBear}; use p3_challenger::DuplexChallenger; use p3_commit::ExtensionMmcs; use p3_dft::Radix2DitParallel; -use p3_field::{extension::BinomialExtensionField, AbstractField, Field}; +use p3_field::{extension::BinomialExtensionField, Field}; use p3_fri::{FriConfig, TwoAdicFriPcs}; use p3_merkle_tree::FieldMerkleTreeMmcs; use p3_poseidon2::{Poseidon2, Poseidon2ExternalMatrixGeneral}; @@ -17,7 +17,7 @@ use p3_uni_stark::StarkConfig; use rand::{distributions::Standard, Rng, SeedableRng}; -use powdr_number::{BabyBearField, FieldElement, LargeInt}; +use powdr_number::BabyBearField; const D: u64 = 7; // params directly taken from plonky3's poseidon2_round_numbers_128 function @@ -77,7 +77,7 @@ lazy_static! { impl FieldElementMap for BabyBearField { type Config = StarkConfig; fn into_p3_field(self) -> Plonky3Field { - BabyBear::from_canonical_u32(self.to_integer().try_into_u32().unwrap()) + self.0 } fn get_challenger() -> Challenger { From 4fec39f15a946d9d74bccdbd57621c067b34d52e Mon Sep 17 00:00:00 2001 From: Leo Alt Date: Fri, 6 Sep 2024 14:45:47 +0200 Subject: [PATCH 17/17] into inner --- number/src/baby_bear.rs | 6 +++++- plonky3/src/baby_bear.rs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/number/src/baby_bear.rs b/number/src/baby_bear.rs index b571cb7ac0..cc79e1f219 100644 --- a/number/src/baby_bear.rs +++ b/number/src/baby_bear.rs @@ -32,7 +32,7 @@ use p3_field::{AbstractField, Field, PrimeField32}; Deserialize, derive_more::Display, )] -pub struct BabyBearField(pub BabyBear); +pub struct BabyBearField(BabyBear); const P: u32 = 0x78000001; @@ -48,6 +48,10 @@ impl BabyBearField { fn to_canonical_u32(self) -> u32 { self.0.as_canonical_u32() } + + pub fn into_inner(self) -> BabyBear { + self.0 + } } impl FieldElement for BabyBearField { diff --git a/plonky3/src/baby_bear.rs b/plonky3/src/baby_bear.rs index 6e149b6b80..bf6b0533eb 100644 --- a/plonky3/src/baby_bear.rs +++ b/plonky3/src/baby_bear.rs @@ -77,7 +77,7 @@ lazy_static! { impl FieldElementMap for BabyBearField { type Config = StarkConfig; fn into_p3_field(self) -> Plonky3Field { - self.0 + self.into_inner() } fn get_challenger() -> Challenger {