diff --git a/Cargo.toml b/Cargo.toml index ac383b4b..c36e3023 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,60 +1,2 @@ -[package] -name = "plonky2" -description = "Recursive SNARKs based on Plonk and FRI" -version = "0.1.0" -authors = ["Daniel Lubarov "] -readme = "README.md" -license = "MIT OR Apache-2.0" -repository = "https://github.com/mir-protocol/plonky2" -keywords = ["cryptography", "SNARK", "FRI"] -categories = ["cryptography"] -edition = "2021" -default-run = "bench_recursion" - -[dependencies] -array_tool = "1.0.3" -bimap = "0.6.1" -env_logger = "0.9.0" -log = "0.4.14" -itertools = "0.10.0" -num = { version = "0.4", features = [ "rand" ] } -rand = "0.8.4" -rand_chacha = "0.3.1" -rayon = "1.5.1" -unroll = "0.1.5" -anyhow = "1.0.40" -serde = { version = "1.0", features = ["derive"] } -serde_cbor = "0.11.1" -keccak-hash = "0.8.0" -static_assertions = "1.1.0" - -[target.'cfg(not(target_env = "msvc"))'.dependencies] -jemallocator = "0.3.2" - -[dev-dependencies] -criterion = "0.3.5" -tynm = "0.1.6" - -[[bench]] -name = "field_arithmetic" -harness = false - -[[bench]] -name = "ffts" -harness = false - -[[bench]] -name = "hashing" -harness = false - -[[bench]] -name = "transpose" -harness = false - -[profile.release] -opt-level = 3 -#lto = "fat" -#codegen-units = 1 - -[profile.bench] -opt-level = 3 +[workspace] +members = ["field", "insertion", "plonky2", "util", "waksman"] diff --git a/field/Cargo.toml b/field/Cargo.toml new file mode 100644 index 00000000..1a974852 --- /dev/null +++ b/field/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "plonky2_field" +version = "0.1.0" +edition = "2021" + +[dependencies] +plonky2_util = { path = "../util" } +anyhow = "1.0.40" +itertools = "0.10.0" +num = { version = "0.4", features = [ "rand" ] } +rand = "0.8.4" +serde = { version = "1.0", features = ["derive"] } +unroll = "0.1.5" diff --git a/src/field/arch/mod.rs b/field/src/arch/mod.rs similarity index 100% rename from src/field/arch/mod.rs rename to field/src/arch/mod.rs diff --git a/src/field/arch/x86_64/avx2_goldilocks_field.rs b/field/src/arch/x86_64/avx2_goldilocks_field.rs similarity index 98% rename from src/field/arch/x86_64/avx2_goldilocks_field.rs rename to field/src/arch/x86_64/avx2_goldilocks_field.rs index 5cf7c1fa..db6ab2b0 100644 --- a/src/field/arch/x86_64/avx2_goldilocks_field.rs +++ b/field/src/arch/x86_64/avx2_goldilocks_field.rs @@ -5,9 +5,9 @@ use std::iter::{Product, Sum}; use std::mem::transmute; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; -use crate::field::field_types::{Field, PrimeField}; -use crate::field::goldilocks_field::GoldilocksField; -use crate::field::packed_field::PackedField; +use crate::field_types::{Field, PrimeField}; +use crate::goldilocks_field::GoldilocksField; +use crate::packed_field::PackedField; // Ideally `Avx2GoldilocksField` would wrap `__m256i`. Unfortunately, `__m256i` has an alignment of // 32B, which would preclude us from casting `[GoldilocksField; 4]` (alignment 8B) to @@ -506,10 +506,10 @@ unsafe fn interleave2(x: __m256i, y: __m256i) -> (__m256i, __m256i) { #[cfg(test)] mod tests { - use crate::field::arch::x86_64::avx2_goldilocks_field::Avx2GoldilocksField; - use crate::field::field_types::PrimeField; - use crate::field::goldilocks_field::GoldilocksField; - use crate::field::packed_field::PackedField; + use crate::arch::x86_64::avx2_goldilocks_field::Avx2GoldilocksField; + use crate::field_types::PrimeField; + use crate::goldilocks_field::GoldilocksField; + use crate::packed_field::PackedField; fn test_vals_a() -> [GoldilocksField; 4] { [ diff --git a/src/field/arch/x86_64/mod.rs b/field/src/arch/x86_64/mod.rs similarity index 100% rename from src/field/arch/x86_64/mod.rs rename to field/src/arch/x86_64/mod.rs diff --git a/src/field/batch_util.rs b/field/src/batch_util.rs similarity index 95% rename from src/field/batch_util.rs rename to field/src/batch_util.rs index 6ff5fc1d..11ef0edf 100644 --- a/src/field/batch_util.rs +++ b/field/src/batch_util.rs @@ -1,6 +1,6 @@ -use crate::field::field_types::Field; -use crate::field::packable::Packable; -use crate::field::packed_field::PackedField; +use crate::field_types::Field; +use crate::packable::Packable; +use crate::packed_field::PackedField; fn pack_with_leftovers_split_point(slice: &[P::Scalar]) -> usize { let n = slice.len(); diff --git a/src/field/cosets.rs b/field/src/cosets.rs similarity index 83% rename from src/field/cosets.rs rename to field/src/cosets.rs index 62be67dc..3dcc953f 100644 --- a/src/field/cosets.rs +++ b/field/src/cosets.rs @@ -1,10 +1,10 @@ use num::bigint::BigUint; -use crate::field::field_types::Field; +use crate::field_types::Field; /// Finds a set of shifts that result in unique cosets for the multiplicative subgroup of size /// `2^subgroup_bits`. -pub(crate) fn get_unique_coset_shifts(subgroup_size: usize, num_shifts: usize) -> Vec { +pub fn get_unique_coset_shifts(subgroup_size: usize, num_shifts: usize) -> Vec { // From Lagrange's theorem. let num_cosets = (F::order() - 1u32) / (subgroup_size as u32); assert!( @@ -25,9 +25,9 @@ pub(crate) fn get_unique_coset_shifts(subgroup_size: usize, num_shifts mod tests { use std::collections::HashSet; - use crate::field::cosets::get_unique_coset_shifts; - use crate::field::field_types::Field; - use crate::field::goldilocks_field::GoldilocksField; + use crate::cosets::get_unique_coset_shifts; + use crate::field_types::Field; + use crate::goldilocks_field::GoldilocksField; #[test] fn distinct_cosets() { diff --git a/src/field/extension_field/algebra.rs b/field/src/extension_field/algebra.rs similarity index 96% rename from src/field/extension_field/algebra.rs rename to field/src/extension_field/algebra.rs index 93d25de4..58244726 100644 --- a/src/field/extension_field/algebra.rs +++ b/field/src/extension_field/algebra.rs @@ -2,7 +2,7 @@ use std::fmt::{Debug, Display, Formatter}; use std::iter::{Product, Sum}; use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; -use crate::field::extension_field::OEF; +use crate::extension_field::OEF; /// Let `F_D` be the optimal extension field `F[X]/(X^D-W)`. Then `ExtensionAlgebra` is the quotient `F_D[X]/(X^D-W)`. /// It's a `D`-dimensional algebra over `F_D` useful to lift the multiplication over `F_D` to a multiplication over `(F_D)^D`. @@ -192,10 +192,10 @@ impl, const D: usize> PolynomialCoeffsAlgebra { mod tests { use itertools::Itertools; - use crate::field::extension_field::algebra::ExtensionAlgebra; - use crate::field::extension_field::{Extendable, FieldExtension}; - use crate::field::field_types::Field; - use crate::field::goldilocks_field::GoldilocksField; + use crate::extension_field::algebra::ExtensionAlgebra; + use crate::extension_field::{Extendable, FieldExtension}; + use crate::field_types::Field; + use crate::goldilocks_field::GoldilocksField; /// Tests that the multiplication on the extension algebra lifts that of the field extension. fn test_extension_algebra, const D: usize>() { diff --git a/src/field/extension_field/mod.rs b/field/src/extension_field/mod.rs similarity index 95% rename from src/field/extension_field/mod.rs rename to field/src/extension_field/mod.rs index f8322e6d..abd8e65c 100644 --- a/src/field/extension_field/mod.rs +++ b/field/src/extension_field/mod.rs @@ -1,11 +1,10 @@ use std::convert::TryInto; -use crate::field::field_types::{Field, RichField}; +use crate::field_types::Field; pub mod algebra; pub mod quadratic; pub mod quartic; -pub mod target; /// Optimal extension field trait. /// A degree `d` field extension is optimal if there exists a base field element `W`, @@ -61,7 +60,7 @@ pub trait Frobenius: OEF { } } -pub trait Extendable: RichField + Sized { +pub trait Extendable: Field + Sized { type Extension: Field + OEF + Frobenius + From; const W: Self; @@ -76,7 +75,7 @@ pub trait Extendable: RichField + Sized { const EXT_POWER_OF_TWO_GENERATOR: [Self; D]; } -impl + FieldExtension<1, BaseField = F>> Extendable<1> for F { +impl + FieldExtension<1, BaseField = F>> Extendable<1> for F { type Extension = F; const W: Self = F::ZERO; const DTH_ROOT: Self = F::ZERO; diff --git a/src/field/extension_field/quadratic.rs b/field/src/extension_field/quadratic.rs similarity index 93% rename from src/field/extension_field/quadratic.rs rename to field/src/extension_field/quadratic.rs index 2243612e..3b2651cf 100644 --- a/src/field/extension_field/quadratic.rs +++ b/field/src/extension_field/quadratic.rs @@ -7,12 +7,12 @@ use num::Integer; use rand::Rng; use serde::{Deserialize, Serialize}; -use crate::field::extension_field::{Extendable, FieldExtension, Frobenius, OEF}; -use crate::field::field_types::Field; +use crate::extension_field::{Extendable, FieldExtension, Frobenius, OEF}; +use crate::field_types::Field; #[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] #[serde(bound = "")] -pub struct QuadraticExtension>(pub(crate) [F; 2]); +pub struct QuadraticExtension>(pub [F; 2]); impl> Default for QuadraticExtension { fn default() -> Self { @@ -230,10 +230,10 @@ mod tests { mod goldilocks { use crate::{test_field_arithmetic, test_field_extension}; - test_field_extension!(crate::field::goldilocks_field::GoldilocksField, 2); + test_field_extension!(crate::goldilocks_field::GoldilocksField, 2); test_field_arithmetic!( - crate::field::extension_field::quadratic::QuadraticExtension< - crate::field::goldilocks_field::GoldilocksField, + crate::extension_field::quadratic::QuadraticExtension< + crate::goldilocks_field::GoldilocksField, > ); } diff --git a/src/field/extension_field/quartic.rs b/field/src/extension_field/quartic.rs similarity index 94% rename from src/field/extension_field/quartic.rs rename to field/src/extension_field/quartic.rs index 781f79f5..b060b778 100644 --- a/src/field/extension_field/quartic.rs +++ b/field/src/extension_field/quartic.rs @@ -8,12 +8,12 @@ use num::Integer; use rand::Rng; use serde::{Deserialize, Serialize}; -use crate::field::extension_field::{Extendable, FieldExtension, Frobenius, OEF}; -use crate::field::field_types::Field; +use crate::extension_field::{Extendable, FieldExtension, Frobenius, OEF}; +use crate::field_types::Field; #[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] #[serde(bound = "")] -pub struct QuarticExtension>(pub(crate) [F; 4]); +pub struct QuarticExtension>(pub [F; 4]); impl> Default for QuarticExtension { fn default() -> Self { @@ -267,10 +267,10 @@ mod tests { mod goldilocks { use crate::{test_field_arithmetic, test_field_extension}; - test_field_extension!(crate::field::goldilocks_field::GoldilocksField, 4); + test_field_extension!(crate::goldilocks_field::GoldilocksField, 4); test_field_arithmetic!( - crate::field::extension_field::quartic::QuarticExtension< - crate::field::goldilocks_field::GoldilocksField, + crate::extension_field::quartic::QuarticExtension< + crate::goldilocks_field::GoldilocksField, > ); } diff --git a/src/field/fft.rs b/field/src/fft.rs similarity index 95% rename from src/field/fft.rs rename to field/src/fft.rs index ba94f6a7..14112dfc 100644 --- a/src/field/fft.rs +++ b/field/src/fft.rs @@ -1,15 +1,15 @@ use std::cmp::{max, min}; use std::option::Option; +use plonky2_util::{log2_strict, reverse_index_bits}; use unroll::unroll_for_loops; -use crate::field::field_types::Field; -use crate::field::packable::Packable; -use crate::field::packed_field::PackedField; +use crate::field_types::Field; +use crate::packable::Packable; +use crate::packed_field::PackedField; use crate::polynomial::{PolynomialCoeffs, PolynomialValues}; -use crate::util::{log2_strict, reverse_index_bits}; -pub(crate) type FftRootTable = Vec>; +pub type FftRootTable = Vec>; pub fn fft_root_table(n: usize) -> FftRootTable { let lg_n = log2_strict(n); @@ -209,11 +209,12 @@ pub(crate) fn fft_classic(input: &[F], r: usize, root_table: &FftRootT #[cfg(test)] mod tests { - use crate::field::fft::{fft, fft_with_options, ifft}; - use crate::field::field_types::Field; - use crate::field::goldilocks_field::GoldilocksField; + use plonky2_util::{log2_ceil, log2_strict}; + + use crate::fft::{fft, fft_with_options, ifft}; + use crate::field_types::Field; + use crate::goldilocks_field::GoldilocksField; use crate::polynomial::{PolynomialCoeffs, PolynomialValues}; - use crate::util::{log2_ceil, log2_strict}; #[test] fn fft_and_ifft() { diff --git a/src/field/field_testing.rs b/field/src/field_testing.rs similarity index 91% rename from src/field/field_testing.rs rename to field/src/field_testing.rs index b4ee0595..672fb554 100644 --- a/src/field/field_testing.rs +++ b/field/src/field_testing.rs @@ -1,6 +1,6 @@ -use crate::field::extension_field::Extendable; -use crate::field::extension_field::Frobenius; -use crate::field::field_types::Field; +use crate::extension_field::Extendable; +use crate::extension_field::Frobenius; +use crate::field_types::Field; #[macro_export] macro_rules! test_field_arithmetic { @@ -9,7 +9,7 @@ macro_rules! test_field_arithmetic { use num::bigint::BigUint; use rand::Rng; - use crate::field::field_types::Field; + use crate::field_types::Field; #[test] fn batch_inversion() { @@ -168,23 +168,23 @@ macro_rules! test_field_extension { mod field_extension { #[test] fn test_add_neg_sub_mul() { - crate::field::field_testing::test_add_neg_sub_mul::<$field, $d>(); + crate::field_testing::test_add_neg_sub_mul::<$field, $d>(); } #[test] fn test_inv_div() { - crate::field::field_testing::test_inv_div::<$field, $d>(); + crate::field_testing::test_inv_div::<$field, $d>(); } #[test] fn test_frobenius() { - crate::field::field_testing::test_frobenius::<$field, $d>(); + crate::field_testing::test_frobenius::<$field, $d>(); } #[test] fn test_field_order() { - crate::field::field_testing::test_field_order::<$field, $d>(); + crate::field_testing::test_field_order::<$field, $d>(); } #[test] fn test_power_of_two_gen() { - crate::field::field_testing::test_power_of_two_gen::<$field, $d>(); + crate::field_testing::test_power_of_two_gen::<$field, $d>(); } } }; diff --git a/src/field/field_types.rs b/field/src/field_types.rs similarity index 98% rename from src/field/field_types.rs rename to field/src/field_types.rs index 68c42dc5..4ac6ab75 100644 --- a/src/field/field_types.rs +++ b/field/src/field_types.rs @@ -5,17 +5,12 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssi use num::bigint::BigUint; use num::{Integer, One, ToPrimitive, Zero}; +use plonky2_util::bits_u64; use rand::Rng; use serde::de::DeserializeOwned; use serde::Serialize; -use crate::field::extension_field::Frobenius; -use crate::hash::gmimc::GMiMC; -use crate::hash::poseidon::Poseidon; -use crate::util::bits_u64; - -/// A prime order field with the features we need to use it as a base field in our argument system. -pub trait RichField: PrimeField + GMiMC<12> + Poseidon {} +use crate::extension_field::Frobenius; /// A finite field. pub trait Field: diff --git a/src/field/goldilocks_field.rs b/field/src/goldilocks_field.rs similarity index 95% rename from src/field/goldilocks_field.rs rename to field/src/goldilocks_field.rs index e25dc172..54866b1f 100644 --- a/src/field/goldilocks_field.rs +++ b/field/src/goldilocks_field.rs @@ -5,15 +5,15 @@ use std::iter::{Product, Sum}; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use num::{BigUint, Integer}; +use plonky2_util::{assume, branch_hint}; use rand::Rng; use serde::{Deserialize, Serialize}; -use crate::field::extension_field::quadratic::QuadraticExtension; -use crate::field::extension_field::quartic::QuarticExtension; -use crate::field::extension_field::{Extendable, Frobenius}; -use crate::field::field_types::{Field, PrimeField, RichField}; -use crate::field::inversion::try_inverse_u64; -use crate::util::{assume, branch_hint}; +use crate::extension_field::quadratic::QuadraticExtension; +use crate::extension_field::quartic::QuarticExtension; +use crate::extension_field::{Extendable, Frobenius}; +use crate::field_types::{Field, PrimeField}; +use crate::inversion::try_inverse_u64; const EPSILON: u64 = (1 << 32) - 1; @@ -313,8 +313,6 @@ impl Extendable<4> for GoldilocksField { [Self(0), Self(0), Self(0), Self(12587610116473453104)]; } -impl RichField for GoldilocksField {} - /// Fast addition modulo ORDER for x86-64. /// This function is marked unsafe for the following reasons: /// - It is only correct if x + y < 2**64 + ORDER = 0x1ffffffff00000001. @@ -385,6 +383,6 @@ impl Frobenius<1> for GoldilocksField {} mod tests { use crate::{test_field_arithmetic, test_prime_field_arithmetic}; - test_prime_field_arithmetic!(crate::field::goldilocks_field::GoldilocksField); - test_field_arithmetic!(crate::field::goldilocks_field::GoldilocksField); + test_prime_field_arithmetic!(crate::goldilocks_field::GoldilocksField); + test_field_arithmetic!(crate::goldilocks_field::GoldilocksField); } diff --git a/src/field/interpolation.rs b/field/src/interpolation.rs similarity index 92% rename from src/field/interpolation.rs rename to field/src/interpolation.rs index ad3ddf72..ac6f6437 100644 --- a/src/field/interpolation.rs +++ b/field/src/interpolation.rs @@ -1,13 +1,14 @@ -use crate::field::fft::ifft; -use crate::field::field_types::Field; +use plonky2_util::log2_ceil; + +use crate::fft::ifft; +use crate::field_types::Field; use crate::polynomial::{PolynomialCoeffs, PolynomialValues}; -use crate::util::log2_ceil; /// Computes the unique degree < n interpolant of an arbitrary list of n (point, value) pairs. /// /// Note that the implementation assumes that `F` is two-adic, in particular that /// `2^{F::TWO_ADICITY} >= points.len()`. This leads to a simple FFT-based implementation. -pub(crate) fn interpolant(points: &[(F, F)]) -> PolynomialCoeffs { +pub fn interpolant(points: &[(F, F)]) -> PolynomialCoeffs { let n = points.len(); let n_log = log2_ceil(n); @@ -77,9 +78,9 @@ pub fn interpolate2(points: [(F, F); 2], x: F) -> F { #[cfg(test)] mod tests { use super::*; - use crate::field::extension_field::quartic::QuarticExtension; - use crate::field::field_types::Field; - use crate::field::goldilocks_field::GoldilocksField; + use crate::extension_field::quartic::QuarticExtension; + use crate::field_types::Field; + use crate::goldilocks_field::GoldilocksField; use crate::polynomial::PolynomialCoeffs; #[test] diff --git a/src/field/inversion.rs b/field/src/inversion.rs similarity index 98% rename from src/field/inversion.rs rename to field/src/inversion.rs index e3cca682..bbfb8e0d 100644 --- a/src/field/inversion.rs +++ b/field/src/inversion.rs @@ -1,4 +1,4 @@ -use crate::field::field_types::PrimeField; +use crate::field_types::PrimeField; /// This is a 'safe' iteration for the modular inversion algorithm. It /// is safe in the sense that it will produce the right answer even diff --git a/field/src/lib.rs b/field/src/lib.rs new file mode 100644 index 00000000..b17bdc5e --- /dev/null +++ b/field/src/lib.rs @@ -0,0 +1,29 @@ +#![allow(incomplete_features)] +#![allow(clippy::new_without_default)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::type_complexity)] +#![allow(clippy::len_without_is_empty)] +#![allow(clippy::needless_range_loop)] +#![allow(clippy::return_self_not_must_use)] +#![feature(generic_const_exprs)] +#![feature(specialization)] + +pub(crate) mod arch; +pub mod batch_util; +pub mod cosets; +pub mod extension_field; +pub mod fft; +pub mod field_types; +pub mod goldilocks_field; +pub mod interpolation; +mod inversion; +pub mod packable; +pub mod packed_field; +pub mod polynomial; +pub mod secp256k1_base; +pub mod secp256k1_scalar; + +#[cfg(test)] +mod field_testing; +#[cfg(test)] +mod prime_field_testing; diff --git a/src/field/packable.rs b/field/src/packable.rs similarity index 66% rename from src/field/packable.rs rename to field/src/packable.rs index ec0618bd..754a7fb6 100644 --- a/src/field/packable.rs +++ b/field/src/packable.rs @@ -1,5 +1,5 @@ -use crate::field::field_types::Field; -use crate::field::packed_field::PackedField; +use crate::field_types::Field; +use crate::packed_field::PackedField; /// Points us to the default packing for a particular field. There may me multiple choices of /// PackedField for a particular Field (e.g. every Field is also a PackedField), but this is the @@ -13,6 +13,6 @@ impl Packable for F { } #[cfg(all(target_arch = "x86_64", target_feature = "avx2"))] -impl Packable for crate::field::goldilocks_field::GoldilocksField { - type Packing = crate::field::arch::x86_64::avx2_goldilocks_field::Avx2GoldilocksField; +impl Packable for crate::goldilocks_field::GoldilocksField { + type Packing = crate::arch::x86_64::avx2_goldilocks_field::Avx2GoldilocksField; } diff --git a/src/field/packed_field.rs b/field/src/packed_field.rs similarity index 99% rename from src/field/packed_field.rs rename to field/src/packed_field.rs index 00b99d6c..091dbc97 100644 --- a/src/field/packed_field.rs +++ b/field/src/packed_field.rs @@ -3,7 +3,7 @@ use std::iter::{Product, Sum}; use std::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign}; use std::slice; -use crate::field::field_types::Field; +use crate::field_types::Field; /// # Safety /// - WIDTH is assumed to be a power of 2. diff --git a/src/polynomial/division.rs b/field/src/polynomial/division.rs similarity index 95% rename from src/polynomial/division.rs rename to field/src/polynomial/division.rs index 671b7715..4f3cafae 100644 --- a/src/polynomial/division.rs +++ b/field/src/polynomial/division.rs @@ -1,6 +1,7 @@ -use crate::field::field_types::Field; +use plonky2_util::log2_ceil; + +use crate::field_types::Field; use crate::polynomial::PolynomialCoeffs; -use crate::util::log2_ceil; impl PolynomialCoeffs { /// Polynomial division. @@ -68,7 +69,7 @@ impl PolynomialCoeffs { /// Let `self=p(X)`, this returns `(p(X)-p(z))/(X-z)` and `p(z)`. /// See https://en.wikipedia.org/wiki/Horner%27s_method - pub(crate) fn divide_by_linear(&self, z: F) -> (PolynomialCoeffs, F) { + pub fn divide_by_linear(&self, z: F) -> (PolynomialCoeffs, F) { let mut bs = self .coeffs .iter() @@ -126,9 +127,9 @@ impl PolynomialCoeffs { mod tests { use std::time::Instant; - use crate::field::extension_field::quartic::QuarticExtension; - use crate::field::field_types::Field; - use crate::field::goldilocks_field::GoldilocksField; + use crate::extension_field::quartic::QuarticExtension; + use crate::field_types::Field; + use crate::goldilocks_field::GoldilocksField; use crate::polynomial::PolynomialCoeffs; #[test] diff --git a/src/polynomial/mod.rs b/field/src/polynomial/mod.rs similarity index 96% rename from src/polynomial/mod.rs rename to field/src/polynomial/mod.rs index 1a7b90fe..1f777ca3 100644 --- a/src/polynomial/mod.rs +++ b/field/src/polynomial/mod.rs @@ -5,12 +5,12 @@ use std::iter::Sum; use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; use anyhow::{ensure, Result}; +use plonky2_util::log2_strict; use serde::{Deserialize, Serialize}; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::fft::{fft, fft_with_options, ifft, FftRootTable}; -use crate::field::field_types::Field; -use crate::util::log2_strict; +use crate::extension_field::{Extendable, FieldExtension}; +use crate::fft::{fft, fft_with_options, ifft, FftRootTable}; +use crate::field_types::Field; /// A polynomial in point-value form. /// @@ -78,7 +78,7 @@ impl From> for PolynomialValues { #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(bound = "")] pub struct PolynomialCoeffs { - pub(crate) coeffs: Vec, + pub coeffs: Vec, } impl PolynomialCoeffs { @@ -86,15 +86,15 @@ impl PolynomialCoeffs { PolynomialCoeffs { coeffs } } - pub(crate) fn empty() -> Self { + pub fn empty() -> Self { Self::new(Vec::new()) } - pub(crate) fn zero(len: usize) -> Self { + pub fn zero(len: usize) -> Self { Self::new(vec![F::ZERO; len]) } - pub(crate) fn is_zero(&self) -> bool { + pub fn is_zero(&self) -> bool { self.coeffs.iter().all(|x| x.is_zero()) } @@ -108,7 +108,7 @@ impl PolynomialCoeffs { log2_strict(self.len()) } - pub(crate) fn chunks(&self, chunk_size: usize) -> Vec { + pub fn chunks(&self, chunk_size: usize) -> Vec { self.coeffs .chunks(chunk_size) .map(|chunk| PolynomialCoeffs::new(chunk.to_vec())) @@ -163,7 +163,7 @@ impl PolynomialCoeffs { self.padded(self.len() << rate_bits) } - pub(crate) fn pad(&mut self, new_len: usize) -> Result<()> { + pub fn pad(&mut self, new_len: usize) -> Result<()> { ensure!( new_len >= self.len(), "Trying to pad a polynomial of length {} to a length of {}.", @@ -174,7 +174,7 @@ impl PolynomialCoeffs { Ok(()) } - pub(crate) fn padded(&self, new_len: usize) -> Self { + pub fn padded(&self, new_len: usize) -> Self { let mut poly = self.clone(); poly.pad(new_len).unwrap(); poly @@ -192,7 +192,7 @@ impl PolynomialCoeffs { } /// Degree of the polynomial + 1, or 0 for a polynomial with no non-zero coefficients. - pub(crate) fn degree_plus_one(&self) -> usize { + pub fn degree_plus_one(&self) -> usize { (0usize..self.len()) .rev() .find(|&i| self.coeffs[i].is_nonzero()) @@ -397,7 +397,7 @@ mod tests { use rand::{thread_rng, Rng}; use super::*; - use crate::field::goldilocks_field::GoldilocksField; + use crate::goldilocks_field::GoldilocksField; #[test] fn test_trimmed() { diff --git a/src/field/prime_field_testing.rs b/field/src/prime_field_testing.rs similarity index 88% rename from src/field/prime_field_testing.rs rename to field/src/prime_field_testing.rs index 1b7b97eb..42a7bee7 100644 --- a/src/field/prime_field_testing.rs +++ b/field/src/prime_field_testing.rs @@ -1,4 +1,4 @@ -use crate::field::field_types::PrimeField; +use crate::field_types::PrimeField; /// Generates a series of non-negative integers less than `modulus` which cover a range of /// interesting test values. @@ -70,12 +70,12 @@ macro_rules! test_prime_field_arithmetic { mod prime_field_arithmetic { use std::ops::{Add, Mul, Neg, Sub}; - use crate::field::field_types::{Field, PrimeField}; + use crate::field_types::{Field, PrimeField}; #[test] fn arithmetic_addition() { let modulus = <$field>::ORDER; - crate::field::prime_field_testing::run_binaryop_test_cases(<$field>::add, |x, y| { + crate::prime_field_testing::run_binaryop_test_cases(<$field>::add, |x, y| { ((x as u128 + y as u128) % (modulus as u128)) as u64 }) } @@ -83,7 +83,7 @@ macro_rules! test_prime_field_arithmetic { #[test] fn arithmetic_subtraction() { let modulus = <$field>::ORDER; - crate::field::prime_field_testing::run_binaryop_test_cases(<$field>::sub, |x, y| { + crate::prime_field_testing::run_binaryop_test_cases(<$field>::sub, |x, y| { if x >= y { x - y } else { @@ -95,7 +95,7 @@ macro_rules! test_prime_field_arithmetic { #[test] fn arithmetic_negation() { let modulus = <$field>::ORDER; - crate::field::prime_field_testing::run_unaryop_test_cases(<$field>::neg, |x| { + crate::prime_field_testing::run_unaryop_test_cases(<$field>::neg, |x| { if x == 0 { 0 } else { @@ -107,7 +107,7 @@ macro_rules! test_prime_field_arithmetic { #[test] fn arithmetic_multiplication() { let modulus = <$field>::ORDER; - crate::field::prime_field_testing::run_binaryop_test_cases(<$field>::mul, |x, y| { + crate::prime_field_testing::run_binaryop_test_cases(<$field>::mul, |x, y| { ((x as u128) * (y as u128) % (modulus as u128)) as u64 }) } @@ -115,7 +115,7 @@ macro_rules! test_prime_field_arithmetic { #[test] fn arithmetic_square() { let modulus = <$field>::ORDER; - crate::field::prime_field_testing::run_unaryop_test_cases( + crate::prime_field_testing::run_unaryop_test_cases( |x: $field| x.square(), |x| ((x as u128 * x as u128) % (modulus as u128)) as u64, ) @@ -129,7 +129,7 @@ macro_rules! test_prime_field_arithmetic { assert_eq!(zero.try_inverse(), None); - let inputs = crate::field::prime_field_testing::test_inputs(modulus); + let inputs = crate::prime_field_testing::test_inputs(modulus); for x in inputs { if x != 0 { diff --git a/src/field/secp256k1_base.rs b/field/src/secp256k1_base.rs similarity index 98% rename from src/field/secp256k1_base.rs rename to field/src/secp256k1_base.rs index 0d79000f..23702420 100644 --- a/src/field/secp256k1_base.rs +++ b/field/src/secp256k1_base.rs @@ -10,7 +10,7 @@ use num::{Integer, One}; use rand::Rng; use serde::{Deserialize, Serialize}; -use crate::field::field_types::Field; +use crate::field_types::Field; /// The base field of the secp256k1 elliptic curve. /// @@ -244,5 +244,5 @@ impl DivAssign for Secp256K1Base { mod tests { use crate::test_field_arithmetic; - test_field_arithmetic!(crate::field::secp256k1_base::Secp256K1Base); + test_field_arithmetic!(crate::secp256k1_base::Secp256K1Base); } diff --git a/src/field/secp256k1_scalar.rs b/field/src/secp256k1_scalar.rs similarity index 98% rename from src/field/secp256k1_scalar.rs rename to field/src/secp256k1_scalar.rs index a5b7a315..f10892af 100644 --- a/src/field/secp256k1_scalar.rs +++ b/field/src/secp256k1_scalar.rs @@ -11,7 +11,7 @@ use num::{Integer, One}; use rand::Rng; use serde::{Deserialize, Serialize}; -use crate::field::field_types::Field; +use crate::field_types::Field; /// The base field of the secp256k1 elliptic curve. /// @@ -253,5 +253,5 @@ impl DivAssign for Secp256K1Scalar { mod tests { use crate::test_field_arithmetic; - test_field_arithmetic!(crate::field::secp256k1_scalar::Secp256K1Scalar); + test_field_arithmetic!(crate::secp256k1_scalar::Secp256K1Scalar); } diff --git a/insertion/Cargo.toml b/insertion/Cargo.toml new file mode 100644 index 00000000..481c2d5d --- /dev/null +++ b/insertion/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "plonky2_insertion" +description = "Circuit implementation of list insertion" +version = "0.1.0" +edition = "2021" + +[dependencies] +plonky2 = { path = "../plonky2" } +anyhow = "1.0.40" diff --git a/src/gadgets/insert.rs b/insertion/src/insert_gadget.rs similarity index 76% rename from src/gadgets/insert.rs rename to insertion/src/insert_gadget.rs index 5fc5fd48..9f8aa4bf 100644 --- a/src/gadgets/insert.rs +++ b/insertion/src/insert_gadget.rs @@ -1,14 +1,26 @@ -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::RichField; -use crate::gates::insertion::InsertionGate; -use crate::iop::target::Target; -use crate::plonk::circuit_builder::CircuitBuilder; +use plonky2::field::extension_field::Extendable; +use plonky2::hash::hash_types::RichField; +use plonky2::iop::ext_target::ExtensionTarget; +use plonky2::iop::target::Target; +use plonky2::plonk::circuit_builder::CircuitBuilder; -impl, const D: usize> CircuitBuilder { +use crate::insertion_gate::InsertionGate; + +pub trait CircuitBuilderInsert, const D: usize> { /// Inserts a `Target` in a vector at a non-deterministic index. /// Note: `index` is not range-checked. - pub fn insert( + fn insert( + &mut self, + index: Target, + element: ExtensionTarget, + v: Vec>, + ) -> Vec>; +} + +impl, const D: usize> CircuitBuilderInsert + for CircuitBuilder +{ + fn insert( &mut self, index: Target, element: ExtensionTarget, @@ -41,13 +53,12 @@ impl, const D: usize> CircuitBuilder { #[cfg(test)] mod tests { use anyhow::Result; + use plonky2::field::field_types::Field; + use plonky2::iop::witness::PartialWitness; + use plonky2::plonk::circuit_data::CircuitConfig; + use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; use super::*; - use crate::field::field_types::Field; - use crate::iop::witness::PartialWitness; - use crate::plonk::circuit_data::CircuitConfig; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - use crate::plonk::verifier::verify; fn real_insert( index: usize, @@ -88,7 +99,7 @@ mod tests { let data = builder.build::(); let proof = data.prove(pw)?; - verify(proof, &data.verifier_only, &data.common) + data.verify(proof) } #[test] diff --git a/src/gates/insertion.rs b/insertion/src/insertion_gate.rs similarity index 92% rename from src/gates/insertion.rs rename to insertion/src/insertion_gate.rs index 7f4efaa1..8ee60483 100644 --- a/src/gates/insertion.rs +++ b/insertion/src/insertion_gate.rs @@ -1,26 +1,27 @@ use std::marker::PhantomData; use std::ops::Range; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::{Field, RichField}; -use crate::gates::gate::Gate; -use crate::gates::util::StridedConstraintConsumer; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; -use crate::iop::target::Target; -use crate::iop::wire::Wire; -use crate::iop::witness::{PartitionWitness, Witness}; -use crate::plonk::circuit_builder::CircuitBuilder; -use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; +use plonky2::field::extension_field::{Extendable, FieldExtension}; +use plonky2::field::field_types::Field; +use plonky2::gates::gate::Gate; +use plonky2::gates::util::StridedConstraintConsumer; +use plonky2::hash::hash_types::RichField; +use plonky2::iop::ext_target::ExtensionTarget; +use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use plonky2::iop::target::Target; +use plonky2::iop::wire::Wire; +use plonky2::iop::witness::{PartitionWitness, Witness}; +use plonky2::plonk::circuit_builder::CircuitBuilder; +use plonky2::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; /// A gate for inserting a value into a list at a non-deterministic location. #[derive(Clone, Debug)] -pub(crate) struct InsertionGate, const D: usize> { +pub(crate) struct InsertionGate, const D: usize> { pub vec_size: usize, _phantom: PhantomData, } -impl, const D: usize> InsertionGate { +impl, const D: usize> InsertionGate { pub fn new(vec_size: usize) -> Self { Self { vec_size, @@ -70,7 +71,7 @@ impl, const D: usize> InsertionGate { } } -impl, const D: usize> Gate for InsertionGate { +impl, const D: usize> Gate for InsertionGate { fn id(&self) -> String { format!("{:?}", self, D) } @@ -323,15 +324,15 @@ mod tests { use std::marker::PhantomData; use anyhow::Result; + use plonky2::field::field_types::Field; + use plonky2::field::goldilocks_field::GoldilocksField; + use plonky2::gates::gate::Gate; + use plonky2::gates::gate_testing::{test_eval_fns, test_low_degree}; + use plonky2::hash::hash_types::HashOut; + use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; + use plonky2::plonk::vars::EvaluationVars; - use crate::field::field_types::Field; - use crate::field::goldilocks_field::GoldilocksField; - use crate::gates::gate::Gate; - use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; - use crate::gates::insertion::InsertionGate; - use crate::hash::hash_types::HashOut; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - use crate::plonk::vars::EvaluationVars; + use crate::insertion_gate::InsertionGate; #[test] fn wire_indices() { diff --git a/insertion/src/lib.rs b/insertion/src/lib.rs new file mode 100644 index 00000000..15c91253 --- /dev/null +++ b/insertion/src/lib.rs @@ -0,0 +1,9 @@ +#![allow(clippy::new_without_default)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::type_complexity)] +#![allow(clippy::len_without_is_empty)] +#![allow(clippy::needless_range_loop)] +#![allow(clippy::return_self_not_must_use)] + +pub mod insert_gadget; +pub mod insertion_gate; diff --git a/plonky2/Cargo.toml b/plonky2/Cargo.toml new file mode 100644 index 00000000..0dbfa2d7 --- /dev/null +++ b/plonky2/Cargo.toml @@ -0,0 +1,61 @@ +[package] +name = "plonky2" +description = "Recursive SNARKs based on Plonk and FRI" +version = "0.1.0" +authors = ["Daniel Lubarov "] +readme = "README.md" +license = "MIT OR Apache-2.0" +repository = "https://github.com/mir-protocol/plonky2" +keywords = ["cryptography", "SNARK", "FRI"] +categories = ["cryptography"] +edition = "2021" +default-run = "bench_recursion" + +[dependencies] +plonky2_field = { path = "../field" } +plonky2_util = { path = "../util" } +array_tool = "1.0.3" +env_logger = "0.9.0" +log = "0.4.14" +itertools = "0.10.0" +num = { version = "0.4", features = [ "rand" ] } +rand = "0.8.4" +rand_chacha = "0.3.1" +rayon = "1.5.1" +unroll = "0.1.5" +anyhow = "1.0.40" +serde = { version = "1.0", features = ["derive"] } +serde_cbor = "0.11.1" +keccak-hash = "0.8.0" +static_assertions = "1.1.0" + +[target.'cfg(not(target_env = "msvc"))'.dependencies] +jemallocator = "0.3.2" + +[dev-dependencies] +criterion = "0.3.5" +tynm = "0.1.6" + +[[bench]] +name = "field_arithmetic" +harness = false + +[[bench]] +name = "ffts" +harness = false + +[[bench]] +name = "hashing" +harness = false + +[[bench]] +name = "transpose" +harness = false + +[profile.release] +opt-level = 3 +#lto = "fat" +#codegen-units = 1 + +[profile.bench] +opt-level = 3 diff --git a/benches/ffts.rs b/plonky2/benches/ffts.rs similarity index 96% rename from benches/ffts.rs rename to plonky2/benches/ffts.rs index 745d53a8..cfa02a25 100644 --- a/benches/ffts.rs +++ b/plonky2/benches/ffts.rs @@ -1,7 +1,7 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use plonky2::field::field_types::Field; use plonky2::field::goldilocks_field::GoldilocksField; -use plonky2::polynomial::PolynomialCoeffs; +use plonky2::field::polynomial::PolynomialCoeffs; use tynm::type_name; pub(crate) fn bench_ffts(c: &mut Criterion) { diff --git a/benches/field_arithmetic.rs b/plonky2/benches/field_arithmetic.rs similarity index 100% rename from benches/field_arithmetic.rs rename to plonky2/benches/field_arithmetic.rs diff --git a/benches/hashing.rs b/plonky2/benches/hashing.rs similarity index 100% rename from benches/hashing.rs rename to plonky2/benches/hashing.rs diff --git a/benches/transpose.rs b/plonky2/benches/transpose.rs similarity index 100% rename from benches/transpose.rs rename to plonky2/benches/transpose.rs diff --git a/src/bin/bench_ldes.rs b/plonky2/src/bin/bench_ldes.rs similarity index 86% rename from src/bin/bench_ldes.rs rename to plonky2/src/bin/bench_ldes.rs index dbcfa6df..57f31290 100644 --- a/src/bin/bench_ldes.rs +++ b/plonky2/src/bin/bench_ldes.rs @@ -1,8 +1,8 @@ use std::time::Instant; -use plonky2::field::field_types::Field; -use plonky2::field::goldilocks_field::GoldilocksField; -use plonky2::polynomial::PolynomialValues; +use plonky2_field::field_types::Field; +use plonky2_field::goldilocks_field::GoldilocksField; +use plonky2_field::polynomial::PolynomialValues; use rayon::prelude::*; type F = GoldilocksField; diff --git a/src/bin/bench_recursion.rs b/plonky2/src/bin/bench_recursion.rs similarity index 100% rename from src/bin/bench_recursion.rs rename to plonky2/src/bin/bench_recursion.rs diff --git a/src/bin/generate_constants.rs b/plonky2/src/bin/generate_constants.rs similarity index 93% rename from src/bin/generate_constants.rs rename to plonky2/src/bin/generate_constants.rs index 89630fc7..eb35aec3 100644 --- a/src/bin/generate_constants.rs +++ b/plonky2/src/bin/generate_constants.rs @@ -2,8 +2,8 @@ #![allow(clippy::needless_range_loop)] -use plonky2::field::field_types::PrimeField; -use plonky2::field::goldilocks_field::GoldilocksField; +use plonky2_field::field_types::PrimeField; +use plonky2_field::goldilocks_field::GoldilocksField; use rand::{Rng, SeedableRng}; use rand_chacha::ChaCha8Rng; diff --git a/src/curve/curve_adds.rs b/plonky2/src/curve/curve_adds.rs similarity index 99% rename from src/curve/curve_adds.rs rename to plonky2/src/curve/curve_adds.rs index f25d3847..3638d450 100644 --- a/src/curve/curve_adds.rs +++ b/plonky2/src/curve/curve_adds.rs @@ -1,7 +1,8 @@ use std::ops::Add; +use plonky2_field::field_types::Field; + use crate::curve::curve_types::{AffinePoint, Curve, ProjectivePoint}; -use crate::field::field_types::Field; impl Add> for ProjectivePoint { type Output = ProjectivePoint; diff --git a/src/curve/curve_msm.rs b/plonky2/src/curve/curve_msm.rs similarity index 98% rename from src/curve/curve_msm.rs rename to plonky2/src/curve/curve_msm.rs index d2cb8049..388c0321 100644 --- a/src/curve/curve_msm.rs +++ b/plonky2/src/curve/curve_msm.rs @@ -1,9 +1,9 @@ use itertools::Itertools; +use plonky2_field::field_types::Field; use rayon::prelude::*; use crate::curve::curve_summation::affine_multisummation_best; use crate::curve::curve_types::{AffinePoint, Curve, ProjectivePoint}; -use crate::field::field_types::Field; /// In Yao's method, we compute an affine summation for each digit. In a parallel setting, it would /// be easiest to assign individual summations to threads, but this would be sub-optimal because @@ -186,12 +186,12 @@ pub(crate) fn to_digits(x: &C::ScalarField, w: usize) -> Vec { #[cfg(test)] mod tests { use num::BigUint; + use plonky2_field::field_types::Field; + use plonky2_field::secp256k1_scalar::Secp256K1Scalar; use crate::curve::curve_msm::{msm_execute, msm_precompute, to_digits}; use crate::curve::curve_types::Curve; use crate::curve::secp256k1::Secp256K1; - use crate::field::field_types::Field; - use crate::field::secp256k1_scalar::Secp256K1Scalar; #[test] fn test_to_digits() { diff --git a/src/curve/curve_multiplication.rs b/plonky2/src/curve/curve_multiplication.rs similarity index 98% rename from src/curve/curve_multiplication.rs rename to plonky2/src/curve/curve_multiplication.rs index eb5bade1..30da4973 100644 --- a/src/curve/curve_multiplication.rs +++ b/plonky2/src/curve/curve_multiplication.rs @@ -1,7 +1,8 @@ use std::ops::Mul; +use plonky2_field::field_types::Field; + use crate::curve::curve_types::{Curve, CurveScalar, ProjectivePoint}; -use crate::field::field_types::Field; const WINDOW_BITS: usize = 4; const BASE: usize = 1 << WINDOW_BITS; diff --git a/src/curve/curve_summation.rs b/plonky2/src/curve/curve_summation.rs similarity index 99% rename from src/curve/curve_summation.rs rename to plonky2/src/curve/curve_summation.rs index c67bc026..67f8023c 100644 --- a/src/curve/curve_summation.rs +++ b/plonky2/src/curve/curve_summation.rs @@ -1,7 +1,8 @@ use std::iter::Sum; +use plonky2_field::field_types::Field; + use crate::curve::curve_types::{AffinePoint, Curve, ProjectivePoint}; -use crate::field::field_types::Field; impl Sum> for ProjectivePoint { fn sum>>(iter: I) -> ProjectivePoint { diff --git a/src/curve/curve_types.rs b/plonky2/src/curve/curve_types.rs similarity index 99% rename from src/curve/curve_types.rs rename to plonky2/src/curve/curve_types.rs index ef1f6186..c02db73f 100644 --- a/src/curve/curve_types.rs +++ b/plonky2/src/curve/curve_types.rs @@ -1,7 +1,7 @@ use std::fmt::Debug; use std::ops::Neg; -use crate::field::field_types::Field; +use plonky2_field::field_types::Field; // To avoid implementation conflicts from associated types, // see https://github.com/rust-lang/rust/issues/20400 diff --git a/src/curve/mod.rs b/plonky2/src/curve/mod.rs similarity index 100% rename from src/curve/mod.rs rename to plonky2/src/curve/mod.rs diff --git a/src/curve/secp256k1.rs b/plonky2/src/curve/secp256k1.rs similarity index 91% rename from src/curve/secp256k1.rs rename to plonky2/src/curve/secp256k1.rs index 58472eb4..d9039719 100644 --- a/src/curve/secp256k1.rs +++ b/plonky2/src/curve/secp256k1.rs @@ -1,7 +1,8 @@ +use plonky2_field::field_types::Field; +use plonky2_field::secp256k1_base::Secp256K1Base; +use plonky2_field::secp256k1_scalar::Secp256K1Scalar; + use crate::curve::curve_types::{AffinePoint, Curve}; -use crate::field::field_types::Field; -use crate::field::secp256k1_base::Secp256K1Base; -use crate::field::secp256k1_scalar::Secp256K1Scalar; #[derive(Debug, Copy, Clone)] pub struct Secp256K1; @@ -38,11 +39,11 @@ const SECP256K1_GENERATOR_Y: Secp256K1Base = Secp256K1Base([ #[cfg(test)] mod tests { use num::BigUint; + use plonky2_field::field_types::Field; + use plonky2_field::secp256k1_scalar::Secp256K1Scalar; use crate::curve::curve_types::{AffinePoint, Curve, ProjectivePoint}; use crate::curve::secp256k1::Secp256K1; - use crate::field::field_types::Field; - use crate::field::secp256k1_scalar::Secp256K1Scalar; #[test] fn test_generator() { diff --git a/src/fri/commitment.rs b/plonky2/src/fri/commitment.rs similarity index 93% rename from src/fri/commitment.rs rename to plonky2/src/fri/commitment.rs index 54a2ebbc..52ed0645 100644 --- a/src/fri/commitment.rs +++ b/plonky2/src/fri/commitment.rs @@ -1,27 +1,34 @@ +use plonky2_field::extension_field::Extendable; +use plonky2_field::fft::FftRootTable; +use plonky2_field::field_types::Field; +use plonky2_field::polynomial::{PolynomialCoeffs, PolynomialValues}; +use plonky2_util::{log2_strict, reverse_index_bits_in_place}; use rayon::prelude::*; -use crate::field::extension_field::Extendable; -use crate::field::fft::FftRootTable; -use crate::field::field_types::Field; use crate::fri::proof::FriProof; use crate::fri::prover::fri_proof; +use crate::hash::hash_types::RichField; use crate::hash::merkle_tree::MerkleTree; use crate::iop::challenger::Challenger; use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::config::GenericConfig; use crate::plonk::plonk_common::PlonkPolynomials; use crate::plonk::proof::OpeningSet; -use crate::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::timed; use crate::util::reducing::ReducingFactor; +use crate::util::reverse_bits; use crate::util::timing::TimingTree; -use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place, transpose}; +use crate::util::transpose; /// Four (~64 bit) field elements gives ~128 bit security. pub const SALT_SIZE: usize = 4; /// Represents a batch FRI based commitment to a list of polynomials. -pub struct PolynomialBatchCommitment, C: GenericConfig, const D: usize> { +pub struct PolynomialBatchCommitment< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, +> { pub polynomials: Vec>, pub merkle_tree: MerkleTree, pub degree_log: usize, @@ -29,7 +36,7 @@ pub struct PolynomialBatchCommitment, C: GenericConfig, C: GenericConfig, const D: usize> +impl, C: GenericConfig, const D: usize> PolynomialBatchCommitment { /// Creates a list polynomial commitment for the polynomials interpolating the values in `values`. diff --git a/src/fri/mod.rs b/plonky2/src/fri/mod.rs similarity index 100% rename from src/fri/mod.rs rename to plonky2/src/fri/mod.rs diff --git a/src/fri/proof.rs b/plonky2/src/fri/proof.rs similarity index 94% rename from src/fri/proof.rs rename to plonky2/src/fri/proof.rs index ccd80a37..98362af6 100644 --- a/src/fri/proof.rs +++ b/plonky2/src/fri/proof.rs @@ -1,27 +1,27 @@ use std::collections::HashMap; use itertools::izip; +use plonky2_field::extension_field::{flatten, unflatten, Extendable}; +use plonky2_field::polynomial::PolynomialCoeffs; use serde::{Deserialize, Serialize}; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::{flatten, unflatten, Extendable}; -use crate::field::field_types::RichField; use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; use crate::hash::hash_types::MerkleCapTarget; +use crate::hash::hash_types::RichField; use crate::hash::merkle_proofs::{MerkleProof, MerkleProofTarget}; use crate::hash::merkle_tree::MerkleCap; use crate::hash::path_compression::{compress_merkle_proofs, decompress_merkle_proofs}; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::config::{GenericConfig, Hasher}; use crate::plonk::plonk_common::PolynomialsIndexBlinding; use crate::plonk::proof::{FriInferredElements, ProofChallenges}; -use crate::polynomial::PolynomialCoeffs; /// Evaluations and Merkle proof produced by the prover in a FRI query step. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[serde(bound = "")] -pub struct FriQueryStep, H: Hasher, const D: usize> { +pub struct FriQueryStep, H: Hasher, const D: usize> { pub evals: Vec, pub merkle_proof: MerkleProof, } @@ -70,7 +70,7 @@ impl FriInitialTreeProofTarget { /// Proof for a FRI query round. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[serde(bound = "")] -pub struct FriQueryRound, H: Hasher, const D: usize> { +pub struct FriQueryRound, H: Hasher, const D: usize> { pub initial_trees_proof: FriInitialTreeProof, pub steps: Vec>, } @@ -84,7 +84,7 @@ pub struct FriQueryRoundTarget { /// Compressed proof of the FRI query rounds. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[serde(bound = "")] -pub struct CompressedFriQueryRounds, H: Hasher, const D: usize> { +pub struct CompressedFriQueryRounds, H: Hasher, const D: usize> { /// Query indices. pub indices: Vec, /// Map from initial indices `i` to the `FriInitialProof` for the `i`th leaf. @@ -95,7 +95,7 @@ pub struct CompressedFriQueryRounds, H: Hasher, const D: usi #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[serde(bound = "")] -pub struct FriProof, H: Hasher, const D: usize> { +pub struct FriProof, H: Hasher, const D: usize> { /// A Merkle cap for each reduced polynomial in the commit phase. pub commit_phase_merkle_caps: Vec>, /// Query rounds proofs @@ -115,7 +115,7 @@ pub struct FriProofTarget { #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[serde(bound = "")] -pub struct CompressedFriProof, H: Hasher, const D: usize> { +pub struct CompressedFriProof, H: Hasher, const D: usize> { /// A Merkle cap for each reduced polynomial in the commit phase. pub commit_phase_merkle_caps: Vec>, /// Compressed query rounds proof. @@ -126,7 +126,7 @@ pub struct CompressedFriProof, H: Hasher, const D: usize> { pub pow_witness: F, } -impl, H: Hasher, const D: usize> FriProof { +impl, H: Hasher, const D: usize> FriProof { /// Compress all the Merkle paths in the FRI proof and remove duplicate indices. pub fn compress>( self, @@ -232,7 +232,7 @@ impl, H: Hasher, const D: usize> FriProof { } } -impl, H: Hasher, const D: usize> CompressedFriProof { +impl, H: Hasher, const D: usize> CompressedFriProof { /// Decompress all the Merkle paths in the FRI proof and reinsert duplicate indices. pub(crate) fn decompress>( self, diff --git a/src/fri/prover.rs b/plonky2/src/fri/prover.rs similarity index 88% rename from src/fri/prover.rs rename to plonky2/src/fri/prover.rs index e902986b..20c4f133 100644 --- a/src/fri/prover.rs +++ b/plonky2/src/fri/prover.rs @@ -1,21 +1,21 @@ +use plonky2_field::extension_field::{flatten, unflatten, Extendable}; +use plonky2_field::polynomial::{PolynomialCoeffs, PolynomialValues}; +use plonky2_util::reverse_index_bits_in_place; use rayon::prelude::*; -use crate::field::extension_field::{flatten, unflatten, Extendable}; use crate::fri::proof::{FriInitialTreeProof, FriProof, FriQueryRound, FriQueryStep}; use crate::fri::FriConfig; -use crate::hash::hash_types::HashOut; +use crate::hash::hash_types::{HashOut, RichField}; use crate::hash::merkle_tree::MerkleTree; use crate::iop::challenger::Challenger; use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::config::{GenericConfig, Hasher}; use crate::plonk::plonk_common::reduce_with_powers; -use crate::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::timed; -use crate::util::reverse_index_bits_in_place; use crate::util::timing::TimingTree; /// Builds a FRI proof. -pub fn fri_proof, C: GenericConfig, const D: usize>( +pub fn fri_proof, C: GenericConfig, const D: usize>( initial_merkle_trees: &[&MerkleTree], // Coefficients of the polynomial on which the LDT is performed. Only the first `1/rate` coefficients are non-zero. lde_polynomial_coeffs: PolynomialCoeffs, @@ -60,7 +60,7 @@ pub fn fri_proof, C: GenericConfig, const D: usize>( } } -fn fri_committed_trees, C: GenericConfig, const D: usize>( +fn fri_committed_trees, C: GenericConfig, const D: usize>( mut coeffs: PolynomialCoeffs, mut values: PolynomialValues, challenger: &mut Challenger, @@ -108,7 +108,7 @@ fn fri_committed_trees, C: GenericConfig, const D: us (trees, coeffs) } -fn fri_proof_of_work, C: GenericConfig, const D: usize>( +fn fri_proof_of_work, C: GenericConfig, const D: usize>( current_hash: HashOut, config: &FriConfig, ) -> F { @@ -133,7 +133,11 @@ fn fri_proof_of_work, C: GenericConfig, const D: usiz .expect("Proof of work failed. This is highly unlikely!") } -fn fri_prover_query_rounds, C: GenericConfig, const D: usize>( +fn fri_prover_query_rounds< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, +>( initial_merkle_trees: &[&MerkleTree], trees: &[MerkleTree], challenger: &mut Challenger, @@ -145,7 +149,11 @@ fn fri_prover_query_rounds, C: GenericConfig, const D .collect() } -fn fri_prover_query_round, C: GenericConfig, const D: usize>( +fn fri_prover_query_round< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, +>( initial_merkle_trees: &[&MerkleTree], trees: &[MerkleTree], challenger: &mut Challenger, diff --git a/src/fri/recursive_verifier.rs b/plonky2/src/fri/recursive_verifier.rs similarity index 98% rename from src/fri/recursive_verifier.rs rename to plonky2/src/fri/recursive_verifier.rs index 0423e8c8..80a39f12 100644 --- a/src/fri/recursive_verifier.rs +++ b/plonky2/src/fri/recursive_verifier.rs @@ -1,6 +1,7 @@ -use crate::field::extension_field::target::{flatten_target, ExtensionTarget}; -use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, RichField}; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::Field; +use plonky2_util::{log2_strict, reverse_index_bits_in_place}; + use crate::fri::proof::{FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget}; use crate::fri::FriConfig; use crate::gadgets::interpolation::InterpolationGate; @@ -9,7 +10,9 @@ use crate::gates::interpolation::HighDegreeInterpolationGate; use crate::gates::low_degree_interpolation::LowDegreeInterpolationGate; use crate::gates::random_access::RandomAccessGate; use crate::hash::hash_types::MerkleCapTarget; +use crate::hash::hash_types::RichField; use crate::iop::challenger::RecursiveChallenger; +use crate::iop::ext_target::{flatten_target, ExtensionTarget}; use crate::iop::target::{BoolTarget, Target}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::{CircuitConfig, CommonCircuitData}; @@ -17,10 +20,9 @@ use crate::plonk::config::{AlgebraicConfig, AlgebraicHasher, GenericConfig}; use crate::plonk::plonk_common::PlonkPolynomials; use crate::plonk::proof::OpeningSetTarget; use crate::util::reducing::ReducingFactorTarget; -use crate::util::{log2_strict, reverse_index_bits_in_place}; use crate::with_context; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Computes P'(x^arity) from {P(x*g^i)}_(i=0..arity), where g is a `arity`-th root of unity /// and P' is the FRI reduced polynomial. fn compute_evaluation>( diff --git a/src/fri/reduction_strategies.rs b/plonky2/src/fri/reduction_strategies.rs similarity index 100% rename from src/fri/reduction_strategies.rs rename to plonky2/src/fri/reduction_strategies.rs diff --git a/src/fri/verifier.rs b/plonky2/src/fri/verifier.rs similarity index 92% rename from src/fri/verifier.rs rename to plonky2/src/fri/verifier.rs index 1b067a42..cf883be6 100644 --- a/src/fri/verifier.rs +++ b/plonky2/src/fri/verifier.rs @@ -1,10 +1,12 @@ use anyhow::{ensure, Result}; +use plonky2_field::extension_field::{flatten, Extendable, FieldExtension}; +use plonky2_field::field_types::Field; +use plonky2_field::interpolation::{barycentric_weights, interpolate, interpolate2}; +use plonky2_util::{log2_strict, reverse_index_bits_in_place}; -use crate::field::extension_field::{flatten, Extendable, FieldExtension}; -use crate::field::field_types::{Field, RichField}; -use crate::field::interpolation::{barycentric_weights, interpolate, interpolate2}; use crate::fri::proof::{FriInitialTreeProof, FriProof, FriQueryRound}; use crate::fri::FriConfig; +use crate::hash::hash_types::RichField; use crate::hash::merkle_proofs::verify_merkle_proof; use crate::hash::merkle_tree::MerkleCap; use crate::plonk::circuit_data::CommonCircuitData; @@ -12,7 +14,7 @@ use crate::plonk::config::{GenericConfig, Hasher}; use crate::plonk::plonk_common::PlonkPolynomials; use crate::plonk::proof::{OpeningSet, ProofChallenges}; use crate::util::reducing::ReducingFactor; -use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place}; +use crate::util::reverse_bits; /// Computes P'(x^arity) from {P(x*g^i)}_(i=0..arity), where g is a `arity`-th root of unity /// and P' is the FRI reduced polynomial. @@ -123,13 +125,13 @@ fn fri_verify_initial_proof>( /// Holds the reduced (by `alpha`) evaluations at `zeta` for the polynomial opened just at /// zeta, for `Z` at zeta and for `Z` at `g*zeta`. #[derive(Copy, Clone, Debug)] -pub(crate) struct PrecomputedReducedEvals, const D: usize> { +pub(crate) struct PrecomputedReducedEvals, const D: usize> { pub single: F::Extension, pub zs: F::Extension, pub zs_right: F::Extension, } -impl, const D: usize> PrecomputedReducedEvals { +impl, const D: usize> PrecomputedReducedEvals { pub(crate) fn from_os_and_alpha(os: &OpeningSet, alpha: F::Extension) -> Self { let mut alpha = ReducingFactor::new(alpha); let single = alpha.reduce( @@ -151,7 +153,11 @@ impl, const D: usize> PrecomputedReducedEvals { } } -pub(crate) fn fri_combine_initial, C: GenericConfig, const D: usize>( +pub(crate) fn fri_combine_initial< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, +>( proof: &FriInitialTreeProof, alpha: F::Extension, zeta: F::Extension, @@ -212,7 +218,11 @@ pub(crate) fn fri_combine_initial, C: GenericConfig, sum } -fn fri_verifier_query_round, C: GenericConfig, const D: usize>( +fn fri_verifier_query_round< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, +>( challenges: &ProofChallenges, precomputed_reduced_evals: PrecomputedReducedEvals, initial_merkle_caps: &[MerkleCap], diff --git a/src/gadgets/arithmetic.rs b/plonky2/src/gadgets/arithmetic.rs similarity index 98% rename from src/gadgets/arithmetic.rs rename to plonky2/src/gadgets/arithmetic.rs index 1ea2f769..e280fa5e 100644 --- a/src/gadgets/arithmetic.rs +++ b/plonky2/src/gadgets/arithmetic.rs @@ -1,13 +1,15 @@ use std::borrow::Borrow; -use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::PrimeField; + use crate::gates::arithmetic_base::ArithmeticGate; use crate::gates::exponentiation::ExponentiationGate; +use crate::hash::hash_types::RichField; use crate::iop::target::{BoolTarget, Target}; use crate::plonk::circuit_builder::CircuitBuilder; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Computes `-x`. pub fn neg(&mut self, x: Target) -> Target { let neg_one = self.neg_one(); diff --git a/src/gadgets/arithmetic_extension.rs b/plonky2/src/gadgets/arithmetic_extension.rs similarity index 96% rename from src/gadgets/arithmetic_extension.rs rename to plonky2/src/gadgets/arithmetic_extension.rs index 32c80bc4..125fb49a 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/plonky2/src/gadgets/arithmetic_extension.rs @@ -1,16 +1,18 @@ -use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget}; -use crate::field::extension_field::FieldExtension; -use crate::field::extension_field::{Extendable, OEF}; -use crate::field::field_types::{Field, PrimeField}; +use plonky2_field::extension_field::FieldExtension; +use plonky2_field::extension_field::{Extendable, OEF}; +use plonky2_field::field_types::{Field, PrimeField}; +use plonky2_util::bits_u64; + use crate::gates::arithmetic_extension::ArithmeticExtensionGate; use crate::gates::multiplication_extension::MulExtensionGate; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::{ExtensionAlgebraTarget, ExtensionTarget}; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; -use crate::util::bits_u64; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { pub fn arithmetic_extension( &mut self, const_0: F, @@ -484,7 +486,9 @@ struct QuotientGeneratorExtension { quotient: ExtensionTarget, } -impl, const D: usize> SimpleGenerator for QuotientGeneratorExtension { +impl, const D: usize> SimpleGenerator + for QuotientGeneratorExtension +{ fn dependencies(&self) -> Vec { let mut deps = self.numerator.to_target_array().to_vec(); deps.extend(&self.denominator.to_target_array()); @@ -507,7 +511,7 @@ pub struct PowersTarget { } impl PowersTarget { - pub fn next>( + pub fn next>( &mut self, builder: &mut CircuitBuilder, ) -> ExtensionTarget { @@ -516,7 +520,7 @@ impl PowersTarget { result } - pub fn repeated_frobenius>( + pub fn repeated_frobenius>( self, k: usize, builder: &mut CircuitBuilder, @@ -529,7 +533,7 @@ impl PowersTarget { } } -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { pub fn powers(&mut self, base: ExtensionTarget) -> PowersTarget { PowersTarget { base, @@ -551,10 +555,10 @@ pub(crate) struct ExtensionArithmeticOperation, co #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::extension_field::algebra::ExtensionAlgebra; + use plonky2_field::field_types::Field; - use crate::field::extension_field::algebra::ExtensionAlgebra; - use crate::field::extension_field::target::ExtensionAlgebraTarget; - use crate::field::field_types::Field; + use crate::iop::ext_target::ExtensionAlgebraTarget; use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; diff --git a/src/gadgets/arithmetic_u32.rs b/plonky2/src/gadgets/arithmetic_u32.rs similarity index 98% rename from src/gadgets/arithmetic_u32.rs rename to plonky2/src/gadgets/arithmetic_u32.rs index 3bf6ce58..6116f61b 100644 --- a/src/gadgets/arithmetic_u32.rs +++ b/plonky2/src/gadgets/arithmetic_u32.rs @@ -1,7 +1,8 @@ -use crate::field::extension_field::Extendable; -use crate::field::field_types::RichField; +use plonky2_field::extension_field::Extendable; + use crate::gates::arithmetic_u32::U32ArithmeticGate; use crate::gates::subtraction_u32::U32SubtractionGate; +use crate::hash::hash_types::RichField; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; diff --git a/src/gadgets/biguint.rs b/plonky2/src/gadgets/biguint.rs similarity index 99% rename from src/gadgets/biguint.rs rename to plonky2/src/gadgets/biguint.rs index ec70ec3f..77013d27 100644 --- a/src/gadgets/biguint.rs +++ b/plonky2/src/gadgets/biguint.rs @@ -1,10 +1,10 @@ use std::marker::PhantomData; use num::{BigUint, Integer}; +use plonky2_field::extension_field::Extendable; -use crate::field::extension_field::Extendable; -use crate::field::field_types::RichField; use crate::gadgets::arithmetic_u32::U32Target; +use crate::hash::hash_types::RichField; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; use crate::iop::witness::{PartitionWitness, Witness}; diff --git a/src/gadgets/curve.rs b/plonky2/src/gadgets/curve.rs similarity index 97% rename from src/gadgets/curve.rs rename to plonky2/src/gadgets/curve.rs index 6ffe7ec4..63e96721 100644 --- a/src/gadgets/curve.rs +++ b/plonky2/src/gadgets/curve.rs @@ -1,7 +1,9 @@ +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::Field; + use crate::curve::curve_types::{AffinePoint, Curve, CurveScalar}; -use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, RichField}; use crate::gadgets::nonnative::NonNativeTarget; +use crate::hash::hash_types::RichField; use crate::plonk::circuit_builder::CircuitBuilder; /// A Target representing an affine point on the curve `C`. We use incomplete arithmetic for efficiency, @@ -176,12 +178,12 @@ impl, const D: usize> CircuitBuilder { #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::field_types::Field; + use plonky2_field::secp256k1_base::Secp256K1Base; + use plonky2_field::secp256k1_scalar::Secp256K1Scalar; use crate::curve::curve_types::{AffinePoint, Curve, CurveScalar}; use crate::curve::secp256k1::Secp256K1; - use crate::field::field_types::Field; - use crate::field::secp256k1_base::Secp256K1Base; - use crate::field::secp256k1_scalar::Secp256K1Scalar; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; diff --git a/src/gadgets/hash.rs b/plonky2/src/gadgets/hash.rs similarity index 91% rename from src/gadgets/hash.rs rename to plonky2/src/gadgets/hash.rs index 5ec47323..90b77371 100644 --- a/src/gadgets/hash.rs +++ b/plonky2/src/gadgets/hash.rs @@ -1,5 +1,6 @@ -use crate::field::extension_field::Extendable; -use crate::field::field_types::RichField; +use plonky2_field::extension_field::Extendable; + +use crate::hash::hash_types::RichField; use crate::hash::hashing::SPONGE_WIDTH; use crate::iop::target::{BoolTarget, Target}; use crate::plonk::circuit_builder::CircuitBuilder; diff --git a/src/gadgets/interpolation.rs b/plonky2/src/gadgets/interpolation.rs similarity index 94% rename from src/gadgets/interpolation.rs rename to plonky2/src/gadgets/interpolation.rs index 1d092631..7907a337 100644 --- a/src/gadgets/interpolation.rs +++ b/plonky2/src/gadgets/interpolation.rs @@ -1,16 +1,17 @@ use std::ops::Range; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::RichField; +use plonky2_field::extension_field::Extendable; + use crate::gates::gate::Gate; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; /// Trait for gates which interpolate a polynomial, whose points are a (base field) coset of the multiplicative subgroup /// with the given size, and whose values are extension field elements, given by input wires. /// Outputs the evaluation of the interpolant at a given (extension field) evaluation point. -pub(crate) trait InterpolationGate, const D: usize>: +pub(crate) trait InterpolationGate, const D: usize>: Gate + Copy { fn new(subgroup_bits: usize) -> Self; @@ -107,10 +108,10 @@ impl, const D: usize> CircuitBuilder { #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::extension_field::FieldExtension; + use plonky2_field::field_types::Field; + use plonky2_field::interpolation::interpolant; - use crate::field::extension_field::FieldExtension; - use crate::field::field_types::Field; - use crate::field::interpolation::interpolant; use crate::gates::interpolation::HighDegreeInterpolationGate; use crate::gates::low_degree_interpolation::LowDegreeInterpolationGate; use crate::iop::witness::PartialWitness; diff --git a/src/gadgets/mod.rs b/plonky2/src/gadgets/mod.rs similarity index 85% rename from src/gadgets/mod.rs rename to plonky2/src/gadgets/mod.rs index 09acb9de..b73e2a7f 100644 --- a/src/gadgets/mod.rs +++ b/plonky2/src/gadgets/mod.rs @@ -4,15 +4,12 @@ pub mod arithmetic_u32; pub mod biguint; pub mod curve; pub mod hash; -pub mod insert; pub mod interpolation; pub mod multiple_comparison; pub mod nonnative; -pub mod permutation; pub mod polynomial; pub mod random_access; pub mod range_check; pub mod select; -pub mod sorting; pub mod split_base; pub(crate) mod split_join; diff --git a/src/gadgets/multiple_comparison.rs b/plonky2/src/gadgets/multiple_comparison.rs similarity index 96% rename from src/gadgets/multiple_comparison.rs rename to plonky2/src/gadgets/multiple_comparison.rs index cd66720c..88b94f3f 100644 --- a/src/gadgets/multiple_comparison.rs +++ b/plonky2/src/gadgets/multiple_comparison.rs @@ -1,10 +1,11 @@ +use plonky2_field::extension_field::Extendable; +use plonky2_util::ceil_div_usize; + use super::arithmetic_u32::U32Target; -use crate::field::extension_field::Extendable; -use crate::field::field_types::RichField; use crate::gates::comparison::ComparisonGate; +use crate::hash::hash_types::RichField; use crate::iop::target::{BoolTarget, Target}; use crate::plonk::circuit_builder::CircuitBuilder; -use crate::util::ceil_div_usize; impl, const D: usize> CircuitBuilder { /// Returns true if a is less than or equal to b, considered as base-`2^num_bits` limbs of a large value. @@ -69,9 +70,9 @@ impl, const D: usize> CircuitBuilder { mod tests { use anyhow::Result; use num::BigUint; + use plonky2_field::field_types::Field; use rand::Rng; - use crate::field::field_types::Field; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; diff --git a/src/gadgets/nonnative.rs b/plonky2/src/gadgets/nonnative.rs similarity index 97% rename from src/gadgets/nonnative.rs rename to plonky2/src/gadgets/nonnative.rs index d5a01961..16fd022e 100644 --- a/src/gadgets/nonnative.rs +++ b/plonky2/src/gadgets/nonnative.rs @@ -1,16 +1,16 @@ use std::marker::PhantomData; use num::{BigUint, Zero}; +use plonky2_field::{extension_field::Extendable, field_types::Field}; +use plonky2_util::ceil_div_usize; -use crate::field::field_types::RichField; -use crate::field::{extension_field::Extendable, field_types::Field}; use crate::gadgets::arithmetic_u32::U32Target; use crate::gadgets::biguint::BigUintTarget; +use crate::hash::hash_types::RichField; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; -use crate::util::ceil_div_usize; #[derive(Clone, Debug)] pub struct NonNativeTarget { @@ -212,9 +212,9 @@ impl, const D: usize, FF: Field> SimpleGenerator #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::field_types::Field; + use plonky2_field::secp256k1_base::Secp256K1Base; - use crate::field::field_types::Field; - use crate::field::secp256k1_base::Secp256K1Base; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; diff --git a/src/gadgets/polynomial.rs b/plonky2/src/gadgets/polynomial.rs similarity index 85% rename from src/gadgets/polynomial.rs rename to plonky2/src/gadgets/polynomial.rs index 1008b2ab..195eabd3 100644 --- a/src/gadgets/polynomial.rs +++ b/plonky2/src/gadgets/polynomial.rs @@ -1,5 +1,7 @@ -use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget}; -use crate::field::extension_field::Extendable; +use plonky2_field::extension_field::Extendable; + +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::{ExtensionAlgebraTarget, ExtensionTarget}; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::reducing::ReducingFactorTarget; @@ -11,7 +13,7 @@ impl PolynomialCoeffsExtTarget { self.0.len() } - pub fn eval_scalar>( + pub fn eval_scalar>( &self, builder: &mut CircuitBuilder, point: Target, @@ -21,7 +23,7 @@ impl PolynomialCoeffsExtTarget { point.reduce(&self.0, builder) } - pub fn eval>( + pub fn eval>( &self, builder: &mut CircuitBuilder, point: ExtensionTarget, @@ -40,7 +42,7 @@ impl PolynomialCoeffsExtAlgebraTarget { point: ExtensionTarget, ) -> ExtensionAlgebraTarget where - F: Extendable, + F: RichField + Extendable, { let mut acc = builder.zero_ext_algebra(); for &c in self.0.iter().rev() { @@ -55,7 +57,7 @@ impl PolynomialCoeffsExtAlgebraTarget { point: ExtensionAlgebraTarget, ) -> ExtensionAlgebraTarget where - F: Extendable, + F: RichField + Extendable, { let mut acc = builder.zero_ext_algebra(); for &c in self.0.iter().rev() { @@ -71,7 +73,7 @@ impl PolynomialCoeffsExtAlgebraTarget { powers: &[ExtensionAlgebraTarget], ) -> ExtensionAlgebraTarget where - F: Extendable, + F: RichField + Extendable, { debug_assert_eq!(self.0.len(), powers.len() + 1); let acc = self.0[0]; diff --git a/src/gadgets/random_access.rs b/plonky2/src/gadgets/random_access.rs similarity index 91% rename from src/gadgets/random_access.rs rename to plonky2/src/gadgets/random_access.rs index c9f150f8..a688292d 100644 --- a/src/gadgets/random_access.rs +++ b/plonky2/src/gadgets/random_access.rs @@ -1,11 +1,13 @@ -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; +use plonky2_field::extension_field::Extendable; +use plonky2_util::log2_strict; + use crate::gates::random_access::RandomAccessGate; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; -use crate::util::log2_strict; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Checks that a `Target` matches a vector at a non-deterministic index. /// Note: `access_index` is not range-checked. pub fn random_access(&mut self, access_index: Target, claimed_element: Target, v: Vec) { @@ -55,9 +57,9 @@ impl, const D: usize> CircuitBuilder { #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::field_types::Field; use super::*; - use crate::field::field_types::Field; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; diff --git a/src/gadgets/range_check.rs b/plonky2/src/gadgets/range_check.rs similarity index 92% rename from src/gadgets/range_check.rs rename to plonky2/src/gadgets/range_check.rs index 8b80bde3..f8ada106 100644 --- a/src/gadgets/range_check.rs +++ b/plonky2/src/gadgets/range_check.rs @@ -1,11 +1,12 @@ -use crate::field::extension_field::Extendable; -use crate::field::field_types::RichField; +use plonky2_field::extension_field::Extendable; + +use crate::hash::hash_types::RichField; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Checks that `x < 2^n_log` using a `BaseSumGate`. pub fn range_check(&mut self, x: Target, n_log: usize) { self.split_le(x, n_log); diff --git a/src/gadgets/select.rs b/plonky2/src/gadgets/select.rs similarity index 91% rename from src/gadgets/select.rs rename to plonky2/src/gadgets/select.rs index 80b5073e..9312c4cc 100644 --- a/src/gadgets/select.rs +++ b/plonky2/src/gadgets/select.rs @@ -1,9 +1,11 @@ -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; +use plonky2_field::extension_field::Extendable; + +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::{BoolTarget, Target}; use crate::plonk::circuit_builder::CircuitBuilder; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Selects `x` or `y` based on `b`, i.e., this returns `if b { x } else { y }`. pub fn select_ext( &mut self, @@ -39,8 +41,8 @@ impl, const D: usize> CircuitBuilder { #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::field_types::Field; - use crate::field::field_types::Field; use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; diff --git a/src/gadgets/split_base.rs b/plonky2/src/gadgets/split_base.rs similarity index 96% rename from src/gadgets/split_base.rs rename to plonky2/src/gadgets/split_base.rs index 1105710c..d4589476 100644 --- a/src/gadgets/split_base.rs +++ b/plonky2/src/gadgets/split_base.rs @@ -1,16 +1,17 @@ use std::borrow::Borrow; use itertools::Itertools; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::Field; -use crate::field::extension_field::Extendable; -use crate::field::field_types::Field; use crate::gates::base_sum::BaseSumGate; +use crate::hash::hash_types::RichField; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Split the given element into a list of targets, where each one represents a /// base-B limb of the element, with little-endian ordering. pub fn split_le_base(&mut self, x: Target, num_limbs: usize) -> Vec { @@ -104,9 +105,9 @@ impl SimpleGenerator for BaseSumGenerator { #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::field_types::Field; use rand::{thread_rng, Rng}; - use crate::field::field_types::Field; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; diff --git a/src/gadgets/split_join.rs b/plonky2/src/gadgets/split_join.rs similarity index 97% rename from src/gadgets/split_join.rs rename to plonky2/src/gadgets/split_join.rs index 72786bd8..8c7c9c3f 100644 --- a/src/gadgets/split_join.rs +++ b/plonky2/src/gadgets/split_join.rs @@ -1,11 +1,12 @@ -use crate::field::extension_field::Extendable; -use crate::field::field_types::RichField; +use plonky2_field::extension_field::Extendable; +use plonky2_util::ceil_div_usize; + use crate::gates::base_sum::BaseSumGate; +use crate::hash::hash_types::RichField; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; -use crate::util::ceil_div_usize; impl, const D: usize> CircuitBuilder { /// Split the given integer into a list of wires, where each one represents a diff --git a/src/gates/arithmetic_base.rs b/plonky2/src/gates/arithmetic_base.rs similarity index 96% rename from src/gates/arithmetic_base.rs rename to plonky2/src/gates/arithmetic_base.rs index a765ff61..8f67dab2 100644 --- a/src/gates/arithmetic_base.rs +++ b/plonky2/src/gates/arithmetic_base.rs @@ -1,10 +1,11 @@ -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::RichField; -use crate::field::packed_field::PackedField; +use plonky2_field::extension_field::Extendable; +use plonky2_field::packed_field::PackedField; + use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness}; @@ -213,8 +214,8 @@ impl, const D: usize> SimpleGenerator #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::goldilocks_field::GoldilocksField; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::arithmetic_base::ArithmeticGate; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::plonk::circuit_data::CircuitConfig; diff --git a/src/gates/arithmetic_extension.rs b/plonky2/src/gates/arithmetic_extension.rs similarity index 93% rename from src/gates/arithmetic_extension.rs rename to plonky2/src/gates/arithmetic_extension.rs index c52224a2..93f7277c 100644 --- a/src/gates/arithmetic_extension.rs +++ b/plonky2/src/gates/arithmetic_extension.rs @@ -1,10 +1,12 @@ use std::ops::Range; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::extension_field::FieldExtension; +use plonky2_field::extension_field::Extendable; +use plonky2_field::extension_field::FieldExtension; + use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness}; @@ -47,7 +49,7 @@ impl ArithmeticExtensionGate { } } -impl, const D: usize> Gate for ArithmeticExtensionGate { +impl, const D: usize> Gate for ArithmeticExtensionGate { fn id(&self) -> String { format!("{:?}", self) } @@ -157,14 +159,16 @@ impl, const D: usize> Gate for ArithmeticExtensionGate } #[derive(Clone, Debug)] -struct ArithmeticExtensionGenerator, const D: usize> { +struct ArithmeticExtensionGenerator, const D: usize> { gate_index: usize, const_0: F, const_1: F, i: usize, } -impl, const D: usize> SimpleGenerator for ArithmeticExtensionGenerator { +impl, const D: usize> SimpleGenerator + for ArithmeticExtensionGenerator +{ fn dependencies(&self) -> Vec { ArithmeticExtensionGate::::wires_ith_multiplicand_0(self.i) .chain(ArithmeticExtensionGate::::wires_ith_multiplicand_1( @@ -204,8 +208,8 @@ impl, const D: usize> SimpleGenerator for ArithmeticExtensio #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::goldilocks_field::GoldilocksField; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::arithmetic_extension::ArithmeticExtensionGate; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::plonk::circuit_data::CircuitConfig; diff --git a/src/gates/arithmetic_u32.rs b/plonky2/src/gates/arithmetic_u32.rs similarity index 94% rename from src/gates/arithmetic_u32.rs rename to plonky2/src/gates/arithmetic_u32.rs index b3c31b13..baf30ea8 100644 --- a/src/gates/arithmetic_u32.rs +++ b/plonky2/src/gates/arithmetic_u32.rs @@ -1,14 +1,15 @@ use std::marker::PhantomData; use itertools::unfold; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::Field; +use plonky2_field::packed_field::PackedField; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::Field; -use crate::field::packed_field::PackedField; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; @@ -22,12 +23,12 @@ use crate::plonk::vars::{ /// A gate to perform a basic mul-add on 32-bit values (we assume they are range-checked beforehand). #[derive(Copy, Clone, Debug)] -pub struct U32ArithmeticGate, const D: usize> { +pub struct U32ArithmeticGate, const D: usize> { pub num_ops: usize, _phantom: PhantomData, } -impl, const D: usize> U32ArithmeticGate { +impl, const D: usize> U32ArithmeticGate { pub fn new_from_config(config: &CircuitConfig) -> Self { Self { num_ops: Self::num_ops(config), @@ -77,7 +78,7 @@ impl, const D: usize> U32ArithmeticGate { } } -impl, const D: usize> Gate for U32ArithmeticGate { +impl, const D: usize> Gate for U32ArithmeticGate { fn id(&self) -> String { format!("{:?}", self) } @@ -231,7 +232,9 @@ impl, const D: usize> Gate for U32ArithmeticGate { } } -impl, const D: usize> PackedEvaluableBase for U32ArithmeticGate { +impl, const D: usize> PackedEvaluableBase + for U32ArithmeticGate +{ fn eval_unfiltered_base_packed>( &self, vars: EvaluationVarsBasePacked

, @@ -277,14 +280,16 @@ impl, const D: usize> PackedEvaluableBase for U32Arithmet } #[derive(Clone, Debug)] -struct U32ArithmeticGenerator, const D: usize> { +struct U32ArithmeticGenerator, const D: usize> { gate: U32ArithmeticGate, gate_index: usize, i: usize, _phantom: PhantomData, } -impl, const D: usize> SimpleGenerator for U32ArithmeticGenerator { +impl, const D: usize> SimpleGenerator + for U32ArithmeticGenerator +{ fn dependencies(&self) -> Vec { let local_target = |input| Target::wire(self.gate_index, input); @@ -344,10 +349,10 @@ mod tests { use std::marker::PhantomData; use anyhow::Result; + use plonky2_field::field_types::Field; + use plonky2_field::goldilocks_field::GoldilocksField; use rand::Rng; - use crate::field::field_types::Field; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::arithmetic_u32::U32ArithmeticGate; use crate::gates::gate::Gate; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; diff --git a/src/gates/assert_le.rs b/plonky2/src/gates/assert_le.rs similarity index 98% rename from src/gates/assert_le.rs rename to plonky2/src/gates/assert_le.rs index 3ab50b4e..2f7adb40 100644 --- a/src/gates/assert_le.rs +++ b/plonky2/src/gates/assert_le.rs @@ -1,12 +1,15 @@ use std::marker::PhantomData; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField, RichField}; -use crate::field::packed_field::PackedField; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::{Field, PrimeField}; +use plonky2_field::packed_field::PackedField; +use plonky2_util::{bits_u64, ceil_div_usize}; + use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; @@ -17,7 +20,6 @@ use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationVarsBasePacked, }; -use crate::util::{bits_u64, ceil_div_usize}; // TODO: replace/merge this gate with `ComparisonGate`. @@ -453,11 +455,11 @@ mod tests { use std::marker::PhantomData; use anyhow::Result; + use plonky2_field::extension_field::quartic::QuarticExtension; + use plonky2_field::field_types::{Field, PrimeField}; + use plonky2_field::goldilocks_field::GoldilocksField; use rand::Rng; - use crate::field::extension_field::quartic::QuarticExtension; - use crate::field::field_types::{Field, PrimeField}; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::assert_le::AssertLessThanGate; use crate::gates::gate::Gate; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; diff --git a/src/gates/base_sum.rs b/plonky2/src/gates/base_sum.rs similarity index 93% rename from src/gates/base_sum.rs rename to plonky2/src/gates/base_sum.rs index db5a5d80..a5391abf 100644 --- a/src/gates/base_sum.rs +++ b/plonky2/src/gates/base_sum.rs @@ -1,12 +1,14 @@ use std::ops::Range; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField, RichField}; -use crate::field::packed_field::PackedField; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::{Field, PrimeField}; +use plonky2_field::packed_field::PackedField; + use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness}; @@ -43,7 +45,7 @@ impl BaseSumGate { } } -impl, const D: usize, const B: usize> Gate for BaseSumGate { +impl, const D: usize, const B: usize> Gate for BaseSumGate { fn id(&self) -> String { format!("{:?} + Base: {}", self, B) } @@ -134,7 +136,7 @@ impl, const D: usize, const B: usize> Gate for BaseSumGat } } -impl, const D: usize, const B: usize> PackedEvaluableBase +impl, const D: usize, const B: usize> PackedEvaluableBase for BaseSumGate { fn eval_unfiltered_base_packed>( @@ -197,8 +199,8 @@ impl SimpleGenerator for BaseSplitGenerator #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::goldilocks_field::GoldilocksField; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::base_sum::BaseSumGate; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; diff --git a/src/gates/comparison.rs b/plonky2/src/gates/comparison.rs similarity index 96% rename from src/gates/comparison.rs rename to plonky2/src/gates/comparison.rs index d04b4ba4..d8238295 100644 --- a/src/gates/comparison.rs +++ b/plonky2/src/gates/comparison.rs @@ -1,12 +1,15 @@ use std::marker::PhantomData; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField}; -use crate::field::packed_field::PackedField; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::{Field, PrimeField}; +use plonky2_field::packed_field::PackedField; +use plonky2_util::{bits_u64, ceil_div_usize}; + use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; @@ -17,7 +20,6 @@ use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationVarsBasePacked, }; -use crate::util::{bits_u64, ceil_div_usize}; /// A gate for checking that one value is less than or equal to another. #[derive(Clone, Debug)] @@ -27,7 +29,7 @@ pub struct ComparisonGate, const D: usize> { _phantom: PhantomData, } -impl, const D: usize> ComparisonGate { +impl, const D: usize> ComparisonGate { pub fn new(num_bits: usize, num_chunks: usize) -> Self { debug_assert!(num_bits < bits_u64(F::ORDER)); Self { @@ -88,7 +90,7 @@ impl, const D: usize> ComparisonGate { } } -impl, const D: usize> Gate for ComparisonGate { +impl, const D: usize> Gate for ComparisonGate { fn id(&self) -> String { format!("{:?}", self, D) } @@ -312,7 +314,9 @@ impl, const D: usize> Gate for ComparisonGate { } } -impl, const D: usize> PackedEvaluableBase for ComparisonGate { +impl, const D: usize> PackedEvaluableBase + for ComparisonGate +{ fn eval_unfiltered_base_packed>( &self, vars: EvaluationVarsBasePacked

, @@ -394,12 +398,14 @@ impl, const D: usize> PackedEvaluableBase for ComparisonG } #[derive(Debug)] -struct ComparisonGenerator, const D: usize> { +struct ComparisonGenerator, const D: usize> { gate_index: usize, gate: ComparisonGate, } -impl, const D: usize> SimpleGenerator for ComparisonGenerator { +impl, const D: usize> SimpleGenerator + for ComparisonGenerator +{ fn dependencies(&self) -> Vec { let local_target = |input| Target::wire(self.gate_index, input); @@ -515,10 +521,10 @@ mod tests { use std::marker::PhantomData; use anyhow::Result; + use plonky2_field::field_types::{Field, PrimeField}; + use plonky2_field::goldilocks_field::GoldilocksField; use rand::Rng; - use crate::field::field_types::{Field, PrimeField}; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::comparison::ComparisonGate; use crate::gates::gate::Gate; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; diff --git a/src/gates/constant.rs b/plonky2/src/gates/constant.rs similarity index 90% rename from src/gates/constant.rs rename to plonky2/src/gates/constant.rs index e3dfc47f..14b21867 100644 --- a/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -1,12 +1,14 @@ use std::ops::Range; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::Field; -use crate::field::packed_field::PackedField; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::Field; +use plonky2_field::packed_field::PackedField; + use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; @@ -33,7 +35,7 @@ impl ConstantGate { } } -impl, const D: usize> Gate for ConstantGate { +impl, const D: usize> Gate for ConstantGate { fn id(&self) -> String { format!("{:?}", self) } @@ -100,7 +102,7 @@ impl, const D: usize> Gate for ConstantGate { } } -impl, const D: usize> PackedEvaluableBase for ConstantGate { +impl, const D: usize> PackedEvaluableBase for ConstantGate { fn eval_unfiltered_base_packed>( &self, vars: EvaluationVarsBasePacked

, @@ -140,8 +142,8 @@ impl SimpleGenerator for ConstantGenerator { #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::goldilocks_field::GoldilocksField; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::constant::ConstantGate; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::plonk::circuit_data::CircuitConfig; diff --git a/src/gates/exponentiation.rs b/plonky2/src/gates/exponentiation.rs similarity index 93% rename from src/gates/exponentiation.rs rename to plonky2/src/gates/exponentiation.rs index 5eb377b6..b70b3577 100644 --- a/src/gates/exponentiation.rs +++ b/plonky2/src/gates/exponentiation.rs @@ -1,12 +1,14 @@ use std::marker::PhantomData; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::Field; -use crate::field::packed_field::PackedField; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::Field; +use plonky2_field::packed_field::PackedField; + use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; @@ -20,12 +22,12 @@ use crate::plonk::vars::{ /// A gate for raising a value to a power. #[derive(Clone, Debug)] -pub(crate) struct ExponentiationGate, const D: usize> { +pub(crate) struct ExponentiationGate, const D: usize> { pub num_power_bits: usize, pub _phantom: PhantomData, } -impl, const D: usize> ExponentiationGate { +impl, const D: usize> ExponentiationGate { pub fn new(num_power_bits: usize) -> Self { Self { num_power_bits, @@ -65,7 +67,7 @@ impl, const D: usize> ExponentiationGate { } } -impl, const D: usize> Gate for ExponentiationGate { +impl, const D: usize> Gate for ExponentiationGate { fn id(&self) -> String { format!("{:?}", self, D) } @@ -187,7 +189,9 @@ impl, const D: usize> Gate for ExponentiationGate { } } -impl, const D: usize> PackedEvaluableBase for ExponentiationGate { +impl, const D: usize> PackedEvaluableBase + for ExponentiationGate +{ fn eval_unfiltered_base_packed>( &self, vars: EvaluationVarsBasePacked

, @@ -225,12 +229,14 @@ impl, const D: usize> PackedEvaluableBase for Exponentiat } #[derive(Debug)] -struct ExponentiationGenerator, const D: usize> { +struct ExponentiationGenerator, const D: usize> { gate_index: usize, gate: ExponentiationGate, } -impl, const D: usize> SimpleGenerator for ExponentiationGenerator { +impl, const D: usize> SimpleGenerator + for ExponentiationGenerator +{ fn dependencies(&self) -> Vec { let local_target = |input| Target::wire(self.gate_index, input); @@ -282,10 +288,11 @@ mod tests { use std::marker::PhantomData; use anyhow::Result; + use plonky2_field::field_types::Field; + use plonky2_field::goldilocks_field::GoldilocksField; + use plonky2_util::log2_ceil; use rand::Rng; - use crate::field::field_types::Field; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::exponentiation::ExponentiationGate; use crate::gates::gate::Gate; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; @@ -293,7 +300,6 @@ mod tests { use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; use crate::plonk::vars::EvaluationVars; - use crate::util::log2_ceil; const MAX_POWER_BITS: usize = 17; diff --git a/src/gates/gate.rs b/plonky2/src/gates/gate.rs similarity index 93% rename from src/gates/gate.rs rename to plonky2/src/gates/gate.rs index f31a60c2..9ae2a271 100644 --- a/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -2,12 +2,14 @@ use std::fmt::{Debug, Error, Formatter}; use std::hash::{Hash, Hasher}; use std::sync::Arc; -use crate::field::batch_util::batch_multiply_inplace; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::{Field, RichField}; +use plonky2_field::batch_util::batch_multiply_inplace; +use plonky2_field::extension_field::{Extendable, FieldExtension}; +use plonky2_field::field_types::Field; + use crate::gates::gate_tree::Tree; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::WitnessGenerator; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{ @@ -15,7 +17,7 @@ use crate::plonk::vars::{ }; /// A custom gate. -pub trait Gate, const D: usize>: 'static + Send + Sync { +pub trait Gate, const D: usize>: 'static + Send + Sync { fn id(&self) -> String; fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec; @@ -141,9 +143,9 @@ pub trait Gate, const D: usize>: 'static + Send + Sync { /// A wrapper around an `Rc` which implements `PartialEq`, `Eq` and `Hash` based on gate IDs. #[derive(Clone)] -pub struct GateRef, const D: usize>(pub(crate) Arc>); +pub struct GateRef, const D: usize>(pub(crate) Arc>); -impl, const D: usize> GateRef { +impl, const D: usize> GateRef { pub fn new>(gate: G) -> GateRef { GateRef(Arc::new(gate)) } diff --git a/src/gates/gate_testing.rs b/plonky2/src/gates/gate_testing.rs similarity index 92% rename from src/gates/gate_testing.rs rename to plonky2/src/gates/gate_testing.rs index e9e823e1..ea1ef9a4 100644 --- a/src/gates/gate_testing.rs +++ b/plonky2/src/gates/gate_testing.rs @@ -1,26 +1,26 @@ use anyhow::{ensure, Result}; +use plonky2_field::extension_field::{Extendable, FieldExtension}; +use plonky2_field::field_types::Field; +use plonky2_field::polynomial::{PolynomialCoeffs, PolynomialValues}; +use plonky2_util::log2_ceil; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::{Field, RichField}; use crate::gates::gate::Gate; use crate::hash::hash_types::HashOut; +use crate::hash::hash_types::RichField; use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::config::GenericConfig; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBaseBatch}; use crate::plonk::verifier::verify; -use crate::polynomial::{PolynomialCoeffs, PolynomialValues}; -use crate::util::{log2_ceil, transpose}; +use crate::util::transpose; const WITNESS_SIZE: usize = 1 << 5; const WITNESS_DEGREE: usize = WITNESS_SIZE - 1; /// Tests that the constraints imposed by the given gate are low-degree by applying them to random /// low-degree witness polynomials. -pub(crate) fn test_low_degree, G: Gate, const D: usize>( - gate: G, -) { +pub fn test_low_degree, G: Gate, const D: usize>(gate: G) { let rate_bits = log2_ceil(gate.degree() + 1); let wire_ldes = random_low_degree_matrix::(gate.num_wires(), rate_bits); @@ -85,8 +85,8 @@ fn random_low_degree_values(rate_bits: usize) -> Vec { .values } -pub(crate) fn test_eval_fns< - F: Extendable, +pub fn test_eval_fns< + F: RichField + Extendable, C: GenericConfig, G: Gate, const D: usize, diff --git a/src/gates/gate_tree.rs b/plonky2/src/gates/gate_tree.rs similarity index 99% rename from src/gates/gate_tree.rs rename to plonky2/src/gates/gate_tree.rs index eb1b5ad7..029616a8 100644 --- a/src/gates/gate_tree.rs +++ b/plonky2/src/gates/gate_tree.rs @@ -1,8 +1,8 @@ use log::debug; +use plonky2_field::extension_field::Extendable; -use crate::field::extension_field::Extendable; -use crate::field::field_types::RichField; use crate::gates::gate::GateRef; +use crate::hash::hash_types::RichField; /// A binary tree where leaves hold some type `T` and other nodes are empty. #[derive(Debug, Clone)] diff --git a/src/gates/gmimc.rs b/plonky2/src/gates/gmimc.rs similarity index 92% rename from src/gates/gmimc.rs rename to plonky2/src/gates/gmimc.rs index 1819ccef..7f59271a 100644 --- a/src/gates/gmimc.rs +++ b/plonky2/src/gates/gmimc.rs @@ -1,14 +1,16 @@ use std::marker::PhantomData; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::Field; -use crate::field::packed_field::PackedField; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::Field; +use plonky2_field::packed_field::PackedField; + use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; use crate::hash::gmimc; use crate::hash::gmimc::GMiMC; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; @@ -25,11 +27,17 @@ use crate::plonk::vars::{ /// It has a flag which can be used to swap the first four inputs with the next four, for ordering /// sibling digests. #[derive(Debug)] -pub struct GMiMCGate + GMiMC, const D: usize, const WIDTH: usize> { +pub struct GMiMCGate< + F: RichField + Extendable + GMiMC, + const D: usize, + const WIDTH: usize, +> { _phantom: PhantomData, } -impl + GMiMC, const D: usize, const WIDTH: usize> GMiMCGate { +impl + GMiMC, const D: usize, const WIDTH: usize> + GMiMCGate +{ pub fn new() -> Self { GMiMCGate { _phantom: PhantomData, @@ -61,7 +69,7 @@ impl + GMiMC, const D: usize, const WIDTH: usize> GMiMCG } } -impl + GMiMC, const D: usize, const WIDTH: usize> Gate +impl + GMiMC, const D: usize, const WIDTH: usize> Gate for GMiMCGate { fn id(&self) -> String { @@ -208,8 +216,8 @@ impl + GMiMC, const D: usize, const WIDTH: usize> Gate + GMiMC, const D: usize, const WIDTH: usize> PackedEvaluableBase - for GMiMCGate +impl + GMiMC, const D: usize, const WIDTH: usize> + PackedEvaluableBase for GMiMCGate { fn eval_unfiltered_base_packed>( &self, @@ -258,13 +266,17 @@ impl + GMiMC, const D: usize, const WIDTH: usize> Packed } #[derive(Debug)] -struct GMiMCGenerator + GMiMC, const D: usize, const WIDTH: usize> { +struct GMiMCGenerator< + F: RichField + Extendable + GMiMC, + const D: usize, + const WIDTH: usize, +> { gate_index: usize, _phantom: PhantomData, } -impl + GMiMC, const D: usize, const WIDTH: usize> SimpleGenerator - for GMiMCGenerator +impl + GMiMC, const D: usize, const WIDTH: usize> + SimpleGenerator for GMiMCGenerator { fn dependencies(&self) -> Vec { let mut dep_input_indices = Vec::with_capacity(WIDTH + 1); @@ -341,9 +353,9 @@ impl + GMiMC, const D: usize, const WIDTH: usize> Simple #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::field_types::Field; + use plonky2_field::goldilocks_field::GoldilocksField; - use crate::field::field_types::Field; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::gmimc::GMiMCGate; use crate::hash::gmimc::GMiMC; diff --git a/src/gates/interpolation.rs b/plonky2/src/gates/interpolation.rs similarity index 92% rename from src/gates/interpolation.rs rename to plonky2/src/gates/interpolation.rs index 61adce4a..9d3d6e3f 100644 --- a/src/gates/interpolation.rs +++ b/plonky2/src/gates/interpolation.rs @@ -1,31 +1,33 @@ use std::marker::PhantomData; use std::ops::Range; -use crate::field::extension_field::algebra::PolynomialCoeffsAlgebra; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::interpolation::interpolant; +use plonky2_field::extension_field::algebra::PolynomialCoeffsAlgebra; +use plonky2_field::extension_field::{Extendable, FieldExtension}; +use plonky2_field::interpolation::interpolant; +use plonky2_field::polynomial::PolynomialCoeffs; + use crate::gadgets::interpolation::InterpolationGate; use crate::gadgets::polynomial::PolynomialCoeffsExtAlgebraTarget; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; -use crate::polynomial::PolynomialCoeffs; /// Interpolation gate with constraints of degree at most `1<, const D: usize> { +pub(crate) struct HighDegreeInterpolationGate, const D: usize> { pub subgroup_bits: usize, _phantom: PhantomData, } -impl, const D: usize> InterpolationGate +impl, const D: usize> InterpolationGate for HighDegreeInterpolationGate { fn new(subgroup_bits: usize) -> Self { @@ -40,7 +42,7 @@ impl, const D: usize> InterpolationGate } } -impl, const D: usize> HighDegreeInterpolationGate { +impl, const D: usize> HighDegreeInterpolationGate { /// End of wire indices, exclusive. fn end(&self) -> usize { self.start_coeffs() + self.num_points() * D @@ -79,7 +81,9 @@ impl, const D: usize> HighDegreeInterpolationGate { } } -impl, const D: usize> Gate for HighDegreeInterpolationGate { +impl, const D: usize> Gate + for HighDegreeInterpolationGate +{ fn id(&self) -> String { format!("{:?}", self, D) } @@ -200,13 +204,15 @@ impl, const D: usize> Gate for HighDegreeInterpolationGat } #[derive(Debug)] -struct InterpolationGenerator, const D: usize> { +struct InterpolationGenerator, const D: usize> { gate_index: usize, gate: HighDegreeInterpolationGate, _phantom: PhantomData, } -impl, const D: usize> SimpleGenerator for InterpolationGenerator { +impl, const D: usize> SimpleGenerator + for InterpolationGenerator +{ fn dependencies(&self) -> Vec { let local_target = |input| { Target::Wire(Wire { @@ -269,9 +275,10 @@ mod tests { use std::marker::PhantomData; use anyhow::Result; + use plonky2_field::field_types::Field; + use plonky2_field::goldilocks_field::GoldilocksField; + use plonky2_field::polynomial::PolynomialCoeffs; - use crate::field::field_types::Field; - use crate::field::goldilocks_field::GoldilocksField; use crate::gadgets::interpolation::InterpolationGate; use crate::gates::gate::Gate; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; @@ -279,7 +286,6 @@ mod tests { use crate::hash::hash_types::HashOut; use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; use crate::plonk::vars::EvaluationVars; - use crate::polynomial::PolynomialCoeffs; #[test] fn wire_indices() { diff --git a/src/gates/low_degree_interpolation.rs b/plonky2/src/gates/low_degree_interpolation.rs similarity index 96% rename from src/gates/low_degree_interpolation.rs rename to plonky2/src/gates/low_degree_interpolation.rs index 1462af3b..b7307470 100644 --- a/src/gates/low_degree_interpolation.rs +++ b/plonky2/src/gates/low_degree_interpolation.rs @@ -1,22 +1,24 @@ use std::marker::PhantomData; use std::ops::Range; -use crate::field::extension_field::algebra::PolynomialCoeffsAlgebra; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::{Field, RichField}; -use crate::field::interpolation::interpolant; +use plonky2_field::extension_field::algebra::PolynomialCoeffsAlgebra; +use plonky2_field::extension_field::{Extendable, FieldExtension}; +use plonky2_field::field_types::Field; +use plonky2_field::interpolation::interpolant; +use plonky2_field::polynomial::PolynomialCoeffs; + use crate::gadgets::interpolation::InterpolationGate; use crate::gadgets::polynomial::PolynomialCoeffsExtAlgebraTarget; use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; -use crate::polynomial::PolynomialCoeffs; /// Interpolation gate with constraints of degree 2. /// `eval_unfiltered_recursively` uses more gates than `HighDegreeInterpolationGate`. @@ -384,10 +386,11 @@ impl, const D: usize> SimpleGenerator #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::extension_field::quadratic::QuadraticExtension; + use plonky2_field::field_types::Field; + use plonky2_field::goldilocks_field::GoldilocksField; + use plonky2_field::polynomial::PolynomialCoeffs; - use crate::field::extension_field::quadratic::QuadraticExtension; - use crate::field::field_types::Field; - use crate::field::goldilocks_field::GoldilocksField; use crate::gadgets::interpolation::InterpolationGate; use crate::gates::gate::Gate; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; @@ -395,7 +398,6 @@ mod tests { use crate::hash::hash_types::HashOut; use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; use crate::plonk::vars::EvaluationVars; - use crate::polynomial::PolynomialCoeffs; #[test] fn low_degree() { diff --git a/src/gates/mod.rs b/plonky2/src/gates/mod.rs similarity index 78% rename from src/gates/mod.rs rename to plonky2/src/gates/mod.rs index b26f88f8..aae46dc5 100644 --- a/src/gates/mod.rs +++ b/plonky2/src/gates/mod.rs @@ -12,7 +12,6 @@ pub mod exponentiation; pub mod gate; pub mod gate_tree; pub mod gmimc; -pub mod insertion; pub mod interpolation; pub mod low_degree_interpolation; pub mod multiplication_extension; @@ -26,7 +25,8 @@ pub mod reducing; pub mod reducing_extension; pub mod subtraction_u32; pub mod switch; -mod util; +pub mod util; -#[cfg(test)] -mod gate_testing; +// Can't use #[cfg(test)] here because it needs to be visible to other crates. +// See https://github.com/rust-lang/cargo/issues/8379 +pub mod gate_testing; diff --git a/src/gates/multiplication_extension.rs b/plonky2/src/gates/multiplication_extension.rs similarity index 96% rename from src/gates/multiplication_extension.rs rename to plonky2/src/gates/multiplication_extension.rs index a2041689..9ccfe637 100644 --- a/src/gates/multiplication_extension.rs +++ b/plonky2/src/gates/multiplication_extension.rs @@ -1,11 +1,12 @@ use std::ops::Range; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::extension_field::FieldExtension; -use crate::field::field_types::RichField; +use plonky2_field::extension_field::Extendable; +use plonky2_field::extension_field::FieldExtension; + use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness}; @@ -186,8 +187,8 @@ impl, const D: usize> SimpleGenerator #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::goldilocks_field::GoldilocksField; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::multiplication_extension::MulExtensionGate; use crate::plonk::circuit_data::CircuitConfig; diff --git a/src/gates/noop.rs b/plonky2/src/gates/noop.rs similarity index 86% rename from src/gates/noop.rs rename to plonky2/src/gates/noop.rs index 4230e678..4cd872d8 100644 --- a/src/gates/noop.rs +++ b/plonky2/src/gates/noop.rs @@ -1,6 +1,8 @@ -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; +use plonky2_field::extension_field::Extendable; + use crate::gates::gate::Gate; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::WitnessGenerator; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBaseBatch}; @@ -8,7 +10,7 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBaseBa /// A gate which does nothing. pub struct NoopGate; -impl, const D: usize> Gate for NoopGate { +impl, const D: usize> Gate for NoopGate { fn id(&self) -> String { "NoopGate".into() } @@ -56,7 +58,8 @@ impl, const D: usize> Gate for NoopGate { #[cfg(test)] mod tests { - use crate::field::goldilocks_field::GoldilocksField; + use plonky2_field::goldilocks_field::GoldilocksField; + use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::noop::NoopGate; use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; diff --git a/src/gates/packed_util.rs b/plonky2/src/gates/packed_util.rs similarity index 85% rename from src/gates/packed_util.rs rename to plonky2/src/gates/packed_util.rs index b8874b40..7b420343 100644 --- a/src/gates/packed_util.rs +++ b/plonky2/src/gates/packed_util.rs @@ -1,11 +1,13 @@ -use crate::field::extension_field::Extendable; -use crate::field::packable::Packable; -use crate::field::packed_field::PackedField; +use plonky2_field::extension_field::Extendable; +use plonky2_field::packable::Packable; +use plonky2_field::packed_field::PackedField; + use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; use crate::plonk::vars::{EvaluationVarsBaseBatch, EvaluationVarsBasePacked}; -pub trait PackedEvaluableBase, const D: usize>: Gate { +pub trait PackedEvaluableBase, const D: usize>: Gate { fn eval_unfiltered_base_packed>( &self, vars_base: EvaluationVarsBasePacked

, diff --git a/src/gates/poseidon.rs b/plonky2/src/gates/poseidon.rs similarity index 97% rename from src/gates/poseidon.rs rename to plonky2/src/gates/poseidon.rs index 141983e9..366e200e 100644 --- a/src/gates/poseidon.rs +++ b/plonky2/src/gates/poseidon.rs @@ -1,14 +1,16 @@ use std::marker::PhantomData; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, RichField}; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::Field; + use crate::gates::gate::Gate; use crate::gates::poseidon_mds::PoseidonMdsGate; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; use crate::hash::hashing::SPONGE_WIDTH; use crate::hash::poseidon; use crate::hash::poseidon::Poseidon; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; @@ -22,11 +24,11 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; /// It has a flag which can be used to swap the first four inputs with the next four, for ordering /// sibling digests. #[derive(Debug)] -pub struct PoseidonGate, const D: usize> { +pub struct PoseidonGate, const D: usize> { _phantom: PhantomData, } -impl, const D: usize> PoseidonGate { +impl, const D: usize> PoseidonGate { pub fn new() -> Self { PoseidonGate { _phantom: PhantomData, @@ -94,7 +96,7 @@ impl, const D: usize> PoseidonGate { } } -impl, const D: usize> Gate for PoseidonGate { +impl, const D: usize> Gate for PoseidonGate { fn id(&self) -> String { format!("{:?}", self, SPONGE_WIDTH) } @@ -508,9 +510,9 @@ impl + Poseidon, const D: usize> SimpleGenerator #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::field_types::Field; + use plonky2_field::goldilocks_field::GoldilocksField; - use crate::field::field_types::Field; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::poseidon::PoseidonGate; use crate::hash::hashing::SPONGE_WIDTH; diff --git a/src/gates/poseidon_mds.rs b/plonky2/src/gates/poseidon_mds.rs similarity index 96% rename from src/gates/poseidon_mds.rs rename to plonky2/src/gates/poseidon_mds.rs index da54ab2c..81583f88 100644 --- a/src/gates/poseidon_mds.rs +++ b/plonky2/src/gates/poseidon_mds.rs @@ -1,15 +1,17 @@ use std::marker::PhantomData; use std::ops::Range; -use crate::field::extension_field::algebra::ExtensionAlgebra; -use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget}; -use crate::field::extension_field::Extendable; -use crate::field::extension_field::FieldExtension; -use crate::field::field_types::{Field, RichField}; +use plonky2_field::extension_field::algebra::ExtensionAlgebra; +use plonky2_field::extension_field::Extendable; +use plonky2_field::extension_field::FieldExtension; +use plonky2_field::field_types::Field; + use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; use crate::hash::hashing::SPONGE_WIDTH; use crate::hash::poseidon::Poseidon; +use crate::iop::ext_target::{ExtensionAlgebraTarget, ExtensionTarget}; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness}; diff --git a/src/gates/public_input.rs b/plonky2/src/gates/public_input.rs similarity index 88% rename from src/gates/public_input.rs rename to plonky2/src/gates/public_input.rs index 1e32cab6..20fc59c8 100644 --- a/src/gates/public_input.rs +++ b/plonky2/src/gates/public_input.rs @@ -1,11 +1,13 @@ use std::ops::Range; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::packed_field::PackedField; +use plonky2_field::extension_field::Extendable; +use plonky2_field::packed_field::PackedField; + use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::WitnessGenerator; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{ @@ -22,7 +24,7 @@ impl PublicInputGate { } } -impl, const D: usize> Gate for PublicInputGate { +impl, const D: usize> Gate for PublicInputGate { fn id(&self) -> String { "PublicInputGate".into() } @@ -85,7 +87,7 @@ impl, const D: usize> Gate for PublicInputGate { } } -impl, const D: usize> PackedEvaluableBase for PublicInputGate { +impl, const D: usize> PackedEvaluableBase for PublicInputGate { fn eval_unfiltered_base_packed>( &self, vars: EvaluationVarsBasePacked

, @@ -101,7 +103,8 @@ impl, const D: usize> PackedEvaluableBase for PublicInput #[cfg(test)] mod tests { - use crate::field::goldilocks_field::GoldilocksField; + use plonky2_field::goldilocks_field::GoldilocksField; + use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::public_input::PublicInputGate; use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; diff --git a/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs similarity index 94% rename from src/gates/random_access.rs rename to plonky2/src/gates/random_access.rs index b1197883..c266bd3c 100644 --- a/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -1,14 +1,15 @@ use std::marker::PhantomData; use itertools::Itertools; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::Field; +use plonky2_field::packed_field::PackedField; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::Field; -use crate::field::packed_field::PackedField; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; @@ -22,13 +23,13 @@ use crate::plonk::vars::{ /// A gate for checking that a particular element of a list matches a given value. #[derive(Copy, Clone, Debug)] -pub(crate) struct RandomAccessGate, const D: usize> { +pub(crate) struct RandomAccessGate, const D: usize> { pub bits: usize, pub num_copies: usize, _phantom: PhantomData, } -impl, const D: usize> RandomAccessGate { +impl, const D: usize> RandomAccessGate { fn new(num_copies: usize, bits: usize) -> Self { Self { bits, @@ -84,7 +85,7 @@ impl, const D: usize> RandomAccessGate { } } -impl, const D: usize> Gate for RandomAccessGate { +impl, const D: usize> Gate for RandomAccessGate { fn id(&self) -> String { format!("{:?}", self, D) } @@ -229,7 +230,9 @@ impl, const D: usize> Gate for RandomAccessGate { } } -impl, const D: usize> PackedEvaluableBase for RandomAccessGate { +impl, const D: usize> PackedEvaluableBase + for RandomAccessGate +{ fn eval_unfiltered_base_packed>( &self, vars: EvaluationVarsBasePacked

, @@ -271,13 +274,15 @@ impl, const D: usize> PackedEvaluableBase for RandomAcces } #[derive(Debug)] -struct RandomAccessGenerator, const D: usize> { +struct RandomAccessGenerator, const D: usize> { gate_index: usize, gate: RandomAccessGate, copy: usize, } -impl, const D: usize> SimpleGenerator for RandomAccessGenerator { +impl, const D: usize> SimpleGenerator + for RandomAccessGenerator +{ fn dependencies(&self) -> Vec { let local_target = |input| Target::wire(self.gate_index, input); @@ -326,10 +331,10 @@ mod tests { use std::marker::PhantomData; use anyhow::Result; + use plonky2_field::field_types::Field; + use plonky2_field::goldilocks_field::GoldilocksField; use rand::{thread_rng, Rng}; - use crate::field::field_types::Field; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::gate::Gate; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::random_access::RandomAccessGate; diff --git a/src/gates/reducing.rs b/plonky2/src/gates/reducing.rs similarity index 95% rename from src/gates/reducing.rs rename to plonky2/src/gates/reducing.rs index 5d918781..2abf8425 100644 --- a/src/gates/reducing.rs +++ b/plonky2/src/gates/reducing.rs @@ -1,11 +1,12 @@ use std::ops::Range; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::extension_field::FieldExtension; -use crate::field::field_types::RichField; +use plonky2_field::extension_field::Extendable; +use plonky2_field::extension_field::FieldExtension; + use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness}; @@ -171,7 +172,7 @@ struct ReducingGenerator { gate: ReducingGate, } -impl, const D: usize> SimpleGenerator for ReducingGenerator { +impl, const D: usize> SimpleGenerator for ReducingGenerator { fn dependencies(&self) -> Vec { ReducingGate::::wires_alpha() .chain(ReducingGate::::wires_old_acc()) @@ -214,8 +215,8 @@ impl, const D: usize> SimpleGenerator for ReducingGenerator< #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::goldilocks_field::GoldilocksField; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::reducing::ReducingGate; use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; diff --git a/src/gates/reducing_extension.rs b/plonky2/src/gates/reducing_extension.rs similarity index 95% rename from src/gates/reducing_extension.rs rename to plonky2/src/gates/reducing_extension.rs index 8d06dfbd..6655f1d7 100644 --- a/src/gates/reducing_extension.rs +++ b/plonky2/src/gates/reducing_extension.rs @@ -1,11 +1,12 @@ use std::ops::Range; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::extension_field::FieldExtension; -use crate::field::field_types::RichField; +use plonky2_field::extension_field::Extendable; +use plonky2_field::extension_field::FieldExtension; + use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness}; @@ -171,7 +172,7 @@ struct ReducingGenerator { gate: ReducingExtensionGate, } -impl, const D: usize> SimpleGenerator for ReducingGenerator { +impl, const D: usize> SimpleGenerator for ReducingGenerator { fn dependencies(&self) -> Vec { ReducingExtensionGate::::wires_alpha() .chain(ReducingExtensionGate::::wires_old_acc()) @@ -207,8 +208,8 @@ impl, const D: usize> SimpleGenerator for ReducingGenerator< #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::goldilocks_field::GoldilocksField; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::reducing_extension::ReducingExtensionGate; use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; diff --git a/src/gates/subtraction_u32.rs b/plonky2/src/gates/subtraction_u32.rs similarity index 97% rename from src/gates/subtraction_u32.rs rename to plonky2/src/gates/subtraction_u32.rs index aaa5dd09..3ae9105b 100644 --- a/src/gates/subtraction_u32.rs +++ b/plonky2/src/gates/subtraction_u32.rs @@ -1,12 +1,14 @@ use std::marker::PhantomData; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, RichField}; -use crate::field::packed_field::PackedField; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::Field; +use plonky2_field::packed_field::PackedField; + use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; @@ -335,11 +337,11 @@ mod tests { use std::marker::PhantomData; use anyhow::Result; + use plonky2_field::extension_field::quartic::QuarticExtension; + use plonky2_field::field_types::{Field, PrimeField}; + use plonky2_field::goldilocks_field::GoldilocksField; use rand::Rng; - use crate::field::extension_field::quartic::QuarticExtension; - use crate::field::field_types::{Field, PrimeField}; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::gate::Gate; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::subtraction_u32::U32SubtractionGate; diff --git a/src/gates/switch.rs b/plonky2/src/gates/switch.rs similarity index 94% rename from src/gates/switch.rs rename to plonky2/src/gates/switch.rs index fc4da35c..9315ab4f 100644 --- a/src/gates/switch.rs +++ b/plonky2/src/gates/switch.rs @@ -1,14 +1,15 @@ use std::marker::PhantomData; use array_tool::vec::Union; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::Field; +use plonky2_field::packed_field::PackedField; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::Field; -use crate::field::packed_field::PackedField; use crate::gates::gate::Gate; use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{GeneratedValues, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; @@ -22,13 +23,13 @@ use crate::plonk::vars::{ /// A gate for conditionally swapping input values based on a boolean. #[derive(Clone, Debug)] -pub(crate) struct SwitchGate, const D: usize> { +pub struct SwitchGate, const D: usize> { pub(crate) chunk_size: usize, pub(crate) num_copies: usize, _phantom: PhantomData, } -impl, const D: usize> SwitchGate { +impl, const D: usize> SwitchGate { pub fn new(num_copies: usize, chunk_size: usize) -> Self { Self { chunk_size, @@ -72,7 +73,7 @@ impl, const D: usize> SwitchGate { } } -impl, const D: usize> Gate for SwitchGate { +impl, const D: usize> Gate for SwitchGate { fn id(&self) -> String { format!("{:?}", self, D) } @@ -188,7 +189,7 @@ impl, const D: usize> Gate for SwitchGate { } } -impl, const D: usize> PackedEvaluableBase for SwitchGate { +impl, const D: usize> PackedEvaluableBase for SwitchGate { fn eval_unfiltered_base_packed>( &self, vars: EvaluationVarsBasePacked

, @@ -214,13 +215,13 @@ impl, const D: usize> PackedEvaluableBase for SwitchGate< } #[derive(Debug)] -struct SwitchGenerator, const D: usize> { +struct SwitchGenerator, const D: usize> { gate_index: usize, gate: SwitchGate, copy: usize, } -impl, const D: usize> SwitchGenerator { +impl, const D: usize> SwitchGenerator { fn in_out_dependencies(&self) -> Vec { let local_target = |input| Target::wire(self.gate_index, input); @@ -307,7 +308,7 @@ impl, const D: usize> SwitchGenerator { } } -impl, const D: usize> WitnessGenerator for SwitchGenerator { +impl, const D: usize> WitnessGenerator for SwitchGenerator { fn watch_list(&self) -> Vec { self.in_out_dependencies() .union(self.in_switch_dependencies()) @@ -331,9 +332,9 @@ mod tests { use std::marker::PhantomData; use anyhow::Result; + use plonky2_field::field_types::Field; + use plonky2_field::goldilocks_field::GoldilocksField; - use crate::field::field_types::Field; - use crate::field::goldilocks_field::GoldilocksField; use crate::gates::gate::Gate; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::switch::SwitchGate; diff --git a/src/gates/util.rs b/plonky2/src/gates/util.rs similarity index 98% rename from src/gates/util.rs rename to plonky2/src/gates/util.rs index 8f83e445..b4dd5fd6 100644 --- a/src/gates/util.rs +++ b/plonky2/src/gates/util.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; -use crate::field::packed_field::PackedField; +use plonky2_field::packed_field::PackedField; /// Writes constraints yielded by a gate to a buffer, with a given stride. /// Permits us to abstract the underlying memory layout. In particular, we can make a matrix of diff --git a/src/hash/arch/aarch64/mod.rs b/plonky2/src/hash/arch/aarch64/mod.rs similarity index 100% rename from src/hash/arch/aarch64/mod.rs rename to plonky2/src/hash/arch/aarch64/mod.rs diff --git a/src/hash/arch/aarch64/poseidon_goldilocks_neon.rs b/plonky2/src/hash/arch/aarch64/poseidon_goldilocks_neon.rs similarity index 99% rename from src/hash/arch/aarch64/poseidon_goldilocks_neon.rs rename to plonky2/src/hash/arch/aarch64/poseidon_goldilocks_neon.rs index 6736cd34..a7f61bf5 100644 --- a/src/hash/arch/aarch64/poseidon_goldilocks_neon.rs +++ b/plonky2/src/hash/arch/aarch64/poseidon_goldilocks_neon.rs @@ -3,11 +3,11 @@ use std::arch::aarch64::*; use std::arch::asm; +use plonky2_field::field_types::PrimeField; +use plonky2_field::goldilocks_field::GoldilocksField; use static_assertions::const_assert; use unroll::unroll_for_loops; -use crate::field::field_types::PrimeField; -use crate::field::goldilocks_field::GoldilocksField; use crate::hash::poseidon::{ Poseidon, ALL_ROUND_CONSTANTS, HALF_N_FULL_ROUNDS, N_PARTIAL_ROUNDS, N_ROUNDS, }; diff --git a/src/hash/arch/aarch64/readme-asm.md b/plonky2/src/hash/arch/aarch64/readme-asm.md similarity index 100% rename from src/hash/arch/aarch64/readme-asm.md rename to plonky2/src/hash/arch/aarch64/readme-asm.md diff --git a/src/hash/arch/mod.rs b/plonky2/src/hash/arch/mod.rs similarity index 100% rename from src/hash/arch/mod.rs rename to plonky2/src/hash/arch/mod.rs diff --git a/src/hash/arch/x86_64/mod.rs b/plonky2/src/hash/arch/x86_64/mod.rs similarity index 100% rename from src/hash/arch/x86_64/mod.rs rename to plonky2/src/hash/arch/x86_64/mod.rs diff --git a/src/hash/arch/x86_64/poseidon_goldilocks_avx2_bmi2.rs b/plonky2/src/hash/arch/x86_64/poseidon_goldilocks_avx2_bmi2.rs similarity index 99% rename from src/hash/arch/x86_64/poseidon_goldilocks_avx2_bmi2.rs rename to plonky2/src/hash/arch/x86_64/poseidon_goldilocks_avx2_bmi2.rs index 86b7edbb..0fddeba7 100644 --- a/src/hash/arch/x86_64/poseidon_goldilocks_avx2_bmi2.rs +++ b/plonky2/src/hash/arch/x86_64/poseidon_goldilocks_avx2_bmi2.rs @@ -2,10 +2,10 @@ use std::arch::asm; use std::arch::x86_64::*; use std::mem::size_of; +use plonky2_field::field_types::Field; +use plonky2_field::goldilocks_field::GoldilocksField; use static_assertions::const_assert; -use crate::field::field_types::Field; -use crate::field::goldilocks_field::GoldilocksField; use crate::hash::poseidon::{ Poseidon, ALL_ROUND_CONSTANTS, HALF_N_FULL_ROUNDS, N_PARTIAL_ROUNDS, N_ROUNDS, }; diff --git a/src/hash/gmimc.rs b/plonky2/src/hash/gmimc.rs similarity index 96% rename from src/hash/gmimc.rs rename to plonky2/src/hash/gmimc.rs index c559dd2f..d5c0fb81 100644 --- a/src/hash/gmimc.rs +++ b/plonky2/src/hash/gmimc.rs @@ -1,8 +1,7 @@ +use plonky2_field::field_types::Field; +use plonky2_field::goldilocks_field::GoldilocksField; use unroll::unroll_for_loops; -use crate::field::field_types::Field; -use crate::field::goldilocks_field::GoldilocksField; - pub(crate) const NUM_ROUNDS: usize = 101; pub trait GMiMC: Field @@ -88,7 +87,8 @@ impl GMiMC<12> for GoldilocksField { #[cfg(test)] mod tests { - use crate::field::goldilocks_field::GoldilocksField; + use plonky2_field::goldilocks_field::GoldilocksField; + use crate::hash::gmimc::GMiMC; fn check_consistency, const WIDTH: usize>() { diff --git a/src/hash/hash_types.rs b/plonky2/src/hash/hash_types.rs similarity index 73% rename from src/hash/hash_types.rs rename to plonky2/src/hash/hash_types.rs index 79ca3950..2efb16e9 100644 --- a/src/hash/hash_types.rs +++ b/plonky2/src/hash/hash_types.rs @@ -1,8 +1,20 @@ +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::{Field, PrimeField}; +use plonky2_field::goldilocks_field::GoldilocksField; use rand::Rng; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use crate::field::field_types::{Field, PrimeField, RichField}; +use crate::hash::gmimc::GMiMC; +use crate::hash::poseidon::Poseidon; use crate::iop::target::Target; +use crate::plonk::config::GenericHashOut; + +/// A prime order field with the features we need to use it as a base field in our argument system. +pub trait RichField: PrimeField + GMiMC<12> + Poseidon {} + +pub trait RichField2: PrimeField + GMiMC<12> + Poseidon + Extendable {} + +impl RichField for GoldilocksField {} /// Represents a ~256 bit hash output. #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] @@ -16,14 +28,14 @@ impl HashOut { elements: [F::ZERO; 4], }; - pub(crate) fn from_vec(elements: Vec) -> Self { + pub fn from_vec(elements: Vec) -> Self { debug_assert!(elements.len() == 4); Self { elements: elements.try_into().unwrap(), } } - pub(crate) fn from_partial(mut elements: Vec) -> Self { + pub fn from_partial(mut elements: Vec) -> Self { debug_assert!(elements.len() <= 4); while elements.len() < 4 { elements.push(F::ZERO); @@ -51,16 +63,17 @@ impl HashOut { } } -impl Default for HashOut { - fn default() -> Self { - Self::ZERO +impl GenericHashOut for HashOut { + fn to_bytes(&self) -> Vec { + self.elements + .into_iter() + .flat_map(|x| x.to_canonical_u64().to_le_bytes()) + .collect() } -} -impl From> for HashOut { - fn from(v: Vec) -> Self { + fn from_bytes(bytes: &[u8]) -> Self { HashOut { - elements: v + elements: bytes .chunks(8) .take(4) .map(|x| F::from_canonical_u64(u64::from_le_bytes(x.try_into().unwrap()))) @@ -69,26 +82,15 @@ impl From> for HashOut { .unwrap(), } } -} -impl From> for Vec { - fn from(h: HashOut) -> Self { - h.elements - .into_iter() - .flat_map(|x| x.to_canonical_u64().to_le_bytes()) - .collect() + fn to_vec(&self) -> Vec { + self.elements.to_vec() } } -impl From> for Vec { - fn from(h: HashOut) -> Self { - h.elements.to_vec() - } -} - -impl From> for u64 { - fn from(h: HashOut) -> Self { - h.elements[0].to_canonical_u64() +impl Default for HashOut { + fn default() -> Self { + Self::ZERO } } @@ -123,44 +125,18 @@ pub struct MerkleCapTarget(pub Vec); /// Hash consisting of a byte array. #[derive(Eq, PartialEq, Copy, Clone, Debug)] pub struct BytesHash(pub [u8; N]); -impl Serialize for BytesHash { - fn serialize(&self, _serializer: S) -> Result - where - S: Serializer, - { - todo!() - } -} -impl<'de, const N: usize> Deserialize<'de> for BytesHash { - fn deserialize(_deserializer: D) -> Result - where - D: Deserializer<'de>, - { - todo!() - } -} -impl From> for BytesHash { - fn from(v: Vec) -> Self { - Self(v.try_into().unwrap()) +impl GenericHashOut for BytesHash { + fn to_bytes(&self) -> Vec { + self.0.to_vec() } -} -impl From> for Vec { - fn from(hash: BytesHash) -> Self { - hash.0.to_vec() + fn from_bytes(bytes: &[u8]) -> Self { + Self(bytes.try_into().unwrap()) } -} -impl From> for u64 { - fn from(hash: BytesHash) -> Self { - u64::from_le_bytes(hash.0[..8].try_into().unwrap()) - } -} - -impl From> for Vec { - fn from(hash: BytesHash) -> Self { - hash.0 + fn to_vec(&self) -> Vec { + self.0 // Chunks of 7 bytes since 8 bytes would allow collisions. .chunks(7) .map(|bytes| { @@ -171,3 +147,21 @@ impl From> for Vec { .collect() } } + +impl Serialize for BytesHash { + fn serialize(&self, _serializer: S) -> Result + where + S: Serializer, + { + todo!() + } +} + +impl<'de, const N: usize> Deserialize<'de> for BytesHash { + fn deserialize(_deserializer: D) -> Result + where + D: Deserializer<'de>, + { + todo!() + } +} diff --git a/src/hash/hashing.rs b/plonky2/src/hash/hashing.rs similarity index 96% rename from src/hash/hashing.rs rename to plonky2/src/hash/hashing.rs index 4760b882..45ae01dd 100644 --- a/src/hash/hashing.rs +++ b/plonky2/src/hash/hashing.rs @@ -1,7 +1,8 @@ //! Concrete instantiation of a hash function. -use crate::field::extension_field::Extendable; -use crate::field::field_types::RichField; +use plonky2_field::extension_field::Extendable; + +use crate::hash::hash_types::RichField; use crate::hash::hash_types::{HashOut, HashOutTarget}; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; @@ -21,7 +22,7 @@ pub fn hash_or_noop>(inputs: Vec) -> Ha } } -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { pub fn hash_or_noop>(&mut self, inputs: Vec) -> HashOutTarget { let zero = self.zero(); if inputs.len() <= 4 { diff --git a/src/hash/merkle_proofs.rs b/plonky2/src/hash/merkle_proofs.rs similarity index 96% rename from src/hash/merkle_proofs.rs rename to plonky2/src/hash/merkle_proofs.rs index ad269699..543c06fd 100644 --- a/src/hash/merkle_proofs.rs +++ b/plonky2/src/hash/merkle_proofs.rs @@ -1,8 +1,8 @@ use anyhow::{ensure, Result}; +use plonky2_field::extension_field::Extendable; use serde::{Deserialize, Serialize}; -use crate::field::extension_field::Extendable; -use crate::field::field_types::RichField; +use crate::hash::hash_types::RichField; use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget}; use crate::hash::hashing::SPONGE_WIDTH; use crate::hash::merkle_tree::MerkleCap; @@ -50,7 +50,7 @@ pub(crate) fn verify_merkle_proof>( Ok(()) } -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Verifies that the given leaf data is present at the given index in the Merkle tree with the /// given cap. The index is given by it's little-endian bits. #[cfg(test)] @@ -125,10 +125,10 @@ impl, const D: usize> CircuitBuilder { #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::field_types::Field; use rand::{thread_rng, Rng}; use super::*; - use crate::field::field_types::Field; use crate::hash::merkle_tree::MerkleTree; use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; diff --git a/src/hash/merkle_tree.rs b/plonky2/src/hash/merkle_tree.rs similarity index 90% rename from src/hash/merkle_tree.rs rename to plonky2/src/hash/merkle_tree.rs index 26a318e3..88c1ebdc 100644 --- a/src/hash/merkle_tree.rs +++ b/plonky2/src/hash/merkle_tree.rs @@ -1,8 +1,9 @@ use rayon::prelude::*; use serde::{Deserialize, Serialize}; -use crate::field::field_types::RichField; +use crate::hash::hash_types::RichField; use crate::hash::merkle_proofs::MerkleProof; +use crate::plonk::config::GenericHashOut; use crate::plonk::config::Hasher; /// The Merkle cap of height `h` of a Merkle tree is the `h`-th layer (from the root) of the tree. @@ -17,13 +18,7 @@ impl> MerkleCap { } pub fn flatten(&self) -> Vec { - self.0 - .iter() - .flat_map(|&h| { - let felts: Vec = h.into(); - felts - }) - .collect() + self.0.iter().flat_map(|&h| h.to_vec()).collect() } } @@ -86,9 +81,9 @@ impl> MerkleTree { #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::extension_field::Extendable; use super::*; - use crate::field::extension_field::Extendable; use crate::hash::merkle_proofs::verify_merkle_proof; use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; @@ -96,7 +91,11 @@ mod tests { (0..n).map(|_| F::rand_vec(k)).collect() } - fn verify_all_leaves, C: GenericConfig, const D: usize>( + fn verify_all_leaves< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( leaves: Vec>, n: usize, ) -> Result<()> { diff --git a/src/hash/mod.rs b/plonky2/src/hash/mod.rs similarity index 100% rename from src/hash/mod.rs rename to plonky2/src/hash/mod.rs diff --git a/src/hash/path_compression.rs b/plonky2/src/hash/path_compression.rs similarity index 98% rename from src/hash/path_compression.rs rename to plonky2/src/hash/path_compression.rs index 7ecbeb24..75c63331 100644 --- a/src/hash/path_compression.rs +++ b/plonky2/src/hash/path_compression.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use num::Integer; -use crate::field::field_types::RichField; +use crate::hash::hash_types::RichField; use crate::hash::merkle_proofs::MerkleProof; use crate::plonk::config::Hasher; @@ -112,10 +112,10 @@ pub(crate) fn decompress_merkle_proofs>( #[cfg(test)] mod tests { + use plonky2_field::field_types::Field; use rand::{thread_rng, Rng}; use super::*; - use crate::field::field_types::Field; use crate::hash::merkle_tree::MerkleTree; use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; diff --git a/src/hash/poseidon.rs b/plonky2/src/hash/poseidon.rs similarity index 97% rename from src/hash/poseidon.rs rename to plonky2/src/hash/poseidon.rs index b00bfbce..a224fa55 100644 --- a/src/hash/poseidon.rs +++ b/plonky2/src/hash/poseidon.rs @@ -1,14 +1,15 @@ //! Implementation of the Poseidon hash function, as described in //! https://eprint.iacr.org/2019/458.pdf +use plonky2_field::extension_field::{Extendable, FieldExtension}; +use plonky2_field::field_types::{Field, PrimeField}; use unroll::unroll_for_loops; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::{Field, PrimeField}; use crate::gates::gate::Gate; use crate::gates::poseidon_mds::PoseidonMdsGate; +use crate::hash::hash_types::RichField; use crate::hash::hashing::SPONGE_WIDTH; +use crate::iop::ext_target::ExtensionTarget; use crate::plonk::circuit_builder::CircuitBuilder; // The number of full rounds and partial rounds is given by the @@ -205,7 +206,7 @@ pub trait Poseidon: PrimeField { v: &[ExtensionTarget; WIDTH], ) -> ExtensionTarget where - Self: Extendable, + Self: RichField + Extendable, { debug_assert!(r < WIDTH); let mut res = builder.zero_extension(); @@ -260,7 +261,7 @@ pub trait Poseidon: PrimeField { state: &[ExtensionTarget; WIDTH], ) -> [ExtensionTarget; WIDTH] where - Self: Extendable, + Self: RichField + Extendable, { // If we have enough routed wires, we will use PoseidonMdsGate. let mds_gate = PoseidonMdsGate::::new(); @@ -306,7 +307,7 @@ pub trait Poseidon: PrimeField { builder: &mut CircuitBuilder, state: &mut [ExtensionTarget; WIDTH], ) where - Self: Extendable, + Self: RichField + Extendable, { for i in 0..WIDTH { let c = ::FAST_PARTIAL_FIRST_ROUND_CONSTANT[i]; @@ -352,7 +353,7 @@ pub trait Poseidon: PrimeField { state: &[ExtensionTarget; WIDTH], ) -> [ExtensionTarget; WIDTH] where - Self: Extendable, + Self: RichField + Extendable, { let mut result = [builder.zero_extension(); WIDTH]; @@ -435,7 +436,7 @@ pub trait Poseidon: PrimeField { r: usize, ) -> [ExtensionTarget; WIDTH] where - Self: Extendable, + Self: RichField + Extendable, { let s0 = state[0]; let mut d = builder.mul_const_extension( @@ -489,7 +490,7 @@ pub trait Poseidon: PrimeField { state: &mut [ExtensionTarget; WIDTH], round_ctr: usize, ) where - Self: Extendable, + Self: RichField + Extendable, { for i in 0..WIDTH { let c = ALL_ROUND_CONSTANTS[i + WIDTH * round_ctr]; @@ -514,7 +515,7 @@ pub trait Poseidon: PrimeField { x: ExtensionTarget, ) -> ExtensionTarget where - Self: Extendable, + Self: RichField + Extendable, { // x |--> x^7 builder.exp_u64_extension(x, 7) @@ -544,7 +545,7 @@ pub trait Poseidon: PrimeField { builder: &mut CircuitBuilder, state: &mut [ExtensionTarget; WIDTH], ) where - Self: Extendable, + Self: RichField + Extendable, { for i in 0..WIDTH { state[i] = ::sbox_monomial_recursive(builder, state[i]); @@ -616,7 +617,8 @@ pub trait Poseidon: PrimeField { #[cfg(test)] pub(crate) mod test_helpers { - use crate::field::field_types::Field; + use plonky2_field::field_types::Field; + use crate::hash::hashing::SPONGE_WIDTH; use crate::hash::poseidon::Poseidon; diff --git a/src/hash/poseidon_crandall.rs b/plonky2/src/hash/poseidon_crandall.rs similarity index 100% rename from src/hash/poseidon_crandall.rs rename to plonky2/src/hash/poseidon_crandall.rs diff --git a/src/hash/poseidon_goldilocks.rs b/plonky2/src/hash/poseidon_goldilocks.rs similarity index 99% rename from src/hash/poseidon_goldilocks.rs rename to plonky2/src/hash/poseidon_goldilocks.rs index 4c4221ee..b8f63ab4 100644 --- a/src/hash/poseidon_goldilocks.rs +++ b/plonky2/src/hash/poseidon_goldilocks.rs @@ -4,7 +4,8 @@ //! `poseidon_constants.sage` script in the `mir-protocol/hash-constants` //! repository. -use crate::field::goldilocks_field::GoldilocksField; +use plonky2_field::goldilocks_field::GoldilocksField; + use crate::hash::poseidon::{Poseidon, N_PARTIAL_ROUNDS}; #[rustfmt::skip] @@ -269,8 +270,9 @@ impl Poseidon for GoldilocksField { #[cfg(test)] mod tests { - use crate::field::field_types::{Field, PrimeField}; - use crate::field::goldilocks_field::GoldilocksField as F; + use plonky2_field::field_types::{Field, PrimeField}; + use plonky2_field::goldilocks_field::GoldilocksField as F; + use crate::hash::poseidon::test_helpers::{check_consistency, check_test_vectors}; #[test] diff --git a/src/hash/rescue.rs b/plonky2/src/hash/rescue.rs similarity index 99% rename from src/hash/rescue.rs rename to plonky2/src/hash/rescue.rs index 0a73fdc5..59e9d265 100644 --- a/src/hash/rescue.rs +++ b/plonky2/src/hash/rescue.rs @@ -1,9 +1,8 @@ //! Implements Rescue Prime. +use plonky2_field::field_types::Field; use unroll::unroll_for_loops; -use crate::field::field_types::Field; - const ROUNDS: usize = 8; const W: usize = 12; diff --git a/src/iop/challenger.rs b/plonky2/src/iop/challenger.rs similarity index 94% rename from src/iop/challenger.rs rename to plonky2/src/iop/challenger.rs index 1e2cd293..a97cb5f1 100644 --- a/src/iop/challenger.rs +++ b/plonky2/src/iop/challenger.rs @@ -1,15 +1,16 @@ use std::convert::TryInto; use std::marker::PhantomData; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::RichField; +use plonky2_field::extension_field::{Extendable, FieldExtension}; + +use crate::hash::hash_types::RichField; use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget}; use crate::hash::hashing::{PlonkyPermutation, SPONGE_RATE, SPONGE_WIDTH}; use crate::hash::merkle_tree::MerkleCap; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; -use crate::plonk::config::{AlgebraicHasher, Hasher}; +use crate::plonk::config::{AlgebraicHasher, GenericHashOut, Hasher}; use crate::plonk::proof::{OpeningSet, OpeningSetTarget}; /// Observes prover messages, and generates challenges by hashing the transcript, a la Fiat-Shamir. @@ -48,7 +49,7 @@ impl> Challenger { pub fn observe_extension_element(&mut self, element: &F::Extension) where - F: Extendable, + F: RichField + Extendable, { self.observe_elements(&element.to_basefield_array()); } @@ -61,7 +62,7 @@ impl> Challenger { pub fn observe_extension_elements(&mut self, elements: &[F::Extension]) where - F: Extendable, + F: RichField + Extendable, { for element in elements { self.observe_extension_element(element); @@ -70,7 +71,7 @@ impl> Challenger { pub fn observe_opening_set(&mut self, os: &OpeningSet) where - F: Extendable, + F: RichField + Extendable, { let OpeningSet { constants, @@ -95,8 +96,7 @@ impl> Challenger { } pub fn observe_hash>(&mut self, hash: OH::Hash) { - let felts: Vec = hash.into(); - self.observe_elements(&felts) + self.observe_elements(&hash.to_vec()) } pub fn observe_cap>(&mut self, cap: &MerkleCap) { @@ -136,7 +136,7 @@ impl> Challenger { pub fn get_extension_challenge(&mut self) -> F::Extension where - F: Extendable, + F: RichField + Extendable, { let mut arr = [F::ZERO; D]; arr.copy_from_slice(&self.get_n_challenges(D)); @@ -145,7 +145,7 @@ impl> Challenger { pub fn get_n_extension_challenges(&mut self, n: usize) -> Vec where - F: Extendable, + F: RichField + Extendable, { (0..n) .map(|_| self.get_extension_challenge::()) @@ -183,13 +183,16 @@ impl> Default for Challenger { } /// A recursive version of `Challenger`. -pub struct RecursiveChallenger, H: AlgebraicHasher, const D: usize> { +pub struct RecursiveChallenger, H: AlgebraicHasher, const D: usize> +{ sponge_state: [Target; SPONGE_WIDTH], input_buffer: Vec, output_buffer: Vec, } -impl, H: AlgebraicHasher, const D: usize> RecursiveChallenger { +impl, H: AlgebraicHasher, const D: usize> + RecursiveChallenger +{ pub(crate) fn new(builder: &mut CircuitBuilder) -> Self { let zero = builder.zero(); RecursiveChallenger { @@ -321,7 +324,8 @@ impl, H: AlgebraicHasher, const D: usize> RecursiveChallenge #[cfg(test)] mod tests { - use crate::field::field_types::Field; + use plonky2_field::field_types::Field; + use crate::iop::challenger::{Challenger, RecursiveChallenger}; use crate::iop::generator::generate_partial_witness; use crate::iop::target::Target; diff --git a/src/field/extension_field/target.rs b/plonky2/src/iop/ext_target.rs similarity index 87% rename from src/field/extension_field/target.rs rename to plonky2/src/iop/ext_target.rs index 5517779b..ff154af2 100644 --- a/src/field/extension_field/target.rs +++ b/plonky2/src/iop/ext_target.rs @@ -1,8 +1,10 @@ use std::ops::Range; -use crate::field::extension_field::algebra::ExtensionAlgebra; -use crate::field::extension_field::{Extendable, FieldExtension, OEF}; -use crate::field::field_types::Field; +use plonky2_field::extension_field::algebra::ExtensionAlgebra; +use plonky2_field::extension_field::{Extendable, FieldExtension, OEF}; +use plonky2_field::field_types::Field; + +use crate::hash::hash_types::RichField; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; @@ -15,11 +17,14 @@ impl ExtensionTarget { self.0 } - pub fn frobenius>(&self, builder: &mut CircuitBuilder) -> Self { + pub fn frobenius>( + &self, + builder: &mut CircuitBuilder, + ) -> Self { self.repeated_frobenius(1, builder) } - pub fn repeated_frobenius>( + pub fn repeated_frobenius>( &self, count: usize, builder: &mut CircuitBuilder, @@ -71,7 +76,7 @@ impl ExtensionAlgebraTarget { } } -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { pub fn constant_extension(&mut self, c: F::Extension) -> ExtensionTarget { let c_parts = c.to_basefield_array(); let mut parts = [self.zero(); D]; @@ -136,7 +141,9 @@ pub fn flatten_target(l: &[ExtensionTarget]) -> Vec { } /// Batch every D-sized chunks into extension targets. -pub fn unflatten_target, const D: usize>(l: &[Target]) -> Vec> { +pub fn unflatten_target, const D: usize>( + l: &[Target], +) -> Vec> { debug_assert_eq!(l.len() % D, 0); l.chunks_exact(D) .map(|c| c.to_vec().try_into().unwrap()) diff --git a/src/iop/generator.rs b/plonky2/src/iop/generator.rs similarity index 96% rename from src/iop/generator.rs rename to plonky2/src/iop/generator.rs index d1d300b4..368232fd 100644 --- a/src/iop/generator.rs +++ b/plonky2/src/iop/generator.rs @@ -2,14 +2,14 @@ use std::fmt::Debug; use std::marker::PhantomData; use num::BigUint; +use plonky2_field::extension_field::{Extendable, FieldExtension}; +use plonky2_field::field_types::Field; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::Field; use crate::gadgets::arithmetic_u32::U32Target; use crate::gadgets::biguint::BigUintTarget; use crate::gadgets::nonnative::NonNativeTarget; -use crate::hash::hash_types::{HashOut, HashOutTarget}; +use crate::hash::hash_types::{HashOut, HashOutTarget, RichField}; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; @@ -20,7 +20,7 @@ use crate::plonk::config::GenericConfig; /// given set of generators. pub(crate) fn generate_partial_witness< 'a, - F: Extendable, + F: RichField + Extendable, C: GenericConfig, const D: usize, >( @@ -150,7 +150,7 @@ impl GeneratedValues { value: F::Extension, ) -> Self where - F: Extendable, + F: RichField + Extendable, { let mut witness = Self::with_capacity(D); witness.set_extension_target(et, value); @@ -191,7 +191,7 @@ impl GeneratedValues { et: ExtensionTarget, value: F::Extension, ) where - F: Extendable, + F: RichField + Extendable, { let limbs = value.to_basefield_array(); (0..D).for_each(|i| { @@ -215,7 +215,7 @@ impl GeneratedValues { pub fn set_ext_wires(&mut self, wires: W, value: F::Extension) where - F: Extendable, + F: RichField + Extendable, W: IntoIterator, { self.set_wires(wires, &value.to_basefield_array()); diff --git a/src/iop/mod.rs b/plonky2/src/iop/mod.rs similarity index 86% rename from src/iop/mod.rs rename to plonky2/src/iop/mod.rs index 7c4a33d7..cc11fb56 100644 --- a/src/iop/mod.rs +++ b/plonky2/src/iop/mod.rs @@ -1,5 +1,6 @@ //! Logic common to multiple IOPs. pub(crate) mod challenger; +pub mod ext_target; pub mod generator; pub mod target; pub mod wire; diff --git a/src/iop/target.rs b/plonky2/src/iop/target.rs similarity index 100% rename from src/iop/target.rs rename to plonky2/src/iop/target.rs diff --git a/src/iop/wire.rs b/plonky2/src/iop/wire.rs similarity index 100% rename from src/iop/wire.rs rename to plonky2/src/iop/wire.rs diff --git a/src/iop/witness.rs b/plonky2/src/iop/witness.rs similarity index 95% rename from src/iop/witness.rs rename to plonky2/src/iop/witness.rs index 17fd0823..29ad513e 100644 --- a/src/iop/witness.rs +++ b/plonky2/src/iop/witness.rs @@ -1,16 +1,17 @@ use std::collections::HashMap; use num::{BigUint, FromPrimitive, Zero}; +use plonky2_field::extension_field::{Extendable, FieldExtension}; +use plonky2_field::field_types::Field; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::{Field, RichField}; use crate::gadgets::arithmetic_u32::U32Target; use crate::gadgets::biguint::BigUintTarget; use crate::gadgets::nonnative::NonNativeTarget; use crate::hash::hash_types::HashOutTarget; +use crate::hash::hash_types::RichField; use crate::hash::hash_types::{HashOut, MerkleCapTarget}; use crate::hash::merkle_tree::MerkleCap; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; use crate::plonk::config::AlgebraicHasher; @@ -31,7 +32,7 @@ pub trait Witness { fn get_extension_target(&self, et: ExtensionTarget) -> F::Extension where - F: Extendable, + F: RichField + Extendable, { F::Extension::from_basefield_array( self.get_targets(&et.to_target_array()).try_into().unwrap(), @@ -40,7 +41,7 @@ pub trait Witness { fn get_extension_targets(&self, ets: &[ExtensionTarget]) -> Vec where - F: Extendable, + F: RichField + Extendable, { ets.iter() .map(|&et| self.get_extension_target(et)) @@ -119,7 +120,7 @@ pub trait Witness { fn set_extension_target(&mut self, et: ExtensionTarget, value: F::Extension) where - F: Extendable, + F: RichField + Extendable, { let limbs = value.to_basefield_array(); (0..D).for_each(|i| { @@ -132,7 +133,7 @@ pub trait Witness { ets: &[ExtensionTarget], values: &[F::Extension], ) where - F: Extendable, + F: RichField + Extendable, { debug_assert_eq!(ets.len(), values.len()); ets.iter() @@ -170,7 +171,7 @@ pub trait Witness { fn set_ext_wires(&mut self, wires: W, value: F::Extension) where - F: Extendable, + F: RichField + Extendable, W: IntoIterator, { self.set_wires(wires, &value.to_basefield_array()); diff --git a/src/lib.rs b/plonky2/src/lib.rs similarity index 95% rename from src/lib.rs rename to plonky2/src/lib.rs index 26209c58..3bddec82 100644 --- a/src/lib.rs +++ b/plonky2/src/lib.rs @@ -11,15 +11,15 @@ #![feature(specialization)] #![feature(stdsimd)] +pub use plonky2_field as field; + pub mod curve; -pub mod field; pub mod fri; pub mod gadgets; pub mod gates; pub mod hash; pub mod iop; pub mod plonk; -pub mod polynomial; pub mod util; // Set up Jemalloc diff --git a/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs similarity index 97% rename from src/plonk/circuit_builder.rs rename to plonky2/src/plonk/circuit_builder.rs index e1cd5bbf..dd800ede 100644 --- a/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -3,12 +3,13 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use std::time::Instant; use log::{debug, info, Level}; +use plonky2_field::cosets::get_unique_coset_shifts; +use plonky2_field::extension_field::{Extendable, FieldExtension}; +use plonky2_field::fft::fft_root_table; +use plonky2_field::field_types::Field; +use plonky2_field::polynomial::PolynomialValues; +use plonky2_util::{log2_ceil, log2_strict}; -use crate::field::cosets::get_unique_coset_shifts; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::fft::fft_root_table; -use crate::field::field_types::Field; use crate::fri::commitment::PolynomialBatchCommitment; use crate::fri::{FriConfig, FriParams}; use crate::gadgets::arithmetic::BaseArithmeticOperation; @@ -26,7 +27,8 @@ use crate::gates::public_input::PublicInputGate; use crate::gates::random_access::RandomAccessGate; use crate::gates::subtraction_u32::U32SubtractionGate; use crate::gates::switch::SwitchGate; -use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget}; +use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField}; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{ CopyGenerator, RandomValueGenerator, SimpleGenerator, WitnessGenerator, }; @@ -40,14 +42,13 @@ use crate::plonk::config::{GenericConfig, Hasher}; use crate::plonk::copy_constraint::CopyConstraint; use crate::plonk::permutation_argument::Forest; use crate::plonk::plonk_common::PlonkPolynomials; -use crate::polynomial::PolynomialValues; use crate::util::context_tree::ContextTree; use crate::util::marking::{Markable, MarkedTargets}; use crate::util::partial_products::num_partial_products; use crate::util::timing::TimingTree; -use crate::util::{log2_ceil, log2_strict, transpose, transpose_poly_values}; +use crate::util::{transpose, transpose_poly_values}; -pub struct CircuitBuilder, const D: usize> { +pub struct CircuitBuilder, const D: usize> { pub(crate) config: CircuitConfig, /// The types of gates used in this circuit. @@ -85,7 +86,7 @@ pub struct CircuitBuilder, const D: usize> { batched_gates: BatchedGates, } -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { pub fn new(config: CircuitConfig) -> Self { let builder = CircuitBuilder { config, @@ -765,7 +766,7 @@ impl, const D: usize> CircuitBuilder { /// Various gate types can contain multiple copies in a single Gate. This helper struct lets a /// CircuitBuilder track such gates that are currently being "filled up." -pub struct BatchedGates, const D: usize> { +pub struct BatchedGates, const D: usize> { /// A map `(c0, c1) -> (g, i)` from constants `(c0,c1)` to an available arithmetic gate using /// these constants with gate index `g` and already using `i` arithmetic operations. pub(crate) free_arithmetic: HashMap<(F, F), (usize, usize)>, @@ -792,7 +793,7 @@ pub struct BatchedGates, const D: usize> { pub(crate) free_constant: Option<(usize, usize)>, } -impl, const D: usize> BatchedGates { +impl, const D: usize> BatchedGates { pub fn new() -> Self { Self { free_arithmetic: HashMap::new(), @@ -807,7 +808,7 @@ impl, const D: usize> BatchedGates { } } -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Finds the last available arithmetic gate with the given constants or add one if there aren't any. /// Returns `(g,i)` such that there is an arithmetic gate with the given constants at index /// `g` and the gate's `i`-th operation is available. @@ -926,10 +927,7 @@ impl, const D: usize> CircuitBuilder { (gate, i) } - pub(crate) fn find_switch_gate( - &mut self, - chunk_size: usize, - ) -> (SwitchGate, usize, usize) { + pub fn find_switch_gate(&mut self, chunk_size: usize) -> (SwitchGate, usize, usize) { if self.batched_gates.current_switch_gates.len() < chunk_size { self.batched_gates.current_switch_gates.extend(vec![ None; diff --git a/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs similarity index 89% rename from src/plonk/circuit_data.rs rename to plonky2/src/plonk/circuit_data.rs index 668f350f..df8d51a0 100644 --- a/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -2,14 +2,14 @@ use std::collections::BTreeMap; use std::ops::{Range, RangeFrom}; use anyhow::Result; +use plonky2_field::extension_field::Extendable; +use plonky2_field::fft::FftRootTable; -use crate::field::extension_field::Extendable; -use crate::field::fft::FftRootTable; use crate::fri::commitment::PolynomialBatchCommitment; use crate::fri::reduction_strategies::FriReductionStrategy; use crate::fri::{FriConfig, FriParams}; use crate::gates::gate::PrefixedGate; -use crate::hash::hash_types::MerkleCapTarget; +use crate::hash::hash_types::{MerkleCapTarget, RichField}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::generator::WitnessGenerator; use crate::iop::target::Target; @@ -85,13 +85,15 @@ impl CircuitConfig { } /// Circuit data required by the prover or the verifier. -pub struct CircuitData, C: GenericConfig, const D: usize> { +pub struct CircuitData, C: GenericConfig, const D: usize> { pub(crate) prover_only: ProverOnlyCircuitData, pub(crate) verifier_only: VerifierOnlyCircuitData, pub(crate) common: CommonCircuitData, } -impl, C: GenericConfig, const D: usize> CircuitData { +impl, C: GenericConfig, const D: usize> + CircuitData +{ pub fn prove(&self, inputs: PartialWitness) -> Result> { prove( &self.prover_only, @@ -120,12 +122,18 @@ impl, C: GenericConfig, const D: usize> CircuitData, C: GenericConfig, const D: usize> { +pub struct ProverCircuitData< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, +> { pub(crate) prover_only: ProverOnlyCircuitData, pub(crate) common: CommonCircuitData, } -impl, C: GenericConfig, const D: usize> ProverCircuitData { +impl, C: GenericConfig, const D: usize> + ProverCircuitData +{ pub fn prove(&self, inputs: PartialWitness) -> Result> { prove( &self.prover_only, @@ -138,12 +146,18 @@ impl, C: GenericConfig, const D: usize> ProverCircuit /// Circuit data required by the prover. #[derive(Debug)] -pub struct VerifierCircuitData, C: GenericConfig, const D: usize> { +pub struct VerifierCircuitData< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, +> { pub(crate) verifier_only: VerifierOnlyCircuitData, pub(crate) common: CommonCircuitData, } -impl, C: GenericConfig, const D: usize> VerifierCircuitData { +impl, C: GenericConfig, const D: usize> + VerifierCircuitData +{ pub fn verify(&self, proof_with_pis: ProofWithPublicInputs) -> Result<()> { verify(proof_with_pis, &self.verifier_only, &self.common) } @@ -158,7 +172,7 @@ impl, C: GenericConfig, const D: usize> VerifierCircu /// Circuit data required by the prover, but not the verifier. pub(crate) struct ProverOnlyCircuitData< - F: Extendable, + F: RichField + Extendable, C: GenericConfig, const D: usize, > { @@ -192,7 +206,11 @@ pub(crate) struct VerifierOnlyCircuitData, const D: usize> { /// Circuit data required by both the prover and the verifier. #[derive(Debug)] -pub struct CommonCircuitData, C: GenericConfig, const D: usize> { +pub struct CommonCircuitData< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, +> { pub(crate) config: CircuitConfig, pub(crate) fri_params: FriParams, @@ -225,7 +243,9 @@ pub struct CommonCircuitData, C: GenericConfig, const pub(crate) circuit_digest: <>::Hasher as Hasher>::Hash, } -impl, C: GenericConfig, const D: usize> CommonCircuitData { +impl, C: GenericConfig, const D: usize> + CommonCircuitData +{ pub fn degree(&self) -> usize { 1 << self.degree_bits } diff --git a/src/plonk/config.rs b/plonky2/src/plonk/config.rs similarity index 92% rename from src/plonk/config.rs rename to plonky2/src/plonk/config.rs index c77ce5f5..252e8e3a 100644 --- a/src/plonk/config.rs +++ b/plonky2/src/plonk/config.rs @@ -2,14 +2,14 @@ use std::convert::TryInto; use std::fmt::Debug; use keccak_hash::keccak; +use plonky2_field::extension_field::quadratic::QuadraticExtension; +use plonky2_field::extension_field::{Extendable, FieldExtension}; +use plonky2_field::goldilocks_field::GoldilocksField; use serde::{de::DeserializeOwned, Serialize}; -use crate::field::extension_field::quadratic::QuadraticExtension; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::RichField; -use crate::field::goldilocks_field::GoldilocksField; use crate::gates::gmimc::GMiMCGate; use crate::gates::poseidon::PoseidonGate; +use crate::hash::hash_types::RichField; use crate::hash::hash_types::{BytesHash, HashOut}; use crate::hash::hashing::{ compress, hash_n_to_hash, GMiMCPermutation, PlonkyPermutation, PoseidonPermutation, @@ -19,22 +19,20 @@ use crate::iop::target::{BoolTarget, Target}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::serialization::Buffer; +pub trait GenericHashOut: + Copy + Clone + Debug + Eq + PartialEq + Send + Sync + Serialize + DeserializeOwned +{ + fn to_bytes(&self) -> Vec; + fn from_bytes(bytes: &[u8]) -> Self; + + fn to_vec(&self) -> Vec; +} + /// Trait for hash functions. pub trait Hasher: Sized + Clone + Debug + Eq + PartialEq { /// Size of `Hash` in bytes. const HASH_SIZE: usize; - type Hash: From> - + Into> - + Into> - + Copy - + Clone - + Debug - + Eq - + PartialEq - + Send - + Sync - + Serialize - + DeserializeOwned; + type Hash: GenericHashOut; fn hash(input: Vec, pad: bool) -> Self::Hash; fn two_to_one(left: Self::Hash, right: Self::Hash) -> Self::Hash; @@ -55,7 +53,7 @@ pub trait AlgebraicHasher: Hasher> { builder: &mut CircuitBuilder, ) -> [Target; SPONGE_WIDTH] where - F: Extendable; + F: RichField + Extendable; } /// Poseidon hash function. @@ -83,7 +81,7 @@ impl AlgebraicHasher for PoseidonHash { builder: &mut CircuitBuilder, ) -> [Target; SPONGE_WIDTH] where - F: Extendable, + F: RichField + Extendable, { let gate_type = PoseidonGate::::new(); let gate = builder.add_gate(gate_type, vec![]); @@ -132,7 +130,7 @@ impl AlgebraicHasher for GMiMCHash { builder: &mut CircuitBuilder, ) -> [Target; SPONGE_WIDTH] where - F: Extendable, + F: RichField + Extendable, { let gate_type = GMiMCGate::::new(); let gate = builder.add_gate(gate_type, vec![]); diff --git a/src/plonk/copy_constraint.rs b/plonky2/src/plonk/copy_constraint.rs similarity index 100% rename from src/plonk/copy_constraint.rs rename to plonky2/src/plonk/copy_constraint.rs diff --git a/src/plonk/get_challenges.rs b/plonky2/src/plonk/get_challenges.rs similarity index 94% rename from src/plonk/get_challenges.rs rename to plonky2/src/plonk/get_challenges.rs index 94c14765..12c069a0 100644 --- a/src/plonk/get_challenges.rs +++ b/plonky2/src/plonk/get_challenges.rs @@ -1,8 +1,11 @@ use std::collections::HashSet; -use crate::field::extension_field::Extendable; +use plonky2_field::extension_field::Extendable; +use plonky2_field::polynomial::PolynomialCoeffs; + use crate::fri::proof::{CompressedFriProof, FriProof}; use crate::fri::verifier::{compute_evaluation, fri_combine_initial, PrecomputedReducedEvals}; +use crate::hash::hash_types::RichField; use crate::hash::merkle_tree::MerkleCap; use crate::iop::challenger::Challenger; use crate::plonk::circuit_data::CommonCircuitData; @@ -11,10 +14,9 @@ use crate::plonk::proof::{ CompressedProof, CompressedProofWithPublicInputs, FriInferredElements, OpeningSet, Proof, ProofChallenges, ProofWithPublicInputs, }; -use crate::polynomial::PolynomialCoeffs; use crate::util::reverse_bits; -fn get_challenges, C: GenericConfig, const D: usize>( +fn get_challenges, C: GenericConfig, const D: usize>( public_inputs_hash: <>::InnerHasher as Hasher>::Hash, wires_cap: &MerkleCap, plonk_zs_partial_products_cap: &MerkleCap, @@ -90,7 +92,9 @@ fn get_challenges, C: GenericConfig, const D: usize>( }) } -impl, C: GenericConfig, const D: usize> ProofWithPublicInputs { +impl, C: GenericConfig, const D: usize> + ProofWithPublicInputs +{ pub(crate) fn fri_query_indices( &self, common_data: &CommonCircuitData, @@ -131,7 +135,7 @@ impl, C: GenericConfig, const D: usize> ProofWithPubl } } -impl, C: GenericConfig, const D: usize> +impl, C: GenericConfig, const D: usize> CompressedProofWithPublicInputs { /// Computes all Fiat-Shamir challenges used in the Plonk proof. diff --git a/src/plonk/mod.rs b/plonky2/src/plonk/mod.rs similarity index 100% rename from src/plonk/mod.rs rename to plonky2/src/plonk/mod.rs diff --git a/src/plonk/permutation_argument.rs b/plonky2/src/plonk/permutation_argument.rs similarity index 98% rename from src/plonk/permutation_argument.rs rename to plonky2/src/plonk/permutation_argument.rs index ca3977ce..252db425 100644 --- a/src/plonk/permutation_argument.rs +++ b/plonky2/src/plonk/permutation_argument.rs @@ -1,11 +1,11 @@ use std::collections::HashMap; +use plonky2_field::field_types::Field; +use plonky2_field::polynomial::PolynomialValues; use rayon::prelude::*; -use crate::field::field_types::Field; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::polynomial::PolynomialValues; /// Disjoint Set Forest data-structure following https://en.wikipedia.org/wiki/Disjoint-set_data_structure. pub struct Forest { diff --git a/src/plonk/plonk_common.rs b/plonky2/src/plonk/plonk_common.rs similarity index 96% rename from src/plonk/plonk_common.rs rename to plonky2/src/plonk/plonk_common.rs index 0bf172ae..34e50f33 100644 --- a/src/plonk/plonk_common.rs +++ b/plonky2/src/plonk/plonk_common.rs @@ -1,8 +1,10 @@ -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, RichField}; -use crate::field::packed_field::PackedField; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::Field; +use plonky2_field::packed_field::PackedField; + use crate::fri::commitment::SALT_SIZE; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::reducing::ReducingFactorTarget; diff --git a/src/plonk/proof.rs b/plonky2/src/plonk/proof.rs similarity index 90% rename from src/plonk/proof.rs rename to plonky2/src/plonk/proof.rs index db6a1e2e..91db2b25 100644 --- a/src/plonk/proof.rs +++ b/plonky2/src/plonk/proof.rs @@ -1,12 +1,12 @@ +use plonky2_field::extension_field::Extendable; use rayon::prelude::*; use serde::{Deserialize, Serialize}; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; use crate::fri::commitment::PolynomialBatchCommitment; use crate::fri::proof::{CompressedFriProof, FriProof, FriProofTarget}; -use crate::hash::hash_types::MerkleCapTarget; +use crate::hash::hash_types::{MerkleCapTarget, RichField}; use crate::hash::merkle_tree::MerkleCap; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; use crate::plonk::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData}; use crate::plonk::config::{GenericConfig, Hasher}; @@ -15,7 +15,7 @@ use crate::util::serialization::Buffer; #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[serde(bound = "")] -pub struct Proof, C: GenericConfig, const D: usize> { +pub struct Proof, C: GenericConfig, const D: usize> { /// Merkle cap of LDEs of wire values. pub wires_cap: MerkleCap, /// Merkle cap of LDEs of Z, in the context of Plonk's permutation argument. @@ -36,7 +36,7 @@ pub struct ProofTarget { pub opening_proof: FriProofTarget, } -impl, C: GenericConfig, const D: usize> Proof { +impl, C: GenericConfig, const D: usize> Proof { /// Compress the proof. pub fn compress( self, @@ -63,12 +63,18 @@ impl, C: GenericConfig, const D: usize> Proof, C: GenericConfig, const D: usize> { +pub struct ProofWithPublicInputs< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, +> { pub proof: Proof, pub public_inputs: Vec, } -impl, C: GenericConfig, const D: usize> ProofWithPublicInputs { +impl, C: GenericConfig, const D: usize> + ProofWithPublicInputs +{ pub fn compress( self, common_data: &CommonCircuitData, @@ -105,7 +111,8 @@ impl, C: GenericConfig, const D: usize> ProofWithPubl #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[serde(bound = "")] -pub struct CompressedProof, C: GenericConfig, const D: usize> { +pub struct CompressedProof, C: GenericConfig, const D: usize> +{ /// Merkle cap of LDEs of wire values. pub wires_cap: MerkleCap, /// Merkle cap of LDEs of Z, in the context of Plonk's permutation argument. @@ -118,7 +125,9 @@ pub struct CompressedProof, C: GenericConfig, const D pub opening_proof: CompressedFriProof, } -impl, C: GenericConfig, const D: usize> CompressedProof { +impl, C: GenericConfig, const D: usize> + CompressedProof +{ /// Decompress the proof. pub(crate) fn decompress( self, @@ -147,7 +156,7 @@ impl, C: GenericConfig, const D: usize> CompressedPro #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[serde(bound = "")] pub struct CompressedProofWithPublicInputs< - F: Extendable, + F: RichField + Extendable, C: GenericConfig, const D: usize, > { @@ -155,7 +164,7 @@ pub struct CompressedProofWithPublicInputs< pub public_inputs: Vec, } -impl, C: GenericConfig, const D: usize> +impl, C: GenericConfig, const D: usize> CompressedProofWithPublicInputs { pub fn decompress( @@ -216,7 +225,7 @@ impl, C: GenericConfig, const D: usize> } } -pub(crate) struct ProofChallenges, const D: usize> { +pub(crate) struct ProofChallenges, const D: usize> { // Random values used in Plonk's permutation argument. pub plonk_betas: Vec, @@ -242,7 +251,9 @@ pub(crate) struct ProofChallenges, const D: usize> { } /// Coset elements that can be inferred in the FRI reduction steps. -pub(crate) struct FriInferredElements, const D: usize>(pub Vec); +pub(crate) struct FriInferredElements, const D: usize>( + pub Vec, +); pub struct ProofWithPublicInputsTarget { pub proof: ProofTarget, @@ -251,7 +262,7 @@ pub struct ProofWithPublicInputsTarget { #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] /// The purported values of each polynomial at a single point. -pub struct OpeningSet, const D: usize> { +pub struct OpeningSet, const D: usize> { pub constants: Vec, pub plonk_sigmas: Vec, pub wires: Vec, @@ -261,7 +272,7 @@ pub struct OpeningSet, const D: usize> { pub quotient_polys: Vec, } -impl, const D: usize> OpeningSet { +impl, const D: usize> OpeningSet { pub fn new>( z: F::Extension, g: F::Extension, @@ -309,8 +320,8 @@ pub struct OpeningSetTarget { #[cfg(test)] mod tests { use anyhow::Result; + use plonky2_field::field_types::Field; - use crate::field::field_types::Field; use crate::fri::reduction_strategies::FriReductionStrategy; use crate::gates::noop::NoopGate; use crate::iop::witness::PartialWitness; diff --git a/src/plonk/prover.rs b/plonky2/src/plonk/prover.rs similarity index 96% rename from src/plonk/prover.rs rename to plonky2/src/plonk/prover.rs index 6cf569e6..1ae85f34 100644 --- a/src/plonk/prover.rs +++ b/plonky2/src/plonk/prover.rs @@ -1,10 +1,13 @@ use std::mem::swap; use anyhow::Result; +use plonky2_field::extension_field::Extendable; +use plonky2_field::polynomial::{PolynomialCoeffs, PolynomialValues}; +use plonky2_util::log2_ceil; use rayon::prelude::*; -use crate::field::extension_field::Extendable; use crate::fri::commitment::PolynomialBatchCommitment; +use crate::hash::hash_types::RichField; use crate::iop::challenger::Challenger; use crate::iop::generator::generate_partial_witness; use crate::iop::witness::{MatrixWitness, PartialWitness, Witness}; @@ -15,13 +18,12 @@ use crate::plonk::plonk_common::ZeroPolyOnCoset; use crate::plonk::proof::{Proof, ProofWithPublicInputs}; use crate::plonk::vanishing_poly::eval_vanishing_poly_base_batch; use crate::plonk::vars::EvaluationVarsBaseBatch; -use crate::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::timed; use crate::util::partial_products::{partial_products_and_z_gx, quotient_chunk_products}; use crate::util::timing::TimingTree; -use crate::util::{log2_ceil, transpose}; +use crate::util::transpose; -pub(crate) fn prove, C: GenericConfig, const D: usize>( +pub(crate) fn prove, C: GenericConfig, const D: usize>( prover_data: &ProverOnlyCircuitData, common_data: &CommonCircuitData, inputs: PartialWitness, @@ -202,7 +204,7 @@ pub(crate) fn prove, C: GenericConfig, const D: usize /// Compute the partial products used in the `Z` polynomials. fn all_wires_permutation_partial_products< - F: Extendable, + F: RichField + Extendable, C: GenericConfig, const D: usize, >( @@ -229,7 +231,7 @@ fn all_wires_permutation_partial_products< /// Returns the polynomials interpolating `partial_products(f / g)` /// where `f, g` are the products in the definition of `Z`: `Z(g^i) = f / g`. fn wires_permutation_partial_products_and_zs< - F: Extendable, + F: RichField + Extendable, C: GenericConfig, const D: usize, >( @@ -289,7 +291,12 @@ fn wires_permutation_partial_products_and_zs< const BATCH_SIZE: usize = 32; -fn compute_quotient_polys<'a, F: Extendable, C: GenericConfig, const D: usize>( +fn compute_quotient_polys< + 'a, + F: RichField + Extendable, + C: GenericConfig, + const D: usize, +>( common_data: &CommonCircuitData, prover_data: &'a ProverOnlyCircuitData, public_inputs_hash: &<>::InnerHasher as Hasher>::Hash, diff --git a/src/plonk/recursive_verifier.rs b/plonky2/src/plonk/recursive_verifier.rs similarity index 96% rename from src/plonk/recursive_verifier.rs rename to plonky2/src/plonk/recursive_verifier.rs index 4c57b9e9..1850e320 100644 --- a/src/plonk/recursive_verifier.rs +++ b/plonky2/src/plonk/recursive_verifier.rs @@ -1,5 +1,6 @@ -use crate::field::extension_field::Extendable; -use crate::hash::hash_types::HashOutTarget; +use plonky2_field::extension_field::Extendable; + +use crate::hash::hash_types::{HashOutTarget, RichField}; use crate::iop::challenger::RecursiveChallenger; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::{CircuitConfig, CommonCircuitData, VerifierCircuitTarget}; @@ -10,7 +11,7 @@ use crate::plonk::vars::EvaluationTargets; use crate::util::reducing::ReducingFactorTarget; use crate::with_context; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Recursively verifies an inner proof. pub fn add_recursive_verifier>( &mut self, @@ -125,6 +126,7 @@ impl, const D: usize> CircuitBuilder { mod tests { use anyhow::Result; use log::{info, Level}; + use plonky2_util::log2_strict; use super::*; use crate::fri::proof::{ @@ -145,11 +147,14 @@ mod tests { ProofWithPublicInputs, }; use crate::plonk::prover::prove; - use crate::util::log2_strict; use crate::util::timing::TimingTree; // Construct a `FriQueryRoundTarget` with the same dimensions as the ones in `proof`. - fn get_fri_query_round, C: GenericConfig, const D: usize>( + fn get_fri_query_round< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( proof: &Proof, builder: &mut CircuitBuilder, ) -> FriQueryRoundTarget { @@ -182,7 +187,11 @@ mod tests { } // Construct a `ProofTarget` with the same dimensions as `proof`. - fn proof_to_proof_target, C: GenericConfig, const D: usize>( + fn proof_to_proof_target< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( proof_with_pis: &ProofWithPublicInputs, builder: &mut CircuitBuilder, ) -> ProofWithPublicInputsTarget { @@ -243,7 +252,11 @@ mod tests { } // Set the targets in a `ProofTarget` to their corresponding values in a `Proof`. - fn set_proof_target, C: AlgebraicConfig, const D: usize>( + fn set_proof_target< + F: RichField + Extendable, + C: AlgebraicConfig, + const D: usize, + >( proof: &ProofWithPublicInputs, pt: &ProofWithPublicInputsTarget, pw: &mut PartialWitness, @@ -523,7 +536,7 @@ mod tests { } /// Creates a dummy proof which should have roughly `num_dummy_gates` gates. - fn dummy_proof, C: GenericConfig, const D: usize>( + fn dummy_proof, C: GenericConfig, const D: usize>( config: &CircuitConfig, num_dummy_gates: u64, ) -> Result<( @@ -545,7 +558,7 @@ mod tests { } fn recursive_proof< - F: Extendable, + F: RichField + Extendable, C: GenericConfig, InnerC: AlgebraicConfig, const D: usize, @@ -606,7 +619,11 @@ mod tests { } /// Test serialization and print some size info. - fn test_serialization, C: GenericConfig, const D: usize>( + fn test_serialization< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( proof: &ProofWithPublicInputs, cd: &CommonCircuitData, ) -> Result<()> { diff --git a/src/plonk/vanishing_poly.rs b/plonky2/src/plonk/vanishing_poly.rs similarity index 95% rename from src/plonk/vanishing_poly.rs rename to plonky2/src/plonk/vanishing_poly.rs index e1f35bd4..d4c227de 100644 --- a/src/plonk/vanishing_poly.rs +++ b/plonky2/src/plonk/vanishing_poly.rs @@ -1,8 +1,10 @@ -use crate::field::batch_util::batch_add_inplace; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::Field; +use plonky2_field::batch_util::batch_add_inplace; +use plonky2_field::extension_field::{Extendable, FieldExtension}; +use plonky2_field::field_types::Field; + use crate::gates::gate::PrefixedGate; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CommonCircuitData; @@ -18,7 +20,11 @@ use crate::with_context; /// Evaluate the vanishing polynomial at `x`. In this context, the vanishing polynomial is a random /// linear combination of gate constraints, plus some other terms relating to the permutation /// argument. All such terms should vanish on `H`. -pub(crate) fn eval_vanishing_poly, C: GenericConfig, const D: usize>( +pub(crate) fn eval_vanishing_poly< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, +>( common_data: &CommonCircuitData, x: F::Extension, vars: EvaluationVars, @@ -91,7 +97,7 @@ pub(crate) fn eval_vanishing_poly, C: GenericConfig, /// Like `eval_vanishing_poly`, but specialized for base field points. Batched. pub(crate) fn eval_vanishing_poly_base_batch< - F: Extendable, + F: RichField + Extendable, C: GenericConfig, const D: usize, >( @@ -201,7 +207,7 @@ pub(crate) fn eval_vanishing_poly_base_batch< /// `num_gate_constraints` is the largest number of constraints imposed by any gate. It is not /// strictly necessary, but it helps performance by ensuring that we allocate a vector with exactly /// the capacity that we need. -pub fn evaluate_gate_constraints, const D: usize>( +pub fn evaluate_gate_constraints, const D: usize>( gates: &[PrefixedGate], num_gate_constraints: usize, vars: EvaluationVars, @@ -225,7 +231,7 @@ pub fn evaluate_gate_constraints, const D: usize>( /// Returns a vector of `num_gate_constraints * vars_batch.len()` field elements. The constraints /// corresponding to `vars_batch[i]` are found in `result[i], result[vars_batch.len() + i], /// result[2 * vars_batch.len() + i], ...`. -pub fn evaluate_gate_constraints_base_batch, const D: usize>( +pub fn evaluate_gate_constraints_base_batch, const D: usize>( gates: &[PrefixedGate], num_gate_constraints: usize, vars_batch: EvaluationVarsBaseBatch, @@ -249,7 +255,7 @@ pub fn evaluate_gate_constraints_base_batch, const D: usize>( constraints_batch } -pub fn evaluate_gate_constraints_recursively, const D: usize>( +pub fn evaluate_gate_constraints_recursively, const D: usize>( builder: &mut CircuitBuilder, gates: &[PrefixedGate], num_gate_constraints: usize, @@ -278,7 +284,7 @@ pub fn evaluate_gate_constraints_recursively, const D: usize>( /// Assumes `x != 1`; if `x` could be 1 then this is unsound. This is fine if `x` is a random /// variable drawn from a sufficiently large domain. pub(crate) fn eval_vanishing_poly_recursively< - F: Extendable, + F: RichField + Extendable, C: GenericConfig, const D: usize, >( diff --git a/src/plonk/vars.rs b/plonky2/src/plonk/vars.rs similarity index 83% rename from src/plonk/vars.rs rename to plonky2/src/plonk/vars.rs index 62e770d1..e2e52cfb 100644 --- a/src/plonk/vars.rs +++ b/plonky2/src/plonk/vars.rs @@ -1,18 +1,19 @@ use std::ops::Range; -use crate::field::extension_field::algebra::ExtensionAlgebra; -use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget}; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::Field; -use crate::field::packed_field::PackedField; -use crate::hash::hash_types::{HashOut, HashOutTarget}; +use plonky2_field::extension_field::algebra::ExtensionAlgebra; +use plonky2_field::extension_field::{Extendable, FieldExtension}; +use plonky2_field::field_types::Field; +use plonky2_field::packed_field::PackedField; + +use crate::hash::hash_types::{HashOut, HashOutTarget, RichField}; +use crate::iop::ext_target::{ExtensionAlgebraTarget, ExtensionTarget}; use crate::util::strided_view::PackedStridedView; #[derive(Debug, Copy, Clone)] -pub struct EvaluationVars<'a, F: Extendable, const D: usize> { - pub(crate) local_constants: &'a [F::Extension], - pub(crate) local_wires: &'a [F::Extension], - pub(crate) public_inputs_hash: &'a HashOut, +pub struct EvaluationVars<'a, F: RichField + Extendable, const D: usize> { + pub local_constants: &'a [F::Extension], + pub local_wires: &'a [F::Extension], + pub public_inputs_hash: &'a HashOut, } /// A batch of evaluation vars, in the base field. @@ -21,17 +22,17 @@ pub struct EvaluationVars<'a, F: Extendable, const D: usize> { #[derive(Debug, Copy, Clone)] pub struct EvaluationVarsBaseBatch<'a, F: Field> { batch_size: usize, - pub(crate) local_constants: &'a [F], - pub(crate) local_wires: &'a [F], - pub(crate) public_inputs_hash: &'a HashOut, + pub local_constants: &'a [F], + pub local_wires: &'a [F], + pub public_inputs_hash: &'a HashOut, } /// A view into `EvaluationVarsBaseBatch` for a particular evaluation point. Does not copy the data. #[derive(Debug, Copy, Clone)] pub struct EvaluationVarsBase<'a, F: Field> { - pub(crate) local_constants: PackedStridedView<'a, F>, - pub(crate) local_wires: PackedStridedView<'a, F>, - pub(crate) public_inputs_hash: &'a HashOut, + pub local_constants: PackedStridedView<'a, F>, + pub local_wires: PackedStridedView<'a, F>, + pub public_inputs_hash: &'a HashOut, } /// Like `EvaluationVarsBase`, but packed. @@ -39,12 +40,12 @@ pub struct EvaluationVarsBase<'a, F: Field> { // have packed extension fields. #[derive(Debug, Copy, Clone)] pub struct EvaluationVarsBasePacked<'a, P: PackedField> { - pub(crate) local_constants: PackedStridedView<'a, P>, - pub(crate) local_wires: PackedStridedView<'a, P>, - pub(crate) public_inputs_hash: &'a HashOut, + pub local_constants: PackedStridedView<'a, P>, + pub local_wires: PackedStridedView<'a, P>, + pub public_inputs_hash: &'a HashOut, } -impl<'a, F: Extendable, const D: usize> EvaluationVars<'a, F, D> { +impl<'a, F: RichField + Extendable, const D: usize> EvaluationVars<'a, F, D> { pub fn get_local_ext_algebra( &self, wire_range: Range, @@ -117,7 +118,7 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { impl<'a, F: Field> EvaluationVarsBase<'a, F> { pub fn get_local_ext(&self, wire_range: Range) -> F::Extension where - F: Extendable, + F: RichField + Extendable, { debug_assert_eq!(wire_range.len(), D); let arr = self.local_wires.view(wire_range).try_into().unwrap(); @@ -215,9 +216,9 @@ impl<'a, const D: usize> EvaluationTargets<'a, D> { #[derive(Copy, Clone)] pub struct EvaluationTargets<'a, const D: usize> { - pub(crate) local_constants: &'a [ExtensionTarget], - pub(crate) local_wires: &'a [ExtensionTarget], - pub(crate) public_inputs_hash: &'a HashOutTarget, + pub local_constants: &'a [ExtensionTarget], + pub local_wires: &'a [ExtensionTarget], + pub public_inputs_hash: &'a HashOutTarget, } impl<'a, const D: usize> EvaluationTargets<'a, D> { diff --git a/src/plonk/verifier.rs b/plonky2/src/plonk/verifier.rs similarity index 92% rename from src/plonk/verifier.rs rename to plonky2/src/plonk/verifier.rs index cf27d26f..c3cf4988 100644 --- a/src/plonk/verifier.rs +++ b/plonky2/src/plonk/verifier.rs @@ -1,8 +1,9 @@ use anyhow::{ensure, Result}; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::Field; -use crate::field::extension_field::Extendable; -use crate::field::field_types::Field; use crate::fri::verifier::verify_fri_proof; +use crate::hash::hash_types::RichField; use crate::plonk::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData}; use crate::plonk::config::GenericConfig; use crate::plonk::plonk_common::reduce_with_powers; @@ -10,7 +11,7 @@ use crate::plonk::proof::{ProofChallenges, ProofWithPublicInputs}; use crate::plonk::vanishing_poly::eval_vanishing_poly; use crate::plonk::vars::EvaluationVars; -pub(crate) fn verify, C: GenericConfig, const D: usize>( +pub(crate) fn verify, C: GenericConfig, const D: usize>( proof_with_pis: ProofWithPublicInputs, verifier_data: &VerifierOnlyCircuitData, common_data: &CommonCircuitData, @@ -20,7 +21,7 @@ pub(crate) fn verify, C: GenericConfig, const D: usiz } pub(crate) fn verify_with_challenges< - F: Extendable, + F: RichField + Extendable, C: GenericConfig, const D: usize, >( diff --git a/src/util/context_tree.rs b/plonky2/src/util/context_tree.rs similarity index 100% rename from src/util/context_tree.rs rename to plonky2/src/util/context_tree.rs diff --git a/src/util/marking.rs b/plonky2/src/util/marking.rs similarity index 84% rename from src/util/marking.rs rename to plonky2/src/util/marking.rs index acbf8543..67ef89f4 100644 --- a/src/util/marking.rs +++ b/plonky2/src/util/marking.rs @@ -1,6 +1,7 @@ -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::hash::hash_types::HashOutTarget; +use plonky2_field::extension_field::Extendable; + +use crate::hash::hash_types::{HashOutTarget, RichField}; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness}; @@ -36,7 +37,7 @@ impl>, const D: usize> From> for Markable { impl Markable { /// Display a `Markable` by querying a partial witness. - fn print_markable>(&self, pw: &PartitionWitness) { + fn print_markable>(&self, pw: &PartitionWitness) { match self { Markable::Target(t) => println!("{}", pw.get_target(*t)), Markable::ExtensionTarget(et) => println!("{}", pw.get_extension_target(*et)), @@ -55,7 +56,7 @@ pub struct MarkedTargets { impl MarkedTargets { /// Display the collection of targets along with its name by querying a partial witness. - pub fn display>(&self, pw: &PartitionWitness) { + pub fn display>(&self, pw: &PartitionWitness) { println!("Values for {}:", self.name); self.targets.print_markable(pw); println!("End of values for {}", self.name); diff --git a/src/util/mod.rs b/plonky2/src/util/mod.rs similarity index 53% rename from src/util/mod.rs rename to plonky2/src/util/mod.rs index 5d1de5ec..13a72f78 100644 --- a/src/util/mod.rs +++ b/plonky2/src/util/mod.rs @@ -1,10 +1,6 @@ -use std::arch::asm; -use std::hint::unreachable_unchecked; +use plonky2_field::field_types::Field; +use plonky2_field::polynomial::PolynomialValues; -use crate::field::field_types::Field; -use crate::polynomial::PolynomialValues; - -pub(crate) mod bimap; pub(crate) mod context_tree; pub(crate) mod marking; pub(crate) mod partial_products; @@ -13,25 +9,6 @@ pub mod serialization; pub(crate) mod strided_view; pub(crate) mod timing; -pub(crate) fn bits_u64(n: u64) -> usize { - (64 - n.leading_zeros()) as usize -} - -pub(crate) const fn ceil_div_usize(a: usize, b: usize) -> usize { - (a + b - 1) / b -} - -/// Computes `ceil(log_2(n))`. -pub(crate) fn log2_ceil(n: usize) -> usize { - n.next_power_of_two().trailing_zeros() as usize -} - -/// Computes `log_2(n)`, panicking if `n` is not a power of two. -pub(crate) fn log2_strict(n: usize) -> usize { - assert!(n.is_power_of_two(), "Not a power of two: {}", n); - log2_ceil(n) -} - pub(crate) fn transpose_poly_values(polys: Vec>) -> Vec> { let poly_values = polys.into_iter().map(|p| p.values).collect::>(); transpose(&poly_values) @@ -69,126 +46,6 @@ pub fn transpose(matrix: &[Vec]) -> Vec> { transposed } -/// Permutes `arr` such that each index is mapped to its reverse in binary. -pub(crate) fn reverse_index_bits(arr: &[T]) -> Vec { - let n = arr.len(); - let n_power = log2_strict(n); - - if n_power <= 6 { - reverse_index_bits_small(arr, n_power) - } else { - reverse_index_bits_large(arr, n_power) - } -} - -/* Both functions below are semantically equivalent to: - for i in 0..n { - result.push(arr[reverse_bits(i, n_power)]); - } - where reverse_bits(i, n_power) computes the n_power-bit reverse. The complications are there - to guide the compiler to generate optimal assembly. -*/ - -fn reverse_index_bits_small(arr: &[T], n_power: usize) -> Vec { - let n = arr.len(); - let mut result = Vec::with_capacity(n); - // BIT_REVERSE_6BIT holds 6-bit reverses. This shift makes them n_power-bit reverses. - let dst_shr_amt = 6 - n_power; - for i in 0..n { - let src = (BIT_REVERSE_6BIT[i] as usize) >> dst_shr_amt; - result.push(arr[src]); - } - result -} - -fn reverse_index_bits_large(arr: &[T], n_power: usize) -> Vec { - let n = arr.len(); - // LLVM does not know that it does not need to reverse src at each iteration (which is expensive - // on x86). We take advantage of the fact that the low bits of dst change rarely and the high - // bits of dst are dependent only on the low bits of src. - let src_lo_shr_amt = 64 - (n_power - 6); - let src_hi_shl_amt = n_power - 6; - let mut result = Vec::with_capacity(n); - for i_chunk in 0..(n >> 6) { - let src_lo = i_chunk.reverse_bits() >> src_lo_shr_amt; - for i_lo in 0..(1 << 6) { - let src_hi = (BIT_REVERSE_6BIT[i_lo] as usize) << src_hi_shl_amt; - let src = src_hi + src_lo; - result.push(arr[src]); - } - } - result -} - -pub(crate) fn reverse_index_bits_in_place(arr: &mut Vec) { - let n = arr.len(); - let n_power = log2_strict(n); - - if n_power <= 6 { - reverse_index_bits_in_place_small(arr, n_power); - } else { - reverse_index_bits_in_place_large(arr, n_power); - } -} - -/* Both functions below are semantically equivalent to: - for src in 0..n { - let dst = reverse_bits(src, n_power); - if src < dst { - arr.swap(src, dst); - } - } - where reverse_bits(src, n_power) computes the n_power-bit reverse. -*/ - -fn reverse_index_bits_in_place_small(arr: &mut Vec, n_power: usize) { - let n = arr.len(); - // BIT_REVERSE_6BIT holds 6-bit reverses. This shift makes them n_power-bit reverses. - let dst_shr_amt = 6 - n_power; - for src in 0..n { - let dst = (BIT_REVERSE_6BIT[src] as usize) >> dst_shr_amt; - if src < dst { - arr.swap(src, dst); - } - } -} - -fn reverse_index_bits_in_place_large(arr: &mut Vec, n_power: usize) { - let n = arr.len(); - // LLVM does not know that it does not need to reverse src at each iteration (which is expensive - // on x86). We take advantage of the fact that the low bits of dst change rarely and the high - // bits of dst are dependent only on the low bits of src. - let dst_lo_shr_amt = 64 - (n_power - 6); - let dst_hi_shl_amt = n_power - 6; - for src_chunk in 0..(n >> 6) { - let src_hi = src_chunk << 6; - let dst_lo = src_chunk.reverse_bits() >> dst_lo_shr_amt; - for src_lo in 0..(1 << 6) { - let dst_hi = (BIT_REVERSE_6BIT[src_lo] as usize) << dst_hi_shl_amt; - - let src = src_hi + src_lo; - let dst = dst_hi + dst_lo; - if src < dst { - arr.swap(src, dst); - } - } - } -} - -// Lookup table of 6-bit reverses. -// NB: 2^6=64 bytes is a cacheline. A smaller table wastes cache space. -#[rustfmt::skip] -const BIT_REVERSE_6BIT: &[u8] = &[ - 0o00, 0o40, 0o20, 0o60, 0o10, 0o50, 0o30, 0o70, - 0o04, 0o44, 0o24, 0o64, 0o14, 0o54, 0o34, 0o74, - 0o02, 0o42, 0o22, 0o62, 0o12, 0o52, 0o32, 0o72, - 0o06, 0o46, 0o26, 0o66, 0o16, 0o56, 0o36, 0o76, - 0o01, 0o41, 0o21, 0o61, 0o11, 0o51, 0o31, 0o71, - 0o05, 0o45, 0o25, 0o65, 0o15, 0o55, 0o35, 0o75, - 0o03, 0o43, 0o23, 0o63, 0o13, 0o53, 0o33, 0o73, - 0o07, 0o47, 0o27, 0o67, 0o17, 0o57, 0o37, 0o77, -]; - pub(crate) fn reverse_bits(n: usize, num_bits: usize) -> usize { // NB: The only reason we need overflowing_shr() here as opposed // to plain '>>' is to accommodate the case n == num_bits == 0, @@ -199,34 +56,11 @@ pub(crate) fn reverse_bits(n: usize, num_bits: usize) -> usize { .0 } -#[inline(always)] -pub(crate) fn assume(p: bool) { - debug_assert!(p); - if !p { - unsafe { - unreachable_unchecked(); - } - } -} - -/// Try to force Rust to emit a branch. Example: -/// if x > 2 { -/// y = foo(); -/// branch_hint(); -/// } else { -/// y = bar(); -/// } -/// This function has no semantics. It is a hint only. -#[inline(always)] -pub(crate) fn branch_hint() { - unsafe { - asm!("", options(nomem, nostack, preserves_flags)); - } -} - #[cfg(test)] mod tests { - use crate::util::{reverse_bits, reverse_index_bits, reverse_index_bits_in_place}; + use plonky2_util::{reverse_index_bits, reverse_index_bits_in_place}; + + use crate::util::reverse_bits; #[test] fn test_reverse_bits() { diff --git a/src/util/partial_products.rs b/plonky2/src/util/partial_products.rs similarity index 95% rename from src/util/partial_products.rs rename to plonky2/src/util/partial_products.rs index b5e805e9..cc9012ed 100644 --- a/src/util/partial_products.rs +++ b/plonky2/src/util/partial_products.rs @@ -1,12 +1,13 @@ use std::iter; use itertools::Itertools; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::Field; +use plonky2_util::ceil_div_usize; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, RichField}; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::plonk::circuit_builder::CircuitBuilder; -use crate::util::ceil_div_usize; pub(crate) fn quotient_chunk_products( quotient_values: &[F], @@ -108,8 +109,9 @@ pub(crate) fn check_partial_products_recursively, c #[cfg(test)] mod tests { + use plonky2_field::goldilocks_field::GoldilocksField; + use super::*; - use crate::field::goldilocks_field::GoldilocksField; #[test] fn test_partial_products() { diff --git a/src/util/reducing.rs b/plonky2/src/util/reducing.rs similarity index 96% rename from src/util/reducing.rs rename to plonky2/src/util/reducing.rs index 562293e5..8bfe45d1 100644 --- a/src/util/reducing.rs +++ b/plonky2/src/util/reducing.rs @@ -1,14 +1,16 @@ use std::borrow::Borrow; -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::field_types::Field; +use plonky2_field::extension_field::Extendable; +use plonky2_field::field_types::Field; +use plonky2_field::polynomial::PolynomialCoeffs; + use crate::gates::arithmetic_extension::ArithmeticExtensionGate; use crate::gates::reducing::ReducingGate; use crate::gates::reducing_extension::ReducingExtensionGate; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; -use crate::polynomial::PolynomialCoeffs; /// When verifying the composition polynomial in FRI we have to compute sums of the form /// `(sum_0^k a^i * x_i)/d_0 + (sum_k^r a^i * y_i)/d_1` @@ -102,7 +104,7 @@ impl ReducingFactorTarget { builder: &mut CircuitBuilder, ) -> ExtensionTarget where - F: Extendable, + F: RichField + Extendable, { let l = terms.len(); @@ -157,7 +159,7 @@ impl ReducingFactorTarget { builder: &mut CircuitBuilder, ) -> ExtensionTarget where - F: Extendable, + F: RichField + Extendable, { let l = terms.len(); @@ -217,7 +219,7 @@ impl ReducingFactorTarget { builder: &mut CircuitBuilder, ) -> ExtensionTarget where - F: Extendable, + F: RichField + Extendable, { self.count += terms.len() as u64; terms @@ -234,7 +236,7 @@ impl ReducingFactorTarget { builder: &mut CircuitBuilder, ) -> ExtensionTarget where - F: Extendable, + F: RichField + Extendable, { let exp = builder.exp_u64_extension(self.base, self.count); self.count = 0; diff --git a/src/util/serialization.rs b/plonky2/src/util/serialization.rs similarity index 86% rename from src/util/serialization.rs rename to plonky2/src/util/serialization.rs index 06f2a3e5..1b7fdbda 100644 --- a/src/util/serialization.rs +++ b/plonky2/src/util/serialization.rs @@ -2,20 +2,22 @@ use std::collections::HashMap; use std::io::Cursor; use std::io::{Read, Result, Write}; -use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::{PrimeField, RichField}; +use plonky2_field::extension_field::{Extendable, FieldExtension}; +use plonky2_field::field_types::PrimeField; +use plonky2_field::polynomial::PolynomialCoeffs; + use crate::fri::proof::{ CompressedFriProof, CompressedFriQueryRounds, FriInitialTreeProof, FriProof, FriQueryRound, FriQueryStep, }; +use crate::hash::hash_types::RichField; use crate::hash::merkle_proofs::MerkleProof; use crate::hash::merkle_tree::MerkleCap; use crate::plonk::circuit_data::CommonCircuitData; -use crate::plonk::config::{GenericConfig, Hasher}; +use crate::plonk::config::{GenericConfig, GenericHashOut, Hasher}; use crate::plonk::proof::{ CompressedProof, CompressedProofWithPublicInputs, OpeningSet, Proof, ProofWithPublicInputs, }; -use crate::polynomial::PolynomialCoeffs; #[derive(Debug)] pub struct Buffer(Cursor>); @@ -62,13 +64,18 @@ impl Buffer { ))) } - fn write_field_ext, const D: usize>(&mut self, x: F::Extension) -> Result<()> { + fn write_field_ext, const D: usize>( + &mut self, + x: F::Extension, + ) -> Result<()> { for &a in &x.to_basefield_array() { self.write_field(a)?; } Ok(()) } - fn read_field_ext, const D: usize>(&mut self) -> Result { + fn read_field_ext, const D: usize>( + &mut self, + ) -> Result { let mut arr = [F::ZERO; D]; for a in arr.iter_mut() { *a = self.read_field()?; @@ -79,14 +86,13 @@ impl Buffer { } fn write_hash>(&mut self, h: H::Hash) -> Result<()> { - let bytes: Vec = h.into(); - self.0.write_all(&bytes) + self.0.write_all(&h.to_bytes()) } fn read_hash>(&mut self) -> Result { let mut buf = vec![0; H::HASH_SIZE]; self.0.read_exact(&mut buf)?; - Ok(H::Hash::from(buf.to_vec())) + Ok(H::Hash::from_bytes(&buf)) } fn write_merkle_cap>( @@ -122,7 +128,7 @@ impl Buffer { .collect::>>() } - fn write_field_ext_vec, const D: usize>( + fn write_field_ext_vec, const D: usize>( &mut self, v: &[F::Extension], ) -> Result<()> { @@ -131,7 +137,7 @@ impl Buffer { } Ok(()) } - fn read_field_ext_vec, const D: usize>( + fn read_field_ext_vec, const D: usize>( &mut self, length: usize, ) -> Result> { @@ -140,7 +146,7 @@ impl Buffer { .collect::>>() } - fn write_opening_set, const D: usize>( + fn write_opening_set, const D: usize>( &mut self, os: &OpeningSet, ) -> Result<()> { @@ -152,7 +158,11 @@ impl Buffer { self.write_field_ext_vec::(&os.partial_products)?; self.write_field_ext_vec::(&os.quotient_polys) } - fn read_opening_set, C: GenericConfig, const D: usize>( + fn read_opening_set< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( &mut self, common_data: &CommonCircuitData, ) -> Result> { @@ -203,7 +213,11 @@ impl Buffer { }) } - fn write_fri_initial_proof, C: GenericConfig, const D: usize>( + fn write_fri_initial_proof< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( &mut self, fitp: &FriInitialTreeProof, ) -> Result<()> { @@ -213,7 +227,11 @@ impl Buffer { } Ok(()) } - fn read_fri_initial_proof, C: GenericConfig, const D: usize>( + fn read_fri_initial_proof< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( &mut self, common_data: &CommonCircuitData, ) -> Result> { @@ -242,14 +260,22 @@ impl Buffer { Ok(FriInitialTreeProof { evals_proofs }) } - fn write_fri_query_step, C: GenericConfig, const D: usize>( + fn write_fri_query_step< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( &mut self, fqs: &FriQueryStep, ) -> Result<()> { self.write_field_ext_vec::(&fqs.evals)?; self.write_merkle_proof(&fqs.merkle_proof) } - fn read_fri_query_step, C: GenericConfig, const D: usize>( + fn read_fri_query_step< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( &mut self, arity: usize, compressed: bool, @@ -262,7 +288,11 @@ impl Buffer { }) } - fn write_fri_query_rounds, C: GenericConfig, const D: usize>( + fn write_fri_query_rounds< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( &mut self, fqrs: &[FriQueryRound], ) -> Result<()> { @@ -274,7 +304,11 @@ impl Buffer { } Ok(()) } - fn read_fri_query_rounds, C: GenericConfig, const D: usize>( + fn read_fri_query_rounds< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( &mut self, common_data: &CommonCircuitData, ) -> Result>> { @@ -296,7 +330,7 @@ impl Buffer { Ok(fqrs) } - fn write_fri_proof, C: GenericConfig, const D: usize>( + fn write_fri_proof, C: GenericConfig, const D: usize>( &mut self, fp: &FriProof, ) -> Result<()> { @@ -307,7 +341,7 @@ impl Buffer { self.write_field_ext_vec::(&fp.final_poly.coeffs)?; self.write_field(fp.pow_witness) } - fn read_fri_proof, C: GenericConfig, const D: usize>( + fn read_fri_proof, C: GenericConfig, const D: usize>( &mut self, common_data: &CommonCircuitData, ) -> Result> { @@ -327,7 +361,7 @@ impl Buffer { }) } - pub fn write_proof, C: GenericConfig, const D: usize>( + pub fn write_proof, C: GenericConfig, const D: usize>( &mut self, proof: &Proof, ) -> Result<()> { @@ -337,7 +371,7 @@ impl Buffer { self.write_opening_set(&proof.openings)?; self.write_fri_proof::(&proof.opening_proof) } - pub fn read_proof, C: GenericConfig, const D: usize>( + pub fn read_proof, C: GenericConfig, const D: usize>( &mut self, common_data: &CommonCircuitData, ) -> Result> { @@ -358,7 +392,7 @@ impl Buffer { } pub fn write_proof_with_public_inputs< - F: Extendable, + F: RichField + Extendable, C: GenericConfig, const D: usize, >( @@ -373,7 +407,7 @@ impl Buffer { self.write_field_vec(public_inputs) } pub fn read_proof_with_public_inputs< - F: Extendable, + F: RichField + Extendable, C: GenericConfig, const D: usize, >( @@ -392,7 +426,7 @@ impl Buffer { } fn write_compressed_fri_query_rounds< - F: Extendable, + F: RichField + Extendable, C: GenericConfig, const D: usize, >( @@ -418,7 +452,7 @@ impl Buffer { Ok(()) } fn read_compressed_fri_query_rounds< - F: Extendable, + F: RichField + Extendable, C: GenericConfig, const D: usize, >( @@ -463,7 +497,11 @@ impl Buffer { }) } - fn write_compressed_fri_proof, C: GenericConfig, const D: usize>( + fn write_compressed_fri_proof< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( &mut self, fp: &CompressedFriProof, ) -> Result<()> { @@ -474,7 +512,11 @@ impl Buffer { self.write_field_ext_vec::(&fp.final_poly.coeffs)?; self.write_field(fp.pow_witness) } - fn read_compressed_fri_proof, C: GenericConfig, const D: usize>( + fn read_compressed_fri_proof< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( &mut self, common_data: &CommonCircuitData, ) -> Result> { @@ -494,7 +536,11 @@ impl Buffer { }) } - pub fn write_compressed_proof, C: GenericConfig, const D: usize>( + pub fn write_compressed_proof< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( &mut self, proof: &CompressedProof, ) -> Result<()> { @@ -504,7 +550,11 @@ impl Buffer { self.write_opening_set(&proof.openings)?; self.write_compressed_fri_proof::(&proof.opening_proof) } - pub fn read_compressed_proof, C: GenericConfig, const D: usize>( + pub fn read_compressed_proof< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( &mut self, common_data: &CommonCircuitData, ) -> Result> { @@ -525,7 +575,7 @@ impl Buffer { } pub fn write_compressed_proof_with_public_inputs< - F: Extendable, + F: RichField + Extendable, C: GenericConfig, const D: usize, >( @@ -540,7 +590,7 @@ impl Buffer { self.write_field_vec(public_inputs) } pub fn read_compressed_proof_with_public_inputs< - F: Extendable, + F: RichField + Extendable, C: GenericConfig, const D: usize, >( diff --git a/src/util/strided_view.rs b/plonky2/src/util/strided_view.rs similarity index 99% rename from src/util/strided_view.rs rename to plonky2/src/util/strided_view.rs index 9beb13aa..01842bc8 100644 --- a/src/util/strided_view.rs +++ b/plonky2/src/util/strided_view.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; use std::mem::size_of; use std::ops::{Index, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive}; -use crate::field::packed_field::PackedField; +use plonky2_field::packed_field::PackedField; /// Imagine a slice, but with a stride (a la a NumPy array). /// diff --git a/src/util/timing.rs b/plonky2/src/util/timing.rs similarity index 100% rename from src/util/timing.rs rename to plonky2/src/util/timing.rs diff --git a/src/field/mod.rs b/src/field/mod.rs deleted file mode 100644 index dac1c9be..00000000 --- a/src/field/mod.rs +++ /dev/null @@ -1,18 +0,0 @@ -pub(crate) mod arch; -pub(crate) mod batch_util; -pub(crate) mod cosets; -pub mod extension_field; -pub mod fft; -pub mod field_types; -pub mod goldilocks_field; -pub(crate) mod interpolation; -mod inversion; -pub(crate) mod packable; -pub(crate) mod packed_field; -pub mod secp256k1_base; -pub mod secp256k1_scalar; - -#[cfg(test)] -mod field_testing; -#[cfg(test)] -mod prime_field_testing; diff --git a/util/Cargo.toml b/util/Cargo.toml new file mode 100644 index 00000000..4d6e735c --- /dev/null +++ b/util/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "plonky2_util" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/util/src/lib.rs b/util/src/lib.rs new file mode 100644 index 00000000..8cc60a27 --- /dev/null +++ b/util/src/lib.rs @@ -0,0 +1,173 @@ +#![allow(clippy::new_without_default)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::type_complexity)] +#![allow(clippy::len_without_is_empty)] +#![allow(clippy::needless_range_loop)] +#![allow(clippy::return_self_not_must_use)] + +use std::arch::asm; +use std::hint::unreachable_unchecked; + +pub fn bits_u64(n: u64) -> usize { + (64 - n.leading_zeros()) as usize +} + +pub const fn ceil_div_usize(a: usize, b: usize) -> usize { + (a + b - 1) / b +} + +/// Computes `ceil(log_2(n))`. +pub fn log2_ceil(n: usize) -> usize { + n.next_power_of_two().trailing_zeros() as usize +} + +/// Computes `log_2(n)`, panicking if `n` is not a power of two. +pub fn log2_strict(n: usize) -> usize { + assert!(n.is_power_of_two(), "Not a power of two: {}", n); + log2_ceil(n) +} + +/// Permutes `arr` such that each index is mapped to its reverse in binary. +pub fn reverse_index_bits(arr: &[T]) -> Vec { + let n = arr.len(); + let n_power = log2_strict(n); + + if n_power <= 6 { + reverse_index_bits_small(arr, n_power) + } else { + reverse_index_bits_large(arr, n_power) + } +} + +/* Both functions below are semantically equivalent to: + for i in 0..n { + result.push(arr[reverse_bits(i, n_power)]); + } + where reverse_bits(i, n_power) computes the n_power-bit reverse. The complications are there + to guide the compiler to generate optimal assembly. +*/ + +fn reverse_index_bits_small(arr: &[T], n_power: usize) -> Vec { + let n = arr.len(); + let mut result = Vec::with_capacity(n); + // BIT_REVERSE_6BIT holds 6-bit reverses. This shift makes them n_power-bit reverses. + let dst_shr_amt = 6 - n_power; + for i in 0..n { + let src = (BIT_REVERSE_6BIT[i] as usize) >> dst_shr_amt; + result.push(arr[src]); + } + result +} + +fn reverse_index_bits_large(arr: &[T], n_power: usize) -> Vec { + let n = arr.len(); + // LLVM does not know that it does not need to reverse src at each iteration (which is expensive + // on x86). We take advantage of the fact that the low bits of dst change rarely and the high + // bits of dst are dependent only on the low bits of src. + let src_lo_shr_amt = 64 - (n_power - 6); + let src_hi_shl_amt = n_power - 6; + let mut result = Vec::with_capacity(n); + for i_chunk in 0..(n >> 6) { + let src_lo = i_chunk.reverse_bits() >> src_lo_shr_amt; + for i_lo in 0..(1 << 6) { + let src_hi = (BIT_REVERSE_6BIT[i_lo] as usize) << src_hi_shl_amt; + let src = src_hi + src_lo; + result.push(arr[src]); + } + } + result +} + +pub fn reverse_index_bits_in_place(arr: &mut Vec) { + let n = arr.len(); + let n_power = log2_strict(n); + + if n_power <= 6 { + reverse_index_bits_in_place_small(arr, n_power); + } else { + reverse_index_bits_in_place_large(arr, n_power); + } +} + +/* Both functions below are semantically equivalent to: + for src in 0..n { + let dst = reverse_bits(src, n_power); + if src < dst { + arr.swap(src, dst); + } + } + where reverse_bits(src, n_power) computes the n_power-bit reverse. +*/ + +fn reverse_index_bits_in_place_small(arr: &mut Vec, n_power: usize) { + let n = arr.len(); + // BIT_REVERSE_6BIT holds 6-bit reverses. This shift makes them n_power-bit reverses. + let dst_shr_amt = 6 - n_power; + for src in 0..n { + let dst = (BIT_REVERSE_6BIT[src] as usize) >> dst_shr_amt; + if src < dst { + arr.swap(src, dst); + } + } +} + +fn reverse_index_bits_in_place_large(arr: &mut Vec, n_power: usize) { + let n = arr.len(); + // LLVM does not know that it does not need to reverse src at each iteration (which is expensive + // on x86). We take advantage of the fact that the low bits of dst change rarely and the high + // bits of dst are dependent only on the low bits of src. + let dst_lo_shr_amt = 64 - (n_power - 6); + let dst_hi_shl_amt = n_power - 6; + for src_chunk in 0..(n >> 6) { + let src_hi = src_chunk << 6; + let dst_lo = src_chunk.reverse_bits() >> dst_lo_shr_amt; + for src_lo in 0..(1 << 6) { + let dst_hi = (BIT_REVERSE_6BIT[src_lo] as usize) << dst_hi_shl_amt; + + let src = src_hi + src_lo; + let dst = dst_hi + dst_lo; + if src < dst { + arr.swap(src, dst); + } + } + } +} + +// Lookup table of 6-bit reverses. +// NB: 2^6=64 bytes is a cacheline. A smaller table wastes cache space. +#[rustfmt::skip] +const BIT_REVERSE_6BIT: &[u8] = &[ + 0o00, 0o40, 0o20, 0o60, 0o10, 0o50, 0o30, 0o70, + 0o04, 0o44, 0o24, 0o64, 0o14, 0o54, 0o34, 0o74, + 0o02, 0o42, 0o22, 0o62, 0o12, 0o52, 0o32, 0o72, + 0o06, 0o46, 0o26, 0o66, 0o16, 0o56, 0o36, 0o76, + 0o01, 0o41, 0o21, 0o61, 0o11, 0o51, 0o31, 0o71, + 0o05, 0o45, 0o25, 0o65, 0o15, 0o55, 0o35, 0o75, + 0o03, 0o43, 0o23, 0o63, 0o13, 0o53, 0o33, 0o73, + 0o07, 0o47, 0o27, 0o67, 0o17, 0o57, 0o37, 0o77, +]; + +#[inline(always)] +pub fn assume(p: bool) { + debug_assert!(p); + if !p { + unsafe { + unreachable_unchecked(); + } + } +} + +/// Try to force Rust to emit a branch. Example: +/// if x > 2 { +/// y = foo(); +/// branch_hint(); +/// } else { +/// y = bar(); +/// } +/// This function has no semantics. It is a hint only. +#[inline(always)] +pub fn branch_hint() { + unsafe { + asm!("", options(nomem, nostack, preserves_flags)); + } +} diff --git a/waksman/Cargo.toml b/waksman/Cargo.toml new file mode 100644 index 00000000..2fe030a9 --- /dev/null +++ b/waksman/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "plonky2_waksman" +description = "A circuit implementation AS-Waksman networks, useful for checking permutations and sorting" +version = "0.1.0" +edition = "2021" + +[dependencies] +"plonky2" = { path = "../plonky2" } +"plonky2_util" = { path = "../util" } +anyhow = "1.0.40" +bimap = "0.6.1" +itertools = "0.10.0" +rand = "0.8.4" diff --git a/src/util/bimap.rs b/waksman/src/bimap.rs similarity index 93% rename from src/util/bimap.rs rename to waksman/src/bimap.rs index 6fb46db7..28359d9f 100644 --- a/src/util/bimap.rs +++ b/waksman/src/bimap.rs @@ -2,7 +2,6 @@ use std::collections::HashMap; use std::hash::Hash; use bimap::BiMap; -use itertools::enumerate; /// Given two lists which are permutations of one another, creates a BiMap which maps an index in /// one list to an index in the other list with the same associated value. @@ -13,7 +12,7 @@ pub fn bimap_from_lists(a: Vec, b: Vec) -> BiMap(a: Vec, b: Vec) -> BiMap(a: Vec, b: Vec) -> BiMap, const D: usize> CircuitBuilder { - /// Assert that two lists of expressions evaluate to permutations of one another. - pub fn assert_permutation(&mut self, a: Vec>, b: Vec>) { - assert_eq!( - a.len(), - b.len(), - "Permutation must have same number of inputs and outputs" - ); - assert_eq!(a[0].len(), b[0].len(), "Chunk size must be the same"); +use crate::bimap::bimap_from_lists; - let chunk_size = a[0].len(); +/// Assert that two lists of expressions evaluate to permutations of one another. +pub fn assert_permutation, const D: usize>( + builder: &mut CircuitBuilder, + a: Vec>, + b: Vec>, +) { + assert_eq!( + a.len(), + b.len(), + "Permutation must have same number of inputs and outputs" + ); + assert_eq!(a[0].len(), b[0].len(), "Chunk size must be the same"); - match a.len() { - // Two empty lists are permutations of one another, trivially. - 0 => (), - // Two singleton lists are permutations of one another as long as their items are equal. - 1 => { - for e in 0..chunk_size { - self.connect(a[0][e], b[0][e]) - } + let chunk_size = a[0].len(); + + match a.len() { + // Two empty lists are permutations of one another, trivially. + 0 => (), + // Two singleton lists are permutations of one another as long as their items are equal. + 1 => { + for e in 0..chunk_size { + builder.connect(a[0][e], b[0][e]) } - 2 => { - self.assert_permutation_2x2(a[0].clone(), a[1].clone(), b[0].clone(), b[1].clone()) - } - // For larger lists, we recursively use two smaller permutation networks. - _ => self.assert_permutation_recursive(a, b), } + 2 => assert_permutation_2x2( + builder, + a[0].clone(), + a[1].clone(), + b[0].clone(), + b[1].clone(), + ), + // For larger lists, we recursively use two smaller permutation networks. + _ => assert_permutation_recursive(builder, a, b), } +} - /// Assert that [a1, a2] is a permutation of [b1, b2]. - fn assert_permutation_2x2( - &mut self, - a1: Vec, - a2: Vec, - b1: Vec, - b2: Vec, - ) { - assert!( - a1.len() == a2.len() && a2.len() == b1.len() && b1.len() == b2.len(), - "Chunk size must be the same" +/// Assert that [a1, a2] is a permutation of [b1, b2]. +fn assert_permutation_2x2, const D: usize>( + builder: &mut CircuitBuilder, + a1: Vec, + a2: Vec, + b1: Vec, + b2: Vec, +) { + assert!( + a1.len() == a2.len() && a2.len() == b1.len() && b1.len() == b2.len(), + "Chunk size must be the same" + ); + + let chunk_size = a1.len(); + + let (_switch, gate_out1, gate_out2) = create_switch(builder, a1, a2); + for e in 0..chunk_size { + builder.connect(b1[e], gate_out1[e]); + builder.connect(b2[e], gate_out2[e]); + } +} + +/// Given two input wire chunks, add a new switch to the circuit (by adding one copy to a switch +/// gate). Returns the wire for the switch boolean, and the two output wire chunks. +fn create_switch, const D: usize>( + builder: &mut CircuitBuilder, + a1: Vec, + a2: Vec, +) -> (Target, Vec, Vec) { + assert_eq!(a1.len(), a2.len(), "Chunk size must be the same"); + + let chunk_size = a1.len(); + + let (gate, gate_index, next_copy) = builder.find_switch_gate(chunk_size); + + let mut c = Vec::new(); + let mut d = Vec::new(); + for e in 0..chunk_size { + builder.connect( + a1[e], + Target::wire(gate_index, gate.wire_first_input(next_copy, e)), ); - - let chunk_size = a1.len(); - - let (_switch, gate_out1, gate_out2) = self.create_switch(a1, a2); - for e in 0..chunk_size { - self.connect(b1[e], gate_out1[e]); - self.connect(b2[e], gate_out2[e]); - } - } - - /// Given two input wire chunks, add a new switch to the circuit (by adding one copy to a switch - /// gate). Returns the wire for the switch boolean, and the two output wire chunks. - fn create_switch( - &mut self, - a1: Vec, - a2: Vec, - ) -> (Target, Vec, Vec) { - assert_eq!(a1.len(), a2.len(), "Chunk size must be the same"); - - let chunk_size = a1.len(); - - let (gate, gate_index, next_copy) = self.find_switch_gate(chunk_size); - - let mut c = Vec::new(); - let mut d = Vec::new(); - for e in 0..chunk_size { - self.connect( - a1[e], - Target::wire(gate_index, gate.wire_first_input(next_copy, e)), - ); - self.connect( - a2[e], - Target::wire(gate_index, gate.wire_second_input(next_copy, e)), - ); - c.push(Target::wire( - gate_index, - gate.wire_first_output(next_copy, e), - )); - d.push(Target::wire( - gate_index, - gate.wire_second_output(next_copy, e), - )); - } - - let switch = Target::wire(gate_index, gate.wire_switch_bool(next_copy)); - - (switch, c, d) - } - - fn assert_permutation_recursive(&mut self, a: Vec>, b: Vec>) { - assert_eq!( - a.len(), - b.len(), - "Permutation must have same number of inputs and outputs" + builder.connect( + a2[e], + Target::wire(gate_index, gate.wire_second_input(next_copy, e)), ); - assert_eq!(a[0].len(), b[0].len(), "Chunk size must be the same"); - - let n = a.len(); - let even = n % 2 == 0; - - let mut child_1_a = Vec::new(); - let mut child_1_b = Vec::new(); - let mut child_2_a = Vec::new(); - let mut child_2_b = Vec::new(); - - // See Figure 8 in the AS-Waksman paper. - let a_num_switches = n / 2; - let b_num_switches = if even { - a_num_switches - 1 - } else { - a_num_switches - }; - - let mut a_switches = Vec::new(); - let mut b_switches = Vec::new(); - for i in 0..a_num_switches { - let (switch, out_1, out_2) = self.create_switch(a[i * 2].clone(), a[i * 2 + 1].clone()); - a_switches.push(switch); - child_1_a.push(out_1); - child_2_a.push(out_2); - } - for i in 0..b_num_switches { - let (switch, out_1, out_2) = self.create_switch(b[i * 2].clone(), b[i * 2 + 1].clone()); - b_switches.push(switch); - child_1_b.push(out_1); - child_2_b.push(out_2); - } - - // See Figure 8 in the AS-Waksman paper. - if even { - child_1_b.push(b[n - 2].clone()); - child_2_b.push(b[n - 1].clone()); - } else { - child_2_a.push(a[n - 1].clone()); - child_2_b.push(b[n - 1].clone()); - } - - self.assert_permutation(child_1_a, child_1_b); - self.assert_permutation(child_2_a, child_2_b); - - self.add_simple_generator(PermutationGenerator:: { - a, - b, - a_switches, - b_switches, - _phantom: PhantomData, - }); + c.push(Target::wire( + gate_index, + gate.wire_first_output(next_copy, e), + )); + d.push(Target::wire( + gate_index, + gate.wire_second_output(next_copy, e), + )); } + + let switch = Target::wire(gate_index, gate.wire_switch_bool(next_copy)); + + (switch, c, d) +} + +fn assert_permutation_recursive, const D: usize>( + builder: &mut CircuitBuilder, + a: Vec>, + b: Vec>, +) { + assert_eq!( + a.len(), + b.len(), + "Permutation must have same number of inputs and outputs" + ); + assert_eq!(a[0].len(), b[0].len(), "Chunk size must be the same"); + + let n = a.len(); + let even = n % 2 == 0; + + let mut child_1_a = Vec::new(); + let mut child_1_b = Vec::new(); + let mut child_2_a = Vec::new(); + let mut child_2_b = Vec::new(); + + // See Figure 8 in the AS-Waksman paper. + let a_num_switches = n / 2; + let b_num_switches = if even { + a_num_switches - 1 + } else { + a_num_switches + }; + + let mut a_switches = Vec::new(); + let mut b_switches = Vec::new(); + for i in 0..a_num_switches { + let (switch, out_1, out_2) = create_switch(builder, a[i * 2].clone(), a[i * 2 + 1].clone()); + a_switches.push(switch); + child_1_a.push(out_1); + child_2_a.push(out_2); + } + for i in 0..b_num_switches { + let (switch, out_1, out_2) = create_switch(builder, b[i * 2].clone(), b[i * 2 + 1].clone()); + b_switches.push(switch); + child_1_b.push(out_1); + child_2_b.push(out_2); + } + + // See Figure 8 in the AS-Waksman paper. + if even { + child_1_b.push(b[n - 2].clone()); + child_2_b.push(b[n - 1].clone()); + } else { + child_2_a.push(a[n - 1].clone()); + child_2_b.push(b[n - 1].clone()); + } + + assert_permutation(builder, child_1_a, child_1_b); + assert_permutation(builder, child_2_a, child_2_b); + + builder.add_simple_generator(PermutationGenerator:: { + a, + b, + a_switches, + b_switches, + _phantom: PhantomData, + }); } fn route( @@ -359,14 +371,13 @@ impl SimpleGenerator for PermutationGenerator { #[cfg(test)] mod tests { use anyhow::Result; + use plonky2::field::field_types::Field; + use plonky2::iop::witness::PartialWitness; + use plonky2::plonk::circuit_data::CircuitConfig; + use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; use rand::{seq::SliceRandom, thread_rng, Rng}; use super::*; - use crate::field::field_types::Field; - use crate::iop::witness::PartialWitness; - use crate::plonk::circuit_data::CircuitConfig; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - use crate::plonk::verifier::verify; fn test_permutation_good(size: usize) -> Result<()> { const D: usize = 2; @@ -386,12 +397,12 @@ mod tests { let mut b = a.clone(); b.shuffle(&mut thread_rng()); - builder.assert_permutation(a, b); + assert_permutation(&mut builder, a, b); let data = builder.build::(); let proof = data.prove(pw)?; - verify(proof, &data.verifier_only, &data.common) + data.verify(proof) } fn test_permutation_duplicates(size: usize) -> Result<()> { @@ -416,12 +427,12 @@ mod tests { let mut b = a.clone(); b.shuffle(&mut thread_rng()); - builder.assert_permutation(a, b); + assert_permutation(&mut builder, a, b); let data = builder.build::(); let proof = data.prove(pw)?; - verify(proof, &data.verifier_only, &data.common) + data.verify(proof) } fn test_permutation_bad(size: usize) -> Result<()> { @@ -445,7 +456,7 @@ mod tests { .map(|pair| vec![builder.constant(pair[0]), builder.constant(pair[1])]) .collect(); - builder.assert_permutation(a, b); + assert_permutation(&mut builder, a, b); let data = builder.build::(); data.prove(pw)?; diff --git a/src/gadgets/sorting.rs b/waksman/src/sorting.rs similarity index 53% rename from src/gadgets/sorting.rs rename to waksman/src/sorting.rs index 46cfc5b4..b3e616d5 100644 --- a/src/gadgets/sorting.rs +++ b/waksman/src/sorting.rs @@ -1,15 +1,17 @@ use std::marker::PhantomData; use itertools::izip; +use plonky2::field::extension_field::Extendable; +use plonky2::field::field_types::Field; +use plonky2::gates::assert_le::AssertLessThanGate; +use plonky2::hash::hash_types::RichField; +use plonky2::iop::generator::{GeneratedValues, SimpleGenerator}; +use plonky2::iop::target::{BoolTarget, Target}; +use plonky2::iop::witness::{PartitionWitness, Witness}; +use plonky2::plonk::circuit_builder::CircuitBuilder; +use plonky2_util::ceil_div_usize; -use crate::field::extension_field::Extendable; -use crate::field::field_types::Field; -use crate::gates::assert_le::AssertLessThanGate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator}; -use crate::iop::target::{BoolTarget, Target}; -use crate::iop::witness::{PartitionWitness, Witness}; -use crate::plonk::circuit_builder::CircuitBuilder; -use crate::util::ceil_div_usize; +use crate::permutation::assert_permutation; pub struct MemoryOp { is_write: bool, @@ -26,103 +28,114 @@ pub struct MemoryOpTarget { value: Target, } -impl, const D: usize> CircuitBuilder { - pub fn assert_permutation_memory_ops(&mut self, a: &[MemoryOpTarget], b: &[MemoryOpTarget]) { - let a_chunks: Vec> = a - .iter() - .map(|op| vec![op.address, op.timestamp, op.is_write.target, op.value]) - .collect(); - let b_chunks: Vec> = b - .iter() - .map(|op| vec![op.address, op.timestamp, op.is_write.target, op.value]) - .collect(); - - self.assert_permutation(a_chunks, b_chunks); - } - - /// Add an AssertLessThanGate to assert that `lhs` is less than `rhs`, where their values are at most `bits` bits. - pub fn assert_le(&mut self, lhs: Target, rhs: Target, bits: usize, num_chunks: usize) { - let gate = AssertLessThanGate::new(bits, num_chunks); - let gate_index = self.add_gate(gate.clone(), vec![]); - - self.connect(Target::wire(gate_index, gate.wire_first_input()), lhs); - self.connect(Target::wire(gate_index, gate.wire_second_input()), rhs); - } - - /// Sort memory operations by address value, then by timestamp value. - /// This is done by combining address and timestamp into one field element (using their given bit lengths). - pub fn sort_memory_ops( - &mut self, - ops: &[MemoryOpTarget], - address_bits: usize, - timestamp_bits: usize, - ) -> Vec { - let n = ops.len(); - - let combined_bits = address_bits + timestamp_bits; - let chunk_bits = 3; - let num_chunks = ceil_div_usize(combined_bits, chunk_bits); - - // This is safe because `assert_permutation` will force these targets (in the output list) to match the boolean values from the input list. - let is_write_targets: Vec<_> = self - .add_virtual_targets(n) - .iter() - .map(|&t| BoolTarget::new_unsafe(t)) - .collect(); - - let address_targets = self.add_virtual_targets(n); - let timestamp_targets = self.add_virtual_targets(n); - let value_targets = self.add_virtual_targets(n); - - let output_targets: Vec<_> = izip!( - is_write_targets, - address_targets, - timestamp_targets, - value_targets - ) - .map(|(i, a, t, v)| MemoryOpTarget { - is_write: i, - address: a, - timestamp: t, - value: v, - }) +pub fn assert_permutation_memory_ops, const D: usize>( + builder: &mut CircuitBuilder, + a: &[MemoryOpTarget], + b: &[MemoryOpTarget], +) { + let a_chunks: Vec> = a + .iter() + .map(|op| vec![op.address, op.timestamp, op.is_write.target, op.value]) + .collect(); + let b_chunks: Vec> = b + .iter() + .map(|op| vec![op.address, op.timestamp, op.is_write.target, op.value]) .collect(); - let two_n = self.constant(F::from_canonical_usize(1 << timestamp_bits)); - let address_timestamp_combined: Vec<_> = output_targets - .iter() - .map(|op| self.mul_add(op.address, two_n, op.timestamp)) - .collect(); + assert_permutation(builder, a_chunks, b_chunks); +} - for i in 1..n { - self.assert_le( - address_timestamp_combined[i - 1], - address_timestamp_combined[i], - combined_bits, - num_chunks, - ); - } +/// Add an AssertLessThanGate to assert that `lhs` is less than `rhs`, where their values are at most `bits` bits. +pub fn assert_le, const D: usize>( + builder: &mut CircuitBuilder, + lhs: Target, + rhs: Target, + bits: usize, + num_chunks: usize, +) { + let gate = AssertLessThanGate::new(bits, num_chunks); + let gate_index = builder.add_gate(gate.clone(), vec![]); - self.assert_permutation_memory_ops(ops, &output_targets); + builder.connect(Target::wire(gate_index, gate.wire_first_input()), lhs); + builder.connect(Target::wire(gate_index, gate.wire_second_input()), rhs); +} - self.add_simple_generator(MemoryOpSortGenerator:: { - input_ops: ops.to_vec(), - output_ops: output_targets.clone(), - _phantom: PhantomData, - }); +/// Sort memory operations by address value, then by timestamp value. +/// This is done by combining address and timestamp into one field element (using their given bit lengths). +pub fn sort_memory_ops, const D: usize>( + builder: &mut CircuitBuilder, + ops: &[MemoryOpTarget], + address_bits: usize, + timestamp_bits: usize, +) -> Vec { + let n = ops.len(); - output_targets + let combined_bits = address_bits + timestamp_bits; + let chunk_bits = 3; + let num_chunks = ceil_div_usize(combined_bits, chunk_bits); + + // This is safe because `assert_permutation` will force these targets (in the output list) to match the boolean values from the input list. + let is_write_targets: Vec<_> = builder + .add_virtual_targets(n) + .iter() + .map(|&t| BoolTarget::new_unsafe(t)) + .collect(); + + let address_targets = builder.add_virtual_targets(n); + let timestamp_targets = builder.add_virtual_targets(n); + let value_targets = builder.add_virtual_targets(n); + + let output_targets: Vec<_> = izip!( + is_write_targets, + address_targets, + timestamp_targets, + value_targets + ) + .map(|(i, a, t, v)| MemoryOpTarget { + is_write: i, + address: a, + timestamp: t, + value: v, + }) + .collect(); + + let two_n = builder.constant(F::from_canonical_usize(1 << timestamp_bits)); + let address_timestamp_combined: Vec<_> = output_targets + .iter() + .map(|op| builder.mul_add(op.address, two_n, op.timestamp)) + .collect(); + + for i in 1..n { + assert_le( + builder, + address_timestamp_combined[i - 1], + address_timestamp_combined[i], + combined_bits, + num_chunks, + ); } + + assert_permutation_memory_ops(builder, ops, &output_targets); + + builder.add_simple_generator(MemoryOpSortGenerator:: { + input_ops: ops.to_vec(), + output_ops: output_targets.clone(), + _phantom: PhantomData, + }); + + output_targets } #[derive(Debug)] -struct MemoryOpSortGenerator, const D: usize> { +struct MemoryOpSortGenerator, const D: usize> { input_ops: Vec, output_ops: Vec, _phantom: PhantomData, } -impl, const D: usize> SimpleGenerator for MemoryOpSortGenerator { +impl, const D: usize> SimpleGenerator + for MemoryOpSortGenerator +{ fn dependencies(&self) -> Vec { self.input_ops .iter() @@ -170,14 +183,13 @@ impl, const D: usize> SimpleGenerator for MemoryOpSortGenera #[cfg(test)] mod tests { use anyhow::Result; + use plonky2::field::field_types::{Field, PrimeField}; + use plonky2::iop::witness::PartialWitness; + use plonky2::plonk::circuit_data::CircuitConfig; + use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; use rand::{thread_rng, Rng}; use super::*; - use crate::field::field_types::{Field, PrimeField}; - use crate::iop::witness::PartialWitness; - use crate::plonk::circuit_data::CircuitConfig; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - use crate::plonk::verifier::verify; fn test_sorting(size: usize, address_bits: usize, timestamp_bits: usize) -> Result<()> { const D: usize = 2; @@ -225,8 +237,12 @@ mod tests { input_ops_and_keys.sort_by_key(|(_, val)| *val); let input_ops_sorted: Vec<_> = input_ops_and_keys.iter().map(|(x, _)| x).collect(); - let output_ops = - builder.sort_memory_ops(input_ops.as_slice(), address_bits, timestamp_bits); + let output_ops = sort_memory_ops( + &mut builder, + input_ops.as_slice(), + address_bits, + timestamp_bits, + ); for i in 0..size { pw.set_bool_target(output_ops[i].is_write, input_ops_sorted[i].0); @@ -238,7 +254,7 @@ mod tests { let data = builder.build::(); let proof = data.prove(pw).unwrap(); - verify(proof, &data.verifier_only, &data.common) + data.verify(proof) } #[test]