Skip to content

Commit 1fb6678

Browse files
committed
fix edge case: make the proof work even if there is no dot_product (precompile) calls during execution
1 parent 07ad739 commit 1fb6678

File tree

6 files changed

+46
-14
lines changed

6 files changed

+46
-14
lines changed

crates/lean_prover/src/common.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub fn get_base_dims(
2626
) -> Vec<ColDims<F>> {
2727
let n_poseidons_16 = n_poseidons_16.max(1 << LOG_MIN_POSEIDONS_16);
2828
let n_poseidons_24 = n_poseidons_24.max(1 << LOG_MIN_POSEIDONS_24);
29+
let n_rows_table_dot_products = n_rows_table_dot_products.max(1 << LOG_MIN_DOT_PRODUCT_ROWS);
2930

3031
let p16_default_cubes = default_cube_layers::<F, 16, N_COMMITED_CUBES_P16>(p16_gkr_layers);
3132
let p24_default_cubes = default_cube_layers::<F, 24, N_COMMITED_CUBES_P24>(p24_gkr_layers);

crates/lean_prover/src/prove_execution.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ pub fn prove_execution(
4141
dot_products,
4242
multilinear_evals: vm_multilinear_evals,
4343
public_memory_size,
44-
non_zero_memory_size,
45-
memory, // padded with zeros to next power of two
44+
mut non_zero_memory_size,
45+
mut memory, // padded with zeros to next power of two
4646
} = info_span!("Witness generation").in_scope(|| {
4747
let mut execution_result = info_span!("Executing bytecode").in_scope(|| {
4848
execute_bytecode(
@@ -58,6 +58,10 @@ pub fn prove_execution(
5858
.in_scope(|| get_execution_trace(bytecode, execution_result))
5959
});
6060

61+
if memory.len() < 1 << MIN_LOG_MEMORY_SIZE {
62+
memory.resize(1 << MIN_LOG_MEMORY_SIZE, F::ZERO);
63+
non_zero_memory_size = 1 << MIN_LOG_MEMORY_SIZE;
64+
}
6165
let public_memory = &memory[..public_memory_size];
6266
let private_memory = &memory[public_memory_size..non_zero_memory_size];
6367
let log_memory = log2_strict_usize(memory.len());
@@ -95,7 +99,8 @@ pub fn prove_execution(
9599

96100
let dot_product_table = AirTable::<EF, _>::new(DotProductAir);
97101

98-
let (dot_product_columns, dot_product_padding_len) = build_dot_product_columns(&dot_products);
102+
let (dot_product_columns, dot_product_padding_len) =
103+
build_dot_product_columns(&dot_products, 1 << LOG_MIN_DOT_PRODUCT_ROWS);
99104

100105
let dot_product_flags: Vec<PF<EF>> = field_slice_as_base(&dot_product_columns[0]).unwrap();
101106
let dot_product_lengths: Vec<PF<EF>> = field_slice_as_base(&dot_product_columns[1]).unwrap();

crates/lean_prover/src/verify_execution.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ pub fn verify_execution(
5252

5353
if log_n_cycles > 32
5454
|| n_poseidons_16 > 1 << 32
55-
|| n_compressions_16 > n_poseidons_16.next_power_of_two()
55+
|| n_compressions_16
56+
> n_poseidons_16
57+
.next_power_of_two()
58+
.max(1 << LOG_MIN_POSEIDONS_16)
5659
|| n_poseidons_24 > 1 << 32
5760
|| n_dot_products > 1 << 32
5861
|| n_rows_table_dot_products > 1 << 32
@@ -75,9 +78,9 @@ pub fn verify_execution(
7578
return Err(ProofError::InvalidProof);
7679
}
7780

78-
let table_dot_products_log_n_rows = log2_ceil_usize(n_rows_table_dot_products);
79-
let dot_product_padding_len =
80-
n_rows_table_dot_products.next_power_of_two() - n_rows_table_dot_products;
81+
let table_dot_products_log_n_rows =
82+
log2_ceil_usize(n_rows_table_dot_products).max(LOG_MIN_DOT_PRODUCT_ROWS);
83+
let dot_product_padding_len = (1 << table_dot_products_log_n_rows) - n_rows_table_dot_products;
8184

8285
let mut vm_multilinear_evals = Vec::new();
8386
for _ in 0..n_vm_multilinear_evals {
@@ -204,7 +207,7 @@ pub fn verify_execution(
204207
p16_grand_product_evals_on_indexes_res,
205208
] = verifier_state.next_extension_scalars_const().unwrap();
206209
let p16_grand_product_evals_on_compression = mle_of_zeros_then_ones(
207-
n_poseidons_16.next_power_of_two() - n_compressions_16,
210+
(1 << log_n_p16) - n_compressions_16,
208211
&grand_product_p16_statement.point,
209212
);
210213

crates/lean_prover/tests/test_zkvm.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use p3_field::PrimeCharacteristicRing;
88
const NO_VEC_RUNTIME_MEMORY: usize = 1 << 20;
99

1010
#[test]
11-
fn test_zk_vm() {
11+
fn test_zk_vm_all_precompiles() {
1212
let program_str = r#"
1313
const DIM = 5;
1414
const SECOND_POINT = 2;
@@ -59,9 +59,27 @@ fn test_zk_vm() {
5959
6060
return;
6161
}
62-
"#
63-
.to_string();
62+
"#;
6463

64+
test_zk_vm_helper(program_str);
65+
}
66+
67+
#[test]
68+
fn test_zk_vm_no_precompiles() {
69+
let program_str = r#"
70+
71+
fn main() {
72+
for i in 0..1000 {
73+
assert i != 1000;
74+
}
75+
return;
76+
}
77+
"#;
78+
79+
test_zk_vm_helper(program_str);
80+
}
81+
82+
fn test_zk_vm_helper(program_str: &str) {
6583
const SECOND_POINT: usize = 2;
6684
const SECOND_N_VARS: usize = 7;
6785

@@ -82,7 +100,7 @@ fn test_zk_vm() {
82100
.collect::<Vec<_>>();
83101

84102
// utils::init_tracing();
85-
let bytecode = compile_program(program_str);
103+
let bytecode = compile_program(program_str.to_string());
86104
let proof_data = prove_execution(
87105
&bytecode,
88106
(&public_input, &private_input),

crates/lean_prover/vm_air/src/dot_product_air.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,10 @@ impl<AB: AirBuilder> Air<AB> for DotProductAir {
9696
}
9797
}
9898

99-
pub fn build_dot_product_columns(witness: &[WitnessDotProduct]) -> (Vec<Vec<EF>>, usize) {
99+
pub fn build_dot_product_columns(
100+
witness: &[WitnessDotProduct],
101+
min_n_rows: usize,
102+
) -> (Vec<Vec<EF>>, usize) {
100103
let (
101104
mut flag,
102105
mut len,
@@ -149,7 +152,7 @@ pub fn build_dot_product_columns(witness: &[WitnessDotProduct]) -> (Vec<Vec<EF>>
149152
res.extend(vec![dot_product.res; dot_product.len]);
150153
}
151154

152-
let padding_len = flag.len().next_power_of_two() - flag.len();
155+
let padding_len = flag.len().next_power_of_two().max(min_n_rows) - flag.len();
153156
flag.extend(vec![EF::ONE; padding_len]);
154157
len.extend(vec![EF::ONE; padding_len]);
155158
index_a.extend(EF::zero_vec(padding_len));

crates/lean_prover/witness_generation/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,5 +64,7 @@ impl InAirColumnIndex for usize {
6464

6565
// Zero padding will be added to each at least, if this minimum is not reached
6666
// (ensuring AIR / GKR work fine, with SIMD, without too much edge cases)
67+
// Long term, we should find a more elegant solution.
6768
pub const LOG_MIN_POSEIDONS_16: usize = 8;
6869
pub const LOG_MIN_POSEIDONS_24: usize = 8;
70+
pub const LOG_MIN_DOT_PRODUCT_ROWS: usize = 8;

0 commit comments

Comments
 (0)