Skip to content

Commit ff341ef

Browse files
authored
tools: support whitelist shard id (#1173)
support `--shard-id=k` which only prove k-th shard and skip all others
1 parent f7f3374 commit ff341ef

9 files changed

Lines changed: 96 additions & 9 deletions

File tree

ceno_cli/src/commands/common_args/ceno.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ pub struct CenoOptions {
100100
/// Setting any value restricts logs to profiling information
101101
#[arg(long)]
102102
profiling: Option<usize>,
103+
104+
// for debug purpose
105+
// only generate respective shard id and skip others
106+
#[arg(long)]
107+
shard_id: Option<u64>,
103108
}
104109

105110
impl CenoOptions {
@@ -414,6 +419,7 @@ fn run_elf_inner<
414419
&public_io,
415420
options.max_steps,
416421
checkpoint,
422+
options.shard_id.map(|v| v as usize),
417423
))
418424
}
419425

ceno_recursion/src/bin/e2e_aggregate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ fn main() {
261261
&public_io,
262262
max_steps,
263263
Checkpoint::Complete,
264+
None,
264265
);
265266

266267
let zkvm_proofs = result

ceno_zkvm/benches/fibonacci.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ fn fibonacci_prove(c: &mut Criterion) {
5959
&[],
6060
max_steps,
6161
Checkpoint::Complete,
62+
None,
6263
);
6364
let proof = result
6465
.proofs
@@ -100,6 +101,7 @@ fn fibonacci_prove(c: &mut Criterion) {
100101
&[],
101102
max_steps,
102103
Checkpoint::PrepE2EProving,
104+
None,
103105
);
104106
let instant = std::time::Instant::now();
105107
result.next_step();

ceno_zkvm/benches/fibonacci_witness.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ fn fibonacci_witness(c: &mut Criterion) {
7171
&[],
7272
max_steps,
7373
Checkpoint::PrepWitnessGen,
74+
None,
7475
);
7576
let instant = std::time::Instant::now();
7677
result.next_step();

ceno_zkvm/benches/is_prime.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ fn is_prime_1(c: &mut Criterion) {
6868
&[],
6969
max_steps,
7070
Checkpoint::PrepE2EProving,
71+
None,
7172
);
7273
let instant = std::time::Instant::now();
7374
result.next_step();

ceno_zkvm/benches/keccak.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ fn keccak_prove(c: &mut Criterion) {
5656
&[],
5757
max_steps,
5858
Checkpoint::Complete,
59+
None,
5960
);
6061
let proof = result
6162
.proofs
@@ -94,6 +95,7 @@ fn keccak_prove(c: &mut Criterion) {
9495
&[],
9596
max_steps,
9697
Checkpoint::PrepE2EProving,
98+
None,
9799
);
98100
let instant = std::time::Instant::now();
99101
result.next_step();

ceno_zkvm/benches/quadratic_sorting.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ fn quadratic_sorting_1(c: &mut Criterion) {
6969
&[],
7070
max_steps,
7171
Checkpoint::PrepE2EProving,
72+
None,
7273
);
7374
let instant = std::time::Instant::now();
7475
result.next_step();

ceno_zkvm/src/bin/e2e.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ struct Args {
126126
// => 2^30 * 16 / 4 / 2
127127
#[arg(long, default_value = "2147483648")]
128128
max_cell_per_shard: u64,
129+
130+
// for debug purpose
131+
// only generate respective shard id and skip others
132+
#[arg(long)]
133+
shard_id: Option<u64>,
129134
}
130135

131136
fn main() {
@@ -265,6 +270,8 @@ fn main() {
265270
args.max_cycle_per_shard,
266271
);
267272

273+
let target_shard_id = args.shard_id.map(|v| v as usize);
274+
268275
match (args.pcs, args.field) {
269276
(PcsKind::Basefold, FieldType::Goldilocks) => {
270277
let backend = create_backend(args.max_num_variables, args.security_level);
@@ -280,6 +287,7 @@ fn main() {
280287
args.proof_file,
281288
args.vk_file,
282289
Checkpoint::Complete,
290+
target_shard_id,
283291
)
284292
}
285293
(PcsKind::Basefold, FieldType::BabyBear) => {
@@ -296,6 +304,7 @@ fn main() {
296304
args.proof_file,
297305
args.vk_file,
298306
Checkpoint::Complete,
307+
target_shard_id,
299308
)
300309
}
301310
(PcsKind::Whir, FieldType::Goldilocks) => {
@@ -312,6 +321,7 @@ fn main() {
312321
args.proof_file,
313322
args.vk_file,
314323
Checkpoint::PrepVerify, // TODO: when whir and babybear is ready
324+
target_shard_id,
315325
)
316326
}
317327
(PcsKind::Whir, FieldType::BabyBear) => {
@@ -328,6 +338,7 @@ fn main() {
328338
args.proof_file,
329339
args.vk_file,
330340
Checkpoint::PrepVerify, // TODO: when whir and babybear is ready
341+
target_shard_id,
331342
)
332343
}
333344
};
@@ -355,6 +366,7 @@ fn run_inner<
355366
proof_file: PathBuf,
356367
vk_file: PathBuf,
357368
checkpoint: Checkpoint,
369+
target_shard_id: Option<usize>,
358370
) {
359371
let result = run_e2e_with_checkpoint::<E, PCS, _, _>(
360372
pd,
@@ -365,6 +377,7 @@ fn run_inner<
365377
public_io,
366378
max_steps,
367379
checkpoint,
380+
target_shard_id,
368381
);
369382

370383
let zkvm_proofs = result
@@ -377,7 +390,7 @@ fn run_inner<
377390
let vk_bytes = bincode::serialize(&vk).unwrap();
378391
fs::write(&vk_file, vk_bytes).unwrap();
379392

380-
if checkpoint > Checkpoint::PrepVerify {
393+
if checkpoint > Checkpoint::PrepVerify && target_shard_id.is_none() {
381394
let verifier = ZKVMVerifier::new(vk);
382395
verify(zkvm_proofs.clone(), &verifier).expect("Verification failed");
383396
soundness_test(zkvm_proofs.first().cloned().unwrap(), &verifier);

ceno_zkvm/src/e2e.rs

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,8 @@ pub fn generate_witness<'a, E: ExtensionField>(
993993
system_config: &ConstraintSystemConfig<E>,
994994
mut emul_result: EmulationResult<'a>,
995995
program: &Program,
996+
// this is for debug purpose, which only run target shard id and skip all others
997+
target_shard_id: Option<usize>,
996998
) -> impl Iterator<Item = (ZKVMWitnesses<E>, ShardContext<'a>, PublicValues)> {
997999
let mut shard_ctx_builder = std::mem::take(&mut emul_result.shard_ctx_builder);
9981000
let all_records = std::mem::take(&mut emul_result.all_records);
@@ -1038,6 +1040,21 @@ pub fn generate_witness<'a, E: ExtensionField>(
10381040
let current_shard_end_pc = all_records[cur_index..end].last().unwrap().pc().after.0;
10391041

10401042
let mut zkvm_witness = ZKVMWitnesses::default();
1043+
1044+
if let Some(target_shard_id) = target_shard_id {
1045+
if shard_ctx.shard_id < target_shard_id {
1046+
tracing::debug!("{}th shard skipped", shard_ctx.shard_id);
1047+
// update next round start
1048+
// early stop and return empty zkvm witness, skipped all the potiential cost
1049+
cur_index = end;
1050+
return Some((zkvm_witness, shard_ctx, pi));
1051+
} else if shard_ctx.shard_id > target_shard_id {
1052+
tracing::debug!("{}th shard skipped", shard_ctx.shard_id);
1053+
return None;
1054+
}
1055+
// go ahead to generate witness
1056+
}
1057+
10411058
let time = std::time::Instant::now();
10421059
// assign opcode circuits
10431060
let dummy_records = system_config
@@ -1353,6 +1370,8 @@ pub fn run_e2e_with_checkpoint<
13531370
public_io: &[u32],
13541371
max_steps: usize,
13551372
checkpoint: Checkpoint,
1373+
// for debug purpose
1374+
target_shard_id: Option<usize>,
13561375
) -> E2ECheckpointResult<E, PCS> {
13571376
let start = std::time::Instant::now();
13581377
let ctx = setup_program::<E>(program, platform, multi_prover);
@@ -1377,7 +1396,13 @@ pub fn run_e2e_with_checkpoint<
13771396
proofs: None,
13781397
vk: Some(vk),
13791398
next_step: Some(Box::new(move || {
1380-
_ = run_e2e_proof::<E, _, _, _>(&prover, &init_full_mem, max_steps, is_mock_proving)
1399+
_ = run_e2e_proof::<E, _, _, _>(
1400+
&prover,
1401+
&init_full_mem,
1402+
max_steps,
1403+
is_mock_proving,
1404+
target_shard_id,
1405+
)
13811406
})),
13821407
};
13831408
}
@@ -1408,12 +1433,22 @@ pub fn run_e2e_with_checkpoint<
14081433
&prover.pk.program_ctx.as_ref().unwrap().system_config,
14091434
emul_result,
14101435
&prover.pk.program_ctx.as_ref().unwrap().program,
1436+
target_shard_id,
14111437
)
14121438
})),
14131439
};
14141440
}
14151441

1416-
let zkvm_proofs = create_proofs_helper(emul_result, &prover, is_mock_proving);
1442+
let zkvm_proofs = create_proofs_helper(emul_result, &prover, is_mock_proving, target_shard_id);
1443+
1444+
if target_shard_id.is_some() {
1445+
// skip verify as the proof are in-completed
1446+
return E2ECheckpointResult {
1447+
proofs: Some(zkvm_proofs),
1448+
vk: Some(vk),
1449+
next_step: None,
1450+
};
1451+
}
14171452

14181453
let verifier = ZKVMVerifier::new(vk.clone());
14191454

@@ -1451,6 +1486,8 @@ pub fn run_e2e_proof<
14511486
init_full_mem: &InitMemState,
14521487
max_steps: usize,
14531488
is_mock_proving: bool,
1489+
// for debug purpose
1490+
target_shard_id: Option<usize>,
14541491
) -> Vec<ZKVMProof<E, PCS>> {
14551492
let ctx = prover.pk.program_ctx.as_ref().unwrap();
14561493
// Emulate program
@@ -1461,7 +1498,7 @@ pub fn run_e2e_proof<
14611498
&ctx.platform,
14621499
&ctx.multi_prover,
14631500
);
1464-
create_proofs_helper(emul_result, prover, is_mock_proving)
1501+
create_proofs_helper(emul_result, prover, is_mock_proving, target_shard_id)
14651502
}
14661503

14671504
/// defines a lightweight CPU -> GPU pipeline for witness generation and proof creation.
@@ -1499,6 +1536,7 @@ fn create_proofs_helper<
14991536
emulation_result: EmulationResult,
15001537
prover: &ZKVMProver<E, PCS, PB, PD>,
15011538
is_mock_proving: bool,
1539+
target_shard_id: Option<usize>,
15021540
) -> Vec<ZKVMProof<E, PCS>> {
15031541
let ctx = prover.pk.program_ctx.as_ref().unwrap();
15041542
#[cfg(feature = "gpu")]
@@ -1510,9 +1548,20 @@ fn create_proofs_helper<
15101548
// cpu producer
15111549
s.spawn({
15121550
move || {
1513-
for proof_input in
1514-
generate_witness(&ctx.system_config, emulation_result, &ctx.program)
1515-
{
1551+
let wit_iter = generate_witness(
1552+
&ctx.system_config,
1553+
emulation_result,
1554+
&ctx.program,
1555+
target_shard_id,
1556+
);
1557+
1558+
let wit_iter = if let Some(target_shard_id) = target_shard_id {
1559+
Box::new(wit_iter.skip(target_shard_id)) as Box<dyn Iterator<Item = _>>
1560+
} else {
1561+
Box::new(wit_iter)
1562+
};
1563+
1564+
for proof_input in wit_iter {
15161565
tx.send(proof_input).unwrap()
15171566
}
15181567
}
@@ -1552,9 +1601,20 @@ fn create_proofs_helper<
15521601
#[cfg(not(feature = "gpu"))]
15531602
{
15541603
// Generate witness
1555-
let zkvm_witness = generate_witness(&ctx.system_config, emulation_result, &ctx.program);
1604+
let wit_iter = generate_witness(
1605+
&ctx.system_config,
1606+
emulation_result,
1607+
&ctx.program,
1608+
target_shard_id,
1609+
);
15561610

1557-
zkvm_witness
1611+
let wit_iter = if let Some(target_shard_id) = target_shard_id {
1612+
Box::new(wit_iter.skip(target_shard_id)) as Box<dyn Iterator<Item = _>>
1613+
} else {
1614+
Box::new(wit_iter)
1615+
};
1616+
1617+
wit_iter
15581618
.map(|(zkvm_witness, shard_ctx, pi)| {
15591619
if is_mock_proving {
15601620
MockProver::assert_satisfied_full(

0 commit comments

Comments
 (0)