Skip to content

Commit

Permalink
Merge pull request #749 from powdr-labs/get-degree-from-namespaces
Browse files Browse the repository at this point in the history
Get degree from namespaces
  • Loading branch information
Schaeff authored Nov 7, 2023
2 parents e063f7e + 844dd39 commit f5e176d
Show file tree
Hide file tree
Showing 17 changed files with 91 additions and 87 deletions.
6 changes: 6 additions & 0 deletions ast/src/analyzed/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ pub enum StatementIdentifier {

#[derive(Debug)]
pub struct Analyzed<T> {
/// The degree of all namespaces, which must match. If there are no namespaces, then `None`.
pub degree: Option<DegreeType>,
pub definitions: HashMap<String, (Symbol, Option<FunctionValueDefinition<T>>)>,
pub public_declarations: HashMap<String, PublicDeclaration>,
pub intermediate_columns: HashMap<String, (Symbol, AlgebraicExpression<T>)>,
Expand All @@ -35,6 +37,10 @@ pub struct Analyzed<T> {
}

impl<T> Analyzed<T> {
/// @returns the degree if any. Panics if there is none.
pub fn degree(&self) -> DegreeType {
self.degree.unwrap()
}
/// @returns the number of committed polynomials (with multiplicities for arrays)
pub fn commitment_count(&self) -> usize {
self.declaration_type_count(PolynomialType::Committed)
Expand Down
11 changes: 9 additions & 2 deletions backend/src/pilstark/estark.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::iter::{once, repeat};

use crate::{pilstark, BackendImpl};
use ast::analyzed::Analyzed;
use number::{BigInt, DegreeType, FieldElement, GoldilocksField};
Expand Down Expand Up @@ -58,6 +60,8 @@ impl<F: FieldElement> BackendImpl<F> for EStark {

log::info!("Creating eSTARK proof.");

let degree = pil.degree();

let mut pil: PIL = pilstark::json_exporter::export(pil);

// TODO starky requires a fixed column with the equivalent
Expand All @@ -77,15 +81,18 @@ impl<F: FieldElement> BackendImpl<F> for EStark {
polType: None,
type_: "constP".to_string(),
id: fixed.len(),
polDeg: fixed[0].1.len(),
polDeg: degree as usize,
isArray: false,
elementType: None,
len: None,
},
);
fixed.push((
"main.first_step".to_string(),
[vec![F::one()], vec![F::zero(); fixed[0].1.len() - 1]].concat(),
once(F::one())
.chain(repeat(F::zero()))
.take(degree as usize)
.collect(),
));
}

Expand Down
5 changes: 2 additions & 3 deletions compiler/benches/executor_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ fn get_pil() -> Analyzed<T> {

fn run_witgen<T: FieldElement>(analyzed: &Analyzed<T>, input: Vec<T>) {
let query_callback = inputs_to_query_callback(input);
let (constants, degree) = constant_evaluator::generate(analyzed);
executor::witgen::WitnessGenerator::new(analyzed, degree, &constants, query_callback)
.generate();
let constants = constant_evaluator::generate(analyzed);
executor::witgen::WitnessGenerator::new(analyzed, &constants, query_callback).generate();
}

fn criterion_benchmark(c: &mut Criterion) {
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,13 @@ fn compile<T: FieldElement, Q: QueryCallback<T>>(
log::info!("Wrote {}.", optimized_pil_file_name.to_str().unwrap());
let start = Instant::now();
log::info!("Evaluating fixed columns...");
let (constants, degree) = constant_evaluator::generate(&analyzed);
let constants = constant_evaluator::generate(&analyzed);
log::info!("Took {}", start.elapsed().as_secs_f32());

let witness = (analyzed.constant_count() == constants.len()).then(|| {
log::info!("Deducing witness columns...");
let commits =
executor::witgen::WitnessGenerator::new(&analyzed, degree, &constants, query_callback)
executor::witgen::WitnessGenerator::new(&analyzed, &constants, query_callback)
.with_external_witness_values(external_witness_values)
.generate();

Expand All @@ -251,7 +251,7 @@ fn compile<T: FieldElement, Q: QueryCallback<T>>(
// still output the constraint serialization.
let (proof, constraints_serialization) = if let Some(backend) = prove_with {
let factory = backend.factory::<T>();
let backend = factory.create(degree);
let backend = factory.create(analyzed.degree());

backend.prove(
&analyzed,
Expand Down
4 changes: 0 additions & 4 deletions compiler/src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,6 @@ pub fn verify(temp_dir: &Path) {

let constants_file = format!("{}/constants.bin", temp_dir.to_str().unwrap());
let commits_file = format!("{}/commits.bin", temp_dir.to_str().unwrap());
assert!(
fs::metadata(&constants_file).unwrap().len() > 0,
"Empty constants file"
);

let verifier_output = Command::new("node")
.args([
Expand Down
55 changes: 25 additions & 30 deletions executor/src/constant_evaluator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,20 @@ use rayon::prelude::{IntoParallelIterator, ParallelIterator};
/// Generates the constant polynomial values for all constant polynomials
/// that are defined (and not just declared).
/// @returns the values (in source order) and the degree of the polynomials.
pub fn generate<T: FieldElement>(analyzed: &Analyzed<T>) -> (Vec<(&str, Vec<T>)>, DegreeType) {
let mut degree = None;
pub fn generate<T: FieldElement>(analyzed: &Analyzed<T>) -> Vec<(&str, Vec<T>)> {
let mut other_constants = HashMap::new();
for (poly, value) in analyzed.constant_polys_in_source_order() {
if let Some(value) = value {
if let Some(degree) = degree {
assert!(degree == poly.degree);
} else {
degree = Some(poly.degree);
}
assert!(analyzed.degree() == poly.degree);
let values = generate_values(analyzed, poly.degree, value, &other_constants);
other_constants.insert(&poly.absolute_name, values);
}
}
let values = other_constants

other_constants
.into_iter()
.sorted_by_key(|(name, _)| analyzed.definitions[&name.to_string()].0.id)
.collect::<Vec<_>>();
(values, degree.unwrap_or_default())
.collect::<Vec<_>>()
}

fn generate_values<T: FieldElement>(
Expand Down Expand Up @@ -105,8 +100,8 @@ mod test {
} };
"#;
let analyzed = analyze_string(src);
let (constants, degree) = generate(&analyzed);
assert_eq!(degree, 8);
assert_eq!(analyzed.degree(), 8);
let constants = generate(&analyzed);
assert_eq!(
constants,
vec![("F.LAST", convert(vec![0, 0, 0, 0, 0, 0, 0, 1]))]
Expand All @@ -121,8 +116,8 @@ mod test {
pol constant EVEN(i) { 2 * (i - 1) };
"#;
let analyzed = analyze_string(src);
let (constants, degree) = generate(&analyzed);
assert_eq!(degree, 8);
assert_eq!(analyzed.degree(), 8);
let constants = generate(&analyzed);
assert_eq!(
constants,
vec![("F.EVEN", convert(vec![-2, 0, 2, 4, 6, 8, 10, 12]))]
Expand All @@ -137,8 +132,8 @@ mod test {
pol constant X(i) { i ^ (i + 17) | 3 };
"#;
let analyzed = analyze_string(src);
let (constants, degree) = generate(&analyzed);
assert_eq!(degree, 8);
assert_eq!(analyzed.degree(), 8);
let constants = generate(&analyzed);
assert_eq!(
constants,
vec![("F.X", convert((0..8).map(|i| i ^ (i + 17) | 3).collect()))]
Expand All @@ -158,8 +153,8 @@ mod test {
} + 1 };
"#;
let analyzed = analyze_string(src);
let (constants, degree) = generate(&analyzed);
assert_eq!(degree, 8);
assert_eq!(analyzed.degree(), 8);
let constants = generate(&analyzed);
assert_eq!(
constants,
vec![("F.X", convert(vec![8, 5, 5, 10, 5, 3, 5, 5]))]
Expand All @@ -175,8 +170,8 @@ mod test {
pol constant EVEN(i) { 2 * minus_one(i) };
"#;
let analyzed = analyze_string(src);
let (constants, degree) = generate(&analyzed);
assert_eq!(degree, 8);
assert_eq!(analyzed.degree(), 8);
let constants = generate(&analyzed);
assert_eq!(
constants,
vec![("F.EVEN", convert(vec![-2, 0, 2, 4, 6, 8, 10, 12]))]
Expand All @@ -196,8 +191,8 @@ mod test {
pol constant TEN(i) { ite(is_equal(i, 10), 1, 0) };
"#;
let analyzed = analyze_string(src);
let (constants, degree) = generate(&analyzed);
assert_eq!(degree, 12);
assert_eq!(analyzed.degree(), 12);
let constants = generate(&analyzed);
assert_eq!(
constants,
vec![(
Expand All @@ -218,8 +213,8 @@ mod test {
col fixed doubled_half_nibble(i) { half_nibble(i / 2) };
"#;
let analyzed = analyze_string(src);
let (constants, degree) = generate(&analyzed);
assert_eq!(degree, 10);
assert_eq!(analyzed.degree(), 10);
let constants = generate(&analyzed);
assert_eq!(constants.len(), 4);
assert_eq!(
constants[0],
Expand Down Expand Up @@ -258,8 +253,8 @@ mod test {
col fixed ref_other = [%N-1, alt(1), 8] + [0]*;
"#;
let analyzed = analyze_string(src);
let (constants, degree) = generate(&analyzed);
assert_eq!(degree, 10);
assert_eq!(analyzed.degree(), 10);
let constants = generate(&analyzed);
assert_eq!(constants.len(), 3);
assert_eq!(
constants[0],
Expand All @@ -283,8 +278,8 @@ mod test {
col fixed arr = [0, 1, 2]* + [7];
"#;
let analyzed = analyze_string(src);
let (constants, degree) = generate(&analyzed);
assert_eq!(degree, 10);
assert_eq!(analyzed.degree(), 10);
let constants = generate(&analyzed);
assert_eq!(constants.len(), 1);
assert_eq!(
constants[0],
Expand Down Expand Up @@ -312,8 +307,8 @@ mod test {
col fixed greater_eq(i) { id(i) >= inv(i) };
"#;
let analyzed = analyze_string(src);
let (constants, degree) = generate(&analyzed);
assert_eq!(degree, 6);
assert_eq!(analyzed.degree(), 6);
let constants = generate(&analyzed);
assert_eq!(constants[0], ("F.id", convert([0, 1, 2, 3, 4, 5].to_vec())));
assert_eq!(
constants[1],
Expand Down
6 changes: 3 additions & 3 deletions executor/src/witgen/block_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ mod tests {
f: impl Fn(BlockProcessor<T, Q, WithoutCalldata>, BTreeMap<String, PolyID>, u64, usize) -> R,
) -> R {
let analyzed = analyze_string(src);
let (constants, degree) = generate(&analyzed);
let fixed_data = FixedData::new(&analyzed, degree, &constants, vec![]);
let constants = generate(&analyzed);
let fixed_data = FixedData::new(&analyzed, &constants, vec![]);

// No global range constraints
let global_range_constraints = GlobalConstraints {
Expand Down Expand Up @@ -185,7 +185,7 @@ mod tests {
f(
processor,
name_to_poly_id(&fixed_data),
degree,
analyzed.degree(),
identities.len(),
)
}
Expand Down
2 changes: 1 addition & 1 deletion executor/src/witgen/global_constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ namespace Global(2**20);
{ D } in { SHIFTED };
";
let analyzed = pil_analyzer::analyze_string::<GoldilocksField>(pil_source);
let (constants, _) = crate::constant_evaluator::generate(&analyzed);
let constants = crate::constant_evaluator::generate(&analyzed);
let fixed_polys = (0..constants.len())
.map(|i| constant_poly_id(i as u64))
.collect::<Vec<_>>();
Expand Down
13 changes: 2 additions & 11 deletions executor/src/witgen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::collections::BTreeMap;
use ast::analyzed::{
AlgebraicReference, Analyzed, Expression, FunctionValueDefinition, PolyID, PolynomialType,
};
use num_traits::Zero;
use number::{DegreeType, FieldElement};

use self::data_structures::column_map::{FixedColumnMap, WitnessColumnMap};
Expand Down Expand Up @@ -50,7 +49,6 @@ pub struct MutableState<'a, 'b, T: FieldElement, Q: QueryCallback<T>> {

pub struct WitnessGenerator<'a, 'b, T: FieldElement, Q: QueryCallback<T>> {
analyzed: &'a Analyzed<T>,
degree: DegreeType,
fixed_col_values: &'b [(&'a str, Vec<T>)],
query_callback: Q,
external_witness_values: Vec<(&'a str, Vec<T>)>,
Expand All @@ -59,13 +57,11 @@ pub struct WitnessGenerator<'a, 'b, T: FieldElement, Q: QueryCallback<T>> {
impl<'a, 'b, T: FieldElement, Q: QueryCallback<T>> WitnessGenerator<'a, 'b, T, Q> {
pub fn new(
analyzed: &'a Analyzed<T>,
degree: DegreeType,
fixed_col_values: &'b [(&'a str, Vec<T>)],
query_callback: Q,
) -> Self {
WitnessGenerator {
analyzed,
degree,
fixed_col_values,
query_callback,
external_witness_values: Vec::new(),
Expand All @@ -85,12 +81,8 @@ impl<'a, 'b, T: FieldElement, Q: QueryCallback<T>> WitnessGenerator<'a, 'b, T, Q
/// Generates the committed polynomial values
/// @returns the values (in source order) and the degree of the polynomials.
pub fn generate(self) -> Vec<(&'a str, Vec<T>)> {
if self.degree.is_zero() {
panic!("Resulting degree is zero. Please ensure that there is at least one non-constant fixed column to set the degree.");
}
let fixed = FixedData::new(
self.analyzed,
self.degree,
self.fixed_col_values,
self.external_witness_values,
);
Expand Down Expand Up @@ -169,7 +161,6 @@ pub struct FixedData<'a, T> {
impl<'a, T: FieldElement> FixedData<'a, T> {
pub fn new(
analyzed: &'a Analyzed<T>,
degree: DegreeType,
fixed_col_values: &'a [(&str, Vec<T>)],
external_witness_values: Vec<(&'a str, Vec<T>)>,
) -> Self {
Expand All @@ -187,7 +178,7 @@ impl<'a, T: FieldElement> FixedData<'a, T> {
let external_values =
external_witness_values.remove(poly.absolute_name.as_str());
if let Some(external_values) = &external_values {
assert_eq!(external_values.len(), degree as usize);
assert_eq!(external_values.len(), analyzed.degree() as usize);
}
let col = WitnessColumn::new(i, &poly.absolute_name, value, external_values);
col
Expand All @@ -204,7 +195,7 @@ impl<'a, T: FieldElement> FixedData<'a, T> {
let fixed_cols =
FixedColumnMap::from(fixed_col_values.iter().map(|(n, v)| FixedColumn::new(n, v)));
FixedData {
degree,
degree: analyzed.degree(),
fixed_cols,
witness_cols,
}
Expand Down
2 changes: 1 addition & 1 deletion halo2/src/circuit_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl<'a, T: FieldElement> CircuitData<'a, T> {
}

pub fn len(&self) -> usize {
self.fixed.get(0).unwrap().1.len()
self.witness.get(0).unwrap().1.len()
}

pub fn insert_constant<IT: IntoIterator<Item = T>>(
Expand Down
10 changes: 4 additions & 6 deletions halo2/src/mock_prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,9 @@ mod test {

let analyzed = pil_analyzer::analyze_string(&format!("{pil}"));

let (fixed, degree) = executor::constant_evaluator::generate(&analyzed);
let fixed = executor::constant_evaluator::generate(&analyzed);
let witness =
executor::witgen::WitnessGenerator::new(&analyzed, degree, &fixed, query_callback)
.generate();
executor::witgen::WitnessGenerator::new(&analyzed, &fixed, query_callback).generate();

let fixed = to_owned_values(fixed);
let witness = to_owned_values(witness);
Expand All @@ -103,13 +102,12 @@ mod test {
fn simple_pil_halo2() {
let content = "namespace Global(8); pol fixed z = [0]*; pol witness a; a = 0;";
let analyzed: Analyzed<Bn254Field> = pil_analyzer::analyze_string(content);
let (fixed, degree) = executor::constant_evaluator::generate(&analyzed);
let fixed = executor::constant_evaluator::generate(&analyzed);

let query_callback = |_: &str| -> Option<Bn254Field> { None };

let witness =
executor::witgen::WitnessGenerator::new(&analyzed, degree, &fixed, query_callback)
.generate();
executor::witgen::WitnessGenerator::new(&analyzed, &fixed, query_callback).generate();

let fixed = to_owned_values(fixed);
let witness = to_owned_values(witness);
Expand Down
4 changes: 2 additions & 2 deletions halo2/src/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl Halo2Prover {
witness: &[(String, Vec<F>)],
) -> Vec<u8> {
// TODO this is hacky
let degree = usize::BITS - fixed[0].1.len().leading_zeros() + 1;
let degree = usize::BITS - pil.degree().leading_zeros() + 1;
let params = {
let mut params = self.params.clone();
params.downsize(degree);
Expand Down Expand Up @@ -111,7 +111,7 @@ impl Halo2Prover {
log::info!("Starting proof aggregation...");

// TODO this is hacky
let degree = usize::BITS - fixed[0].1.len().leading_zeros() + 1;
let degree = usize::BITS - pil.degree().leading_zeros() + 1;
let params_app = {
let mut params = self.params.clone();
params.downsize(degree);
Expand Down
Loading

0 comments on commit f5e176d

Please sign in to comment.