Skip to content

Commit c9e0002

Browse files
rdalaltamirhemo
authored andcommitted
feat: transparent backend for VEIL frontend (#2741)
1 parent 45f7af8 commit c9e0002

26 files changed

Lines changed: 2447 additions & 1585 deletions

File tree

.claude/settings.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
"Bash(xargs sed:*)",
1313
"Bash(for i:*)",
1414
"Bash(do cargo:*)",
15-
"Bash(git worktree *)"
15+
"Bash(git worktree *)",
16+
"Bash(find /Users/rdalalsuccinct/Documents/sp1-wip/slop/crates/*/tests -maxdepth 2 -type d)",
17+
"Bash(find /Users/rdalalsuccinct/Documents/sp1-wip/slop/crates/*/src -mindepth 1 -maxdepth 2 -type d)",
18+
"Bash(awk -F/ '{print $NF}')"
1619
]
1720
}
18-
}
21+
}

slop/crates/veil/benchmarking/common.rs

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use slop_multilinear::{Mle, MultilinearPcsProver, Point};
1919
use slop_stacked::{StackedPcsProver, StackedPcsVerifier};
2020
use slop_sumcheck::{partially_verify_sumcheck_proof, reduce_sumcheck_to_evaluation};
2121
use slop_veil::compiler::{ConstraintCtx, ReadingCtx};
22-
use slop_veil::protocols::sumcheck::SumcheckParam;
22+
use slop_veil::protocols::sumcheck::{SumcheckInputClaim, SumcheckParam};
2323
use slop_veil::zk::stacked_pcs::{initialize_zk_prover_and_verifier, StackedPcsZkProverCtx};
2424
use slop_veil::zk::{compute_mask_length, ZkProverCtx, ZkVerifierCtx};
2525

@@ -84,11 +84,13 @@ fn single_mle_read<C: ReadingCtx>(
8484
fn single_mle_build_constraints<C: ConstraintCtx>(
8585
ctx: &mut C,
8686
oracle: C::MleOracle,
87+
claim: C::Extension,
8788
view: slop_veil::protocols::sumcheck::SumcheckView<C>,
8889
) {
89-
let point: Point<C::Challenge> = Point::from(view.point.clone());
90-
ctx.assert_mle_eval(oracle, point, view.claimed_eval.clone());
91-
view.build_constraints(ctx).unwrap();
90+
let point: Point<C::Challenge> = Point::from(view.out_claim.point.clone());
91+
ctx.assert_mle_eval(oracle, point, view.out_claim.claimed_eval.clone());
92+
let in_claim = SumcheckInputClaim::from_value(claim);
93+
view.build_constraints(&in_claim, ctx).unwrap();
9294
}
9395

9496
fn run_standard_single(
@@ -188,18 +190,17 @@ fn run_zk_single(
188190

189191
let masks_length = compute_mask_length::<GC, _>(
190192
|ctx| single_mle_read(ctx, num_encoding_variables, log_num_polynomials, num_variables),
191-
|(oracle, view), ctx| single_mle_build_constraints(ctx, oracle, view),
193+
|(oracle, view), ctx| single_mle_build_constraints(ctx, oracle, claim, view),
192194
);
193195

194196
let mut ctx: StackedPcsZkProverCtx<GC, MK> =
195197
ZkProverCtx::initialize_with_pcs_only_lin(masks_length, pcs_prover, rng);
196198

197199
let commit = ctx.commit_mle(original_mle.clone(), log_num_polynomials, rng).unwrap();
198200

199-
let view = param.prove(mle_ef.clone(), &mut ctx, claim);
200-
let point: Point<EF> = Point::from(view.point.clone());
201-
ctx.assert_mle_eval(commit, point, view.claimed_eval.clone());
202-
view.build_constraints(&mut ctx).unwrap();
201+
let in_claim = SumcheckInputClaim::from_value(claim);
202+
let view = param.prove(&in_claim, mle_ef.clone(), &mut ctx);
203+
single_mle_build_constraints(&mut ctx, commit, claim, view);
203204

204205
let zkproof = ctx.prove(rng);
205206
(zkproof, prover_start.elapsed())
@@ -211,7 +212,7 @@ fn run_zk_single(
211212
let mut ctx = ZkVerifierCtx::init(zkproof, Some(zk_stacked_verifier));
212213
let (oracle, view) =
213214
single_mle_read(&mut ctx, num_encoding_variables, log_num_polynomials, num_variables);
214-
single_mle_build_constraints(&mut ctx, oracle, view);
215+
single_mle_build_constraints(&mut ctx, oracle, claim, view);
215216
ctx.verify().expect("Failed to verify");
216217

217218
verifier_start.elapsed()
@@ -243,17 +244,23 @@ fn hadamard_read<C: ReadingCtx>(
243244
HadamardReadData { ci_base, ci_ext, view }
244245
}
245246

246-
fn hadamard_build_constraints<C: ConstraintCtx>(ctx: &mut C, data: HadamardReadData<C>) {
247-
let point: Point<C::Challenge> = Point::from(data.view.point.clone());
248-
let base_eval = data.view.component_evals[0].clone();
249-
let ext_eval = data.view.component_evals[1].clone();
247+
fn hadamard_build_constraints<C: ConstraintCtx>(
248+
ctx: &mut C,
249+
claim: C::Extension,
250+
data: HadamardReadData<C>,
251+
) {
252+
let point: Point<C::Challenge> = Point::from(data.view.out_claim.point.clone());
253+
let base_eval = data.view.out_claim.component_evals[0][0].clone();
254+
let ext_eval = data.view.out_claim.component_evals[0][1].clone();
250255
ctx.assert_a_times_b_equals_c(
251256
base_eval.clone(),
252257
ext_eval.clone(),
253-
data.view.claimed_eval.clone(),
254-
);
258+
data.view.out_claim.claimed_eval.clone(),
259+
)
260+
.unwrap();
255261
ctx.assert_mle_multi_eval(vec![(data.ci_base, base_eval), (data.ci_ext, ext_eval)], point);
256-
data.view.build_constraints(ctx).unwrap();
262+
let in_claim = SumcheckInputClaim::from_value(claim);
263+
data.view.build_constraints(&in_claim, ctx).unwrap();
257264
}
258265

259266
fn run_standard_hadamard(
@@ -385,7 +392,7 @@ fn run_zk_hadamard(
385392

386393
let masks_length = compute_mask_length::<GC, _>(
387394
|ctx| hadamard_read(ctx, num_encoding_variables, log_num_polynomials, num_variables),
388-
|data, ctx| hadamard_build_constraints(ctx, data),
395+
|data, ctx| hadamard_build_constraints(ctx, claim, data),
389396
);
390397

391398
let mut ctx: StackedPcsZkProverCtx<GC, MK> =
@@ -394,9 +401,10 @@ fn run_zk_hadamard(
394401
let ci_base = ctx.commit_mle(mle_1.clone(), log_num_polynomials, rng).unwrap();
395402
let ci_ext = ctx.commit_mle(mle_2.clone(), log_num_polynomials, rng).unwrap();
396403

397-
let view = param.prove(hadamard_product, &mut ctx, claim);
404+
let in_claim = SumcheckInputClaim::from_value(claim);
405+
let view = param.prove(&in_claim, hadamard_product, &mut ctx);
398406
let data = HadamardReadData { ci_base, ci_ext, view };
399-
hadamard_build_constraints(&mut ctx, data);
407+
hadamard_build_constraints(&mut ctx, claim, data);
400408

401409
let zkproof = ctx.prove(rng);
402410
(zkproof, prover_start.elapsed())
@@ -410,7 +418,7 @@ fn run_zk_hadamard(
410418
let mut ctx = ZkVerifierCtx::init(zkproof, Some(zk_stacked_verifier));
411419
let data =
412420
hadamard_read(&mut ctx, num_encoding_variables, log_num_polynomials, num_variables);
413-
hadamard_build_constraints(&mut ctx, data);
421+
hadamard_build_constraints(&mut ctx, claim, data);
414422
ctx.verify().expect("Failed to verify");
415423

416424
verifier_start.elapsed()
Lines changed: 105 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
1-
//! Example: ZK sumcheck using the public VEIL interface.
1+
//! Example: random-opening "protocol" for a committed MLE, run against two backends.
22
//!
3-
//! Demonstrates the full prove/verify flow:
4-
//! 1. Generate a random MLE and compute its hypercube sum
5-
//! 2. Prover sends sumcheck messages via `SendingCtx`
6-
//! 3. Verifier reads and checks via `ReadingCtx` + compiler `SumcheckParam`
3+
//! This is the degenerate terminal case of a veil protocol: nothing is really being
4+
//! reduced — we just commit an MLE, sample a random point, open at that point, and
5+
//! discharge the resulting evaluation claim via the primitive `ctx.assert_mle_eval`.
6+
//! Effectively a PCS smoke test.
7+
//!
8+
//! The protocol is written once, generically over `SendingCtx` / `ReadingCtx`, then
9+
//! run first with the zero-knowledge backend (`ZkProverCtx` / `ZkVerifierCtx`) and
10+
//! afterwards with the transparent backend (`TransparentProverCtx` /
11+
//! `TransparentVerifierCtx`).
12+
//!
13+
//! Shape:
14+
//!
15+
//! - `mle_eval_read` / `mle_eval_prove`: mirror entry points — one reads the
16+
//! transcript on the verifier side, the other commits + samples + sends on the
17+
//! prover side. Both return an [`MleEvalView`].
18+
//! - `mle_eval_build_constraints`: the shared constraint-building pass used by both
19+
//! sides.
720
821
use rand::SeedableRng;
922
use rand_chacha::ChaCha20Rng;
@@ -12,77 +25,118 @@ use slop_koala_bear::KoalaBearDegree4Duplex;
1225
use slop_merkle_tree::Poseidon2KoalaBear16Prover;
1326
use slop_multilinear::{Mle, Point};
1427
use slop_veil::compiler::{ConstraintCtx, ReadingCtx, SendingCtx};
28+
use slop_veil::transparent::{
29+
initialize_transparent_prover_and_verifier, TransparentProverCtx, TransparentVerifierCtx,
30+
};
1531
use slop_veil::zk::stacked_pcs::{initialize_zk_prover_and_verifier, StackedPcsZkProverCtx};
1632
use slop_veil::zk::{compute_mask_length, ZkProverCtx, ZkVerifierCtx};
1733

1834
type GC = KoalaBearDegree4Duplex;
35+
type F = <GC as IopCtx>::F;
1936
type MK = Poseidon2KoalaBear16Prover;
2037

2138
const LOG_NUM_POLYNOMIALS: u32 = 8;
2239
const NUM_ENCODING_VARIABLES: u32 = 8;
2340
const NUM_VARIABLES: u32 = LOG_NUM_POLYNOMIALS + NUM_ENCODING_VARIABLES;
2441

25-
fn read<C: ReadingCtx>(ctx: &mut C) -> (C::MleOracle, Point<C::Challenge>, C::Expr) {
26-
let p_oracle = ctx.read_oracle(NUM_ENCODING_VARIABLES, LOG_NUM_POLYNOMIALS).unwrap();
27-
let point = ctx.sample_point(NUM_VARIABLES);
28-
let eval = ctx.read_one().unwrap();
29-
(p_oracle, point, eval)
30-
}
42+
// ============================================================================
43+
// Generic protocol code
44+
// ============================================================================
3145

32-
fn build_constraints<C: ConstraintCtx>(
33-
ctx: &mut C,
34-
p_oracle: C::MleOracle,
46+
struct MleEvalView<C: ConstraintCtx> {
47+
oracle: C::MleOracle,
3548
point: Point<C::Challenge>,
36-
eval: C::Expr,
37-
) {
38-
ctx.assert_mle_eval(p_oracle, point, eval);
49+
claimed_eval: C::Expr,
3950
}
4051

41-
fn main() {
42-
let mut rng = ChaCha20Rng::from_entropy();
52+
/// Verifier-side entry point: read the committed oracle, sample the opening point,
53+
/// and read the prover's claimed evaluation out of the transcript.
54+
fn mle_eval_read<C: ReadingCtx>(ctx: &mut C) -> MleEvalView<C> {
55+
let oracle = ctx.read_oracle(NUM_ENCODING_VARIABLES, LOG_NUM_POLYNOMIALS).unwrap();
56+
let point = ctx.sample_point(NUM_VARIABLES);
57+
let claimed_eval = ctx.read_one().unwrap();
58+
MleEvalView { oracle, point, claimed_eval }
59+
}
4360

44-
// Generate a random MLE
45-
let p = Mle::<<GC as IopCtx>::F>::rand(&mut rng, 1, NUM_VARIABLES);
61+
/// Prover-side entry point: commit `mle`, sample the opening point, compute the
62+
/// evaluation, send it on the transcript, and return the matching [`MleEvalView`]
63+
/// for the caller to feed into [`mle_eval_build_constraints`].
64+
fn mle_eval_prove<C, RNG>(ctx: &mut C, mle: Mle<C::Field>, rng: &mut RNG) -> MleEvalView<C>
65+
where
66+
C: SendingCtx,
67+
RNG: rand::CryptoRng + rand::Rng,
68+
rand::distributions::Standard: rand::distributions::Distribution<C::Field>,
69+
{
70+
let oracle =
71+
ctx.commit_mle(mle.clone(), LOG_NUM_POLYNOMIALS, rng).expect("failed to commit mle");
72+
let point = ctx.sample_point(NUM_VARIABLES);
73+
let eval = mle.eval_at(&point).evaluations().as_slice()[0];
74+
let claimed_eval = ctx.send_value(eval.into());
75+
MleEvalView { oracle, point, claimed_eval }
76+
}
4677

47-
let mask_length = compute_mask_length::<GC, _>(read, |(p_o, point, eval), ctx| {
48-
build_constraints(ctx, p_o, point, eval)
49-
});
50-
eprintln!("Mask length: {}", mask_length);
78+
/// Shared constraint-building pass used by both sides.
79+
fn mle_eval_build_constraints<C: ConstraintCtx>(view: MleEvalView<C>, ctx: &mut C) {
80+
ctx.assert_mle_eval(view.oracle, view.point, view.claimed_eval);
81+
}
5182

52-
let (pcs_prover, verifier) = initialize_zk_prover_and_verifier(1, NUM_ENCODING_VARIABLES);
83+
fn main() {
84+
let mut rng = ChaCha20Rng::from_entropy();
5385

54-
// === PROVER ===
55-
eprintln!("\n=== PROVER ===");
56-
let proof = {
57-
eprintln!("Proving...");
58-
let mut ctx: StackedPcsZkProverCtx<GC, MK> =
59-
ZkProverCtx::initialize_with_pcs_only_lin(mask_length, pcs_prover, &mut rng);
86+
let p = Mle::<F>::rand(&mut rng, 1, NUM_VARIABLES);
6087

61-
// Commit to p
62-
let commit =
63-
ctx.commit_mle(p.clone(), LOG_NUM_POLYNOMIALS, &mut rng).expect("failed to commit");
64-
// Get a random point
65-
let point = ctx.sample_point(NUM_VARIABLES);
88+
// ZK backend.
89+
eprintln!("\n=== ZK BACKEND ===");
90+
let (zk_pcs_prover, zk_pcs_verifier) =
91+
initialize_zk_prover_and_verifier(1, NUM_ENCODING_VARIABLES);
6692

67-
let eval = p.eval_at(&point)[0];
68-
let eval = ctx.send_value(eval);
93+
let zk_proof = {
94+
let now = std::time::Instant::now();
95+
let mask_length = compute_mask_length::<GC, _>(mle_eval_read, mle_eval_build_constraints);
96+
eprintln!("Mask length: {mask_length}");
6997

70-
ctx.assert_mle_eval(commit, point, eval);
98+
let mut pctx: StackedPcsZkProverCtx<GC, MK> =
99+
ZkProverCtx::initialize_with_pcs_only_lin(mask_length, zk_pcs_prover, &mut rng);
100+
let view = mle_eval_prove(&mut pctx, p.clone(), &mut rng);
101+
mle_eval_build_constraints(view, &mut pctx);
102+
let proof = pctx.prove(&mut rng);
71103

72-
let proof = ctx.prove(&mut rng);
73-
eprintln!("Proving complete");
104+
eprintln!("Prover time: {:?}", now.elapsed());
105+
proof
106+
};
107+
{
108+
let mut vctx = ZkVerifierCtx::init(zk_proof, Some(zk_pcs_verifier));
109+
let view = mle_eval_read(&mut vctx);
110+
mle_eval_build_constraints(view, &mut vctx);
111+
vctx.verify().expect("zk verification failed");
112+
}
113+
eprintln!("ZK backend: PASSED");
114+
115+
// Transparent backend.
116+
eprintln!("\n=== TRANSPARENT BACKEND ===");
117+
let (stacked_prover, stacked_verifier) = initialize_transparent_prover_and_verifier::<GC, MK>(
118+
1,
119+
NUM_ENCODING_VARIABLES,
120+
LOG_NUM_POLYNOMIALS,
121+
);
122+
123+
let transparent_proof = {
124+
let now = std::time::Instant::now();
125+
let mut pctx: TransparentProverCtx<GC, MK> =
126+
TransparentProverCtx::initialize(stacked_prover);
127+
let view = mle_eval_prove(&mut pctx, p.clone(), &mut rng);
128+
mle_eval_build_constraints(view, &mut pctx);
129+
let proof = pctx.prove(&mut rng).expect("transparent prove failed");
130+
eprintln!("Prover time: {:?}", now.elapsed());
74131
proof
75132
};
76-
77-
// === VERIFIER ===
78-
eprintln!("\n=== VERIFIER ===");
79133
{
80-
let mut ctx = ZkVerifierCtx::init(proof, Some(verifier));
81-
// Verifier reads from transcript and builds constraints
82-
let (p_oracle, point, eval) = read(&mut ctx);
83-
build_constraints(&mut ctx, p_oracle, point, eval);
84-
ctx.verify().expect("verification failed");
134+
let mut vctx = TransparentVerifierCtx::<GC>::new(transparent_proof, Some(stacked_verifier));
135+
let view = mle_eval_read(&mut vctx);
136+
mle_eval_build_constraints(view, &mut vctx);
137+
vctx.verify().expect("transparent verification failed");
85138
}
139+
eprintln!("Transparent backend: PASSED");
86140

87-
eprintln!("\n=== PASSED ===");
141+
eprintln!("\n=== ALL PASSED ===");
88142
}

0 commit comments

Comments
 (0)