Skip to content

Commit a4066d3

Browse files
Merge branch 'reduce-padding-overhead' into main.
Mnual import of Plonky3 field, koala-bear, poseidon2 and symetric crates, and of whir-p3, for easier customization and R&D. New optimization: remove padding (when there are zeros at the end of the polynomial committed in WHIR) overhead in DFT + in the hashing of the Merkle leaves (using a "right-to-left" t-sponge). Co-authored-by: Thomas Coratger <thomas.coratger@gmail.com>
1 parent 9151d55 commit a4066d3

File tree

199 files changed

+25037
-1093
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

199 files changed

+25037
-1093
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,18 @@ version = "0.1.0"
88
edition = "2024"
99

1010
[workspace]
11-
members = ["crates/*"]
11+
members = [
12+
"crates/*",
13+
"crates/backend/utils",
14+
"crates/backend/field",
15+
"crates/backend/koala-bear",
16+
"crates/backend/poly",
17+
"crates/backend/symetric",
18+
"crates/backend/air",
19+
"crates/backend/fiat-shamir",
20+
"crates/backend/sumcheck",
21+
"crates/whir",
22+
]
1223

1324
[workspace.lints]
1425
rust.missing_debug_implementations = "warn"
@@ -37,6 +48,7 @@ should_panic_without_expect = "allow"
3748
similar_names = "allow"
3849
suboptimal_flops = "allow"
3950
cast_sign_loss = "allow"
51+
wildcard_imports = "allow"
4052

4153
[workspace.dependencies]
4254
# Local
@@ -50,33 +62,21 @@ lean_prover = { path = "crates/lean_prover" }
5062
rec_aggregation = { path = "crates/rec_aggregation" }
5163

5264
# External
53-
thiserror = "2.0"
54-
clap = { version = "4.5.52", features = ["derive"] }
65+
clap = { version = "4.5.59", features = ["derive"] }
5566
rand = "0.9.2"
56-
sha3 = "0.10.8"
67+
rayon = "1.11.0"
5768
pest = "2.7"
5869
pest_derive = "2.7"
5970
itertools = "0.14.0"
60-
colored = "3.0.0"
6171
tracing = "0.1.26"
6272
serde_json = "1.0.145"
63-
strum = { version = "0.27.2", features = ["derive"] }
6473
serde = { version = "1.0.228", features = ["derive"] }
65-
bincode = "1.3.3"
66-
lz4_flex = "0.12.0"
67-
num_enum = "0.7.5"
68-
owo-colors = "4.2.3"
6974
tracing-subscriber = { version = "0.3.19", features = ["std", "env-filter"] }
7075
tracing-forest = { version = "0.3.0", features = ["ansi", "smallvec"] }
71-
p3-koala-bear = { git = "https://github.com/TomWambsgans/Plonky3.git", branch = "lean-multisig" }
72-
p3-baby-bear = { git = "https://github.com/TomWambsgans/Plonky3.git", branch = "lean-multisig" }
73-
p3-poseidon2 = { git = "https://github.com/TomWambsgans/Plonky3.git", branch = "lean-multisig" }
74-
p3-symmetric = { git = "https://github.com/TomWambsgans/Plonky3.git", branch = "lean-multisig" }
75-
p3-goldilocks = { git = "https://github.com/TomWambsgans/Plonky3.git", branch = "lean-multisig" }
76-
p3-util = { git = "https://github.com/TomWambsgans/Plonky3.git", branch = "lean-multisig" }
77-
p3-monty-31 = { git = "https://github.com/TomWambsgans/Plonky3.git", branch = "lean-multisig" }
76+
postcard = { version = "1.1.3", features = ["alloc"] }
77+
lz4_flex = "0.12.0"
7878

79-
multilinear-toolkit = { git = "https://github.com/leanEthereum/multilinear-toolkit.git" }
79+
backend = { path = "crates/backend" }
8080

8181
[features]
8282
prox-gaps-conjecture = ["rec_aggregation/prox-gaps-conjecture"]
@@ -89,9 +89,9 @@ air.workspace = true
8989
rand.workspace = true
9090
sub_protocols.workspace = true
9191
utils.workspace = true
92-
p3-koala-bear.workspace = true
92+
9393
lean_vm.workspace = true
94-
multilinear-toolkit.workspace = true
94+
backend.workspace = true
9595

9696

9797
[profile.release]

TODO.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ But we can get the bost of both worlds (suggested by Lev, TODO implement):
3939
- Double Check AIR constraints, logup overflows etc
4040
- Formal Verification
4141
- Padd with noop cycles to always ensure memory size >= bytecode size (liveness), and ensure this condition is checked by the verifier (soundness)
42-
- re-enable grinding at folding in whir (should be small, like 1 or 2 bits?)
4342

4443
# Ideas
4544

crates/air/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ workspace = true
99
[dependencies]
1010
tracing.workspace = true
1111
utils.workspace = true
12-
p3-util.workspace = true
13-
multilinear-toolkit.workspace = true
12+
13+
backend.workspace = true
1414

1515
[dev-dependencies]
16-
p3-koala-bear.workspace = true
16+
1717
rand.workspace = true

crates/air/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod utils;
66
mod validity_check;
77
mod verify;
88

9-
use multilinear_toolkit::prelude::{Field, MultilinearPoint};
9+
use backend::{Field, MultilinearPoint};
1010
pub use prove::*;
1111
pub use validity_check::*;
1212
pub use verify::*;

crates/air/src/prove.rs

Lines changed: 14 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
use multilinear_toolkit::prelude::*;
2-
use p3_util::{log2_ceil_usize, log2_strict_usize};
1+
use backend::*;
32
use tracing::{info_span, instrument};
4-
use utils::{fold_multilinear_chunks, multilinears_linear_combination};
3+
use utils::multilinears_linear_combination;
54

65
use crate::{AirClaims, uni_skip_utils::matrix_next_mle_folded, utils::column_shifted};
76

@@ -17,7 +16,6 @@ pub fn prove_air<EF: ExtensionField<PF<EF>>, A: Air>(
1716
prover_state: &mut impl FSProver<EF>,
1817
air: &A,
1918
extra_data: A::ExtraData,
20-
univariate_skips: usize,
2119
columns_f: &[impl AsRef<[PF<EF>]>],
2220
columns_ef: &[impl AsRef<[EF]>],
2321
virtual_column_statement: Option<Evaluation<EF>>, // point should be randomness generated after committing to the columns
@@ -32,22 +30,16 @@ where
3230
assert!(columns_f.iter().all(|col| col.len() == n_rows));
3331
assert!(columns_ef.iter().all(|col| col.len() == n_rows));
3432
let log_n_rows = log2_strict_usize(n_rows);
35-
assert!(
36-
univariate_skips < log_n_rows,
37-
"TODO handle the case UNIVARIATE_SKIPS >= log_length"
38-
);
3933

4034
// crate::check_air_validity(air, &extra_data, &columns_f, &columns_ef).unwrap();
4135

4236
assert!(extra_data.alpha_powers().len() >= air.n_constraints() + virtual_column_statement.is_some() as usize);
4337

44-
let n_sc_rounds = log_n_rows + 1 - univariate_skips;
45-
4638
let zerocheck_challenges = virtual_column_statement
4739
.as_ref()
4840
.map(|st| st.point.0.clone())
49-
.unwrap_or_else(|| prover_state.sample_vec(n_sc_rounds));
50-
assert_eq!(zerocheck_challenges.len(), n_sc_rounds);
41+
.unwrap_or_else(|| prover_state.sample_vec(log_n_rows));
42+
assert_eq!(zerocheck_challenges.len(), log_n_rows);
5143

5244
let shifted_rows_f = air
5345
.down_column_indexes_f()
@@ -74,7 +66,6 @@ where
7466

7567
let (outer_sumcheck_challenge, inner_sums, _) = info_span!("zerocheck").in_scope(|| {
7668
sumcheck_prove(
77-
univariate_skips,
7869
columns_up_down_group_f_packed,
7970
Some(columns_up_down_group_ef_packed),
8071
air,
@@ -92,121 +83,19 @@ where
9283

9384
prover_state.add_extension_scalars(&inner_sums);
9485

95-
if univariate_skips == 1 {
96-
open_columns_no_skip(
97-
prover_state,
98-
&inner_sums,
99-
&air.down_column_indexes_f(),
100-
&air.down_column_indexes_ef(),
101-
&columns_f,
102-
&columns_ef,
103-
&outer_sumcheck_challenge,
104-
)
105-
} else if shifted_rows_f.is_empty() && shifted_rows_ef.is_empty() {
106-
// usefull for poseidon2 benchmark
107-
open_flat_columns(
108-
prover_state,
109-
univariate_skips,
110-
&columns_f,
111-
&columns_ef,
112-
&outer_sumcheck_challenge,
113-
)
114-
} else {
115-
panic!(
116-
"Currently unsupported for simplicty (checkout c7944152a4325b1e1913446e6684112099db5d78 for a version that supported this case)"
117-
);
118-
}
119-
}
120-
121-
#[instrument(skip_all)]
122-
fn open_flat_columns<EF: ExtensionField<PF<EF>>>(
123-
prover_state: &mut impl FSProver<EF>,
124-
univariate_skips: usize,
125-
columns_f: &[&[PF<EF>]],
126-
columns_ef: &[&[EF]],
127-
outer_sumcheck_challenge: &[EF],
128-
) -> AirClaims<EF> {
129-
let n_up_down_columns = columns_f.len() + columns_ef.len();
130-
let batching_scalars = prover_state.sample_vec(log2_ceil_usize(n_up_down_columns));
131-
132-
let eval_eq_batching_scalars = eval_eq(&batching_scalars)[..n_up_down_columns].to_vec();
133-
134-
let mut batched_column_up =
135-
multilinears_linear_combination(columns_f, &eval_eq_batching_scalars[..columns_f.len()]);
136-
if !columns_ef.is_empty() {
137-
let batched_column_up_ef = multilinears_linear_combination(
138-
columns_ef,
139-
&eval_eq_batching_scalars[columns_f.len()..][..columns_ef.len()],
140-
);
141-
batched_column_up
142-
.par_iter_mut()
143-
.zip(&batched_column_up_ef)
144-
.for_each(|(a, &b)| {
145-
*a += b;
146-
});
147-
}
148-
149-
let sub_evals = fold_multilinear_chunks(
150-
&batched_column_up,
151-
&MultilinearPoint(outer_sumcheck_challenge[1..].to_vec()),
152-
);
153-
prover_state.add_extension_scalars(&sub_evals);
154-
155-
let epsilons = prover_state.sample_vec(univariate_skips);
156-
157-
let inner_sum = sub_evals.evaluate(&MultilinearPoint(epsilons.clone()));
158-
159-
let point = [epsilons, outer_sumcheck_challenge[1..].to_vec()].concat();
160-
161-
// TODO opti in case of flat AIR (no need of `matrix_next_mle_folded`)
162-
let matrix_up = eval_eq(&point);
163-
let inner_mle = info_span!("packing").in_scope(|| {
164-
MleGroupOwned::ExtensionPacked(vec![pack_extension(&matrix_up), pack_extension(&batched_column_up)])
165-
});
166-
167-
let (inner_challenges, _, _) = info_span!("structured columns sumcheck").in_scope(|| {
168-
sumcheck_prove::<EF, _, _>(
169-
1,
170-
inner_mle,
171-
None,
172-
&ProductComputation {},
173-
&vec![],
174-
None,
175-
false,
176-
prover_state,
177-
inner_sum,
178-
false,
179-
)
180-
});
181-
182-
let (evaluations_remaining_to_prove_f, evaluations_remaining_to_prove_ef) =
183-
info_span!("final evals").in_scope(|| {
184-
(
185-
columns_f
186-
.par_iter()
187-
.map(|col| col.evaluate(&inner_challenges))
188-
.collect::<Vec<_>>(),
189-
columns_ef
190-
.par_iter()
191-
.map(|col| col.evaluate(&inner_challenges))
192-
.collect::<Vec<_>>(),
193-
)
194-
});
195-
prover_state.add_extension_scalars(&evaluations_remaining_to_prove_f);
196-
prover_state.add_extension_scalars(&evaluations_remaining_to_prove_ef);
197-
198-
AirClaims {
199-
point: inner_challenges,
200-
evals_f: evaluations_remaining_to_prove_f,
201-
evals_ef: evaluations_remaining_to_prove_ef,
202-
down_point: None,
203-
evals_f_on_down_columns: vec![],
204-
evals_ef_on_down_columns: vec![],
205-
}
86+
open_columns(
87+
prover_state,
88+
&inner_sums,
89+
&air.down_column_indexes_f(),
90+
&air.down_column_indexes_ef(),
91+
&columns_f,
92+
&columns_ef,
93+
&outer_sumcheck_challenge,
94+
)
20695
}
20796

20897
#[instrument(skip_all)]
209-
fn open_columns_no_skip<EF: ExtensionField<PF<EF>>>(
98+
fn open_columns<EF: ExtensionField<PF<EF>>>(
21099
prover_state: &mut impl FSProver<EF>,
211100
inner_evals: &[EF],
212101
columns_with_shift_f: &[usize],
@@ -270,7 +159,6 @@ fn open_columns_no_skip<EF: ExtensionField<PF<EF>>>(
270159

271160
let (inner_challenges, _, _) = info_span!("structured columns sumcheck").in_scope(|| {
272161
sumcheck_prove::<EF, _, _>(
273-
1,
274162
inner_mle,
275163
None,
276164
&ProductComputation {},

crates/air/src/uni_skip_utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use multilinear_toolkit::prelude::*;
1+
use backend::*;
22
use tracing::instrument;
33

44
#[instrument(skip_all)]
@@ -27,7 +27,7 @@ mod tests {
2727
use crate::utils::next_mle;
2828

2929
use super::*;
30-
type F = p3_koala_bear::KoalaBear;
30+
type F = KoalaBear;
3131

3232
#[test]
3333
fn test_matrix_down_folded() {

crates/air/src/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use multilinear_toolkit::prelude::*;
1+
use backend::*;
22

33
/// Returns a multilinear polynomial in 2n variables that evaluates to 1
44
/// if and only if the second n-bit vector is equal to the first vector plus one (viewed as big-endian integers).

crates/air/src/validity_check.rs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,60 @@
1-
use multilinear_toolkit::prelude::*;
1+
use backend::*;
22
use tracing::instrument;
3-
use utils::ConstraintChecker;
3+
4+
#[derive(Debug)]
5+
pub struct ConstraintChecker<EF: ExtensionField<PF<EF>>> {
6+
pub up_f: Vec<PF<EF>>,
7+
pub up_ef: Vec<EF>,
8+
pub down_f: Vec<PF<EF>>,
9+
pub down_ef: Vec<EF>,
10+
pub constraint_index: usize,
11+
pub errors: Vec<usize>,
12+
}
13+
14+
impl<EF: ExtensionField<PF<EF>>> AirBuilder for ConstraintChecker<EF> {
15+
type F = PF<EF>;
16+
type EF = EF;
17+
18+
#[inline]
19+
fn up_f(&self) -> &[Self::F] {
20+
&self.up_f
21+
}
22+
23+
#[inline]
24+
fn up_ef(&self) -> &[Self::EF] {
25+
&self.up_ef
26+
}
27+
28+
#[inline]
29+
fn down_f(&self) -> &[Self::F] {
30+
&self.down_f
31+
}
32+
33+
#[inline]
34+
fn down_ef(&self) -> &[Self::EF] {
35+
&self.down_ef
36+
}
37+
38+
#[inline]
39+
fn assert_zero(&mut self, x: Self::F) {
40+
if !x.is_zero() {
41+
self.errors.push(self.constraint_index);
42+
}
43+
self.constraint_index += 1;
44+
}
45+
46+
#[inline]
47+
fn assert_zero_ef(&mut self, x: Self::EF) {
48+
if !x.is_zero() {
49+
self.errors.push(self.constraint_index);
50+
}
51+
self.constraint_index += 1;
52+
}
53+
54+
fn eval_virtual_column(&mut self, _: Self::EF) {
55+
// do nothing
56+
}
57+
}
458

559
#[instrument(name = "Check trace validity", skip_all)]
660
pub fn check_air_validity<A: Air, EF: ExtensionField<PF<EF>>>(

0 commit comments

Comments
 (0)