Skip to content
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

Adding zero-knowledge #293

Draft
wants to merge 1 commit into
base: next
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
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: 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
161 changes: 142 additions & 19 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,26 +316,102 @@ 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).div_ceil(trace_length);
(highest_constraint_degree - transition_divisior_degree).div_ceil(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);

(quotient_degree + 1).div_ceil(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
}
}
let trace_length = self.trace_len();
let transition_divisior_degree = trace_length - self.num_transition_exemptions();

cmp::max(num_constraint_col, 1)
// 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();

(quotient_degree + 1).div_ceil(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 +447,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 +462,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.div_ceil(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
Loading