Skip to content
Draft
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
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.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ keywords = ["SNARK", "cryptography", "proofs"]

[workspace]
members = [
"crates/jolt-claim-expr",
"crates/jolt-claims",
"crates/jolt-claims-derive",
"crates/jolt-akita",
Expand Down Expand Up @@ -452,6 +453,7 @@ common = { path = "./common", default-features = false }
tracer = { path = "./tracer", default-features = false }
jolt-akita = { path = "./crates/jolt-akita" }
jolt-zk = { path = "./crates/jolt-zk" }
jolt-claim-expr = { path = "./crates/jolt-claim-expr" }
jolt-claims = { path = "./crates/jolt-claims" }
jolt-claims-derive = { path = "./crates/jolt-claims-derive" }
jolt-crypto = { path = "./crates/jolt-crypto", default-features = false }
Expand Down
17 changes: 17 additions & 0 deletions crates/jolt-claim-expr/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "jolt-claim-expr"
version = "0.1.0"
edition = "2021"
license = "MIT"
description = "Protocol-free symbolic claim expressions for Jolt"

[lints]
workspace = true

[dependencies]
jolt-algebra.workspace = true
serde = { workspace = true, features = ["alloc", "derive"] }
thiserror.workspace = true

[dev-dependencies]
jolt-algebra = { workspace = true, features = ["bn254"] }
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use jolt_field::Ring;
use jolt_algebra::Ring;
use serde::{Deserialize, Serialize};

/// An atomic value used inside a symbolic claim expression.
Expand Down Expand Up @@ -191,7 +191,7 @@ pub fn constant<F: Ring, O, P, C>(value: F) -> Expr<F, O, P, C> {
#[cfg(test)]
mod tests {
use super::*;
use jolt_field::{Fr, Ring};
use jolt_algebra::{Fr, Ring};

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum Opening {
Expand Down
23 changes: 23 additions & 0 deletions crates/jolt-claim-expr/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//! Protocol-free symbolic claim expressions and sumcheck descriptions.

#![forbid(unsafe_code)]
#![deny(
clippy::get_unwrap,
clippy::string_slice,
clippy::fallible_impl_from,
clippy::mem_forget,
clippy::exit,
clippy::panic_in_result_fn,
clippy::let_underscore_must_use,
clippy::host_endian_bytes
)]

mod claims;
pub mod formula_error;
mod ops;
mod sumcheck;
mod symbolic;

pub use claims::{challenge, constant, derived, opening, Expr, Source, Term};
pub use sumcheck::SumcheckDomain;
pub use symbolic::{referenced_openings, SymbolicSumcheck};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::ops::{Add, Mul, Neg, Sub};

use jolt_field::Ring;
use jolt_algebra::Ring;

use crate::{Expr, Term};

Expand Down Expand Up @@ -232,7 +232,7 @@ impl<F: Ring + Ring, O, P, C> Mul<Expr<F, O, P, C>> for i128 {
#[cfg(test)]
mod tests {
use crate::{constant, opening, Expr};
use jolt_field::{Fr, Ring};
use jolt_algebra::{Fr, Ring};

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum Opening {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::BTreeSet;

use jolt_field::Ring;
use jolt_algebra::Ring;

use crate::{Expr, Source, SumcheckDomain};

Expand All @@ -21,16 +21,16 @@ pub trait SymbolicSumcheck {

/// The relation's drawn Fiat-Shamir challenges, parameterized by the field
/// (challenges carry no opening point). A relation with no challenges uses
/// [`NoChallenges`](crate::NoChallenges).
/// `jolt_claims::NoChallenges`.
type Challenges<F>;

/// The relation's consumed-claim struct, generic over the opening *cell*,
/// instantiated at `F` (the serialized wire value) or `Vec<F>` (the derived
/// opening point). A symbolic-only relation uses [`NoInputs`](crate::NoInputs).
/// opening point). A symbolic-only relation uses `jolt_claims::NoInputs`.
type Inputs<C>;
/// The relation's produced-claim struct, generic over the opening *cell*
/// (`F` value | `Vec<F>` point). A symbolic-only relation uses
/// [`NoOutputs`](crate::NoOutputs).
/// `jolt_claims::NoOutputs`.
type Outputs<C>;

fn new(shape: Self::Shape) -> Self;
Expand Down Expand Up @@ -99,128 +99,3 @@ pub fn referenced_openings<F, O: Ord, D, C>(
}
openings
}

#[cfg(test)]
mod tests {
use super::*;
use crate::{challenge, constant, derived, opening, NoChallenges, NoInputs, NoOutputs};
use jolt_field::{Fr, Ring};
use std::collections::BTreeSet;

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
enum Opening {
A,
B,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum Derived {
Offset,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum Challenge {
Gamma,
}

struct Mock;

impl SymbolicSumcheck for Mock {
type RelationId = u8;
type OpeningId = Opening;
type DerivedId = Derived;
type ChallengeId = Challenge;
type Shape = ();
type Challenges<F> = NoChallenges<F>;
type Inputs<C> = NoInputs<C>;
type Outputs<C> = NoOutputs<C>;

fn new((): ()) -> Self {
Self
}

fn id() -> u8 {
7
}

fn rounds(&self) -> usize {
0
}

fn degree(&self) -> usize {
2
}

fn input_expression<F: Ring>(&self) -> Expr<F, Opening, Derived, Challenge> {
Expr::zero()
}

fn output_expression<F: Ring>(&self) -> Expr<F, Opening, Derived, Challenge> {
let two = constant::<F, _, _, _>(F::one() + F::one());
(two * opening(Opening::A) + challenge(Challenge::Gamma))
* (opening(Opening::B) + Expr::one())
- derived(Derived::Offset) * opening(Opening::A)
}
}

fn resolve(expr: &Expr<Fr, Opening, Derived, Challenge>) -> Fr {
expr.evaluate(
|id| match id {
Opening::A => Fr::from_u64(3),
Opening::B => Fr::from_u64(5),
},
|id| match id {
Challenge::Gamma => Fr::from_u64(7),
},
|id| match id {
Derived::Offset => Fr::from_u64(11),
},
)
}

#[test]
fn nested_output_expression_evaluates_to_hand_computed_value() {
let output = resolve(&Mock::new(()).output_expression::<Fr>());
assert_eq!(output, Fr::from_u64(45));
}

#[test]
fn expected_output_openings_deduplicate_and_skip_non_opening_leaves() {
let openings = Mock::new(()).expected_output_openings::<Fr>();
let expected: BTreeSet<Opening> = [Opening::A, Opening::B].into_iter().collect();
assert_eq!(openings, expected);
}

#[test]
fn try_evaluate_propagates_resolver_errors_and_agrees_with_evaluate() {
let expr = Mock::new(()).output_expression::<Fr>();

let failed: Result<Fr, &str> = expr.try_evaluate(
|id| match id {
Opening::A => Ok(Fr::from_u64(3)),
Opening::B => Err("missing opening B"),
},
|id| match id {
Challenge::Gamma => Ok(Fr::from_u64(7)),
},
|id| match id {
Derived::Offset => Ok(Fr::from_u64(11)),
},
);
assert_eq!(failed, Err("missing opening B"));

let succeeded: Result<Fr, &str> = expr.try_evaluate(
|id| match id {
Opening::A => Ok(Fr::from_u64(3)),
Opening::B => Ok(Fr::from_u64(5)),
},
|id| match id {
Challenge::Gamma => Ok(Fr::from_u64(7)),
},
|id| match id {
Derived::Offset => Ok(Fr::from_u64(11)),
},
);
assert_eq!(succeeded, Ok(resolve(&expr)));
}
}
1 change: 1 addition & 0 deletions crates/jolt-claims/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ test-utils = []
[dependencies]
allocative = { workspace = true, optional = true }
derive_more.workspace = true
jolt-claim-expr.workspace = true
jolt-claims-derive.workspace = true
jolt-field.workspace = true
jolt-lookup-tables.workspace = true
Expand Down
10 changes: 10 additions & 0 deletions crates/jolt-claims/fuzz/Cargo.lock

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

15 changes: 7 additions & 8 deletions crates/jolt-claims/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,20 @@
extern crate self as jolt_claims;

mod claim_data;
mod claims;
mod formula_error;
pub mod lattice;
mod ops;
pub mod protocols;
pub mod r1cs;
mod sumcheck;
mod symbolic;
#[cfg(test)]
mod symbolic_tests;
pub mod twist;

pub use claim_data::{
ChallengeDrawError, InputClaims, MissingOpeningValue, NoChallenges, NoInputs, NoOutputs,
OutputClaims, SumcheckChallenges,
};
pub use claims::{challenge, constant, derived, opening, Expr, Source, Term};
use jolt_claim_expr::formula_error;
pub use jolt_claim_expr::{
challenge, constant, derived, opening, referenced_openings, Expr, Source, SumcheckDomain,
SymbolicSumcheck, Term,
};
pub use jolt_claims_derive::{InputClaims, OutputClaims, SumcheckChallenges};
pub use sumcheck::SumcheckDomain;
pub use symbolic::{referenced_openings, SymbolicSumcheck};
Loading
Loading