1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00
This commit is contained in:
schaeff 2018-09-19 18:38:40 +02:00
parent 3dde82b2d8
commit 6c0eea26d7
9 changed files with 248 additions and 168 deletions

8
Cargo.lock generated
View file

@ -58,6 +58,11 @@ dependencies = [
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bimap"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bincode"
version = "0.8.0"
@ -550,8 +555,8 @@ name = "zokrates_core"
version = "0.2.0"
dependencies = [
"assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"bimap 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cmake 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
@ -577,6 +582,7 @@ version = "0.1.0"
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
"checksum bimap 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6b282b982237078bfac61a948a2198f185aceea8b9a6e794b70b96fd31923d3d"
"checksum bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e103c8b299b28a9c6990458b7013dc4a8356a9b854c51b9883241f5866fac36e"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"

View file

@ -16,14 +16,13 @@ num = {version = "0.1.36", default-features = false}
num-bigint = {version = "0.1.36", default-features = false}
lazy_static = "0.1.*"
reduce = "0.1.1"
# cli
clap = "2.26.2"
# serialization and deserialization
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
bincode = "0.8.0"
regex = "0.2"
bimap = "0.1"
[dev-dependencies]
glob = "0.2.11"

View file

@ -3,7 +3,7 @@ use substitution::Substitution;
#[derive(Clone, PartialEq, Serialize, Deserialize)]
pub struct FlatParameter {
pub id: String,
pub id: usize,
pub private: bool,
}
@ -22,9 +22,10 @@ impl fmt::Debug for FlatParameter {
impl FlatParameter {
pub fn apply_substitution(self, substitution: &Substitution) -> FlatParameter {
FlatParameter {
id: substitution.get(&self.id).unwrap().to_string(),
private: self.private
}
panic!("TODO: substitution")
// FlatParameter {
// id: substitution.get(&self.id).unwrap().to_string(),
// private: self.private
// }
}
}

View file

@ -0,0 +1,45 @@
use std::fmt;
#[derive(Serialize, Deserialize, Clone, PartialEq, Hash, Eq)]
pub struct FlatVariable {
pub id: usize,
pub binary: Option<usize>
}
impl FlatVariable {
pub fn new(id: usize) -> Self {
FlatVariable {
id,
binary: None
}
}
pub fn binary(id: usize, bit: usize) -> Self {
FlatVariable {
id,
binary: Some(bit)
}
}
pub fn one() -> Self {
Self::new(0)
}
}
impl fmt::Display for FlatVariable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.binary {
Some(b) => write!(f, "{}_b{}", self.id, b),
None => write!(f, "{}", self.id),
}
}
}
impl fmt::Debug for FlatVariable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.binary {
Some(b) => write!(f, "FlatVariable(id: {}, bit: {})", self.id, b),
None => write!(f, "FlatVariable(id: {})", self.id),
}
}
}

View file

@ -6,10 +6,12 @@
//! @date 2017
pub mod flat_parameter;
pub mod flat_variable;
const BINARY_SEPARATOR: &str = "_b";
use self::flat_parameter::FlatParameter;
use self::flat_variable::FlatVariable;
use std::fmt;
use std::collections::{BTreeMap};
use field::Field;
@ -17,6 +19,7 @@ use substitution::Substitution;
#[cfg(feature = "libsnark")]
use standard;
use helpers::{DirectiveStatement, Executable};
use bimap::BiMap;
#[derive(Serialize, Deserialize, Clone)]
pub struct FlatProg<T: Field> {
@ -82,6 +85,8 @@ pub struct FlatFunction<T: Field> {
pub statements: Vec<FlatStatement<T>>,
/// number of returns
pub return_count: usize,
/// map to get variable name from index and back
pub bijection: BiMap<String, FlatVariable>
}
impl<T: Field> FlatFunction<T> {
@ -184,7 +189,7 @@ impl<T: Field> fmt::Debug for FlatFunction<T> {
pub enum FlatStatement<T: Field> {
Return(FlatExpressionList<T>),
Condition(FlatExpression<T>, FlatExpression<T>),
Definition(String, FlatExpression<T>),
Definition(FlatVariable, FlatExpression<T>),
Directive(DirectiveStatement)
}
@ -245,7 +250,7 @@ impl<T: Field> FlatStatement<T> {
#[derive(Clone, PartialEq, Serialize, Deserialize)]
pub enum FlatExpression<T: Field> {
Number(T),
Identifier(String),
Identifier(FlatVariable),
Add(Box<FlatExpression<T>>, Box<FlatExpression<T>>),
Sub(Box<FlatExpression<T>>, Box<FlatExpression<T>>),
Div(Box<FlatExpression<T>>, Box<FlatExpression<T>>),
@ -290,25 +295,31 @@ impl<T: Field> FlatExpression<T> {
FlatExpression::Number(ref x) => x.clone(),
FlatExpression::Identifier(ref var) => {
if let None = inputs.get(var) {
if var.contains(BINARY_SEPARATOR) {
let var_name = var.split(BINARY_SEPARATOR).collect::<Vec<_>>()[0];
let mut num = inputs[var_name].clone();
let bits = T::get_required_bits();
for i in (0..bits).rev() {
if T::from(2).pow(i) <= num {
num = num - T::from(2).pow(i);
inputs.insert(format!("{}{}{}", &var_name, BINARY_SEPARATOR, i), T::one());
} else {
inputs.insert(format!("{}{}{}", &var_name, BINARY_SEPARATOR, i), T::zero());
match var.binary {
// if the variable reprensents a bit from x, we can get its value from x
Some(b) => {
let var_name = var.id;
// TODO id => name
let var_name = String::from("TODO"); // remove
let mut num = inputs[var_name].clone();
let bits = T::get_required_bits();
for i in (0..bits).rev() {
if T::from(2).pow(i) <= num {
num = num - T::from(2).pow(i);
inputs.insert(format!("{}{}{}", &var_name, BINARY_SEPARATOR, i), T::one());
} else {
inputs.insert(format!("{}{}{}", &var_name, BINARY_SEPARATOR, i), T::zero());
}
}
assert_eq!(num, T::zero());
}
None => {
panic!(
"Variable {:?} is undeclared in inputs: {:?}",
var,
inputs
);
}
assert_eq!(num, T::zero());
} else {
panic!(
"Variable {:?} is undeclared in inputs: {:?}",
var,
inputs
);
}
}
inputs[var].clone()

View file

@ -13,6 +13,7 @@ use typed_absy::*;
use field::Field;
use flat_absy::*;
use flat_absy::flat_parameter::FlatParameter;
use flat_absy::flat_variable::FlatVariable;
use substitution::direct_substitution::DirectSubstitution;
use substitution::Substitution;
use helpers::{DirectiveStatement, Helper, RustHelper};
@ -21,19 +22,22 @@ use types::Signature;
use types::conversions::cast;
use absy::variable::Variable;
use absy::parameter::Parameter;
use bimap::BiMap;
/// Flattener, computes flattened program.
pub struct Flattener {
/// Number of bits needed to represent the maximum value.
bits: usize,
/// Vector containing all used variables while processing the program.
variables: HashSet<String>,
variables: HashSet<FlatVariable>,
/// Map of renamings for reassigned variables while processing the program.
substitution: DirectSubstitution,
/// Map of function id to invocation counter
function_calls: HashMap<String, usize>,
/// Index of the next introduced variable while processing the program.
next_var_idx: usize,
/// bijection for name <=> id
bijection: BiMap<String, FlatVariable>
}
impl Flattener {
/// Returns a `Flattener` with fresh a fresh [substitution] and [variables].
@ -48,6 +52,7 @@ impl Flattener {
substitution: DirectSubstitution::new(),
function_calls: HashMap::new(),
next_var_idx: 0,
bijection: BiMap::new()
}
}
@ -162,16 +167,14 @@ impl Flattener {
);
// lhs
let lhs_name = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let lhs_id = self.use_sym();
statements_flattened
.push(FlatStatement::Definition(lhs_name.to_string(), lhs_flattened));
.push(FlatStatement::Definition(lhs_id, lhs_flattened));
// rhs
let rhs_name = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let rhs_id = self.use_sym();
statements_flattened
.push(FlatStatement::Definition(rhs_name.to_string(), rhs_flattened));
.push(FlatStatement::Definition(rhs_id, rhs_flattened));
// check that lhs and rhs are within the right range, ie, their last two bits are zero
@ -179,12 +182,12 @@ impl Flattener {
{
// bitness checks
for i in 0..self.bits - 2 {
let new_name = format!("{}{}{}", &lhs_name, BINARY_SEPARATOR, i);
let new_id = self.use_binary_variable(&lhs_id, i);
statements_flattened.push(FlatStatement::Definition(
new_name.to_string(),
new_id,
FlatExpression::Mult(
box FlatExpression::Identifier(new_name.to_string()),
box FlatExpression::Identifier(new_name.to_string()),
box FlatExpression::Identifier(new_id),
box FlatExpression::Identifier(new_id),
),
));
}
@ -196,7 +199,7 @@ impl Flattener {
lhs_sum = FlatExpression::Add(
box lhs_sum,
box FlatExpression::Mult(
box FlatExpression::Identifier(format!("{}{}{}", &lhs_name, BINARY_SEPARATOR, i)),
box FlatExpression::Identifier(self.use_binary_variable(&lhs_id, i)),
box FlatExpression::Number(T::from(2).pow(i)),
),
);
@ -204,7 +207,7 @@ impl Flattener {
statements_flattened
.push(FlatStatement::Condition(
FlatExpression::Identifier(lhs_name.clone()),
FlatExpression::Identifier(lhs_id),
lhs_sum
)
);
@ -214,12 +217,12 @@ impl Flattener {
{
// bitness checks
for i in 0..self.bits - 2 {
let new_name = format!("{}{}{}", &rhs_name, BINARY_SEPARATOR, i);
let new_id = self.use_binary_variable(&lhs_id, i);
statements_flattened.push(FlatStatement::Definition(
new_name.to_string(),
new_id,
FlatExpression::Mult(
box FlatExpression::Identifier(new_name.to_string()),
box FlatExpression::Identifier(new_name.to_string()),
box FlatExpression::Identifier(new_id),
box FlatExpression::Identifier(new_id),
),
));
}
@ -231,7 +234,7 @@ impl Flattener {
rhs_sum = FlatExpression::Add(
box rhs_sum,
box FlatExpression::Mult(
box FlatExpression::Identifier(format!("{}{}{}", &rhs_name, BINARY_SEPARATOR, i)),
box FlatExpression::Identifier(self.use_binary_variable(&rhs_id, i)),
box FlatExpression::Number(T::from(2).pow(i)),
),
);
@ -239,32 +242,31 @@ impl Flattener {
statements_flattened
.push(FlatStatement::Condition(
FlatExpression::Identifier(rhs_name.clone()),
FlatExpression::Identifier(rhs_id),
rhs_sum
)
);
}
// sym = (lhs * 2) - (rhs * 2)
let subtraction_result = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let subtraction_result_id = self.use_sym();
statements_flattened.push(FlatStatement::Definition(
subtraction_result.to_string(),
subtraction_result_id,
FlatExpression::Sub(
box FlatExpression::Mult(box FlatExpression::Number(T::from(2)), box FlatExpression::Identifier(lhs_name.to_string())),
box FlatExpression::Mult(box FlatExpression::Number(T::from(2)), box FlatExpression::Identifier(rhs_name.to_string())),
box FlatExpression::Mult(box FlatExpression::Number(T::from(2)), box FlatExpression::Identifier(lhs_id)),
box FlatExpression::Mult(box FlatExpression::Number(T::from(2)), box FlatExpression::Identifier(rhs_id)),
),
));
// sym_b{i} = sym_b{i}**2 (bitness checks)
for i in 0..self.bits {
let new_name = format!("{}{}{}", &subtraction_result, BINARY_SEPARATOR, i);
let new_id = self.use_binary_variable(&subtraction_result_id, i);
statements_flattened.push(FlatStatement::Definition(
new_name.to_string(),
new_id,
FlatExpression::Mult(
box FlatExpression::Identifier(new_name.to_string()),
box FlatExpression::Identifier(new_name.to_string()),
box FlatExpression::Identifier(new_id),
box FlatExpression::Identifier(new_id),
),
));
}
@ -276,7 +278,7 @@ impl Flattener {
expr = FlatExpression::Add(
box expr,
box FlatExpression::Mult(
box FlatExpression::Identifier(format!("{}{}{}", &subtraction_result, BINARY_SEPARATOR, i)),
box FlatExpression::Identifier(self.use_binary_variable(&subtraction_result_id, i)),
box FlatExpression::Number(T::from(2).pow(i)),
),
);
@ -284,23 +286,23 @@ impl Flattener {
statements_flattened
.push(FlatStatement::Condition(
FlatExpression::Identifier(subtraction_result.clone()),
FlatExpression::Identifier(subtraction_result_id),
expr
)
);
// rename output to avoid conflicts with suffixes
let cond_true = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let cond_true_id = self.use_sym();
statements_flattened
.push(FlatStatement::Definition(
cond_true.clone(),
FlatExpression::Identifier(format!("{}{}{}", &subtraction_result, BINARY_SEPARATOR, 0)))
cond_true_id,
FlatExpression::Identifier(FlatVariable::binary(subtraction_result_id.id, 0)))
);
self.next_var_idx += 1;
BooleanExpression::Identifier(cond_true)
// we need to return string-based variables for the rest of flattening, so we use the bijection
BooleanExpression::Identifier(self.bijection.get_by_right(&cond_true_id).unwrap().to_string())
}
BooleanExpression::Eq(box lhs, box rhs) => {
@ -314,14 +316,10 @@ impl Flattener {
// Y == X * M
// 0 == (1-Y) * X
let name_x = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let name_y = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let name_m = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let name_1_y = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let name_x = self.use_sym();
let name_y = self.use_sym();
let name_m = self.use_sym();
let name_1_y = self.use_sym();
let x = self.flatten_field_expression(
functions_flattened,
@ -330,28 +328,28 @@ impl Flattener {
FieldElementExpression::Sub(box lhs, box rhs),
);
statements_flattened.push(FlatStatement::Definition(name_x.to_string(), x));
statements_flattened.push(FlatStatement::Definition(name_x, x));
statements_flattened.push(
FlatStatement::Directive(DirectiveStatement {
outputs: vec![name_y.to_string(), name_m.to_string()],
inputs: vec![name_x.to_string()],
outputs: vec![name_y, name_m],
inputs: vec![name_x],
helper: Helper::Rust(RustHelper::ConditionEq)
})
);
statements_flattened.push(FlatStatement::Condition(
FlatExpression::Identifier(name_y.to_string()),
FlatExpression::Mult(box FlatExpression::Identifier(name_x.to_string()), box FlatExpression::Identifier(name_m)),
FlatExpression::Identifier(name_y),
FlatExpression::Mult(box FlatExpression::Identifier(name_x), box FlatExpression::Identifier(name_m)),
));
statements_flattened.push(FlatStatement::Definition(
name_1_y.to_string(),
FlatExpression::Sub(box FlatExpression::Number(T::one()), box FlatExpression::Identifier(name_y.to_string())),
name_1_y,
FlatExpression::Sub(box FlatExpression::Number(T::one()), box FlatExpression::Identifier(name_y)),
));
statements_flattened.push(FlatStatement::Condition(
FlatExpression::Number(T::zero()),
FlatExpression::Mult(box FlatExpression::Identifier(name_1_y.to_string()), box FlatExpression::Identifier(name_x)),
FlatExpression::Mult(box FlatExpression::Identifier(name_1_y), box FlatExpression::Identifier(name_x)),
));
BooleanExpression::Identifier(name_1_y)
BooleanExpression::Identifier(self.bijection.get_by_right(&name_1_y).unwrap().to_string())
}
_ => unimplemented!(),
}
@ -399,9 +397,9 @@ impl Flattener {
TypedExpression::FieldElement(e) => {
match e {
FieldElementExpression::Identifier(id) => {
new_var = format!("{}param_{}", &prefix, id);
new_var = self.use_variable(&format!("{}param_{}", &prefix, id));
statements_flattened
.push(FlatStatement::Definition(new_var.clone(), FlatExpression::Identifier(id.clone().to_string())));
.push(FlatStatement::Definition(new_var, FlatExpression::Identifier(self.bijection.get_by_left(&id).unwrap().clone())));
},
_ => {
// for field elements, flatten the input and assign it to a new variable
@ -412,24 +410,24 @@ impl Flattener {
statements_flattened,
expr_subbed,
);
new_var = format!("{}param_{}", &prefix, i);
new_var = self.use_variable(&format!("{}param_{}", &prefix, i));
statements_flattened
.push(FlatStatement::Definition(new_var.clone(), rhs));
.push(FlatStatement::Definition(new_var, rhs));
}
}
},
TypedExpression::Boolean(e) => {
match e {
BooleanExpression::Identifier(id) => {
new_var = format!("{}param_{}", &prefix, id);
new_var = self.use_variable(&format!("{}param_{}", &prefix, id));
statements_flattened
.push(FlatStatement::Definition(new_var.clone(), FlatExpression::Identifier(id.clone().to_string())));
.push(FlatStatement::Definition(new_var, FlatExpression::Identifier(self.bijection.get_by_left(&id).unwrap().clone())));
},
_ => panic!("A boolean argument to a function has to be a identifier")
}
}
}
replacement_map.insert(funct.arguments.get(i).unwrap().id.clone(), new_var);
replacement_map.insert(funct.arguments.get(i).unwrap().id.to_string(), new_var.to_string());
}
// Ensure Renaming and correct returns:
@ -443,8 +441,8 @@ impl Flattener {
}
},
FlatStatement::Definition(var, rhs) => {
let new_var: String = format!("{}{}", prefix, var.clone());
replacement_map.insert(var, new_var.clone());
let new_var = self.use_variable(&format!("{}{}", prefix, self.bijection.get_by_right(&var).unwrap()));
replacement_map.insert(var.to_string(), new_var.to_string());
let new_rhs = rhs.apply_substitution(&replacement_map);
statements_flattened.push(
FlatStatement::Definition(new_var, new_rhs)
@ -458,11 +456,11 @@ impl Flattener {
},
FlatStatement::Directive(d) => {
let new_outputs = d.outputs.iter().map(|o| {
let new_o: String = format!("{}{}", prefix, o.clone());
replacement_map.insert(o.to_string(), new_o.clone());
let new_o = self.use_variable(&format!("{}{}", prefix, self.bijection.get_by_right(&o).unwrap()));
replacement_map.insert(o.to_string(), new_o.to_string());
new_o
}).collect();
let new_inputs = d.inputs.iter().map(|i| replacement_map.get(i).unwrap()).collect();
let new_inputs = d.inputs.iter().map(|i| replacement_map.get(&i.to_string()).unwrap()).collect();
statements_flattened.push(
FlatStatement::Directive(
DirectiveStatement {
@ -493,7 +491,7 @@ impl Flattener {
) -> FlatExpression<T> {
match expr {
FieldElementExpression::Number(x) => FlatExpression::Number(x), // force to be a field element
FieldElementExpression::Identifier(x) => FlatExpression::Identifier(x),
FieldElementExpression::Identifier(x) => FlatExpression::Identifier(self.bijection.get_by_left(&x).unwrap().clone()),
FieldElementExpression::Add(box left, box right) => {
let left_flattened = self.flatten_field_expression(
functions_flattened,
@ -510,20 +508,18 @@ impl Flattener {
let new_left = if left_flattened.is_linear() {
left_flattened
} else {
let new_name = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let id = self.use_sym();
statements_flattened
.push(FlatStatement::Definition(new_name.to_string(), left_flattened));
FlatExpression::Identifier(new_name)
.push(FlatStatement::Definition(id, left_flattened));
FlatExpression::Identifier(id)
};
let new_right = if right_flattened.is_linear() {
right_flattened
} else {
let new_name = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let id = self.use_sym();
statements_flattened
.push(FlatStatement::Definition(new_name.to_string(), right_flattened));
FlatExpression::Identifier(new_name)
.push(FlatStatement::Definition(id, right_flattened));
FlatExpression::Identifier(id)
};
FlatExpression::Add(box new_left, box new_right)
},
@ -543,20 +539,18 @@ impl Flattener {
let new_left = if left_flattened.is_linear() {
left_flattened
} else {
let new_name = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let id = self.use_sym();
statements_flattened
.push(FlatStatement::Definition(new_name.to_string(), left_flattened));
FlatExpression::Identifier(new_name)
.push(FlatStatement::Definition(id, left_flattened));
FlatExpression::Identifier(id)
};
let new_right = if right_flattened.is_linear() {
right_flattened
} else {
let new_name = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let id = self.use_sym();
statements_flattened
.push(FlatStatement::Definition(new_name.to_string(), right_flattened));
FlatExpression::Identifier(new_name)
.push(FlatStatement::Definition(id, right_flattened));
FlatExpression::Identifier(id)
};
FlatExpression::Sub(box new_left, box new_right)
},
@ -575,37 +569,33 @@ impl Flattener {
);
let new_left = if left_flattened.is_linear() {
if let FlatExpression::Sub(..) = left_flattened {
let new_name = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let id = self.use_sym();
statements_flattened
.push(FlatStatement::Definition(new_name.to_string(), left_flattened));
FlatExpression::Identifier(new_name)
.push(FlatStatement::Definition(id, left_flattened));
FlatExpression::Identifier(id)
} else {
left_flattened
}
} else {
let new_name = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let id = self.use_sym();
statements_flattened
.push(FlatStatement::Definition(new_name.to_string(), left_flattened));
FlatExpression::Identifier(new_name)
.push(FlatStatement::Definition(id, left_flattened));
FlatExpression::Identifier(id)
};
let new_right = if right_flattened.is_linear() {
if let FlatExpression::Sub(..) = right_flattened {
let new_name = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let id = self.use_sym();
statements_flattened
.push(FlatStatement::Definition(new_name.to_string(), right_flattened));
FlatExpression::Identifier(new_name)
.push(FlatStatement::Definition(id, right_flattened));
FlatExpression::Identifier(id)
} else {
right_flattened
}
} else {
let new_name = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let id = self.use_sym();
statements_flattened
.push(FlatStatement::Definition(new_name.to_string(), right_flattened));
FlatExpression::Identifier(new_name)
.push(FlatStatement::Definition(id, right_flattened));
FlatExpression::Identifier(id)
};
FlatExpression::Mult(box new_left, box new_right)
},
@ -623,18 +613,16 @@ impl Flattener {
right,
);
let new_left = {
let new_name = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let id = self.use_sym();
statements_flattened
.push(FlatStatement::Definition(new_name.to_string(), left_flattened));
FlatExpression::Identifier(new_name)
.push(FlatStatement::Definition(id, left_flattened));
FlatExpression::Identifier(id)
};
let new_right = {
let new_name = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let id = self.use_sym();
statements_flattened
.push(FlatStatement::Definition(new_name.to_string(), right_flattened));
FlatExpression::Identifier(new_name)
.push(FlatStatement::Definition(id, right_flattened));
FlatExpression::Identifier(id)
};
FlatExpression::Div(box new_left, box new_right)
},
@ -653,18 +641,17 @@ impl Flattener {
box FieldElementExpression::Number(x.clone() - T::one()),
),
);
let new_name = format!("sym_{}", self.next_var_idx);
self.next_var_idx += 1;
let id = self.use_sym();
statements_flattened.push(
FlatStatement::Definition(new_name.to_string(), tmp_expression),
FlatStatement::Definition(id, tmp_expression),
);
new_name
id
} else {
var.to_string()
self.bijection.get_by_left(&var).unwrap().clone()
};
FlatExpression::Mult(
box FlatExpression::Identifier(id.to_string()),
box FlatExpression::Identifier(var.to_string()),
box FlatExpression::Identifier(id),
box FlatExpression::Identifier(self.bijection.get_by_left(&var).unwrap().clone()),
)
}
FieldElementExpression::Number(var) => FlatExpression::Mult(box FlatExpression::Number(var.clone()), box FlatExpression::Number(var)),
@ -858,7 +845,7 @@ impl Flattener {
// handle return of function call
let var_to_replace = self.get_latest_var_substitution(&v.id);
if !(var == var_to_replace) && self.variables.contains(&var_to_replace) && !self.substitution.contains_key(&var_to_replace){
self.substitution.insert(var_to_replace.clone().to_string(),var.clone());
self.substitution.insert(var_to_replace.to_string(), var.to_string());
}
statements_flattened.push(FlatStatement::Definition(var, rhs_flattened.expressions[i].clone()));
},
@ -884,6 +871,9 @@ impl Flattener {
) -> FlatFunction<T> {
self.variables = HashSet::new();
self.substitution = DirectSubstitution::new();
self.bijection = BiMap::new();
self.next_var_idx = 0;
let mut arguments_flattened: Vec<FlatParameter> = Vec::new();
let mut statements_flattened: Vec<FlatStatement<T>> = Vec::new();
@ -894,13 +884,13 @@ impl Flattener {
match arg_type {
Type::FieldElement => {
arguments_flattened.push(FlatParameter {
id: self.use_variable(&arg.id.id),
id: self.use_variable(&arg.id.id).id,
private: arg.private
});
},
Type::Boolean => {
arguments_flattened.push(FlatParameter {
id: self.use_variable(&arg.id.id),
id: self.use_variable(&arg.id.id).id,
private: arg.private
});
},
@ -923,7 +913,8 @@ impl Flattener {
id: funct.id.clone(),
arguments: arguments_flattened,
statements: statements_flattened,
return_count: return_count
return_count: return_count,
bijection: self.bijection,
}
}
@ -956,7 +947,9 @@ impl Flattener {
/// # Arguments
///
/// * `name` - A String that holds the name of the variable
fn use_variable(&mut self, name: &String) -> String {
fn use_variable(&mut self, name: &String) -> FlatVariable {
self.next_var_idx += 1;
let mut i = 0;
let mut new_name = name.to_string();
loop {
@ -972,16 +965,34 @@ impl Flattener {
self.substitution
.insert(format!("{}_{}", name, i - 2), new_name.to_string());
}
return new_name;
let var = FlatVariable::new(self.next_var_idx);
self.bijection.insert(new_name, var);
return var;
}
}
}
fn get_latest_var_substitution(&mut self, name: &String)->String{
let mut latest_var = name.to_string();
fn use_binary_variable(&mut self, var: &FlatVariable, bit: usize) -> FlatVariable {
FlatVariable {
binary: Some(bit),
..var.clone()
}
}
fn use_sym(&mut self) -> FlatVariable {
self.next_var_idx += 1;
let name = format!("sym_{}", self.next_var_idx);
let var = FlatVariable::new(self.next_var_idx);
self.bijection.insert(name, var);
var
}
fn get_latest_var_substitution(&mut self, name: &String) -> FlatVariable {
let mut latest_var = self.bijection.get_by_left(name).unwrap().clone();
loop {
match self.substitution.get(&latest_var) {
Some(x) => latest_var = x.to_string(),
match self.substitution.get(&latest_var.to_string()) {
Some(x) => latest_var = x,
None => return latest_var,
}
}

View file

@ -7,18 +7,23 @@ pub use self::libsnark_gadget::LibsnarkGadgetHelper;
pub use self::rust::RustHelper;
use std::fmt;
use field::{Field};
use flat_absy::flat_variable::FlatVariable;
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct DirectiveStatement {
pub inputs: Vec<String>,
pub outputs: Vec<String>,
pub inputs: Vec<FlatVariable>,
pub outputs: Vec<FlatVariable>,
pub helper: Helper
}
impl fmt::Display for DirectiveStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "# {} = {}({})", self.outputs.join(", "), self.helper, self.inputs.join(", "))
write!(f, "# {} = {}({})",
self.outputs.iter().map(|o| o.to_string()).collect().join(", "),
self.helper,
self.inputs.map(|i| i.to_string()).collect().join(", ")
)
}
}

View file

@ -11,6 +11,7 @@ extern crate serde_json;
extern crate serde_derive;
extern crate bincode;
extern crate regex;
extern crate bimap;
mod parser;
mod imports;

View file

@ -5,6 +5,7 @@
//! @author Jacob Eberhardt <jacob.eberhardt@tu-berlin.de
//! @date 2017
use flat_absy::flat_variable::FlatVariable;
use std::collections::HashMap;
use flat_absy::*;
use flat_absy::FlatExpression::*;
@ -52,26 +53,26 @@ fn get_summands<T: Field>(expr: &FlatExpression<T>) -> Vec<&FlatExpression<T>> {
/// # Example
///
/// `7 * x + 4 * y + x` -> { x => 8, y = 4 }
fn count_variables_add<T: Field>(expr: &FlatExpression<T>) -> HashMap<String, T> {
fn count_variables_add<T: Field>(expr: &FlatExpression<T>) -> HashMap<FlatVariable, T> {
let summands = get_summands(expr);
let mut count = HashMap::new();
for s in summands {
match *s {
Number(ref x) => {
let num = count.entry("~one".to_string()).or_insert(T::zero());
let num = count.entry(FlatVariable::one()).or_insert(T::zero());
*num = num.clone() + x;
}
Identifier(ref v) => {
let num = count.entry(v.to_string()).or_insert(T::zero());
let num = count.entry(*v).or_insert(T::zero());
*num = num.clone() + T::one();
}
Mult(box Number(ref x1), box Number(ref x2)) => {
let num = count.entry("~one".to_string()).or_insert(T::zero());
let num = count.entry(FlatVariable::one()).or_insert(T::zero());
*num = num.clone() + x1 + x2;
}
Mult(box Number(ref x), box Identifier(ref v)) |
Mult(box Identifier(ref v), box Number(ref x)) => {
let num = count.entry(v.to_string()).or_insert(T::zero());
let num = count.entry(*v).or_insert(T::zero());
*num = num.clone() + x;
}
ref e => panic!("Not covered: {}", e),
@ -145,7 +146,7 @@ fn swap_sub<T: Field>(lhs: &FlatExpression<T>, rhs: &FlatExpression<T>) -> (Flat
fn r1cs_expression<T: Field>(
linear_expr: FlatExpression<T>,
expr: FlatExpression<T>,
variables: &mut Vec<String>,
variables: &mut Vec<FlatVariable>,
a_row: &mut Vec<(usize, T)>,
b_row: &mut Vec<(usize, T)>,
c_row: &mut Vec<(usize, T)>,
@ -250,11 +251,11 @@ fn r1cs_expression<T: Field>(
///
/// * `variables` - A mutual vector that contains all existing variables. Not found variables will be added.
/// * `var` - Variable to be searched for.
fn get_variable_idx(variables: &mut Vec<String>, var: &String) -> usize {
fn get_variable_idx(variables: &mut Vec<FlatVariable>, var: &FlatVariable) -> usize {
match variables.iter().position(|r| r == var) {
Some(x) => x,
None => {
variables.push(var.to_string());
variables.push(var.clone());
variables.len() - 1
}
}
@ -268,16 +269,16 @@ fn get_variable_idx(variables: &mut Vec<String>, var: &String) -> usize {
///
/// * `prog` - The program the representation is calculated for.
pub fn r1cs_program<T: Field>(
prog: &FlatProg<T>,
prog: &mut FlatProg<T>,
) -> (
Vec<String>,
Vec<FlatVariable>,
usize,
Vec<Vec<(usize, T)>>,
Vec<Vec<(usize, T)>>,
Vec<Vec<(usize, T)>>,
) {
let mut variables: Vec<String> = Vec::new();
variables.push("~one".to_string());
let mut variables = Vec::new();
variables.push(FlatVariable::one());
let mut a: Vec<Vec<(usize, T)>> = Vec::new();
let mut b: Vec<Vec<(usize, T)>> = Vec::new();
let mut c: Vec<Vec<(usize, T)>> = Vec::new();
@ -287,12 +288,12 @@ pub fn r1cs_program<T: Field>(
.iter()
.find(|x: &&FlatFunction<T>| x.id == "main".to_string())
.unwrap();
variables.extend(main.arguments.iter().filter(|x| !x.private).map(|x| format!("{}", x)));
variables.extend(main.arguments.iter().filter(|x| !x.private).map(|x| FlatVariable::new(x.id))); // TODO hacky for binary values
// ~out is added after main's arguments as we want variables (columns)
// in the r1cs to be aligned like "public inputs | private inputs"
for i in 0..main.return_count {
variables.push(format!("~out_{}", i).to_string());
variables.push(FlatVariable::new(42));
}
// position where private part of witness starts
@ -306,7 +307,7 @@ pub fn r1cs_program<T: Field>(
let mut b_row: Vec<(usize, T)> = Vec::new();
let mut c_row: Vec<(usize, T)> = Vec::new();
r1cs_expression(
Identifier(format!("~out_{}", i).to_string()),
Identifier(FlatVariable::new(42)), // should inject in the constraint system, possibly at flattening
val.clone(),
&mut variables,
&mut a_row,
@ -323,7 +324,7 @@ pub fn r1cs_program<T: Field>(
let mut b_row: Vec<(usize, T)> = Vec::new();
let mut c_row: Vec<(usize, T)> = Vec::new();
r1cs_expression(
FlatExpression::Identifier(id.to_string()),
FlatExpression::Identifier(*id),
rhs.clone(),
&mut variables,
&mut a_row,