Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: changes for recursive verifier #26

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 31 additions & 8 deletions air/src/virtual_column.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::borrow::Cow;
use alloc::vec;
use alloc::vec::Vec;
use core::ops::Mul;
Expand All @@ -6,8 +7,8 @@ use p3_field::{AbstractField, Field};

/// An affine function over columns in a PAIR.
#[derive(Clone, Debug)]
pub struct VirtualPairCol<F: Field> {
column_weights: Vec<(PairCol, F)>,
pub struct VirtualPairCol<'a, F: Field> {
column_weights: Cow<'a, [(PairCol, F)]>,
constant: F,
}

Expand All @@ -19,22 +20,36 @@ pub enum PairCol {
}

impl PairCol {
fn get<T: Copy>(&self, preprocessed: &[T], main: &[T]) -> T {
pub const fn get<T: Copy>(&self, preprocessed: &[T], main: &[T]) -> T {
match self {
PairCol::Preprocessed(i) => preprocessed[*i],
PairCol::Main(i) => main[*i],
}
}
}

impl<F: Field> VirtualPairCol<F> {
pub fn new(column_weights: Vec<(PairCol, F)>, constant: F) -> Self {
impl<'a, F: Field> VirtualPairCol<'a, F> {
pub const fn new(column_weights: Cow<'a, [(PairCol, F)]>, constant: F) -> Self {
Self {
column_weights,
constant,
}
}

pub const fn new_owned(column_weights: Vec<(PairCol, F)>, constant: F) -> Self {
Self {
column_weights: Cow::Owned(column_weights),
constant,
}
}

pub const fn new_borrowed(column_weights: &'a [(PairCol, F)], constant: F) -> Self {
Self {
column_weights: Cow::Borrowed(column_weights),
constant,
}
}

pub fn new_preprocessed(column_weights: Vec<(usize, F)>, constant: F) -> Self {
Self::new(
column_weights
Expand All @@ -55,6 +70,14 @@ impl<F: Field> VirtualPairCol<F> {
)
}

pub fn get_column_weights(&self) -> &[(PairCol, F)] {
&self.column_weights
}

pub const fn get_constant(&self) -> F {
self.constant
}

#[must_use]
pub fn one() -> Self {
Self::constant(F::one())
Expand All @@ -63,15 +86,15 @@ impl<F: Field> VirtualPairCol<F> {
#[must_use]
pub fn constant(x: F) -> Self {
Self {
column_weights: vec![],
column_weights: Cow::Owned(vec![]),
constant: x,
}
}

#[must_use]
pub fn single(column: PairCol) -> Self {
Self {
column_weights: vec![(column, F::one())],
column_weights: Cow::Owned(vec![(column, F::one())]),
constant: F::zero(),
}
}
Expand Down Expand Up @@ -117,7 +140,7 @@ impl<F: Field> VirtualPairCol<F> {
Var: Into<Expr> + Copy,
{
let mut result = self.constant.into();
for (column, weight) in &self.column_weights {
for (column, weight) in self.column_weights.iter() {
result += column.get(preprocessed, main).into() * *weight;
}
result
Expand Down
13 changes: 10 additions & 3 deletions baby-bear/src/baby_bear.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign};

use p3_field::{
exp_1725656503, exp_u64_by_squaring, AbstractField, Field, Packable, PrimeField, PrimeField32,
PrimeField64, TwoAdicField,
exp_1725656503, exp_u64_by_squaring, halve_u32, AbstractField, Field, Packable, PrimeField,
PrimeField32, PrimeField64, TwoAdicField,
};
use rand::distributions::{Distribution, Standard};
use rand::Rng;
Expand Down Expand Up @@ -45,7 +45,7 @@ pub struct BabyBear {
impl BabyBear {
/// create a new `BabyBear` from a canonical `u32`.
#[inline]
pub(crate) const fn new(n: u32) -> Self {
pub const fn new(n: u32) -> Self {
Self { value: to_monty(n) }
}
}
Expand Down Expand Up @@ -238,6 +238,13 @@ impl Field for BabyBear {

Some(p1110111111111111111111111111111)
}

#[inline]
fn halve(&self) -> Self {
BabyBear {
value: halve_u32::<P>(self.value),
}
}
}

impl PrimeField for BabyBear {}
Expand Down
2 changes: 1 addition & 1 deletion commit/src/adapters/extension_mmcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub struct ExtensionMmcs<F, EF, InnerMmcs> {
}

impl<F, EF, InnerMmcs> ExtensionMmcs<F, EF, InnerMmcs> {
pub fn new(inner: InnerMmcs) -> Self {
pub const fn new(inner: InnerMmcs) -> Self {
Self {
inner,
_phantom: PhantomData,
Expand Down
1 change: 1 addition & 0 deletions field-testing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ where
assert_eq!(x + (-x), F::zero());
assert_eq!(-x, F::zero() - x);
assert_eq!(x + x, x * F::two());
assert_eq!(x, x.halve() * F::two());
assert_eq!(x * (-x), -x.square());
assert_eq!(x + y, y + x);
assert_eq!(x * y, y * x);
Expand Down
6 changes: 6 additions & 0 deletions field/src/extension/binomial_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,12 @@ impl<F: BinomiallyExtendable<D>, const D: usize> Field for BinomialExtensionFiel
_ => Some(self.frobenius_inv()),
}
}

fn halve(&self) -> Self {
Self {
value: self.value.map(|x| x.halve()),
}
}
}

impl<F, const D: usize> Display for BinomialExtensionField<F, D>
Expand Down
11 changes: 11 additions & 0 deletions field/src/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,17 @@ pub trait Field:
fn inverse(&self) -> Self {
self.try_inverse().expect("Tried to invert zero")
}

/// Computes input/2.
/// Should be overwritten by most field implementations to use bitshifts.
/// Will error if the field characteristic is 2.
#[must_use]
fn halve(&self) -> Self {
let half = Self::two()
.try_inverse()
.expect("Cannot divide by 2 in fields with characteristic 2");
*self * half
}
}

pub trait PrimeField: Field + Ord {}
Expand Down
28 changes: 28 additions & 0 deletions field/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,31 @@ pub fn eval_poly<AF: AbstractField>(poly: &[AF], x: AF) -> AF {
}
acc
}

/// Given an element x from a 32 bit field F_P compute x/2.
#[inline]
pub fn halve_u32<const P: u32>(input: u32) -> u32 {
let shift = (P + 1) >> 1;
let shr = input >> 1;
let lo_bit = input & 1;
let shr_corr = shr + shift;
if lo_bit == 0 {
shr
} else {
shr_corr
}
}

/// Given an element x from a 64 bit field F_P compute x/2.
#[inline]
pub fn halve_u64<const P: u64>(input: u64) -> u64 {
let shift = (P + 1) >> 1;
let shr = input >> 1;
let lo_bit = input & 1;
let shr_corr = shr + shift;
if lo_bit == 0 {
shr
} else {
shr_corr
}
}
2 changes: 1 addition & 1 deletion fri/src/two_adic_pcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pub struct TwoAdicFriPcs<C: TwoAdicFriPcsGenericConfig> {
}

impl<C: TwoAdicFriPcsGenericConfig> TwoAdicFriPcs<C> {
pub fn new(fri: FriConfig<C::FriMmcs>, dft: C::Dft, mmcs: C::InputMmcs) -> Self {
pub const fn new(fri: FriConfig<C::FriMmcs>, dft: C::Dft, mmcs: C::InputMmcs) -> Self {
Self { fri, dft, mmcs }
}
}
Expand Down
14 changes: 11 additions & 3 deletions goldilocks/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign};

use p3_field::{
exp_10540996611094048183, exp_u64_by_squaring, AbstractField, Field, Packable, PrimeField,
PrimeField64, TwoAdicField,
exp_10540996611094048183, exp_u64_by_squaring, halve_u64, AbstractField, Field, Packable,
PrimeField, PrimeField64, TwoAdicField,
};
use p3_util::{assume, branch_hint};
use rand::distributions::{Distribution, Standard};
use rand::Rng;
use serde::{Deserialize, Serialize};

/// The Goldilocks prime
const P: u64 = 0xFFFF_FFFF_0000_0001;

/// The prime field known as Goldilocks, defined as `F_p` where `p = 2^64 - 2^32 + 1`.
#[derive(Copy, Clone, Default, Serialize, Deserialize)]
pub struct Goldilocks {
Expand Down Expand Up @@ -210,12 +213,17 @@ impl Field for Goldilocks {
// compute base^1111111111111111111111111111111011111111111111111111111111111111
Some(t63.square() * *self)
}

#[inline]
fn halve(&self) -> Self {
Goldilocks::new(halve_u64::<P>(self.value))
}
}

impl PrimeField for Goldilocks {}

impl PrimeField64 for Goldilocks {
const ORDER_U64: u64 = 0xFFFF_FFFF_0000_0001;
const ORDER_U64: u64 = P;

#[inline]
fn as_canonical_u64(&self) -> u64 {
Expand Down
4 changes: 4 additions & 0 deletions keccak-air/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ p3-keccak = { path = "../keccak" }
p3-maybe-rayon = { path = "../maybe-rayon" }
p3-mds = { path = "../mds" }
p3-merkle-tree = { path = "../merkle-tree" }
p3-poseidon = {path = "../poseidon"}
p3-poseidon2 = { path = "../poseidon2" }
p3-symmetric = { path = "../symmetric" }
p3-uni-stark = { path = "../uni-stark" }
Expand All @@ -38,6 +39,9 @@ name = "prove_baby_bear_poseidon2"
[[example]]
name = "prove_goldilocks_keccak"

[[example]]
name = "prove_goldilocks_poseidon"

[features]
# TODO: Consider removing, at least when this gets split off into another repository.
# We should be able to enable p3-maybe-rayon/parallel directly; this just doesn't
Expand Down
83 changes: 83 additions & 0 deletions keccak-air/examples/prove_goldilocks_poseidon.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use p3_challenger::DuplexChallenger;
use p3_commit::ExtensionMmcs;
use p3_dft::Radix2DitParallel;
use p3_field::extension::BinomialExtensionField;
use p3_field::Field;
use p3_fri::{FriConfig, TwoAdicFriPcs, TwoAdicFriPcsConfig};
use p3_goldilocks::Goldilocks;
use p3_keccak_air::{generate_trace_rows, KeccakAir};
use p3_mds::goldilocks::MdsMatrixGoldilocks;
use p3_merkle_tree::FieldMerkleTreeMmcs;
use p3_poseidon::Poseidon;
use p3_symmetric::{PaddingFreeSponge, TruncatedPermutation};
use p3_uni_stark::{prove, verify, StarkConfig, VerificationError};
use rand::{random, thread_rng};
use tracing_forest::util::LevelFilter;
use tracing_forest::ForestLayer;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{EnvFilter, Registry};

const NUM_HASHES: usize = 680;

fn main() -> Result<(), VerificationError> {
let env_filter = EnvFilter::builder()
.with_default_directive(LevelFilter::INFO.into())
.from_env_lossy();

Registry::default()
.with(env_filter)
.with(ForestLayer::default())
.init();

type Val = Goldilocks;
type Challenge = BinomialExtensionField<Val, 2>;

type Perm = Poseidon<Val, MdsMatrixGoldilocks, 8, 7>;
let perm = Perm::new_from_rng(4, 22, MdsMatrixGoldilocks, &mut thread_rng());

type MyHash = PaddingFreeSponge<Perm, 8, 4, 4>;
let hash = MyHash::new(perm.clone());

type MyCompress = TruncatedPermutation<Perm, 2, 4, 8>;
let compress = MyCompress::new(perm.clone());

type ValMmcs = FieldMerkleTreeMmcs<
<Val as Field>::Packing,
<Val as Field>::Packing,
MyHash,
MyCompress,
4,
>;
let val_mmcs = ValMmcs::new(hash, compress);

type ChallengeMmcs = ExtensionMmcs<Val, Challenge, ValMmcs>;
let challenge_mmcs = ChallengeMmcs::new(val_mmcs.clone());

type Dft = Radix2DitParallel;
let dft = Dft {};

type Challenger = DuplexChallenger<Val, Perm, 8>;

let fri_config = FriConfig {
log_blowup: 1,
num_queries: 100,
proof_of_work_bits: 16,
mmcs: challenge_mmcs,
};
type Pcs =
TwoAdicFriPcs<TwoAdicFriPcsConfig<Val, Challenge, Challenger, Dft, ValMmcs, ChallengeMmcs>>;
let pcs = Pcs::new(fri_config, dft, val_mmcs);

type MyConfig = StarkConfig<Val, Challenge, Pcs, Challenger>;
let config = StarkConfig::new(pcs);

let mut challenger = Challenger::new(perm.clone());

let inputs = (0..NUM_HASHES).map(|_| random()).collect::<Vec<_>>();
let trace = generate_trace_rows::<Val>(inputs);
let proof = prove::<MyConfig, _>(&config, &KeccakAir {}, &mut challenger, trace);

let mut challenger = Challenger::new(perm);
verify(&config, &KeccakAir {}, &mut challenger, &proof)
}
2 changes: 1 addition & 1 deletion merkle-tree/src/mmcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub struct FieldMerkleTreeMmcs<P, PW, H, C, const DIGEST_ELEMS: usize> {
}

impl<P, PW, H, C, const DIGEST_ELEMS: usize> FieldMerkleTreeMmcs<P, PW, H, C, DIGEST_ELEMS> {
pub fn new(hash: H, compress: C) -> Self {
pub const fn new(hash: H, compress: C) -> Self {
Self {
hash,
compress,
Expand Down
Loading
Loading