Skip to content

Commit 35f581e

Browse files
committed
fix inneficiency: execution trace was committed by power of 2 (i.e. the padding opti of the packed pcs was missing)
1 parent c8b2916 commit 35f581e

File tree

7 files changed

+32
-27
lines changed

7 files changed

+32
-27
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ RUSTFLAGS='-C target-cpu=native' cargo run --release -- recursion
4646
### XMSS aggregation
4747

4848
```console
49-
RUSTFLAGS='-C target-cpu=native' cargo run --release -- xmss --n-signatures 800
49+
RUSTFLAGS='-C target-cpu=native' cargo run --release -- xmss --n-signatures 990
5050
```
5151

5252
[Trivial encoding](docs/XMSS_trivial_encoding.pdf) (for now).

crates/lean_prover/src/prove_execution.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub fn prove_execution(
3333
let mut exec_summary = String::new();
3434
let ExecutionTrace {
3535
full_trace,
36+
n_cycles,
3637
n_poseidons_16,
3738
n_poseidons_24,
3839
poseidons_16, // padded with empty poseidons
@@ -67,8 +68,7 @@ pub fn prove_execution(
6768
let log_memory = log2_strict_usize(memory.len());
6869
let log_public_memory = log2_strict_usize(public_memory.len());
6970

70-
let n_cycles = full_trace[0].len();
71-
let log_n_cycles = log2_strict_usize(n_cycles);
71+
let log_n_cycles = log2_ceil_usize(n_cycles);
7272
assert!(full_trace.iter().all(|col| col.len() == 1 << log_n_cycles));
7373

7474
let log_n_p16 = log2_ceil_usize(n_poseidons_16).max(LOG_MIN_POSEIDONS_16);
@@ -115,7 +115,7 @@ pub fn prove_execution(
115115
let mut prover_state = build_prover_state::<EF>();
116116
prover_state.add_base_scalars(
117117
&[
118-
log_n_cycles,
118+
n_cycles,
119119
n_poseidons_16,
120120
n_compressions_16,
121121
n_poseidons_24,
@@ -215,7 +215,7 @@ pub fn prove_execution(
215215
// Grand Product for consistency with precompiles
216216
let grand_product_challenge_global = prover_state.sample();
217217
let fingerprint_challenge = prover_state.sample();
218-
let mut exec_column_for_grand_product = vec![grand_product_challenge_global; n_cycles];
218+
let mut exec_column_for_grand_product = vec![grand_product_challenge_global; 1 << log_n_cycles];
219219
for pos_16 in &poseidons_16 {
220220
let Some(cycle) = pos_16.cycle else {
221221
break;
@@ -326,7 +326,7 @@ pub fn prove_execution(
326326

327327
let corrected_prod_exec = grand_product_exec_res
328328
/ grand_product_challenge_global.exp_u64(
329-
(n_cycles
329+
((1 << log_n_cycles)
330330
- n_poseidons_16
331331
- n_poseidons_24
332332
- dot_products.len()
@@ -1152,6 +1152,7 @@ pub fn prove_execution(
11521152
dot_product_computation_column_statements,
11531153
]
11541154
.concat();
1155+
11551156
let global_statements_base = packed_pcs_global_statements_for_prover(
11561157
&base_pols,
11571158
&base_dims,

crates/lean_prover/src/verify_execution.rs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub fn verify_execution(
3434
let dot_product_table = AirTable::<EF, _>::new(DotProductAir);
3535

3636
let [
37-
log_n_cycles,
37+
n_cycles,
3838
n_poseidons_16,
3939
n_compressions_16,
4040
n_poseidons_24,
@@ -50,29 +50,22 @@ pub fn verify_execution(
5050
.try_into()
5151
.unwrap();
5252

53-
if log_n_cycles > 32
54-
|| n_poseidons_16 > 1 << 32
55-
|| n_compressions_16
56-
> n_poseidons_16
57-
.next_power_of_two()
58-
.max(1 << LOG_MIN_POSEIDONS_16)
59-
|| n_poseidons_24 > 1 << 32
60-
|| n_dot_products > 1 << 32
61-
|| n_rows_table_dot_products > 1 << 32
62-
|| private_memory_len > 1 << 32
53+
if n_compressions_16
54+
> n_poseidons_16
55+
.next_power_of_two()
56+
.max(1 << LOG_MIN_POSEIDONS_16)
6357
|| n_vm_multilinear_evals > 1 << 10
6458
{
65-
// To avoid "DOS" attack
6659
return Err(ProofError::InvalidProof);
6760
}
68-
let n_cycles = 1 << log_n_cycles;
6961

7062
let public_memory = build_public_memory(public_input);
7163

7264
let log_public_memory = log2_strict_usize(public_memory.len());
7365
let log_memory = log2_ceil_usize(public_memory.len() + private_memory_len);
7466
let log_n_p16 = log2_ceil_usize(n_poseidons_16).max(LOG_MIN_POSEIDONS_16);
7567
let log_n_p24 = log2_ceil_usize(n_poseidons_24).max(LOG_MIN_POSEIDONS_24);
68+
let log_n_cycles = log2_ceil_usize(n_cycles);
7669

7770
if !(MIN_LOG_MEMORY_SIZE..=MAX_LOG_MEMORY_SIZE).contains(&log_memory) {
7871
return Err(ProofError::InvalidProof);
@@ -149,7 +142,7 @@ pub fn verify_execution(
149142

150143
let corrected_prod_exec = grand_product_exec_res
151144
/ grand_product_challenge_global.exp_u64(
152-
(n_cycles
145+
(n_cycles.next_power_of_two()
153146
- n_poseidons_16
154147
- n_poseidons_24
155148
- n_dot_products

crates/lean_prover/witness_generation/src/execution_trace.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use utils::{ToUsize, transposed_par_iter_mut};
1515
#[derive(Debug)]
1616
pub struct ExecutionTrace {
1717
pub full_trace: [Vec<F>; N_TOTAL_COLUMNS],
18+
pub n_cycles: usize, // before padding with the repeated final instruction
1819
pub n_poseidons_16: usize,
1920
pub n_poseidons_24: usize,
2021
pub n_compressions_16: usize,
@@ -46,9 +47,8 @@ pub fn get_execution_trace(
4647

4748
let n_cycles = execution_result.pcs.len();
4849
let memory = &execution_result.memory;
49-
let log_n_cycles_rounded_up = n_cycles.next_power_of_two().ilog2() as usize;
5050
let mut trace: [Vec<F>; N_TOTAL_COLUMNS] =
51-
array::from_fn(|_| F::zero_vec(1 << log_n_cycles_rounded_up));
51+
array::from_fn(|_| F::zero_vec(n_cycles.next_power_of_two()));
5252

5353
transposed_par_iter_mut(&mut trace)
5454
.zip(execution_result.pcs.par_iter())
@@ -138,6 +138,7 @@ pub fn get_execution_trace(
138138

139139
ExecutionTrace {
140140
full_trace: trace,
141+
n_cycles,
141142
n_poseidons_16,
142143
n_poseidons_24,
143144
n_compressions_16,

crates/lookup/src/product_gkr.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,6 @@ where
5353
} else {
5454
MleRef::Extension(final_layer).into()
5555
};
56-
if final_layer.n_vars() > MIN_VARS_FOR_PACKING && !final_layer.is_packed() {
57-
tracing::warn!("GKR product not packed despite being large enough for packing");
58-
}
5956

6057
let mut layers = vec![final_layer];
6158
loop {

crates/packed_pcs/src/lib.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,15 @@ pub fn packed_pcs_global_statements_for_prover<
391391
all_chunk_evals.push(sub_value);
392392
});
393393

394-
// deduce the first sub_value, if it's not public
395-
if dim.log_public_data_size.is_none() {
394+
let initial_missing_vars = statement.point.0.len() - chunks[0].n_vars;
395+
let initial_offset_in_original_booleans = to_big_endian_bits(
396+
chunks[0].offset_in_original >> chunks[0].n_vars,
397+
initial_missing_vars,
398+
);
399+
if initial_booleans.len() < initial_offset_in_original_booleans.len() // if the statement only concern the first chunk, no need to send more data
400+
&& dim.log_public_data_size.is_none()
401+
// if the first value is public, no need to recompute it
402+
{
396403
let retrieved_eval = compute_multilinear_value_from_chunks(
397404
&chunks[1..],
398405
&all_chunk_evals,
@@ -611,6 +618,7 @@ mod tests {
611618
(754, F::from_usize(4), None),
612619
(1023, F::from_usize(7), None),
613620
(2025, F::from_usize(15), None),
621+
(600, F::from_usize(100), None),
614622
];
615623
let mut public_data = BTreeMap::new();
616624
let mut polynomials = Vec::new();
@@ -646,6 +654,10 @@ mod tests {
646654
});
647655
statements_per_polynomial.push(statements);
648656
}
657+
statements_per_polynomial
658+
.last_mut()
659+
.unwrap()
660+
.push(Evaluation::new(vec![EF::ONE; 10], EF::from_usize(100)));
649661

650662
let mut prover_state = build_prover_state();
651663
precompute_dft_twiddles::<F>(1 << 24);

docs/benchmark_graphs/main.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ def create_duration_graph(data, target=None, target_label=None, title="", y_lege
176176
('2025-10-13', 234, None),
177177
('2025-10-18', 255, 465),
178178
('2025-10-27', 314, 555),
179+
('2025-11-02', 350, 555),
179180
],
180181
target=1000,
181182
target_label="Target (1000 XMSS/s)",

0 commit comments

Comments
 (0)