Skip to content

Commit

Permalink
Merge branch 'al-zk' into al-zk-after-merge
Browse files Browse the repository at this point in the history
  • Loading branch information
Al-Kindi-0 committed Nov 6, 2024
2 parents 5a57503 + 589a1c9 commit d11f56a
Show file tree
Hide file tree
Showing 80 changed files with 1,498 additions and 336 deletions.
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ members = [
"prover",
"verifier",
"winterfell",
"examples"
]
"examples"]
resolver = "2"

[profile.release]
Expand Down
2 changes: 2 additions & 0 deletions air/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ libm = "0.2"
math = { version = "0.10", path = "../math", package = "winter-math", default-features = false }
utils = { version = "0.10", path = "../utils/core", package = "winter-utils", default-features = false }

libc-print = "0.1.23"

[dev-dependencies]
rand-utils = { version = "0.10", path = "../utils/rand", package = "winter-rand-utils" }

Expand Down
2 changes: 1 addition & 1 deletion air/src/air/boundary/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ where
let group = groups.entry(key).or_insert_with(|| {
BoundaryConstraintGroup::new(ConstraintDivisor::from_assertion(
&assertion,
context.trace_len(),
context.trace_info().length(),
))
});

Expand Down
165 changes: 148 additions & 17 deletions air/src/air/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ pub struct AirContext<B: StarkField> {
pub(super) trace_domain_generator: B,
pub(super) lde_domain_generator: B,
pub(super) num_transition_exemptions: usize,
pub(super) trace_length_ext: usize,
pub(super) zk_parameters: Option<ZkParameters>,
}

impl<B: StarkField> AirContext<B> {
Expand Down Expand Up @@ -133,18 +135,35 @@ impl<B: StarkField> AirContext<B> {
);
}

let h = options.zk_witness_randomizer_degree().unwrap_or(0);
let trace_length = trace_info.length();
let trace_length_ext = (trace_length + h as usize).next_power_of_two();
let zk_blowup = trace_length_ext / trace_length;
let lde_domain_size = trace_length_ext * options.blowup_factor();
// equation (12) in https://eprint.iacr.org/2024/1037
let h_q = options.num_queries() + 1;
let zk_parameters = if options.is_zk() {
Some(ZkParameters {
degree_witness_randomizer: h as usize,
degree_constraint_randomizer: h_q,
zk_blowup_witness: zk_blowup,
})
} else {
None
};

// determine minimum blowup factor needed to evaluate transition constraints by taking
// the blowup factor of the highest degree constraint
let mut ce_blowup_factor = 0;
for degree in main_transition_constraint_degrees.iter() {
if degree.min_blowup_factor() > ce_blowup_factor {
ce_blowup_factor = degree.min_blowup_factor();
if degree.min_blowup_factor(trace_length, trace_length_ext) > ce_blowup_factor {
ce_blowup_factor = degree.min_blowup_factor(trace_length, trace_length_ext);
}
}

for degree in aux_transition_constraint_degrees.iter() {
if degree.min_blowup_factor() > ce_blowup_factor {
ce_blowup_factor = degree.min_blowup_factor();
if degree.min_blowup_factor(trace_length, trace_length_ext) > ce_blowup_factor {
ce_blowup_factor = degree.min_blowup_factor(trace_length, trace_length_ext);
}
}

Expand All @@ -155,9 +174,6 @@ impl<B: StarkField> AirContext<B> {
options.blowup_factor()
);

let trace_length = trace_info.length();
let lde_domain_size = trace_length * options.blowup_factor();

AirContext {
options,
trace_info,
Expand All @@ -170,6 +186,8 @@ impl<B: StarkField> AirContext<B> {
trace_domain_generator: B::get_root_of_unity(trace_length.ilog2()),
lde_domain_generator: B::get_root_of_unity(lde_domain_size.ilog2()),
num_transition_exemptions: 1,
trace_length_ext,
zk_parameters,
}
}

Expand All @@ -188,25 +206,31 @@ impl<B: StarkField> AirContext<B> {
self.trace_info.length()
}

/// Returns length of the possibly extended execution trace. This is the same as the original
/// trace length when zero-knowledge is not enabled.
pub fn trace_length_ext(&self) -> usize {
self.trace_length_ext
}

/// Returns degree of trace polynomials for an instance of a computation.
///
/// The degree is always `trace_length` - 1.
/// The degree is always `trace_length_ext` - 1.
pub fn trace_poly_degree(&self) -> usize {
self.trace_info.length() - 1
self.trace_length_ext() - 1
}

/// Returns size of the constraint evaluation domain.
///
/// This is guaranteed to be a power of two, and is equal to `trace_length * ce_blowup_factor`.
/// This is guaranteed to be a power of two, and is equal to `trace_length_ext * ce_blowup_factor`.
pub fn ce_domain_size(&self) -> usize {
self.trace_info.length() * self.ce_blowup_factor
self.trace_length_ext() * self.ce_blowup_factor
}

/// Returns the size of the low-degree extension domain.
///
/// This is guaranteed to be a power of two, and is equal to `trace_length * lde_blowup_factor`.
/// This is guaranteed to be a power of two, and is equal to `trace_length_ext * lde_blowup_factor`.
pub fn lde_domain_size(&self) -> usize {
self.trace_info.length() * self.options.blowup_factor()
self.trace_length_ext() * self.options.blowup_factor()
}

/// Returns the number of transition constraints for a computation, excluding the Lagrange
Expand Down Expand Up @@ -292,14 +316,57 @@ impl<B: StarkField> AirContext<B> {
/// numerator is `trace_len - 1` for all transition constraints (i.e. the base degree is 1).
/// Hence, no matter what the degree of the divisor is for each, the degree of the fraction will
/// be at most `trace_len - 1`.
///
/// TODO: update documentation
pub fn num_constraint_composition_columns(&self) -> usize {
let mut highest_constraint_degree = 0_usize;
for degree in self
.main_transition_constraint_degrees
.iter()
.chain(self.aux_transition_constraint_degrees.iter())
{
let eval_degree = degree.get_evaluation_degree(self.trace_len());
let eval_degree =
degree.get_evaluation_degree(self.trace_len(), self.trace_length_ext());
if eval_degree > highest_constraint_degree {
highest_constraint_degree = eval_degree
}
}
let trace_length = self.trace_len();
let trace_length_ext = self.trace_length_ext();
let transition_divisior_degree = trace_length - self.num_transition_exemptions();

// we use the identity: ceil(a/b) = (a + b - 1)/b
let num_constraint_col =
(highest_constraint_degree - transition_divisior_degree + trace_length_ext - 1)
/ trace_length_ext;

if self.zk_parameters.is_some() {
let quotient_degree = if highest_constraint_degree < trace_length_ext {
// This means that our transition constraints have degree 1 and hence the boundary
// constraints will determine the degree
trace_length_ext - 2
} else {
highest_constraint_degree - transition_divisior_degree
};
let n_q = self.options.num_queries();
let den = self.trace_length_ext() - (n_q + 1);

// we use the identity: ceil(a/b) = (a + b - 1)/b
(quotient_degree + 1 + den - 1) / den
} else {
cmp::max(num_constraint_col, 1)
}
}

pub fn constraint_composition_degree(&self) -> usize {
let mut highest_constraint_degree = 0_usize;
for degree in self
.main_transition_constraint_degrees
.iter()
.chain(self.aux_transition_constraint_degrees.iter())
{
let eval_degree =
degree.get_evaluation_degree(self.trace_len(), self.trace_length_ext());
if eval_degree > highest_constraint_degree {
highest_constraint_degree = eval_degree
}
Expand All @@ -310,8 +377,49 @@ impl<B: StarkField> AirContext<B> {
// we use the identity: ceil(a/b) = (a + b - 1)/b
let num_constraint_col =
(highest_constraint_degree - transition_divisior_degree).div_ceil(trace_length);
// highest_constraint_degree - transition_divisior_degree
if highest_constraint_degree < self.trace_length_ext {
// This means that our transition constraints have degree 1 and hence the boundary
// constraints will determine the degree
self.trace_length_ext - 2
} else {
highest_constraint_degree - transition_divisior_degree
}
}

pub fn num_coefficients_chunk_quotient(&self) -> usize {
if self.zk_parameters().is_some() {
let num_constraint_composition_cols = self.num_constraint_composition_columns();
let quotient_degree = self.constraint_composition_degree();

cmp::max(num_constraint_col, 1)
// we use the identity: ceil(a/b) = (a + b - 1)/b
(quotient_degree + 1 + num_constraint_composition_cols - 1)
/ num_constraint_composition_cols
} else {
self.trace_len()
}
}

pub fn zk_parameters(&self) -> Option<ZkParameters> {
self.zk_parameters
}

pub fn zk_blowup_factor(&self) -> usize {
self.zk_parameters()
.map(|parameters| parameters.zk_blowup_witness())
.unwrap_or(1)
}

pub fn zk_witness_randomizer_degree(&self) -> usize {
self.zk_parameters()
.map(|parameters| parameters.degree_witness_randomizer())
.unwrap_or(0)
}

pub fn zk_constraint_randomizer_degree(&self) -> usize {
self.zk_parameters()
.map(|parameters| parameters.degree_constraint_randomizer())
.unwrap_or(0)
}

// DATA MUTATORS
Expand Down Expand Up @@ -347,9 +455,11 @@ impl<B: StarkField> AirContext<B> {
.iter()
.chain(self.aux_transition_constraint_degrees.iter())
{
let eval_degree = degree.get_evaluation_degree(self.trace_len());
let eval_degree =
degree.get_evaluation_degree(self.trace_len(), self.trace_length_ext());
let max_constraint_composition_degree = self.ce_domain_size() - 1;
let max_exemptions = max_constraint_composition_degree + self.trace_len() - eval_degree;
let max_exemptions =
max_constraint_composition_degree + self.trace_length_ext() - eval_degree;
assert!(
n <= max_exemptions,
"number of transition exemptions cannot exceed: {max_exemptions}, but was {n}"
Expand All @@ -360,3 +470,24 @@ impl<B: StarkField> AirContext<B> {
self
}
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub struct ZkParameters {
degree_witness_randomizer: usize,
degree_constraint_randomizer: usize,
zk_blowup_witness: usize,
}

impl ZkParameters {
pub fn degree_witness_randomizer(&self) -> usize {
self.degree_witness_randomizer
}

pub fn degree_constraint_randomizer(&self) -> usize {
self.degree_constraint_randomizer
}

pub fn zk_blowup_witness(&self) -> usize {
self.zk_blowup_witness
}
}
9 changes: 7 additions & 2 deletions air/src/air/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ mod trace_info;
pub use trace_info::TraceInfo;

mod context;
pub use context::AirContext;
pub use context::{AirContext, ZkParameters};

mod assertions;
pub use assertions::Assertion;
Expand Down Expand Up @@ -547,7 +547,7 @@ pub trait Air: Send + Sync {

let lagrange = if self.context().has_lagrange_kernel_aux_column() {
let mut lagrange_kernel_t_coefficients = Vec::new();
for _ in 0..self.context().trace_len().ilog2() {
for _ in 0..self.context().trace_info().length().ilog2() {
lagrange_kernel_t_coefficients.push(public_coin.draw()?);
}

Expand Down Expand Up @@ -600,4 +600,9 @@ pub trait Air: Send + Sync {
lagrange: lagrange_cc,
})
}

/// Returns whether zero-knowledge is enabled.
fn is_zk(&self) -> bool {
self.options().is_zk()
}
}
6 changes: 3 additions & 3 deletions air/src/air/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ impl MockAir {
let mut result = Self::new(
TraceInfo::with_meta(4, trace_length, vec![1]),
(),
ProofOptions::new(32, 8, 0, FieldExtension::None, 4, 31),
ProofOptions::new(32, 8, 0, FieldExtension::None, 4, 31, false),
);
result.periodic_columns = column_values;
result
Expand All @@ -215,7 +215,7 @@ impl MockAir {
let mut result = Self::new(
TraceInfo::with_meta(4, trace_length, vec![assertions.len() as u8]),
(),
ProofOptions::new(32, 8, 0, FieldExtension::None, 4, 31),
ProofOptions::new(32, 8, 0, FieldExtension::None, 4, 31, false),
);
result.assertions = assertions;
result
Expand Down Expand Up @@ -267,7 +267,7 @@ pub fn build_context<B: StarkField>(
trace_width: usize,
num_assertions: usize,
) -> AirContext<B> {
let options = ProofOptions::new(32, 8, 0, FieldExtension::None, 4, 31);
let options = ProofOptions::new(32, 8, 0, FieldExtension::None, 4, 31, false);
let t_degrees = vec![TransitionConstraintDegree::new(2)];
let trace_info = TraceInfo::new(trace_width, trace_length);
AirContext::new(trace_info, t_degrees, num_assertions, options)
Expand Down
17 changes: 12 additions & 5 deletions air/src/air/transition/degree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@ impl TransitionConstraintDegree {
/// $$
/// 2 \cdot (64 - 1) + \frac{64 \cdot (32 - 1)}{32} = 126 + 62 = 188
/// $$
pub fn get_evaluation_degree(&self, trace_length: usize) -> usize {
let mut result = self.base * (trace_length - 1);
///
/// TODO: Update docs
pub fn get_evaluation_degree(&self, trace_length: usize, trace_length_ext: usize) -> usize {
let mut result = self.base * (trace_length_ext - 1);
for cycle_length in self.cycles.iter() {
result += (trace_length / cycle_length) * (cycle_length - 1);
}
Expand All @@ -98,7 +100,7 @@ impl TransitionConstraintDegree {
/// Returns a minimum blowup factor needed to evaluate constraint of this degree.
///
/// This is guaranteed to be a power of two, greater than one.
pub fn min_blowup_factor(&self) -> usize {
pub fn min_blowup_factor(&self, trace_length: usize, trace_length_ext: usize) -> usize {
// The blowup factor needs to be a power of two large enough to accommodate degree of
// transition constraints defined by rational functions `C(x) / z(x)` where `C(x)` is the
// constraint polynomial and `z(x)` is the transition constraint divisor.
Expand All @@ -110,7 +112,12 @@ impl TransitionConstraintDegree {
//
// For example, if degree of our constraints is 6, the blowup factor would need to be 8.
// However, if the degree is 5, the blowup factor could be as small as 4.
let degree_bound = self.base + self.cycles.len() - 1;
cmp::max(degree_bound.next_power_of_two(), ProofOptions::MIN_BLOWUP_FACTOR)
//
// TODO: update documentation
let degree_bound = self.base + self.cycles.len();
let q_deg = degree_bound * (trace_length_ext - 1) - (trace_length - 1);
let blowup_factor = (q_deg + trace_length_ext - 1) / trace_length_ext;

cmp::max(blowup_factor.next_power_of_two(), ProofOptions::MIN_BLOWUP_FACTOR)
}
}
2 changes: 1 addition & 1 deletion air/src/air/transition/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl<E: FieldElement> TransitionConstraints<E> {

// build constraint divisor; the same divisor applies to all transition constraints
let divisor = ConstraintDivisor::from_transition(
context.trace_len(),
context.trace_info().length(),
context.num_transition_exemptions(),
);

Expand Down
2 changes: 1 addition & 1 deletion air/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@ pub use air::{
LagrangeConstraintsCompositionCoefficients, LagrangeKernelBoundaryConstraint,
LagrangeKernelConstraints, LagrangeKernelEvaluationFrame, LagrangeKernelRandElements,
LagrangeKernelTransitionConstraints, TraceInfo, TransitionConstraintDegree,
TransitionConstraints,
TransitionConstraints, ZkParameters,
};
Loading

0 comments on commit d11f56a

Please sign in to comment.