Skip to content

Commit

Permalink
feat: dsl derive macro + fri pow witness verify (succinctlabs#422)
Browse files Browse the repository at this point in the history
Co-authored-by: John Guibas <[email protected]>
  • Loading branch information
jtguibas and John Guibas authored Mar 22, 2024
1 parent 22587eb commit e91c38c
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 196 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
// // Eval.
// "eval/Cargo.toml"
],
"rust-analyzer.showUnlinkedFileNotification": false,
// "rust-analyzer.showUnlinkedFileNotification": false,
// "rust-analyzer.check.workspace": false,
// "rust-analyzer.check.invocationStrategy": "once",
Expand Down
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions recursion/compiler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ sp1-recursion-core = { path = "../core" }
sp1-core = { path = "../../core" }
itertools = "0.12.1"
serde = { version = "1.0.197", features = ["derive"] }
sp1-recursion-derive = { path = "../derive" }

[dev-dependencies]
p3-baby-bear = { workspace = true }
Expand Down
14 changes: 14 additions & 0 deletions recursion/compiler/src/verifier/challenger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,18 @@ impl<C: Config> DuplexChallenger<C> {
});
sum
}

/// Reference: https://github.com/Plonky3/Plonky3/blob/4809fa7bedd9ba8f6f5d3267b1592618e3776c57/challenger/src/grinding_challenger.rs#L16
pub fn check_witness(
&mut self,
builder: &mut Builder<C>,
nb_bits: Var<C::N>,
witness: Felt<C::F>,
) {
self.observe(builder, witness);
let element = self.sample_bits(builder, Usize::Var(nb_bits));
builder
.if_eq(element, C::N::one())
.then(|builder| builder.error());
}
}
14 changes: 4 additions & 10 deletions recursion/compiler/src/verifier/fri/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,15 @@ pub fn verify_shape_and_sample_challenges<C: Config>(
});

let num_commit_phase_commits = proof.commit_phase_commits.len().materialize(builder);
let num_queries = config.num_queries.materialize(builder);
builder
.if_ne(num_commit_phase_commits, num_queries)
.if_ne(num_commit_phase_commits, config.num_queries)
.then(|builder| {
builder.error();
});

// TODO: Check PoW.
// if !challenger.check_witness(config.proof_of_work_bits, proof.pow_witness) {
// return Err(FriError::InvalidPowWitness);
// }
challenger.check_witness(builder, config.proof_of_work_bits, proof.pow_witness);

let log_blowup = config.log_blowup.materialize(builder);
let log_max_height: Var<_> = builder.eval(num_commit_phase_commits + log_blowup);
let log_max_height: Var<_> = builder.eval(num_commit_phase_commits + config.log_blowup);
let mut query_indices = builder.array(config.num_queries);
builder.range(0, config.num_queries).for_each(|i, builder| {
let index = challenger.sample_bits(builder, Usize::Var(log_max_height));
Expand Down Expand Up @@ -80,8 +75,7 @@ pub fn verify_challenges<C: Config>(
C::EF: TwoAdicField,
{
let nb_commit_phase_commits = proof.commit_phase_commits.len().materialize(builder);
let log_blowup = config.log_blowup.materialize(builder);
let log_max_height = builder.eval(nb_commit_phase_commits + log_blowup);
let log_max_height = builder.eval(nb_commit_phase_commits + config.log_blowup);
builder
.range(0, challenges.query_indices.len())
.for_each(|i, builder| {
Expand Down
7 changes: 3 additions & 4 deletions recursion/compiler/src/verifier/fri/pcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ pub fn verify_two_adic_pcs<C: Config>(
verify_shape_and_sample_challenges(builder, config, &proof.fri_proof, challenger);

let commit_phase_commits_len = builder.materialize(proof.fri_proof.commit_phase_commits.len());
let log_blowup = config.log_blowup.materialize(builder);
let log_max_height: Var<_> = builder.eval(commit_phase_commits_len + log_blowup);
let log_max_height: Var<_> = builder.eval(commit_phase_commits_len + config.log_blowup);

let mut reduced_openings: Array<C, Array<C, Ext<C::F, C::EF>>> =
builder.array(proof.query_openings.len());
Expand Down Expand Up @@ -110,8 +109,8 @@ pub fn verify_two_adic_pcs<C: Config>(
let mat_values = mat.values;

let log2_domain_size = builder.log2(mat_domain);
let log_height = log2_domain_size + config.log_blowup.materialize(builder);
let log_height: Var<C::N> = builder.eval(log_height);
let log_height: Var<C::N> =
builder.eval(log2_domain_size + config.log_blowup);

let bits_reduced: Var<C::N> = builder.eval(log_max_height - log_height);
let rev_reduced_index =
Expand Down
193 changes: 11 additions & 182 deletions recursion/compiler/src/verifier/fri/types.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::marker::PhantomData;
use sp1_recursion_derive::DslVariable;

use crate::prelude::{Array, Builder, Config, Felt, MemVariable, Ptr, Usize, Var, Variable};

Expand All @@ -13,215 +13,44 @@ pub const DIGEST_SIZE: usize = 8;
pub type Commitment<C: Config> = Array<C, Felt<C::F>>;

/// Reference: https://github.com/Plonky3/Plonky3/blob/4809fa7bedd9ba8f6f5d3267b1592618e3776c57/fri/src/config.rs#L1
#[derive(DslVariable, Clone)]
pub struct FriConfig<C: Config> {
pub log_blowup: Usize<C::N>,
pub num_queries: Usize<C::N>,
pub proof_of_work_bits: Usize<C::N>,
pub log_blowup: Var<C::N>,
pub num_queries: Var<C::N>,
pub proof_of_work_bits: Var<C::N>,
}

/// Reference: https://github.com/Plonky3/Plonky3/blob/4809fa7bedd9ba8f6f5d3267b1592618e3776c57/fri/src/proof.rs#L12
#[derive(DslVariable, Clone)]
pub struct FriProof<C: Config> {
pub commit_phase_commits: Array<C, Commitment<C>>,
pub query_proofs: Array<C, FriQueryProof<C>>,
pub final_poly: Felt<C::F>,
pub pow_witness: Var<C::N>,
pub pow_witness: Felt<C::F>,
}

/// Reference: https://github.com/Plonky3/Plonky3/blob/4809fa7bedd9ba8f6f5d3267b1592618e3776c57/fri/src/proof.rs#L23
#[derive(Clone)]
#[derive(DslVariable, Clone)]
pub struct FriQueryProof<C: Config> {
pub commit_phase_openings: Array<C, FriCommitPhaseProofStep<C>>,
pub phantom: PhantomData<C>,
}

/// Reference: https://github.com/Plonky3/Plonky3/blob/4809fa7bedd9ba8f6f5d3267b1592618e3776c57/fri/src/proof.rs#L32
#[derive(Clone)]
#[derive(DslVariable, Clone)]
pub struct FriCommitPhaseProofStep<C: Config> {
pub sibling_value: Felt<C::F>,
pub opening_proof: Array<C, Commitment<C>>,
pub phantom: PhantomData<C>,
}

/// Reference: https://github.com/Plonky3/Plonky3/blob/4809fa7bedd9ba8f6f5d3267b1592618e3776c57/fri/src/verifier.rs#L22
#[derive(DslVariable, Clone)]
pub struct FriChallenges<C: Config> {
pub query_indices: Array<C, Var<C::N>>,
pub betas: Array<C, Felt<C::F>>,
}

/// Reference: https://github.com/Plonky3/Plonky3/blob/4809fa7bedd9ba8f6f5d3267b1592618e3776c57/matrix/src/lib.rs#L38
#[derive(Clone)]
#[derive(DslVariable, Clone)]
pub struct Dimensions<C: Config> {
pub height: Var<C::N>,
}

impl<C: Config> Variable<C> for Dimensions<C> {
type Expression = Self;

fn uninit(builder: &mut Builder<C>) -> Self {
Dimensions {
height: builder.uninit(),
}
}

fn assign(&self, src: Self::Expression, builder: &mut Builder<C>) {
self.height.assign(src.height.into(), builder);
}

fn assert_eq(
lhs: impl Into<Self::Expression>,
rhs: impl Into<Self::Expression>,
builder: &mut Builder<C>,
) {
let lhs = lhs.into();
let rhs = rhs.into();
Var::<C::N>::assert_eq(lhs.height, rhs.height, builder);
}

fn assert_ne(
lhs: impl Into<Self::Expression>,
rhs: impl Into<Self::Expression>,
builder: &mut Builder<C>,
) {
let lhs = lhs.into();
let rhs = rhs.into();
Var::<C::N>::assert_ne(lhs.height, rhs.height, builder);
}
}

impl<C: Config> MemVariable<C> for Dimensions<C> {
fn size_of() -> usize {
1
}

fn load(&self, ptr: Ptr<<C as Config>::N>, builder: &mut Builder<C>) {
let address = builder.eval(ptr + Usize::Const(0));
self.height.load(address, builder);
}

fn store(&self, ptr: Ptr<<C as Config>::N>, builder: &mut Builder<C>) {
let address = builder.eval(ptr + Usize::Const(0));
self.height.store(address, builder);
}
}

impl<C: Config> Variable<C> for FriQueryProof<C> {
type Expression = Self;

fn uninit(builder: &mut Builder<C>) -> Self {
FriQueryProof {
commit_phase_openings: Array::Dyn(builder.uninit(), builder.uninit()),
phantom: PhantomData,
}
}

fn assign(&self, src: Self::Expression, builder: &mut Builder<C>) {
self.commit_phase_openings
.assign(src.commit_phase_openings, builder);
}

fn assert_eq(
lhs: impl Into<Self::Expression>,
rhs: impl Into<Self::Expression>,
builder: &mut Builder<C>,
) {
let lhs = lhs.into();
let rhs = rhs.into();
Array::<C, FriCommitPhaseProofStep<C>>::assert_eq(
lhs.commit_phase_openings,
rhs.commit_phase_openings,
builder,
);
}

fn assert_ne(
lhs: impl Into<Self::Expression>,
rhs: impl Into<Self::Expression>,
builder: &mut Builder<C>,
) {
let lhs = lhs.into();
let rhs = rhs.into();
Array::<C, FriCommitPhaseProofStep<C>>::assert_ne(
lhs.commit_phase_openings,
rhs.commit_phase_openings,
builder,
);
}
}

impl<C: Config> MemVariable<C> for FriQueryProof<C> {
fn size_of() -> usize {
1
}

fn load(&self, ptr: Ptr<C::N>, builder: &mut Builder<C>) {
let address = builder.eval(ptr + Usize::Const(0));
self.commit_phase_openings.load(address, builder);
}

fn store(&self, ptr: Ptr<<C as Config>::N>, builder: &mut Builder<C>) {
let address = builder.eval(ptr + Usize::Const(0));
self.commit_phase_openings.store(address, builder);
}
}

impl<C: Config> Variable<C> for FriCommitPhaseProofStep<C> {
type Expression = Self;

fn uninit(builder: &mut Builder<C>) -> Self {
Self {
sibling_value: builder.uninit(),
opening_proof: Array::Dyn(builder.uninit(), builder.uninit()),
phantom: PhantomData,
}
}

fn assign(&self, src: Self::Expression, builder: &mut Builder<C>) {
self.sibling_value.assign(src.sibling_value.into(), builder);
self.opening_proof.assign(src.opening_proof, builder);
}

fn assert_eq(
lhs: impl Into<Self::Expression>,
rhs: impl Into<Self::Expression>,
builder: &mut Builder<C>,
) {
let lhs = lhs.into();
let rhs = rhs.into();
Felt::<C::F>::assert_eq(lhs.sibling_value, rhs.sibling_value, builder);
Array::<C, Commitment<C>>::assert_eq(lhs.opening_proof, rhs.opening_proof, builder);
}

fn assert_ne(
lhs: impl Into<Self::Expression>,
rhs: impl Into<Self::Expression>,
builder: &mut Builder<C>,
) {
let lhs = lhs.into();
let rhs = rhs.into();
Felt::<C::F>::assert_ne(lhs.sibling_value, rhs.sibling_value, builder);
Array::<C, Commitment<C>>::assert_ne(lhs.opening_proof, rhs.opening_proof, builder);
}
}

impl<C: Config> MemVariable<C> for FriCommitPhaseProofStep<C> {
fn size_of() -> usize {
let mut size = 0;
size += <Felt<C::F> as MemVariable<C>>::size_of();
size += Array::<C, Commitment<C>>::size_of();
size
}

fn load(&self, ptr: Ptr<<C as Config>::N>, builder: &mut Builder<C>) {
let address = builder.eval(ptr + Usize::Const(0));
self.sibling_value.load(address, builder);
let address = builder.eval(ptr + Usize::Const(<Felt<C::F> as MemVariable<C>>::size_of()));
self.opening_proof.load(address, builder);
}

fn store(&self, ptr: Ptr<<C as Config>::N>, builder: &mut Builder<C>) {
let address = builder.eval(ptr + Usize::Const(0));
self.sibling_value.store(address, builder);
let address = builder.eval(ptr + Usize::Const(<Felt<C::F> as MemVariable<C>>::size_of()));
self.opening_proof.store(address, builder);
}
}
14 changes: 14 additions & 0 deletions recursion/derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "sp1-recursion-derive"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
proc-macro = true

[dependencies]
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "1.0", features = ["full"] }
Loading

0 comments on commit e91c38c

Please sign in to comment.