mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
add constraints and snark functions
This commit is contained in:
parent
4a83a0e879
commit
c4f233e142
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -584,6 +584,10 @@ dependencies = [
|
||||
"pest",
|
||||
"pest-ast",
|
||||
"pest_derive",
|
||||
"rand 0.7.3",
|
||||
"snarkos-algorithms",
|
||||
"snarkos-curves",
|
||||
"snarkos-errors",
|
||||
"snarkos-gadgets",
|
||||
"snarkos-models",
|
||||
]
|
||||
|
@ -18,6 +18,10 @@ lazy_static = "1.3.0"
|
||||
pest = "2.0"
|
||||
pest_derive = "2.0"
|
||||
pest-ast = "0.3.3"
|
||||
rand = { version = "0.7" }
|
||||
|
||||
snarkos-algorithms = { path = "../snarkOS/algorithms" }
|
||||
snarkos-curves = { path = "../snarkOS/curves" }
|
||||
snarkos-errors = { path = "../snarkOS/errors" }
|
||||
snarkos-gadgets = { path = "../snarkOS/gadgets" }
|
||||
snarkos-models = { path = "../snarkOS/models" }
|
||||
|
@ -1 +1 @@
|
||||
return a == 1
|
||||
return a + 1
|
186
src/aleo_program/constraints.rs
Normal file
186
src/aleo_program/constraints.rs
Normal file
@ -0,0 +1,186 @@
|
||||
use crate::aleo_program::{
|
||||
BooleanExpression, Expression, FieldExpression, Program, Statement, Variable,
|
||||
};
|
||||
|
||||
use snarkos_models::curves::Field;
|
||||
use snarkos_models::gadgets::utilities::eq::EqGadget;
|
||||
use snarkos_models::gadgets::{
|
||||
r1cs::ConstraintSystem,
|
||||
utilities::{alloc::AllocGadget, boolean::Boolean, eq::ConditionalEqGadget, uint32::UInt32},
|
||||
};
|
||||
|
||||
fn bool_from_variable<F: Field, CS: ConstraintSystem<F>>(
|
||||
cs: &mut CS,
|
||||
variable: Variable,
|
||||
) -> Boolean {
|
||||
// let argument = std::env::args()
|
||||
// .nth(1)
|
||||
// .unwrap_or("true".into())
|
||||
// .parse::<bool>()
|
||||
// .unwrap();
|
||||
//
|
||||
// println!(" argument passed to command line a = {:?}", argument);
|
||||
let a = true;
|
||||
Boolean::alloc(cs.ns(|| variable.0), || Ok(a)).unwrap()
|
||||
}
|
||||
|
||||
fn u32_from_variable<F: Field, CS: ConstraintSystem<F>>(cs: &mut CS, variable: Variable) -> UInt32 {
|
||||
// let argument = std::env::args()
|
||||
// .nth(1)
|
||||
// .unwrap_or("1".into())
|
||||
// .parse::<u32>()
|
||||
// .unwrap();
|
||||
//
|
||||
// println!(" argument passed to command line a = {:?}", argument);
|
||||
|
||||
let a = 1;
|
||||
UInt32::alloc(cs.ns(|| variable.0), Some(a)).unwrap()
|
||||
}
|
||||
|
||||
fn get_bool_value<F: Field, CS: ConstraintSystem<F>>(
|
||||
cs: &mut CS,
|
||||
expression: BooleanExpression,
|
||||
) -> Boolean {
|
||||
match expression {
|
||||
BooleanExpression::Variable(variable) => bool_from_variable(cs, variable),
|
||||
BooleanExpression::Value(value) => Boolean::Constant(value),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_u32_value<F: Field, CS: ConstraintSystem<F>>(
|
||||
cs: &mut CS,
|
||||
expression: FieldExpression,
|
||||
) -> UInt32 {
|
||||
match expression {
|
||||
FieldExpression::Variable(variable) => u32_from_variable(cs, variable),
|
||||
FieldExpression::Number(number) => UInt32::constant(number),
|
||||
_ => unimplemented!(), // FieldExpression::Add(left, right) =>
|
||||
}
|
||||
}
|
||||
|
||||
fn enforce_or<F: Field, CS: ConstraintSystem<F>>(
|
||||
cs: &mut CS,
|
||||
left: BooleanExpression,
|
||||
right: BooleanExpression,
|
||||
) {
|
||||
let left = get_bool_value(cs, left);
|
||||
let right = get_bool_value(cs, right);
|
||||
|
||||
let _result = Boolean::or(cs, &left, &right).unwrap();
|
||||
}
|
||||
|
||||
fn enforce_and<F: Field, CS: ConstraintSystem<F>>(
|
||||
cs: &mut CS,
|
||||
left: BooleanExpression,
|
||||
right: BooleanExpression,
|
||||
) {
|
||||
let left = get_bool_value(cs, left);
|
||||
let right = get_bool_value(cs, right);
|
||||
|
||||
let _result = Boolean::and(cs, &left, &right).unwrap();
|
||||
}
|
||||
|
||||
fn enforce_bool_equality<F: Field, CS: ConstraintSystem<F>>(
|
||||
cs: &mut CS,
|
||||
left: BooleanExpression,
|
||||
right: BooleanExpression,
|
||||
) {
|
||||
let left = get_bool_value(cs, left);
|
||||
let right = get_bool_value(cs, right);
|
||||
|
||||
left.enforce_equal(cs.ns(|| format!("enforce bool equal")), &right)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn enforce_field_equality<F: Field, CS: ConstraintSystem<F>>(
|
||||
cs: &mut CS,
|
||||
left: FieldExpression,
|
||||
right: FieldExpression,
|
||||
) {
|
||||
let left = get_u32_value(cs, left);
|
||||
let right = get_u32_value(cs, right);
|
||||
|
||||
left.conditional_enforce_equal(
|
||||
cs.ns(|| format!("enforce field equal")),
|
||||
&right,
|
||||
&Boolean::Constant(true),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn enforce_boolean_expression<F: Field, CS: ConstraintSystem<F>>(
|
||||
cs: &mut CS,
|
||||
expression: BooleanExpression,
|
||||
) {
|
||||
match expression {
|
||||
BooleanExpression::Or(left, right) => {
|
||||
enforce_or(cs, *left, *right);
|
||||
}
|
||||
BooleanExpression::And(left, right) => {
|
||||
enforce_and(cs, *left, *right);
|
||||
}
|
||||
BooleanExpression::BoolEq(left, right) => {
|
||||
enforce_bool_equality(cs, *left, *right);
|
||||
}
|
||||
BooleanExpression::FieldEq(left, right) => {
|
||||
enforce_field_equality(cs, *left, *right);
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn enforce_add<F: Field, CS: ConstraintSystem<F>>(
|
||||
cs: &mut CS,
|
||||
left: FieldExpression,
|
||||
right: FieldExpression,
|
||||
) {
|
||||
let left = get_u32_value(cs, left);
|
||||
let right = get_u32_value(cs, right);
|
||||
|
||||
// let _r = UInt32::addmany(cs.ns(|| "addition"), &[left, right]).unwrap();
|
||||
}
|
||||
|
||||
fn enforce_field_expression<F: Field, CS: ConstraintSystem<F>>(
|
||||
cs: &mut CS,
|
||||
expression: FieldExpression,
|
||||
) {
|
||||
match expression {
|
||||
FieldExpression::Add(left, right) => {
|
||||
enforce_add(cs, *left, *right);
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_constraints<F: Field, CS: ConstraintSystem<F>>(cs: &mut CS, program: Program) {
|
||||
program
|
||||
.statements
|
||||
.into_iter()
|
||||
.for_each(|statement| match statement {
|
||||
Statement::Return(statements) => {
|
||||
statements
|
||||
.into_iter()
|
||||
.for_each(|expression| match expression {
|
||||
Expression::Boolean(boolean_expression) => {
|
||||
enforce_boolean_expression(cs, boolean_expression);
|
||||
}
|
||||
Expression::FieldElement(field_expression) => {
|
||||
enforce_field_expression(cs, field_expression);
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
});
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
});
|
||||
}
|
||||
|
||||
// impl Program {
|
||||
// pub fn setup(&self) {
|
||||
// self.statements
|
||||
// .iter()
|
||||
// .for_each(|statement| {
|
||||
//
|
||||
// })
|
||||
// }
|
||||
// }
|
@ -7,8 +7,8 @@
|
||||
pub mod types;
|
||||
pub use self::types::*;
|
||||
|
||||
pub mod setup;
|
||||
pub use self::setup::*;
|
||||
pub mod constraints;
|
||||
pub use self::constraints::*;
|
||||
|
||||
pub mod types_display;
|
||||
pub use self::types_display::*;
|
||||
|
@ -1,15 +0,0 @@
|
||||
// use crate::{
|
||||
// aleo_program::program::{
|
||||
// Program,
|
||||
// },
|
||||
// };
|
||||
|
||||
// impl Program {
|
||||
// pub fn setup(&self) {
|
||||
// self.statements
|
||||
// .iter()
|
||||
// .for_each(|statement| {
|
||||
//
|
||||
// })
|
||||
// }
|
||||
// }
|
@ -66,16 +66,11 @@ impl fmt::Display for Statement {
|
||||
});
|
||||
write!(f, "")
|
||||
}
|
||||
_ => unimplemented!(), // Statement::Constraint(ref quadratic, ref linear) => {
|
||||
// let a = (quadratic.0).0[0].value.clone();
|
||||
// let b = (quadratic.1).0[0].value.clone();
|
||||
// let c = linear.0[0].value.clone();
|
||||
//
|
||||
// write!(f, "constraint {} * {} = {}", a, b, c)
|
||||
// }
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Statement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
@ -85,27 +80,7 @@ impl fmt::Debug for Statement {
|
||||
});
|
||||
write!(f, "")
|
||||
}
|
||||
_ => unimplemented!(), // Statement::Constraint(ref quadratic, ref linear) => {
|
||||
// let a = (quadratic.0).0[0].value.clone();
|
||||
// let b = (quadratic.1).0[0].value.clone();
|
||||
// let c = linear.0[0].value.clone();
|
||||
//
|
||||
// write!(f, "constraint {} * {} = {}", a, b, c)
|
||||
// }
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl fmt::Debug for Statement {
|
||||
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// match *self {
|
||||
// Statement::Constraint(ref quadratic, ref linear) => {
|
||||
// let a = (quadratic.0).0[0].value.clone();
|
||||
// let b = (quadratic.1).0[0].value.clone();
|
||||
// let c = linear.0[0].value.clone();
|
||||
//
|
||||
// write!(f, "constraint {} * {} = {}", a, b, c)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
@ -5,69 +5,13 @@
|
||||
//! @author Collin Chin <collin@aleo.org>
|
||||
//! @date 2020
|
||||
|
||||
use crate::aleo_program::{BooleanExpression, Expression, FieldExpression};
|
||||
use crate::aleo_program::BooleanExpression;
|
||||
use crate::{aleo_program::types, ast};
|
||||
|
||||
// use crate::{
|
||||
// ast,
|
||||
// aleo_program::{program, types, NodeValue},
|
||||
// };
|
||||
//
|
||||
// impl<'ast> From<ast::Boolean<'ast>> for types::ExpressionNode<'ast> {
|
||||
// fn from(boolean: ast::Boolean<'ast>) -> Self {
|
||||
// types::Expression::Boolean(
|
||||
// boolean
|
||||
// .value
|
||||
// .parse::<bool>()
|
||||
// .expect("unable to parse boolean"),
|
||||
// )
|
||||
// .span(boolean.span)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<'ast> From<ast::Field<'ast>> for types::ExpressionNode<'ast> {
|
||||
// fn from(field: ast::Field<'ast>) -> Self {
|
||||
// types::Expression::Field(field.span.as_str()).span(field.span)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<'ast> From<ast::Value<'ast>> for types::ExpressionNode<'ast> {
|
||||
// fn from(value: ast::Value<'ast>) -> Self {
|
||||
// match value {
|
||||
// ast::Value::Boolean(boolean) => types::ExpressionNode::from(boolean),
|
||||
// ast::Value::Field(field) => types::ExpressionNode::from(field),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<'ast> From<ast::Variable<'ast>> for types::VariableNode<'ast> {
|
||||
// fn from(variable: ast::Variable<'ast>) -> Self {
|
||||
// types::Variable {
|
||||
// id: variable.span.as_str(),
|
||||
// }
|
||||
// .span(variable.span)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<'ast> From<ast::Variable<'ast>> for types::ExpressionNode<'ast> {
|
||||
// fn from(variable: ast::Variable<'ast>) -> Self {
|
||||
// types::Expression::Variable(types::VariableNode::from(variable.clone())).span(variable.span)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<'ast> From<ast::NotExpression<'ast>> for types::ExpressionNode<'ast> {
|
||||
// fn from(expression: ast::NotExpression<'ast>) -> Self {
|
||||
// types::Expression::Not(Box::new(types::ExpressionNode::from(
|
||||
// *expression.expression,
|
||||
// )))
|
||||
// .span(expression.span)
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<'ast> From<ast::Field<'ast>> for types::FieldExpression {
|
||||
fn from(field: ast::Field<'ast>) -> Self {
|
||||
let number = field.value.parse::<u32>().expect("unable to unwrap field");
|
||||
FieldExpression::Number(number)
|
||||
types::FieldExpression::Number(number)
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,28 +21,32 @@ impl<'ast> From<ast::Boolean<'ast>> for types::BooleanExpression {
|
||||
.value
|
||||
.parse::<bool>()
|
||||
.expect("unable to unwrap boolean");
|
||||
BooleanExpression::Value(boolean)
|
||||
types::BooleanExpression::Value(boolean)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<ast::Value<'ast>> for types::Expression {
|
||||
fn from(value: ast::Value<'ast>) -> Self {
|
||||
match value {
|
||||
ast::Value::Boolean(value) => Expression::Boolean(BooleanExpression::from(value)),
|
||||
ast::Value::Field(value) => Expression::FieldElement(FieldExpression::from(value)),
|
||||
ast::Value::Boolean(value) => {
|
||||
types::Expression::Boolean(types::BooleanExpression::from(value))
|
||||
}
|
||||
ast::Value::Field(value) => {
|
||||
types::Expression::FieldElement(types::FieldExpression::from(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<ast::Variable<'ast>> for types::FieldExpression {
|
||||
fn from(variable: ast::Variable<'ast>) -> Self {
|
||||
FieldExpression::Variable(types::Variable(variable.value))
|
||||
types::FieldExpression::Variable(types::Variable(variable.value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<ast::Variable<'ast>> for types::BooleanExpression {
|
||||
fn from(variable: ast::Variable<'ast>) -> Self {
|
||||
BooleanExpression::Variable(types::Variable(variable.value))
|
||||
types::BooleanExpression::Variable(types::Variable(variable.value))
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,6 +56,40 @@ impl<'ast> From<ast::Variable<'ast>> for types::Expression {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<ast::NotExpression<'ast>> for types::Expression {
|
||||
fn from(expression: ast::NotExpression<'ast>) -> Self {
|
||||
types::Expression::Boolean(BooleanExpression::Not(Box::new(
|
||||
types::BooleanExpression::from(*expression.expression),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<ast::Expression<'ast>> for types::BooleanExpression {
|
||||
fn from(expression: ast::Expression<'ast>) -> Self {
|
||||
match types::Expression::from(expression) {
|
||||
types::Expression::Boolean(boolean_expression) => boolean_expression,
|
||||
types::Expression::Variable(variable) => types::BooleanExpression::Variable(variable),
|
||||
types::Expression::FieldElement(field_expression) => unimplemented!(
|
||||
"cannot compare field expression {} in boolean expression",
|
||||
field_expression
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<ast::Expression<'ast>> for types::FieldExpression {
|
||||
fn from(expression: ast::Expression<'ast>) -> Self {
|
||||
match types::Expression::from(expression) {
|
||||
types::Expression::FieldElement(field_expression) => field_expression,
|
||||
types::Expression::Variable(variable) => types::FieldExpression::Variable(variable),
|
||||
types::Expression::Boolean(boolean_expression) => unimplemented!(
|
||||
"cannot compare boolean expression {} in field expression",
|
||||
boolean_expression
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> types::BooleanExpression {
|
||||
/// Find out which types we are comparing and output the corresponding expression.
|
||||
fn from_eq(expression: ast::BinaryExpression<'ast>) -> Self {
|
||||
@ -117,51 +99,112 @@ impl<'ast> types::BooleanExpression {
|
||||
// When matching a variable, look at the opposite side to see what we are comparing to and assume that variable type
|
||||
match (left, right) {
|
||||
// Boolean equality
|
||||
(Expression::Boolean(lhs), Expression::Boolean(rhs)) => {
|
||||
BooleanExpression::BoolEq(Box::new(lhs), Box::new(rhs))
|
||||
(types::Expression::Boolean(lhs), types::Expression::Boolean(rhs)) => {
|
||||
types::BooleanExpression::BoolEq(Box::new(lhs), Box::new(rhs))
|
||||
}
|
||||
(Expression::Boolean(lhs), Expression::Variable(rhs)) => {
|
||||
BooleanExpression::BoolEq(Box::new(lhs), Box::new(BooleanExpression::Variable(rhs)))
|
||||
(types::Expression::Boolean(lhs), types::Expression::Variable(rhs)) => {
|
||||
types::BooleanExpression::BoolEq(
|
||||
Box::new(lhs),
|
||||
Box::new(types::BooleanExpression::Variable(rhs)),
|
||||
)
|
||||
}
|
||||
(Expression::Variable(lhs), Expression::Boolean(rhs)) => {
|
||||
BooleanExpression::BoolEq(Box::new(BooleanExpression::Variable(lhs)), Box::new(rhs))
|
||||
(types::Expression::Variable(lhs), types::Expression::Boolean(rhs)) => {
|
||||
types::BooleanExpression::BoolEq(
|
||||
Box::new(types::BooleanExpression::Variable(lhs)),
|
||||
Box::new(rhs),
|
||||
)
|
||||
}
|
||||
// Field equality
|
||||
(Expression::FieldElement(lhs), Expression::FieldElement(rhs)) => {
|
||||
BooleanExpression::FieldEq(Box::new(lhs), Box::new(rhs))
|
||||
(types::Expression::FieldElement(lhs), types::Expression::FieldElement(rhs)) => {
|
||||
types::BooleanExpression::FieldEq(Box::new(lhs), Box::new(rhs))
|
||||
}
|
||||
(Expression::FieldElement(lhs), Expression::Variable(rhs)) => {
|
||||
BooleanExpression::FieldEq(Box::new(lhs), Box::new(FieldExpression::Variable(rhs)))
|
||||
(types::Expression::FieldElement(lhs), types::Expression::Variable(rhs)) => {
|
||||
types::BooleanExpression::FieldEq(
|
||||
Box::new(lhs),
|
||||
Box::new(types::FieldExpression::Variable(rhs)),
|
||||
)
|
||||
}
|
||||
(Expression::Variable(lhs), Expression::FieldElement(rhs)) => {
|
||||
BooleanExpression::FieldEq(Box::new(FieldExpression::Variable(lhs)), Box::new(rhs))
|
||||
(types::Expression::Variable(lhs), types::Expression::FieldElement(rhs)) => {
|
||||
types::BooleanExpression::FieldEq(
|
||||
Box::new(types::FieldExpression::Variable(lhs)),
|
||||
Box::new(rhs),
|
||||
)
|
||||
}
|
||||
|
||||
(_, _) => unimplemented!(),
|
||||
(lhs, rhs) => unimplemented!("pattern {} == {} unimplemented", lhs, rhs),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_neq(expression: ast::BinaryExpression<'ast>) -> Self {
|
||||
types::BooleanExpression::Not(Box::new(Self::from_eq(expression)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<ast::BinaryExpression<'ast>> for types::Expression {
|
||||
fn from(expression: ast::BinaryExpression<'ast>) -> Self {
|
||||
match expression.operation {
|
||||
// Boolean operations
|
||||
ast::BinaryOperator::Or => unimplemented!(),
|
||||
ast::BinaryOperator::And => unimplemented!(),
|
||||
ast::BinaryOperator::Or => types::Expression::Boolean(types::BooleanExpression::Or(
|
||||
Box::new(types::BooleanExpression::from(*expression.left)),
|
||||
Box::new(types::BooleanExpression::from(*expression.right)),
|
||||
)),
|
||||
ast::BinaryOperator::And => types::Expression::Boolean(types::BooleanExpression::And(
|
||||
Box::new(types::BooleanExpression::from(*expression.left)),
|
||||
Box::new(types::BooleanExpression::from(*expression.right)),
|
||||
)),
|
||||
ast::BinaryOperator::Eq => {
|
||||
types::Expression::Boolean(BooleanExpression::from_eq(expression))
|
||||
types::Expression::Boolean(types::BooleanExpression::from_eq(expression))
|
||||
}
|
||||
ast::BinaryOperator::Neq => unimplemented!(),
|
||||
ast::BinaryOperator::Geq => unimplemented!(),
|
||||
ast::BinaryOperator::Gt => unimplemented!(),
|
||||
ast::BinaryOperator::Leq => unimplemented!(),
|
||||
ast::BinaryOperator::Lt => unimplemented!(),
|
||||
ast::BinaryOperator::Neq => {
|
||||
types::Expression::Boolean(types::BooleanExpression::from_neq(expression))
|
||||
}
|
||||
ast::BinaryOperator::Geq => types::Expression::Boolean(types::BooleanExpression::Geq(
|
||||
Box::new(types::FieldExpression::from(*expression.left)),
|
||||
Box::new(types::FieldExpression::from(*expression.right)),
|
||||
)),
|
||||
ast::BinaryOperator::Gt => types::Expression::Boolean(types::BooleanExpression::Gt(
|
||||
Box::new(types::FieldExpression::from(*expression.left)),
|
||||
Box::new(types::FieldExpression::from(*expression.right)),
|
||||
)),
|
||||
ast::BinaryOperator::Leq => types::Expression::Boolean(types::BooleanExpression::Leq(
|
||||
Box::new(types::FieldExpression::from(*expression.left)),
|
||||
Box::new(types::FieldExpression::from(*expression.right)),
|
||||
)),
|
||||
ast::BinaryOperator::Lt => types::Expression::Boolean(types::BooleanExpression::Lt(
|
||||
Box::new(types::FieldExpression::from(*expression.left)),
|
||||
Box::new(types::FieldExpression::from(*expression.right)),
|
||||
)),
|
||||
// Field operations
|
||||
ast::BinaryOperator::Add => unimplemented!(),
|
||||
ast::BinaryOperator::Sub => unimplemented!(),
|
||||
ast::BinaryOperator::Mul => unimplemented!(),
|
||||
ast::BinaryOperator::Div => unimplemented!(),
|
||||
ast::BinaryOperator::Pow => unimplemented!(),
|
||||
ast::BinaryOperator::Add => {
|
||||
types::Expression::FieldElement(types::FieldExpression::Add(
|
||||
Box::new(types::FieldExpression::from(*expression.left)),
|
||||
Box::new(types::FieldExpression::from(*expression.right)),
|
||||
))
|
||||
}
|
||||
ast::BinaryOperator::Sub => {
|
||||
types::Expression::FieldElement(types::FieldExpression::Sub(
|
||||
Box::new(types::FieldExpression::from(*expression.left)),
|
||||
Box::new(types::FieldExpression::from(*expression.right)),
|
||||
))
|
||||
}
|
||||
ast::BinaryOperator::Mul => {
|
||||
types::Expression::FieldElement(types::FieldExpression::Mul(
|
||||
Box::new(types::FieldExpression::from(*expression.left)),
|
||||
Box::new(types::FieldExpression::from(*expression.right)),
|
||||
))
|
||||
}
|
||||
ast::BinaryOperator::Div => {
|
||||
types::Expression::FieldElement(types::FieldExpression::Div(
|
||||
Box::new(types::FieldExpression::from(*expression.left)),
|
||||
Box::new(types::FieldExpression::from(*expression.right)),
|
||||
))
|
||||
}
|
||||
ast::BinaryOperator::Pow => {
|
||||
types::Expression::FieldElement(types::FieldExpression::Pow(
|
||||
Box::new(types::FieldExpression::from(*expression.left)),
|
||||
Box::new(types::FieldExpression::from(*expression.right)),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -171,7 +214,7 @@ impl<'ast> From<ast::Expression<'ast>> for types::Expression {
|
||||
match expression {
|
||||
ast::Expression::Value(value) => types::Expression::from(value),
|
||||
ast::Expression::Variable(variable) => types::Expression::from(variable),
|
||||
ast::Expression::Not(_expression) => unimplemented!(),
|
||||
ast::Expression::Not(expression) => types::Expression::from(expression),
|
||||
ast::Expression::Binary(expression) => types::Expression::from(expression),
|
||||
}
|
||||
}
|
||||
@ -224,102 +267,3 @@ impl<'ast> From<ast::File<'ast>> for types::Program {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use super::*;
|
||||
//
|
||||
// #[test]
|
||||
// fn test_file() {
|
||||
//
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl<'ast> From<ast::Variable<'ast>> for types::LinearCombination {
|
||||
// fn from(variable: ast::Variable<'ast>) -> Self {
|
||||
// LinearCombination(vec![Variable { id: 1, value: variable.value }])
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<'ast> From<ast::Boolean<'ast>> for types::LinearCombination {
|
||||
// fn from(boolean: ast::Boolean<'ast>) -> Self {
|
||||
// LinearCombination(vec![Variable { id: -1, value: boolean.value }])
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<'ast> From<ast::Field<'ast>> for types::LinearCombination {
|
||||
// fn from(field: ast::Field<'ast>) -> Self {
|
||||
// LinearCombination(vec![Variable { id: 0, value: field.value }])
|
||||
// }
|
||||
// }
|
||||
// impl<'ast> From<ast::Value<'ast>> for types::LinearCombination {
|
||||
// fn from(value: ast::Value<'ast>) -> Self {
|
||||
// match value {
|
||||
// ast::Value::Boolean(boolean) => types::LinearCombination::from(boolean),
|
||||
// ast::Value::Field(field) => types::LinearCombination::from(field),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<'ast> From<ast::Expression<'ast>> for types::LinearCombination {
|
||||
// fn from(expression: ast::Expression<'ast>) -> Self {
|
||||
// match expression {
|
||||
// ast::Expression::Value(value) => types::LinearCombination::from(value),
|
||||
// ast::Expression::Variable(variable) => types::LinearCombination::from(variable),
|
||||
// ast::Expression::Not(_) => unimplemented!(),
|
||||
// ast::Expression::Binary(_) => unimplemented!(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<'ast> types::Expression {
|
||||
// fn unwrap_expression(expression: ast::Expression<'ast>) -> Vec<Self> {
|
||||
// match expression {
|
||||
// ast::Expression::Value(value) => unimplemented!(),
|
||||
// ast::Expression::Variable(variable) => unimplemented!(),
|
||||
// ast::Expression::Not(expression) => unimplemented!(),
|
||||
// ast::Expression::Binary(expression) => Self::unwrap_binary(expression),
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn unwrap_binary(expression: ast::BinaryExpression<'ast>) -> Vec<Self> {
|
||||
// match expression.operation {
|
||||
// ast::BinaryOperator::Eq => ,
|
||||
// _ => unimplemented!()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn unwrap_eq(expression: ast::BinaryExpression<'ast>) -> Vec<Self> {
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<'ast> types::Statement {
|
||||
// fn unwrap_statement(statement: ast::Statement<'ast>) -> Self {
|
||||
// match statement {
|
||||
// ast::Statement::Assign(statement) => unimplemented!(),
|
||||
// ast::Statement::Return(statement) => Self::unwrap_return(statement),
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn unwrap_return(statement: ast::ReturnStatement<'ast>) -> Self {
|
||||
// let mut expressions: Vec<types::Expression> = vec![];
|
||||
//
|
||||
// statement
|
||||
// .expressions
|
||||
// .into_iter()
|
||||
// .map(|expression| {
|
||||
// expressions.extend_from_slice(&types::Expression::unwrap_expression(expression))
|
||||
// });
|
||||
//
|
||||
// types::Statement::Return(expressions)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<'ast> From<ast::Statement<'ast>> for types::Statement {
|
||||
// fn from(statement: ast::Statement<'ast>) -> Self {
|
||||
// match statement {
|
||||
// ast::Statement::Assign(statement) => unimplemented!()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
235
src/main.rs
235
src/main.rs
@ -1,169 +1,106 @@
|
||||
use language::*;
|
||||
|
||||
use from_pest::FromPest;
|
||||
use std::fs;
|
||||
use std::{
|
||||
fs,
|
||||
marker::PhantomData,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use snarkos_curves::bls12_377::{Bls12_377, Fr};
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use snarkos_models::curves::Field;
|
||||
use snarkos_models::gadgets::r1cs::{ConstraintSynthesizer, ConstraintSystem};
|
||||
|
||||
use snarkos_algorithms::snark::{
|
||||
create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof,
|
||||
};
|
||||
|
||||
use rand::thread_rng;
|
||||
|
||||
// use std::env;
|
||||
|
||||
pub struct Benchmark<F: Field> {
|
||||
_engine: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F: Field> Benchmark<F> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
_engine: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field> ConstraintSynthesizer<F> for Benchmark<F> {
|
||||
fn generate_constraints<CS: ConstraintSystem<F>>(
|
||||
self,
|
||||
cs: &mut CS,
|
||||
) -> Result<(), SynthesisError> {
|
||||
// Read in file as string
|
||||
let unparsed_file = fs::read_to_string("simple.program").expect("cannot read file");
|
||||
|
||||
// Parse the file using langauge.pest
|
||||
let mut file = ast::parse(&unparsed_file).expect("unsuccessful parse");
|
||||
|
||||
// Build the abstract syntax tree
|
||||
let syntax_tree = ast::File::from_pest(&mut file).expect("infallible");
|
||||
// println!("{:#?}", syntax_tree);
|
||||
|
||||
let program = aleo_program::Program::from(syntax_tree);
|
||||
println!(" compiled: {:#?}", program);
|
||||
|
||||
aleo_program::generate_constraints(cs, program);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// use snarkos_gadgets::curves::edwards_bls12::FqGadget;
|
||||
use snarkos_models::gadgets::{
|
||||
r1cs::{ConstraintSystem, Fr, TestConstraintSystem},
|
||||
utilities::{
|
||||
alloc::AllocGadget, boolean::Boolean, eq::ConditionalEqGadget, uint32::UInt32,
|
||||
},
|
||||
let mut setup = Duration::new(0, 0);
|
||||
let mut proving = Duration::new(0, 0);
|
||||
let mut verifying = Duration::new(0, 0);
|
||||
|
||||
let rng = &mut thread_rng();
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
let params = {
|
||||
let c = Benchmark::<Fr>::new();
|
||||
generate_random_parameters::<Bls12_377, _, _>(c, rng).unwrap()
|
||||
};
|
||||
|
||||
// Read in file as string
|
||||
let unparsed_file = fs::read_to_string("simple.program").expect("cannot read file");
|
||||
let prepared_verifying_key = prepare_verifying_key(¶ms.vk);
|
||||
|
||||
// Parse the file using langauge.pest
|
||||
let mut file = ast::parse(&unparsed_file).expect("unsuccessful parse");
|
||||
setup += start.elapsed();
|
||||
|
||||
// Build the abstract syntax tree
|
||||
let syntax_tree = ast::File::from_pest(&mut file).expect("infallible");
|
||||
// println!("{:#?}", syntax_tree);
|
||||
let start = Instant::now();
|
||||
let proof = {
|
||||
let c = Benchmark::new();
|
||||
create_random_proof(c, ¶ms, rng).unwrap()
|
||||
};
|
||||
|
||||
let program = aleo_program::Program::from(syntax_tree);
|
||||
println!(" compiled: {:#?}", program);
|
||||
proving += start.elapsed();
|
||||
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let argument = std::env::args()
|
||||
.nth(1)
|
||||
.unwrap_or("1".into())
|
||||
.parse::<u32>()
|
||||
.unwrap();
|
||||
// let _inputs: Vec<_> = [1u32; 1].to_vec();
|
||||
|
||||
println!(" argument passed to command line a = {:?}", argument);
|
||||
let start = Instant::now();
|
||||
|
||||
program
|
||||
.statements
|
||||
.into_iter()
|
||||
.for_each(|statement| match statement {
|
||||
aleo_program::Statement::Return(statements) => {
|
||||
statements
|
||||
.into_iter()
|
||||
.for_each(|expression| match expression {
|
||||
aleo_program::Expression::Boolean(operation) => match operation {
|
||||
aleo_program::BooleanExpression::FieldEq(lhs, rhs) => match *lhs {
|
||||
aleo_program::FieldExpression::Variable(variable) => {
|
||||
let left_variable =
|
||||
UInt32::alloc(cs.ns(|| variable.0), Some(argument))
|
||||
.unwrap();
|
||||
match *rhs {
|
||||
aleo_program::FieldExpression::Number(number) => {
|
||||
let right_number = UInt32::constant(number);
|
||||
let _ = verify_proof(&prepared_verifying_key, &proof, &[]).unwrap();
|
||||
|
||||
let bool = Boolean::alloc(
|
||||
cs.ns(|| format!("boolean")),
|
||||
|| Ok(true),
|
||||
)
|
||||
.unwrap();
|
||||
left_variable
|
||||
.conditional_enforce_equal(
|
||||
cs.ns(|| format!("enforce equal")),
|
||||
&right_number,
|
||||
&bool,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
_ => unimplemented!(),
|
||||
});
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
});
|
||||
verifying += start.elapsed();
|
||||
|
||||
// program
|
||||
// .statements
|
||||
// .into_iter()
|
||||
// .for_each(|statement| {
|
||||
// match statement {
|
||||
// aleo_program::Statement::Constraint(quadratic, linear) => {
|
||||
// let a_var = (quadratic.0).0[0].clone();
|
||||
// assert!(a_var.id > 0);
|
||||
println!("\n Setup time: {:?} seconds", setup.as_secs());
|
||||
println!(" Proving time: {:?} seconds", proving.as_secs());
|
||||
println!(" Verifying time: {:?} seconds", verifying.as_secs());
|
||||
|
||||
// let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
//
|
||||
// let c_var = linear.0[0].clone();
|
||||
// let c_value = c_var.value.parse::<u32>().unwrap();
|
||||
// println!("\n satisfied: {:?}", cs.is_satisfied());
|
||||
//
|
||||
// let a_bit = UInt32::alloc(cs.ns(|| "a_bit"), Some(argument)).unwrap();
|
||||
// let c_bit = UInt32::constant(c_value);
|
||||
// let bool = Boolean::alloc(cs.ns(|| format!("boolean")), || Ok(true)).unwrap();
|
||||
// println!(
|
||||
// "\n number of constraints for input: {}",
|
||||
// cs.num_constraints()
|
||||
// );
|
||||
//
|
||||
// a_bit.conditional_enforce_equal(cs.ns(|| format!("enforce equal")), &c_bit, &bool).unwrap();
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
// let program = zokrates_program::Program::from(syntax_tree);
|
||||
|
||||
// println!("{:#?}", program);
|
||||
|
||||
// // Use this code when proving
|
||||
// let left_u32 = left_string.parse::<u32>().unwrap();
|
||||
// let right_u32 = right_string.parse::<u32>().unwrap();
|
||||
//
|
||||
// println!("left u32 value: {:#?}", left_u32);
|
||||
// println!("right u32 value: {:#?}", right_u32);
|
||||
//
|
||||
// let left_constraint = UInt32::alloc(cs.ns(|| "left variable"), Some(left_u32)).unwrap();
|
||||
// let right_constraint = UInt32::constant(right_u32);
|
||||
//
|
||||
// let bool = Boolean::alloc(cs.ns(|| format!("boolean")), || Ok(true)).unwrap();
|
||||
//
|
||||
// left_constraint.conditional_enforce_equal(cs.ns(|| format!("enforce left == right")), &right_constraint, &bool).unwrap();
|
||||
|
||||
// Constraint testing
|
||||
// let bool = Boolean::alloc(cs.ns(|| format!("boolean")), || Ok(true)).unwrap();
|
||||
// let a_bit = UInt32::alloc(cs.ns(|| "a_bit"), Some(4u32)).unwrap();
|
||||
// let b_bit = UInt32::constant(4u32);
|
||||
//
|
||||
// a_bit.conditional_enforce_equal(cs.ns(|| format!("enforce equal")), &b_bit, &bool).unwrap();
|
||||
|
||||
println!("\n satisfied: {:?}", cs.is_satisfied());
|
||||
|
||||
println!(
|
||||
"\n number of constraints for input: {}",
|
||||
cs.num_constraints()
|
||||
);
|
||||
|
||||
// for token in file.into_inner() {
|
||||
// match token.as_rule() {
|
||||
// Rule::statement => println!("{:?}", token.into_inner()),
|
||||
// Rule::EOI => println!("END"),
|
||||
// _ => println!("{:?}", token.into_inner()),
|
||||
// }
|
||||
// // println!("{:?}", token);
|
||||
// }
|
||||
|
||||
// let mut field_sum: f64 = 0.0;
|
||||
// let mut record_count: u64 = 0;
|
||||
//
|
||||
// for record in file.into_inner() {
|
||||
// match record.as_rule() {
|
||||
// Rule::record => {
|
||||
// record_count += 1;
|
||||
//
|
||||
// for field in record.into_inner() {
|
||||
// field_sum += field.as_str().parse::<f64>().unwrap();
|
||||
// }
|
||||
// }
|
||||
// Rule::EOI => (),
|
||||
// _ => unreachable!(),
|
||||
// }
|
||||
// }
|
||||
|
||||
// println!("Sum of fields: {}", field_sum);
|
||||
// println!("Number of records: {}", record_count);
|
||||
|
||||
// let successful_parse = LanguageParser::parse(Rule::value, "-273");
|
||||
// println!("{:?}", successful_parse);
|
||||
|
||||
// let unsuccessful_parse = CSVParser::parse(Rule::field, "this is not a number");
|
||||
// println!("{:?}", unsuccessful_parse);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user