diff --git a/Cargo.toml b/Cargo.toml index 821bc51d..8d1c01d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ "zkit", + "zkvm", "plonky", "starky", "algebraic", diff --git a/README.md b/README.md index b0074872..f40f3afe 100644 --- a/README.md +++ b/README.md @@ -2,21 +2,21 @@ eigen-zkvm is a zkVM on layered proof system, allowing the developers to write Zero-knowledge applications, proving with the layered proof system to achieve no trusted setup, constant on-chain proof size and low gas cost, and finally generating the solidity verifier. -- [x] zkit: universal commandline for starky and plonky +- [x] zkit: universal commandline for stark, plonk and groth16. - [x] Circom 2.x on PlonK prove system; -- [x] Aggregation Proof over both Stark and Snark proof; +- [x] Proof composition: proof aggregation and recursion on Stark; -- [x] Generate solidity verifier; +- [X] Proof Recursion with Snark on Stark; -- [x] GPU acceleration for proving, not opensourced; +- [x] Solidity verifier generation; -- [x] WASM friendly for single proving and verifying, NodeJS/Javascript prover and verifier, [plonkjs](https://github.com/0xEigenLabs/plonkjs) +- [x] GPU acceleration for proving, not opensourced; -- [x] Layered Proof system on Plonk and FRI. +- [x] WASM friendly for single proving and verifying, NodeJS/Javascript prover and verifier, [plonkjs](https://github.com/0xEigenLabs/plonkjs); -- [] State Machine based VM +- [] Eigen zkVM: Risc V, Continuation. ## How layered proof system works diff --git a/starky/Cargo.toml b/starky/Cargo.toml index 2ac1ea1b..b129fc24 100644 --- a/starky/Cargo.toml +++ b/starky/Cargo.toml @@ -34,9 +34,9 @@ plonky = { package="plonky", path = "../plonky", version = "0.0.2" } algebraic = { path = "../algebraic" } #powdr pil compile tool. branch = "main" -pil_analyzer = {git = "https://github.com/powdr-labs/powdr.git", rev = "eb593dee15e194bd066085022f8a6ea52e2dab9b", package = "pil_analyzer"} -number = {git = "https://github.com/powdr-labs/powdr.git", rev = "eb593dee15e194bd066085022f8a6ea52e2dab9b", package = "number"} -ast = {git = "https://github.com/powdr-labs/powdr.git", rev = "eb593dee15e194bd066085022f8a6ea52e2dab9b",package = "ast"} +pil_analyzer = {git = "https://github.com/powdr-labs/powdr.git", branch = "main", package = "pil_analyzer"} +number = {git = "https://github.com/powdr-labs/powdr.git", branch = "main", package = "number"} +ast = {git = "https://github.com/powdr-labs/powdr.git", branch = "main",package = "ast"} [dev-dependencies] @@ -59,4 +59,4 @@ harness = false [[bench]] name = "poseidon" -harness = false \ No newline at end of file +harness = false diff --git a/starky/src/pilcom/export.rs b/starky/src/pilcom/export.rs index 5644299e..8335eff3 100644 --- a/starky/src/pilcom/export.rs +++ b/starky/src/pilcom/export.rs @@ -8,9 +8,8 @@ use crate::types::{ PolIdentity, Public, Reference, PIL, }; use ast::analyzed::{ - Analyzed, BinaryOperator, Expression, FunctionValueDefinition, IdentityKind, PolyID, - PolynomialReference, PolynomialType, Reference::*, StatementIdentifier, SymbolKind, - UnaryOperator, + AlgebraicBinaryOperator, AlgebraicExpression as Expression, AlgebraicUnaryOperator, Analyzed, + IdentityKind, PolyID, PolynomialType, StatementIdentifier, SymbolKind, }; use super::expression_counter::compute_intermediate_expression_ids; @@ -46,23 +45,26 @@ pub fn export(analyzed: &Analyzed) -> PIL { for item in &analyzed.source_order { match item { StatementIdentifier::Definition(name) => { - if let (poly, Some(value)) = &analyzed.definitions[name] { - if poly.kind == SymbolKind::Poly(PolynomialType::Intermediate) { - if let FunctionValueDefinition::Expression(value) = value { - let expression_id = exporter.extract_expression(value, 1); - assert_eq!( - expression_id, - exporter.intermediate_poly_expression_ids[&poly.id] as usize - ); - } else { - panic!("Expected single value"); - } - } + if let Some((poly, value)) = analyzed.intermediate_columns.get(name) { + assert_eq!(poly.kind, SymbolKind::Poly(PolynomialType::Intermediate)); + let expression_id = exporter.extract_expression(value, 1); + assert_eq!( + expression_id, + exporter.intermediate_poly_expression_ids[&poly.id] as usize + ); } } StatementIdentifier::PublicDeclaration(name) => { let pub_def = &analyzed.public_declarations[name]; - let (_, expr) = exporter.polynomial_reference_to_json(&pub_def.polynomial); + let pub_ref = &pub_def.polynomial; + let poly_id = pub_ref.poly_id.unwrap(); + let (_, expr) = exporter.polynomial_reference_to_json( + PolyID { + id: poly_id.id + pub_def.array_index.unwrap_or_default() as u64, + ..poly_id + }, + false, + ); let id = publics.len(); publics.push(Public { polType: polynomial_reference_type_to_type(&expr.op).to_string(), @@ -145,6 +147,7 @@ fn symbol_kind_to_json_string(k: SymbolKind) -> &'static str { match k { SymbolKind::Poly(poly_type) => polynomial_type_to_json_string(poly_type), SymbolKind::Other() => panic!("Cannot translate \"other\" symbol to json."), + SymbolKind::Constant() => unreachable!(), } } @@ -183,23 +186,46 @@ impl<'a, T: FieldElement> Exporter<'a, T> { self.analyzed .definitions .iter() - .map(|(name, (symbol, _value))| { - let id = if symbol.kind == SymbolKind::Poly(PolynomialType::Intermediate) { - self.intermediate_poly_expression_ids[&symbol.id] - } else { - symbol.id - }; + .filter_map(|(name, (symbol, _value))| { + let id = match symbol.kind { + SymbolKind::Poly(PolynomialType::Intermediate) => { + panic!("Should be in intermediates") + } + SymbolKind::Poly(_) => Some(symbol.id), + SymbolKind::Other() | SymbolKind::Constant() => None, + }?; + let out = Reference { polType: None, type_: symbol_kind_to_json_string(symbol.kind).to_string(), id: id as usize, - polDeg: symbol.degree as usize, + polDeg: self.analyzed.degree() as usize, isArray: symbol.is_array(), elementType: None, len: symbol.length.map(|l| l as usize), }; - (name.clone(), out) + Some((name.clone(), out)) }) + .chain( + self.analyzed + .intermediate_columns + .iter() + .map(|(name, (symbol, _))| { + assert_eq!(symbol.kind, SymbolKind::Poly(PolynomialType::Intermediate)); + let id = self.intermediate_poly_expression_ids[&symbol.id]; + + let out = Reference { + polType: None, + type_: symbol_kind_to_json_string(symbol.kind).to_string(), + id: id as usize, + polDeg: self.analyzed.degree() as usize, + isArray: symbol.is_array(), + elementType: None, + len: symbol.length.map(|l| l as usize), + }; + (name.clone(), out) + }), + ) .collect::>() } @@ -235,18 +261,8 @@ impl<'a, T: FieldElement> Exporter<'a, T> { /// returns the degree and the JSON value (intermediate polynomial IDs) fn expression_to_json(&self, expr: &Expression) -> (u32, StarkyExpr) { match expr { - Expression::Constant(name) => ( - 0, - StarkyExpr { - op: "number".to_string(), - deg: 0, - value: Some(format!("{}", self.analyzed.constants[name])), - ..DEFAULT_EXPR - }, - ), - Expression::Reference(Poly(reference)) => self.polynomial_reference_to_json(reference), - Expression::Reference(LocalVar(_, _)) => { - panic!("No local variable references allowed here.") + Expression::Reference(reference) => { + self.polynomial_reference_to_json(reference.poly_id, reference.next) } Expression::PublicReference(name) => ( 0, @@ -270,11 +286,10 @@ impl<'a, T: FieldElement> Exporter<'a, T> { let (deg_left, left) = self.expression_to_json(left); let (deg_right, right) = self.expression_to_json(right); let (op, degree) = match op { - BinaryOperator::Add => ("add", cmp::max(deg_left, deg_right)), - BinaryOperator::Sub => ("sub", cmp::max(deg_left, deg_right)), - BinaryOperator::Mul => ("mul", deg_left + deg_right), - BinaryOperator::Div => panic!("Div is not really allowed"), - BinaryOperator::Pow => { + AlgebraicBinaryOperator::Add => ("add", cmp::max(deg_left, deg_right)), + AlgebraicBinaryOperator::Sub => ("sub", cmp::max(deg_left, deg_right)), + AlgebraicBinaryOperator::Mul => ("mul", deg_left + deg_right), + AlgebraicBinaryOperator::Pow => { assert_eq!( deg_left + deg_right, 0, @@ -282,22 +297,6 @@ impl<'a, T: FieldElement> Exporter<'a, T> { ); ("pow", deg_left + deg_right) } - BinaryOperator::Mod - | BinaryOperator::BinaryAnd - | BinaryOperator::BinaryOr - | BinaryOperator::BinaryXor - | BinaryOperator::ShiftLeft - | BinaryOperator::ShiftRight - | BinaryOperator::LogicalOr - | BinaryOperator::LogicalAnd - | BinaryOperator::Less - | BinaryOperator::LessEqual - | BinaryOperator::Equal - | BinaryOperator::NotEqual - | BinaryOperator::GreaterEqual - | BinaryOperator::Greater => { - panic!("Operator {op:?} not supported on polynomials.") - } }; ( degree, @@ -312,8 +311,8 @@ impl<'a, T: FieldElement> Exporter<'a, T> { Expression::UnaryOperation(op, value) => { let (deg, value) = self.expression_to_json(value); match op { - UnaryOperator::Plus => (deg, value), - UnaryOperator::Minus => ( + AlgebraicUnaryOperator::Plus => (deg, value), + AlgebraicUnaryOperator::Minus => ( deg, StarkyExpr { op: "neg".to_string(), @@ -322,46 +321,26 @@ impl<'a, T: FieldElement> Exporter<'a, T> { ..DEFAULT_EXPR }, ), - UnaryOperator::LogicalNot => panic!("Operator {op} not allowed here."), } } - Expression::FunctionCall(_) => panic!("No function calls allowed here."), - Expression::String(_) => panic!("Strings not allowed here."), - Expression::Tuple(_) => panic!("Tuples not allowed here"), - Expression::ArrayLiteral(_) => panic!("Array literals not allowed here"), - Expression::MatchExpression(_, _) => { - panic!("No match expressions allowed here.") - } - Expression::LambdaExpression(_) => { - panic!("No lambda expressions allowed here.") - } - Expression::FreeInput(_) => { - panic!("No free input expressions allowed here.") - } } } fn polynomial_reference_to_json( &self, - PolynomialReference { - name: _, - index, - poly_id, - next, - }: &PolynomialReference, + PolyID { id, ptype }: PolyID, + next: bool, ) -> (u32, StarkyExpr) { - let PolyID { id, ptype } = poly_id.unwrap(); let id = if ptype == PolynomialType::Intermediate { - assert!(index.is_none()); self.intermediate_poly_expression_ids[&id] } else { - id + index.unwrap_or_default() + id }; let poly = StarkyExpr { id: Some(id as usize), op: polynomial_reference_type_to_json_string(ptype).to_string(), deg: 1, - next: Some(*next), + next: Some(next), ..DEFAULT_EXPR }; (1, poly) diff --git a/starky/src/pilcom/expression_counter.rs b/starky/src/pilcom/expression_counter.rs index d727218c..bb37bb49 100644 --- a/starky/src/pilcom/expression_counter.rs +++ b/starky/src/pilcom/expression_counter.rs @@ -1,9 +1,12 @@ //! porting it from powdr use std::collections::HashMap; -use ast::analyzed::{ - Analyzed, Expression, Identity, PolynomialType, PublicDeclaration, SelectedExpressions, - StatementIdentifier, Symbol, SymbolKind, +use ast::{ + analyzed::{ + Analyzed, Identity, PolynomialType, PublicDeclaration, StatementIdentifier, Symbol, + SymbolKind, + }, + parsed::SelectedExpressions, }; /// Computes expression IDs for each intermediate polynomial. @@ -13,11 +16,16 @@ pub fn compute_intermediate_expression_ids(analyzed: &Analyzed) -> HashMap for item in &analyzed.source_order { expression_counter += match item { StatementIdentifier::Definition(name) => { - let poly = &analyzed.definitions[name].0; - if poly.kind == SymbolKind::Poly(PolynomialType::Intermediate) { + if let Some((poly, _)) = analyzed.definitions.get(name) { + assert!(poly.kind != SymbolKind::Poly(PolynomialType::Intermediate)); + poly.expression_count() + } else if let Some((poly, _)) = analyzed.intermediate_columns.get(name) { + assert!(poly.kind == SymbolKind::Poly(PolynomialType::Intermediate)); ids.insert(poly.id, expression_counter as u64); + poly.expression_count() + } else { + unreachable!() } - poly.expression_count() } StatementIdentifier::PublicDeclaration(name) => { analyzed.public_declarations[name].expression_count() @@ -33,7 +41,7 @@ trait ExpressionCounter { fn expression_count(&self) -> usize; } -impl ExpressionCounter for Identity { +impl ExpressionCounter for Identity { fn expression_count(&self) -> usize { self.left.expression_count() + self.right.expression_count() } @@ -51,20 +59,8 @@ impl ExpressionCounter for PublicDeclaration { } } -impl ExpressionCounter for SelectedExpressions { +impl ExpressionCounter for SelectedExpressions { fn expression_count(&self) -> usize { - self.selector.expression_count() + self.expressions.expression_count() - } -} - -impl ExpressionCounter for Vec> { - fn expression_count(&self) -> usize { - self.len() - } -} - -impl ExpressionCounter for Option> { - fn expression_count(&self) -> usize { - (self.is_some()).into() + self.selector.is_some() as usize + self.expressions.len() } } diff --git a/zkvm/Cargo.toml b/zkvm/Cargo.toml new file mode 100644 index 00000000..16188f9f --- /dev/null +++ b/zkvm/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "zkvm" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/zkvm/src/lib.rs b/zkvm/src/lib.rs new file mode 100644 index 00000000..b91a54ab --- /dev/null +++ b/zkvm/src/lib.rs @@ -0,0 +1 @@ +//! stay tuned