Skip to content

Commit 00865d1

Browse files
committed
fork transcript to support chip concurrent prove
1 parent 3f5214f commit 00865d1

File tree

7 files changed

+118
-29
lines changed

7 files changed

+118
-29
lines changed

Cargo.lock

Lines changed: 11 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@ version = "0.1.0"
2727
ceno_crypto_primitives = { git = "https://github.com/scroll-tech/ceno-patch.git", package = "ceno_crypto_primitives", branch = "main" }
2828
ceno_syscall = { git = "https://github.com/scroll-tech/ceno-patch.git", package = "ceno_syscall", branch = "main" }
2929

30-
ff_ext = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "ff_ext", tag = "v1.0.0-alpha.21" }
31-
mpcs = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "mpcs", tag = "v1.0.0-alpha.21" }
32-
multilinear_extensions = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "multilinear_extensions", tag = "v1.0.0-alpha.21" }
33-
p3 = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "p3", tag = "v1.0.0-alpha.21" }
34-
poseidon = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "poseidon", tag = "v1.0.0-alpha.21" }
35-
sp1-curves = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "sp1-curves", tag = "v1.0.0-alpha.21" }
36-
sumcheck = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "sumcheck", tag = "v1.0.0-alpha.21" }
37-
transcript = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "transcript", tag = "v1.0.0-alpha.21" }
38-
whir = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "whir", tag = "v1.0.0-alpha.21" }
39-
witness = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "witness", tag = "v1.0.0-alpha.21" }
30+
ff_ext = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "ff_ext", tag = "v1.0.0-alpha.22" }
31+
mpcs = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "mpcs", tag = "v1.0.0-alpha.22" }
32+
multilinear_extensions = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "multilinear_extensions", tag = "v1.0.0-alpha.22" }
33+
p3 = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "p3", tag = "v1.0.0-alpha.22" }
34+
poseidon = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "poseidon", tag = "v1.0.0-alpha.22" }
35+
sp1-curves = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "sp1-curves", tag = "v1.0.0-alpha.22" }
36+
sumcheck = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "sumcheck", tag = "v1.0.0-alpha.22" }
37+
transcript = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "transcript", tag = "v1.0.0-alpha.22" }
38+
whir = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "whir", tag = "v1.0.0-alpha.22" }
39+
witness = { git = "https://github.com/scroll-tech/gkr-backend.git", package = "witness", tag = "v1.0.0-alpha.22" }
4040

4141
anyhow = { version = "1.0", default-features = false }
4242
bincode = "1"

Makefile.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ args = [
6363
"nightly-features",
6464
"--path",
6565
"./ceno_cli",
66+
"--locked",
6667
]
6768
command = "cargo"
6869
env = { "JEMALLOC_SYS_WITH_MALLOC_CONF" = "retain:true,metadata_thp:always,thp:always,dirty_decay_ms:-1,muzzy_decay_ms:-1,abort_conf:true" }

ceno_recursion/src/transcript/mod.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,32 @@ pub fn transcript_check_pow_witness<C: Config>(
3131
builder.assert_eq::<Var<C::N>>(bit, Usize::from(0));
3232
});
3333
}
34+
35+
pub fn clone_challenger_state<C: Config>(
36+
builder: &mut Builder<C>,
37+
src: &DuplexChallengerVariable<C>,
38+
) -> DuplexChallengerVariable<C> {
39+
let dst = DuplexChallengerVariable::new(builder);
40+
builder
41+
.range(0, dst.sponge_state.len())
42+
.for_each(|idx_vec, builder| {
43+
let value = builder.get(&src.sponge_state, idx_vec[0]);
44+
builder.set(&dst.sponge_state, idx_vec[0], value);
45+
});
46+
47+
let input_offset = src.input_ptr - src.io_empty_ptr;
48+
builder.assign(&dst.input_ptr, input_offset + dst.io_empty_ptr);
49+
50+
let output_offset = src.output_ptr - src.io_empty_ptr;
51+
builder.assign(&dst.output_ptr, output_offset + dst.io_empty_ptr);
52+
dst
53+
}
54+
55+
pub fn challenger_add_forked_index<C: Config>(
56+
builder: &mut Builder<C>,
57+
challenger: &mut DuplexChallengerVariable<C>,
58+
index: &Usize<C::N>,
59+
) {
60+
let felt = builder.unsafe_cast_var_to_felt(index.get_var());
61+
challenger.observe(builder, felt);
62+
}

ceno_recursion/src/zkvm_verifier/verifier.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use crate::{
3434
use ceno_zkvm::structs::{ComposedConstrainSystem, VerifyingKey, ZKVMVerifyingKey};
3535
use ff_ext::BabyBearExt4;
3636

37+
use crate::transcript::{challenger_add_forked_index, clone_challenger_state};
3738
use gkr_iop::{
3839
evaluation::EvalExpression,
3940
gkr::{
@@ -234,7 +235,7 @@ pub fn verify_zkvm_proof<C: Config<F = F>>(
234235
// not each chip has witness or fixed opening
235236
// therefore we need to truncate these two opening arrays
236237
let witin_openings: Array<C, RoundOpeningVariable<C>> = builder.dyn_array(proofs_len.clone());
237-
let fixed_openings: Array<C, RoundOpeningVariable<C>> = builder.dyn_array(proofs_len);
238+
let fixed_openings: Array<C, RoundOpeningVariable<C>> = builder.dyn_array(proofs_len.clone());
238239

239240
let shard_ec_sum = SepticPointVariable {
240241
x: SepticExtensionVariable {
@@ -260,6 +261,10 @@ pub fn verify_zkvm_proof<C: Config<F = F>>(
260261
builder.set(&chip_indices, i, chip_idx);
261262
});
262263

264+
// collect fork sampling result
265+
let forked_samples: Array<C, Ext<C::F, C::EF>> = builder.dyn_array(proofs_len.get_var());
266+
let forked_sample_index: Usize<C::N> = builder.eval(C::N::ZERO);
267+
263268
for (i, (circuit_name, chip_vk)) in vk.circuit_vks.iter().enumerate() {
264269
let circuit_vk = &vk.circuit_vks[circuit_name];
265270
let chip_id: Var<C::N> = builder.get(&chip_indices, num_chips_verified.get_var());
@@ -270,6 +275,9 @@ pub fn verify_zkvm_proof<C: Config<F = F>>(
270275

271276
iter_zip!(builder, chip_proofs).for_each(|ptr_vec, builder| {
272277
let chip_proof = builder.iter_ptr_get(&chip_proofs, ptr_vec[0]);
278+
// fork transcript to support chip concurrently proved
279+
let mut chip_challenger = clone_challenger_state(builder, &challenger);
280+
challenger_add_forked_index(builder, &mut chip_challenger, &forked_sample_index);
273281
builder.assert_usize_eq(
274282
chip_proof.wits_in_evals.len(),
275283
Usize::from(circuit_vk.get_cs().num_witin()),
@@ -302,7 +310,7 @@ pub fn verify_zkvm_proof<C: Config<F = F>>(
302310
builder.assign(&chip_logup_sum, chip_logup_sum + p1 * q1.inverse());
303311
builder.assign(&chip_logup_sum, chip_logup_sum + p2 * q2.inverse());
304312
});
305-
challenger.observe(builder, chip_proof.idx_felt);
313+
chip_challenger.observe(builder, chip_proof.idx_felt);
306314

307315
if circuit_vk.get_cs().is_with_lk_table() {
308316
builder.assign(&logup_sum, logup_sum - chip_logup_sum);
@@ -344,7 +352,7 @@ pub fn verify_zkvm_proof<C: Config<F = F>>(
344352
let (input_opening_point, chip_shard_ec_sum) = verify_chip_proof(
345353
circuit_name,
346354
builder,
347-
&mut challenger,
355+
&mut chip_challenger,
348356
&chip_proof,
349357
&zkvm_proof_input.pi_evals,
350358
&zkvm_proof_input.raw_pi,
@@ -396,6 +404,10 @@ pub fn verify_zkvm_proof<C: Config<F = F>>(
396404
.then(|builder| {
397405
add_septic_points_in_place(builder, &shard_ec_sum, &chip_shard_ec_sum);
398406
});
407+
408+
let chip_sample = chip_challenger.sample_ext(builder);
409+
builder.set(&forked_samples, forked_sample_index.get_var(), chip_sample);
410+
builder.inc(&forked_sample_index);
399411
});
400412
builder.inc(&num_chips_verified);
401413
});
@@ -414,6 +426,13 @@ pub fn verify_zkvm_proof<C: Config<F = F>>(
414426
logup_sum - dummy_table_item_multiplicity * dummy_table_item.inverse(),
415427
);
416428

429+
// merge forked transcripts into transcript
430+
iter_zip!(builder, forked_samples).for_each(|ptr_vec, builder| {
431+
let sample = builder.iter_ptr_get(&forked_samples, ptr_vec[0]);
432+
let sample_felts = builder.ext2felt(sample);
433+
challenger.observe_slice(builder, sample_felts);
434+
});
435+
417436
let rounds: Array<C, RoundVariable<C>> = if num_fixed_opening > 0 {
418437
builder.dyn_array(2)
419438
} else {

ceno_zkvm/src/scheme/prover.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use sumcheck::{
2525
structs::IOPProverMessage,
2626
};
2727
use tracing::info_span;
28-
use transcript::Transcript;
28+
use transcript::{ForkableTranscript, Transcript};
2929

3030
use super::{PublicValues, ZKVMChipProof, ZKVMProof, hal::ProverDevice};
3131
use crate::{
@@ -128,7 +128,7 @@ impl<
128128
shard_ctx: &ShardContext,
129129
witnesses: ZKVMWitnesses<E>,
130130
pi: PublicValues,
131-
mut transcript: impl Transcript<E> + 'static,
131+
mut transcript: impl ForkableTranscript<E> + 'static,
132132
) -> Result<ZKVMProof<E, PCS>, ZKVMError> {
133133
info_span!(
134134
"[ceno] create_proof_of_shard",
@@ -253,6 +253,21 @@ impl<
253253
let mut witness_iter = self
254254
.device
255255
.extract_witness_mles(&mut witness_mles, &witness_data);
256+
257+
let num_proofs = name_and_instances
258+
.iter()
259+
.filter(|(circuit_name, num_instances)| {
260+
let pk = self.pk.circuit_pks.get(circuit_name).unwrap();
261+
let cs = pk.get_cs();
262+
let has_instances = !num_instances.is_empty();
263+
let skip_omc_init = !shard_ctx.is_first_shard() && cs.with_omc_init_only();
264+
has_instances && !skip_omc_init
265+
})
266+
.count();
267+
268+
// fork transcript to support chip concurrently proved
269+
let mut forked_transcripts = transcript.fork(num_proofs);
270+
let mut proof_index = 0;
256271
for ((circuit_name, num_instances), structural_rmm) in name_and_instances
257272
.into_iter()
258273
.zip_eq(structural_rmms.into_iter())
@@ -277,6 +292,8 @@ impl<
277292
}
278293
continue;
279294
}
295+
let transcript = &mut forked_transcripts[proof_index];
296+
proof_index += 1;
280297
transcript
281298
.append_field_element(&E::BaseField::from_canonical_u64(circuit_idx as u64));
282299

@@ -320,7 +337,7 @@ impl<
320337
circuit_name.as_str(),
321338
pk,
322339
input,
323-
&mut transcript,
340+
transcript,
324341
&challenges,
325342
)
326343
},
@@ -352,6 +369,15 @@ impl<
352369
drop(witness_iter);
353370
exit_span!(main_proofs_span);
354371

372+
// merge forked transcript into transcript
373+
let forked_sampling = forked_transcripts
374+
.into_iter()
375+
.map(|mut fork_transcript| fork_transcript.sample_vec(1)[0])
376+
.collect_vec();
377+
for sample in forked_sampling {
378+
transcript.append_field_element_ext(&sample);
379+
}
380+
355381
// batch opening pcs
356382
// generate static info from prover key for expected num variable
357383
let pcs_opening = entered_span!("pcs_opening", profiling_1 = true);

ceno_zkvm/src/scheme/verifier.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ impl<E: ExtensionField, PCS: PolynomialCommitmentScheme<E>> ZKVMVerifier<E, PCS>
259259
let mut shard_ec_sum = SepticPoint::<E::BaseField>::default();
260260

261261
// check num proofs
262+
let mut num_proofs = 0;
262263
for (index, proofs) in &vm_proof.chip_proofs {
263264
let circuit_name = &self.vk.circuit_index_to_name[index];
264265
let circuit_vk = &self.vk.circuit_vks[circuit_name];
@@ -274,12 +275,16 @@ impl<E: ExtensionField, PCS: PolynomialCommitmentScheme<E>> ZKVMVerifier<E, PCS>
274275
.into(),
275276
));
276277
}
278+
num_proofs += proofs.len();
277279
}
278280

279-
for (index, proof) in vm_proof
281+
// fork transcript to support chip concurrently proved
282+
let mut forked_transcripts = transcript.fork(num_proofs);
283+
for ((index, proof), transcript) in vm_proof
280284
.chip_proofs
281285
.iter()
282286
.flat_map(|(index, proofs)| iter::repeat_n(index, proofs.len()).zip(proofs))
287+
.zip_eq(forked_transcripts.iter_mut())
283288
{
284289
let num_instance: usize = proof.num_instances.iter().sum();
285290
assert!(num_instance > 0);
@@ -359,7 +364,7 @@ impl<E: ExtensionField, PCS: PolynomialCommitmentScheme<E>> ZKVMVerifier<E, PCS>
359364
proof,
360365
pi_evals,
361366
&vm_proof.raw_pi,
362-
&mut transcript,
367+
transcript,
363368
NUM_FANIN,
364369
&point_eval,
365370
&challenges,
@@ -396,6 +401,15 @@ impl<E: ExtensionField, PCS: PolynomialCommitmentScheme<E>> ZKVMVerifier<E, PCS>
396401
);
397402
}
398403

404+
// merge forked transcript into transcript
405+
let forked_samples = forked_transcripts
406+
.into_iter()
407+
.map(|mut fork_transcript| fork_transcript.sample_vec(1)[0])
408+
.collect_vec();
409+
for sample in forked_samples {
410+
transcript.append_field_element_ext(&sample);
411+
}
412+
399413
// verify mpcs
400414
let mut rounds = vec![(vm_proof.witin_commit.clone(), witin_openings)];
401415

0 commit comments

Comments
 (0)