Skip to content

Refactor compute_deep_composition_poly function #200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 48 commits into from
Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
0718670
[WIP] Deep FRI
jrchatruc Mar 7, 2023
fd7f3a4
Finish implementation
jrchatruc Mar 8, 2023
11ff81a
Document code
jrchatruc Mar 8, 2023
13d950e
Merge branch 'main' into deep-fri
jrchatruc Mar 8, 2023
27ec171
Fix vulnerability tests and add more
jrchatruc Mar 8, 2023
aa3332e
Define basic traits and structs for Air
entropidelic Mar 10, 2023
e6ea1a9
Write basic skeleton of ConstraintEvaluator
entropidelic Mar 13, 2023
ffaf881
Save evaluator progress
entropidelic Mar 13, 2023
1a443c3
Complete evaluator basic methods
entropidelic Mar 13, 2023
bc78949
Fix some compilation errors
jrchatruc Mar 14, 2023
f3cb147
Finish method for computing composition poly from Evaluation Table
entropidelic Mar 14, 2023
60d36e0
More fixes
jrchatruc Mar 14, 2023
437c446
More progress
jrchatruc Mar 14, 2023
ae494de
Comment out tests
jrchatruc Mar 14, 2023
7f70d78
Merge branch 'main' into air-impl
jrchatruc Mar 14, 2023
57e8f36
[WIP] Implement verifier
jrchatruc Mar 15, 2023
98fbf8b
Debugging stuff
jrchatruc Mar 15, 2023
4711f36
Remove debugging stuff as the boundary ood evaluation was correct
jrchatruc Mar 15, 2023
706e09c
Uncomment important line
jrchatruc Mar 15, 2023
69a4877
Start compute_deep_composition_poly refactor
entropidelic Mar 15, 2023
7c10e42
Finish compute_deep_composition_poly refactor
entropidelic Mar 16, 2023
91396d7
Refactor trace function to take the length as a parameter
jrchatruc Mar 16, 2023
26b96f3
Fix hardcoded boundary poly degree on verifier
jrchatruc Mar 16, 2023
ace4b1e
Some fixes
jrchatruc Mar 16, 2023
4b1edfd
Fix transition_divisors implementation
jrchatruc Mar 17, 2023
a90fd0b
Fix transition_divisor once more
jrchatruc Mar 17, 2023
8881e77
Fix calculation of trace primitive root on the verifier
jrchatruc Mar 17, 2023
eafa2a9
Test finally working
jrchatruc Mar 17, 2023
267aaee
Remove unusued num_assertions field
jrchatruc Mar 17, 2023
593db94
Merge branch 'main' into air-impl
jrchatruc Mar 17, 2023
22b7da0
[WIP] fiat-shamir integration
jrchatruc Mar 17, 2023
69ce919
Comment transcript.append line in fri function
entropidelic Mar 17, 2023
0ba2fea
Fix fiat-shamir integration bugs
entropidelic Mar 20, 2023
fa095f5
Fix boundaryconstraints zerofier test
entropidelic Mar 20, 2023
afcaa1c
Fix clippy suggestiojns
entropidelic Mar 20, 2023
a91cc07
Remove outdated comments
jrchatruc Mar 20, 2023
32b6892
Rename compute_transition_evaluations
entropidelic Mar 20, 2023
bfd9ecc
Add Fibonacci AIR test for a 17 finite field
entropidelic Mar 20, 2023
b1fd123
Merge branch 'air-impl' into compute_deep_composition_poly-refactor
entropidelic Mar 20, 2023
2398381
Save refactor WIP
entropidelic Mar 20, 2023
25987bd
Refactor compute_deep_composition_poly to generalize for a trace with…
entropidelic Mar 21, 2023
bcc3ba4
Merge branch 'main' into compute_deep_composition_poly-refactor
entropidelic Mar 21, 2023
d68d220
Add comments to dummy transcript challenge calls in verifier
entropidelic Mar 21, 2023
c9c725b
Use a better variable name
entropidelic Mar 21, 2023
cc90ee2
Merge branch 'main' into compute_deep_composition_poly-refactor
entropidelic Mar 21, 2023
6926477
Remove debug comment
entropidelic Mar 21, 2023
9e77305
Add comments and documentation
entropidelic Mar 22, 2023
75c74f0
Fix typo
entropidelic Mar 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion proving_system/stark/src/air/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pub struct AirContext {
pub options: ProofOptions,
pub trace_length: usize,
pub trace_info: (usize, usize),
pub trace_columns: usize,
pub transition_degrees: Vec<usize>,
/// This is a vector with the indices of all the rows that constitute
/// an evaluation frame. Note that, because of how we write all constraints
Expand Down
35 changes: 26 additions & 9 deletions proving_system/stark/src/air/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,31 @@ impl<F: IsField> Frame<F> {
Self::new(data, 1)
}

/// Given a slice of trace polynomials, an evaluation point `x`, the frame offsets
/// corresponding to the computation of the transitions, and a primitive root,
/// outputs the trace evaluations of each trace polynomial over the values used to
/// compute a transition.
/// Example: For a simple Fibonacci computation, if t(x) is the trace polynomial of
/// the computation, this will output evaluations t(x), t(g * x), t(g^2 * z).
pub fn get_trace_evaluations(
trace_polys: &[Polynomial<FieldElement<F>>],
x: &FieldElement<F>,
frame_offsets: &[usize],
primitive_root: &FieldElement<F>,
) -> Vec<Vec<FieldElement<F>>> {
let mut evaluations = Vec::with_capacity(trace_polys.len());
let evaluation_points: Vec<FieldElement<F>> = frame_offsets
.iter()
.map(|offset| x * primitive_root.pow(*offset))
.collect();

trace_polys
.iter()
.for_each(|p| evaluations.push(p.evaluate_slice(&evaluation_points)));

evaluations
}

/// Returns the Out of Domain Frame for the given trace polynomials, out of domain evaluation point (called `z` in the literature),
/// frame offsets given by the AIR and primitive root used for interpolating the trace polynomials.
/// An out of domain frame is nothing more than the evaluation of the trace polynomials in the points required by the
Expand All @@ -65,15 +90,7 @@ impl<F: IsField> Frame<F> {
frame_offsets: &[usize],
primitive_root: &FieldElement<F>,
) -> Self {
let mut data = vec![];
let evaluation_points: Vec<FieldElement<F>> = frame_offsets
.iter()
.map(|offset| z * primitive_root.pow(*offset))
.collect();

for poly in trace_polys {
data.push(poly.evaluate_slice(&evaluation_points));
}
let data = Self::get_trace_evaluations(trace_polys, z, frame_offsets, primitive_root);

Self {
data: data.into_iter().flatten().collect(),
Expand Down
3 changes: 3 additions & 0 deletions proving_system/stark/src/air/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,7 @@ pub trait AIR: Clone {
fn blowup_factor(&self) -> u8 {
self.options().blowup_factor
}
fn num_transition_constraints(&self) -> usize {
self.context().num_transition_constraints
}
}
23 changes: 11 additions & 12 deletions proving_system/stark/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ mod tests {
#[test]
fn test_prove_fib() {
let trace = fibonacci_trace([FE::from(1), FE::from(1)], 4);
let trace_table = TraceTable {
table: trace.clone(),
num_cols: 1,
};

let context = AirContext {
options: ProofOptions {
Expand All @@ -78,18 +82,13 @@ mod tests {
coset_offset: 3,
},
trace_length: trace.len(),
trace_info: (trace.len(), 1),
trace_columns: trace_table.num_cols,
transition_degrees: vec![1],
transition_exemptions: vec![trace.len() - 2, trace.len() - 1],
transition_offsets: vec![0, 1, 2],
num_transition_constraints: 1,
};

let trace_table = TraceTable {
table: trace.clone(),
num_cols: 1,
};

let fibonacci_air = FibonacciAIR::new(trace_table, context);

let result = prove(&trace, &fibonacci_air);
Expand All @@ -101,25 +100,25 @@ mod tests {
fn test_prove_fib17() {
let trace = fibonacci_trace([FE17::new(1), FE17::new(1)], 4);

let trace_table = TraceTable {
table: trace.clone(),
num_cols: 1,
};

let context = AirContext {
options: ProofOptions {
blowup_factor: 2,
fri_number_of_queries: 1,
coset_offset: 3,
},
trace_length: trace.len(),
trace_info: (trace.len(), 1),
trace_columns: trace_table.num_cols,
transition_degrees: vec![1],
transition_exemptions: vec![trace.len() - 2, trace.len() - 1],
transition_offsets: vec![0, 1, 2],
num_transition_constraints: 1,
};

let trace_table = TraceTable {
table: trace.clone(),
num_cols: 1,
};

let fibonacci_air = Fibonacci17AIR::new(trace_table, context);

let result = prove(&trace, &fibonacci_air);
Expand Down
77 changes: 45 additions & 32 deletions proving_system/stark/src/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use lambdaworks_math::{
element::FieldElement,
traits::{IsField, IsTwoAdicField},
},
polynomial::{self, Polynomial},
polynomial::Polynomial,
traits::ByteConversion,
};

Expand Down Expand Up @@ -100,11 +100,13 @@ where

// Compute DEEP composition polynomial so we can commit to it using FRI.
let mut deep_composition_poly = compute_deep_composition_poly(
&trace_poly,
air,
&[trace_poly],
&composition_poly_even,
&composition_poly_odd,
&z,
&trace_primitive_root,
transcript,
);

// * Do FRI on the composition polynomials
Expand All @@ -121,7 +123,7 @@ where

for _i in 0..air.context().options.fri_number_of_queries {
// * Sample q_1, ..., q_m using Fiat-Shamir
let q_i: usize = transcript_to_usize(transcript) % 2_usize.pow(lde_root_order);
let q_i = transcript_to_usize(transcript) % 2_usize.pow(lde_root_order);
transcript.append(&q_i.to_be_bytes());

// * For every q_i, do FRI decommitment
Expand Down Expand Up @@ -149,52 +151,63 @@ where
/// Returns the DEEP composition polynomial that the prover then commits to using
/// FRI. This polynomial is a linear combination of the trace polynomial and the
/// composition polynomial, with coefficients sampled by the verifier (i.e. using Fiat-Shamir).
fn compute_deep_composition_poly<F: IsField>(
trace_poly: &Polynomial<FieldElement<F>>,
fn compute_deep_composition_poly<A: AIR, F: IsField>(
air: &A,
trace_polys: &[Polynomial<FieldElement<F>>],
even_composition_poly: &Polynomial<FieldElement<F>>,
odd_composition_poly: &Polynomial<FieldElement<F>>,
ood_evaluation_point: &FieldElement<F>,
primitive_root: &FieldElement<F>,
transcript: &mut Transcript,
) -> Polynomial<FieldElement<F>> {
// TODO: Fiat-Shamir
let gamma_1 = FieldElement::one();
let gamma_2 = FieldElement::one();
let gamma_3 = FieldElement::one();
let gamma_4 = FieldElement::one();
let transition_offsets = air.context().transition_offsets;

// Get the number of trace terms the DEEP composition poly will have.
// One coefficient will be sampled for each of them.
let n_trace_terms = transition_offsets.len() * trace_polys.len();
let mut trace_term_coeffs = Vec::with_capacity(n_trace_terms);
for _ in 0..n_trace_terms {
trace_term_coeffs.push(transcript_to_field::<F>(transcript));
}

let first_term = (trace_poly.clone()
- Polynomial::new_monomial(trace_poly.evaluate(ood_evaluation_point), 0))
/ (Polynomial::new_monomial(FieldElement::one(), 1)
- Polynomial::new_monomial(ood_evaluation_point.clone(), 0));
let second_term = (trace_poly.clone()
- Polynomial::new_monomial(
trace_poly.evaluate(&(ood_evaluation_point * primitive_root)),
0,
))
/ (Polynomial::new_monomial(FieldElement::one(), 1)
- Polynomial::new_monomial(ood_evaluation_point * primitive_root, 0));
// Get coefficients for even and odd terms of the composition polynomial H(x)
let gamma_even = transcript_to_field::<F>(transcript);
let gamma_odd = transcript_to_field::<F>(transcript);

// Evaluate in X^2
let even_composition_poly = polynomial::compose(
even_composition_poly,
&Polynomial::new_monomial(FieldElement::one(), 2),
);
let odd_composition_poly = polynomial::compose(
odd_composition_poly,
&Polynomial::new_monomial(FieldElement::one(), 2),
// Get trace evaluations needed for the trace terms of the deep composition polynomial
let trace_evaluations = Frame::get_trace_evaluations(
trace_polys,
ood_evaluation_point,
&transition_offsets,
primitive_root,
);

let third_term = (even_composition_poly.clone()
// Compute all the trace terms of the deep composition polynomial. There will be one
// term for every trace polynomial and every trace evaluation.
let mut trace_terms = Polynomial::zero();
for (trace_evaluation, trace_poly) in trace_evaluations.iter().zip(trace_polys) {
for (eval, coeff) in trace_evaluation.iter().zip(&trace_term_coeffs) {
let poly = (trace_poly.clone()
- Polynomial::new_monomial(trace_poly.evaluate(eval), 0))
/ (Polynomial::new_monomial(FieldElement::<F>::one(), 1)
- Polynomial::new_monomial(eval.clone(), 0));

trace_terms = trace_terms + poly * coeff.clone();
Comment on lines +190 to +195
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid some of the clones here?

}
}

let even_composition_poly_term = (even_composition_poly.clone()
- Polynomial::new_monomial(
even_composition_poly.evaluate(&ood_evaluation_point.clone()),
0,
))
/ (Polynomial::new_monomial(FieldElement::one(), 1)
- Polynomial::new_monomial(ood_evaluation_point * ood_evaluation_point, 0));
let fourth_term = (odd_composition_poly.clone()

let odd_composition_poly_term = (odd_composition_poly.clone()
Comment on lines +199 to +207
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here as well.

- Polynomial::new_monomial(odd_composition_poly.evaluate(ood_evaluation_point), 0))
/ (Polynomial::new_monomial(FieldElement::one(), 1)
- Polynomial::new_monomial(ood_evaluation_point * ood_evaluation_point, 0));

first_term * gamma_1 + second_term * gamma_2 + third_term * gamma_3 + fourth_term * gamma_4
trace_terms + even_composition_poly_term * gamma_even + odd_composition_poly_term * gamma_odd
}
14 changes: 13 additions & 1 deletion proving_system/stark/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ where
let lde_root_order =
(air.context().trace_length * air.options().blowup_factor as usize).trailing_zeros();

// We have to make the call to `transcript.challenge()` a number of times since we need
// the transcript to be in the same state as the one in the prover at this stage.
// The prover samples coefficients when building the deep composition polynomial. These
// sampling is not done in the verifier hence we need to make this dummy calls.
// There will be one call for each trace term in the deep composition polynomial + 2 from
// the even and odd terms of the H(x) polynomial.
let deep_poly_challenges =
air.context().transition_offsets.len() * air.context().trace_columns + 2;
(0..deep_poly_challenges).for_each(|_| {
transcript.challenge();
});

// construct vector of betas
let mut beta_list = Vec::new();
let count_betas = proof.fri_layers_merkle_roots.len() - 1;
Expand All @@ -127,7 +139,7 @@ where
let last_evaluation_bytes = last_evaluation.to_bytes_be();
transcript.append(&last_evaluation_bytes);

let q_i: usize = transcript_to_usize(transcript) % (2_usize.pow(lde_root_order));
let q_i = transcript_to_usize(transcript) % (2_usize.pow(lde_root_order));
transcript.append(&q_i.to_be_bytes());

let fri_decommitment = &proof_i.fri_decommitment;
Expand Down