1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00

Add Compiler statements for witness calculation; Add user input for unknown variables

Statement::Compilter starting with `#`
This commit is contained in:
Dennis Kuhnert 2017-02-22 11:06:28 +01:00
parent 72e3c422af
commit 91515ed726
6 changed files with 55 additions and 18 deletions

View file

@ -0,0 +1,4 @@
// this code does not need to be flattened
def mulwit(x):
a == b * 7
return x + a + b

View file

@ -5,6 +5,7 @@
use std::fmt;
use std::collections::HashMap;
use std::io::{stdin, BufRead};
use field::Field;
pub struct Prog<T: Field> {
@ -26,11 +27,15 @@ impl<T: Field> Prog<T> {
let s = expr.solve(&mut witness);
witness.insert("~out".to_string(), s);
},
Statement::Compiler(ref id, ref expr) |
Statement::Definition(ref id, ref expr) => {
let s = expr.solve(&mut witness);
witness.insert(id.to_string(), s);
},
Statement::Condition(..) => unimplemented!(),
Statement::Condition(ref lhs, ref rhs) => assert_eq!(
lhs.solve(&mut witness),
rhs.solve(&mut witness)
), // TODO check if condition true?
}
}
witness
@ -51,6 +56,7 @@ pub enum Statement<T: Field> {
Return(Expression<T>),
Definition(String, Expression<T>),
Condition(Expression<T>, Expression<T>),
Compiler(String, Expression<T>),
}
impl<T: Field> fmt::Display for Statement<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@ -58,6 +64,7 @@ impl<T: Field> fmt::Display for Statement<T> {
Statement::Return(ref expr) => write!(f, "return {}", expr),
Statement::Definition(ref lhs, ref rhs) => write!(f, "{} = {}", lhs, rhs),
Statement::Condition(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
Statement::Compiler(ref lhs, ref rhs) => write!(f, "# {} = {}", lhs, rhs),
}
}
}
@ -67,6 +74,7 @@ impl<T: Field> fmt::Debug for Statement<T> {
Statement::Return(ref expr) => write!(f, "Return({:?})", expr),
Statement::Definition(ref lhs, ref rhs) => write!(f, "Definition({:?}, {:?})", lhs, rhs),
Statement::Condition(ref lhs, ref rhs) => write!(f, "Condition({:?}, {:?})", lhs, rhs),
Statement::Compiler(ref lhs, ref rhs) => write!(f, "Compiler({:?}, {:?})", lhs, rhs),
}
}
}
@ -141,7 +149,12 @@ impl<T: Field> Expression<T> {
}
assert_eq!(num, T::zero());
} else {
panic!("Variable not found in inputs: {}", var);
println!("Could not calculate variable {:?}, inputs: {:?}", var, inputs);
println!("Please enter a value for {:?}:", var);
let mut input = String::new();
let stdin = stdin();
stdin.lock().read_line(&mut input).expect("Did not enter a correct String");
inputs.insert(var.to_string(), T::from(input.trim()));
}
}
inputs[var].clone()

View file

@ -117,7 +117,10 @@ impl From<usize> for FieldPrime {
impl<'a> From<&'a str> for FieldPrime {
fn from(s: &'a str) -> Self {
let x = BigInt::parse_bytes(s.as_bytes(), 10).unwrap();
let x = match BigInt::parse_bytes(s.as_bytes(), 10) {
Some(x) => x,
None => panic!("Could not parse {:?} to BigInt!", &s)
};
FieldPrime{ value: &x - x.div_floor(&*P) * &*P }
}
}

View file

@ -5,7 +5,7 @@
use absy::*;
use absy::Expression::*;
use std::collections::{HashSet,HashMap};
use std::collections::{HashSet, HashMap};
use field::Field;
pub struct Flattener {
@ -95,12 +95,22 @@ impl Flattener {
// d = {1, if c = 0, 0 else}
let c = self.flatten_expression(statements_flattened, Sub(box lhs, box rhs));
statements_flattened.push(Statement::Definition(name_c.to_string(), c));
statements_flattened.push(Statement::Compiler(name_d.to_string(), IfElse(
box Condition::Eq(
VariableReference(name_c.to_string()),
NumberLiteral(T::zero())
),
box NumberLiteral(T::one()),
box NumberLiteral(T::zero())
)));
statements_flattened.push(Statement::Definition(name_1_d.to_string(), Sub(box NumberLiteral(T::one()), box VariableReference(name_d.to_string()))));
statements_flattened.push(Statement::Definition(name_c_d.to_string(), Sub(box VariableReference(name_c_d.to_string()), box VariableReference(name_d.to_string()))));
statements_flattened.push(Statement::Definition(name_c_d.to_string(), Sub(box VariableReference(name_c.to_string()), box VariableReference(name_d.to_string()))));
// c d = 0, d (1-d) = 0, (c-d)w = 1
statements_flattened.push(Statement::Compiler(name_w.to_string(), Div(box NumberLiteral(T::one()), box VariableReference(name_c_d.to_string()))));
statements_flattened.push(Statement::Condition(NumberLiteral(T::zero()), Mult(box VariableReference(name_c), box VariableReference(name_d.to_string()))));
statements_flattened.push(Statement::Condition(NumberLiteral(T::zero()), Mult(box VariableReference(name_d.to_string()), box VariableReference(name_1_d.to_string()))));
statements_flattened.push(Statement::Condition(NumberLiteral(T::one()), Mult(box VariableReference(name_c_d), box VariableReference(name_w))));
(VariableReference(name_d), VariableReference(name_1_d))
},
_ => unimplemented!(),
@ -293,6 +303,7 @@ impl Flattener {
};
statements_flattened.push(Statement::Condition(lhs, rhs));
},
s @ Statement::Compiler(..) => statements_flattened.push(s),
}
}
println!("DEBUG self.variables {:?}", self.variables);

View file

@ -9,6 +9,7 @@
// | `if' <expr> <comparator> <expr> `then' <expr> `else' <expr> `fi' <expr'> `==` <expr> `\\n`
// | `(' <expr> `)' <term'> <expr'> `==` <expr> `\\n`
// | <num> <term'> <expr'> `==` <expr> `\\n`
// | `#` <ide> `=` <expr> `\\n`
//
// <statement'> ::= `=' <expr> `\\n'
// | <term'> <expr'> `==` <expr> `\\n`
@ -95,7 +96,7 @@ impl<T: Field> fmt::Debug for Error<T> {
#[derive(PartialEq)]
enum Token<T: Field> {
Open, Close, Comma, Colon,
Open, Close, Comma, Colon, Hash,
Eq, Return,
If, Then, Else, Fi,
Lt, Le, Eqeq, Ge, Gt,
@ -113,6 +114,7 @@ impl<T: Field> fmt::Display for Token<T> {
Token::Close => write!(f, ")"),
Token::Comma => write!(f, ","),
Token::Colon => write!(f, ":"),
Token::Hash => write!(f, "#"),
Token::Eq => write!(f, "="),
Token::Return => write!(f, "return"),
Token::If => write!(f, "if"),
@ -194,6 +196,7 @@ fn next_token<T: Field>(input: &String, pos: &Position) -> (Token<T>, String, Po
Some(')') => (Token::Close, input[offset + 1..].to_string(), Position { line: pos.line, col: pos.col + offset + 1 }),
Some(',') => (Token::Comma, input[offset + 1..].to_string(), Position { line: pos.line, col: pos.col + offset + 1 }),
Some(':') => (Token::Colon, input[offset + 1..].to_string(), Position { line: pos.line, col: pos.col + offset + 1 }),
Some('#') => (Token::Hash, input[offset + 1..].to_string(), Position { line: pos.line, col: pos.col + offset + 1 }),
Some('=') => match input.chars().nth(offset + 1) {
Some('=') => (Token::Eqeq, input[offset + 2..].to_string(), Position { line: pos.line, col: pos.col + offset + 2 }),
_ => (Token::Eq, input[offset + 1..].to_string(), Position { line: pos.line, col: pos.col + offset + 1 }),
@ -446,6 +449,16 @@ fn parse_statement<T: Field>(input: &String, pos: &Position) -> Result<(Statemen
},
Err(err) => Err(err),
},
(Token::Hash, s1, p1) => match parse_ide(&s1, &p1) {
(Token::Ide(x2), s2, p2) => match next_token(&s2, &p2) {
(Token::Eq, s3, p3) => match parse_expr(&s3, &p3) {
Ok((e4, s4, p4)) => Ok((Statement::Compiler(x2, e4), s4, p4)),
Err(err) => Err(err),
},
(t3, _, p3) => Err(Error { expected: vec![Token::Eq], got: t3 , pos: p3 }),
},
(t2, _, p2) => Err(Error { expected: vec![Token::ErrIde], got: t2 , pos: p2 }),
},
(Token::Return, s1, p1) => {
match parse_expr(&s1, &p1) {
Ok((expr, s2, p2)) => match next_token(&s2, &p2) {
@ -458,7 +471,7 @@ fn parse_statement<T: Field>(input: &String, pos: &Position) -> Result<(Statemen
Err(err) => Err(err),
}
},
(t1, _, p1) => Err(Error { expected: vec![Token::ErrIde, Token::ErrNum, Token::If, Token::Open, Token::Return], got: t1 , pos: p1 }),
(t1, _, p1) => Err(Error { expected: vec![Token::ErrIde, Token::ErrNum, Token::If, Token::Open, Token::Hash, Token::Return], got: t1 , pos: p1 }),
}
}

View file

@ -330,17 +330,10 @@ pub fn r1cs_program<T: Field>(prog: &Prog<T>) -> (Vec<String>, Vec<Vec<(usize, T
let mut b_row: Vec<(usize, T)> = Vec::new();
let mut c_row: Vec<(usize, T)> = Vec::new();
match *def {
Statement::Return(ref expr) => {
// variables.push("~out".to_string());
r1cs_expression(VariableReference("~out".to_string()), expr.clone(), &mut variables, &mut a_row, &mut b_row, &mut c_row);
},
Statement::Definition(ref id, ref expr) => {
// variables.push(id.to_string());
r1cs_expression(VariableReference(id.to_string()), expr.clone(), &mut variables, &mut a_row, &mut b_row, &mut c_row);
},
Statement::Condition(ref expr1, ref expr2) => {
r1cs_expression(expr1.clone(), expr2.clone(), &mut variables, &mut a_row, &mut b_row, &mut c_row);
},
Statement::Return(ref expr) => r1cs_expression(VariableReference("~out".to_string()), expr.clone(), &mut variables, &mut a_row, &mut b_row, &mut c_row),
Statement::Definition(ref id, ref expr) => r1cs_expression(VariableReference(id.to_string()), expr.clone(), &mut variables, &mut a_row, &mut b_row, &mut c_row),
Statement::Condition(ref expr1, ref expr2) => r1cs_expression(expr1.clone(), expr2.clone(), &mut variables, &mut a_row, &mut b_row, &mut c_row),
Statement::Compiler(..) => continue,
}
a.push(a_row);
b.push(b_row);