Merge pull request #1120 from Zokrates/detect-unconstrained-variables
Detect unconstrained variables gracefully
This commit is contained in:
commit
c598a66039
4 changed files with 66 additions and 3 deletions
1
changelogs/unreleased/1120-schaeff
Normal file
1
changelogs/unreleased/1120-schaeff
Normal file
|
@ -0,0 +1 @@
|
|||
Handle unconstrained variables gracefully
|
|
@ -1,4 +1,7 @@
|
|||
use crate::ir::{ProgIterator, Statement};
|
||||
use crate::{
|
||||
ir::{ProgIterator, Statement},
|
||||
static_analysis::UnconstrainedVariableDetector,
|
||||
};
|
||||
use serde_cbor::{self, StreamDeserializer};
|
||||
use std::io::{Read, Write};
|
||||
use zokrates_field::*;
|
||||
|
@ -49,6 +52,8 @@ impl<T: Field, I: IntoIterator<Item = Statement<T>>> ProgIterator<T, I> {
|
|||
/// serialize a program iterator, returning the number of constraints serialized
|
||||
/// Note that we only return constraints, not other statements such as directives
|
||||
pub fn serialize<W: Write>(self, mut w: W) -> Result<usize, DynamicError> {
|
||||
use crate::ir::folder::Folder;
|
||||
|
||||
w.write_all(ZOKRATES_MAGIC)?;
|
||||
w.write_all(ZOKRATES_VERSION_2)?;
|
||||
w.write_all(&T::id())?;
|
||||
|
@ -56,6 +61,8 @@ impl<T: Field, I: IntoIterator<Item = Statement<T>>> ProgIterator<T, I> {
|
|||
serde_cbor::to_writer(&mut w, &self.arguments)?;
|
||||
serde_cbor::to_writer(&mut w, &self.return_count)?;
|
||||
|
||||
let mut unconstrained_variable_detector = UnconstrainedVariableDetector::new(&self);
|
||||
|
||||
let statements = self.statements.into_iter();
|
||||
|
||||
let mut count = 0;
|
||||
|
@ -63,10 +70,16 @@ impl<T: Field, I: IntoIterator<Item = Statement<T>>> ProgIterator<T, I> {
|
|||
if matches!(s, Statement::Constraint(..)) {
|
||||
count += 1;
|
||||
}
|
||||
serde_cbor::to_writer(&mut w, &s)?;
|
||||
let s = unconstrained_variable_detector.fold_statement(s);
|
||||
for s in s {
|
||||
serde_cbor::to_writer(&mut w, &s)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(count)
|
||||
unconstrained_variable_detector
|
||||
.finalize()
|
||||
.map(|_| count)
|
||||
.map_err(|count| format!("Error: Found {} unconstrained variable(s)", count).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ mod propagation;
|
|||
mod reducer;
|
||||
mod struct_concretizer;
|
||||
mod uint_optimizer;
|
||||
mod unconstrained_vars;
|
||||
mod variable_write_remover;
|
||||
mod zir_propagation;
|
||||
|
||||
|
@ -34,6 +35,7 @@ use crate::static_analysis::zir_propagation::ZirPropagator;
|
|||
use crate::typed_absy::{abi::Abi, TypedProgram};
|
||||
use crate::zir::ZirProgram;
|
||||
use std::fmt;
|
||||
pub use unconstrained_vars::UnconstrainedVariableDetector;
|
||||
use zokrates_field::Field;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
47
zokrates_core/src/static_analysis/unconstrained_vars.rs
Normal file
47
zokrates_core/src/static_analysis/unconstrained_vars.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
use crate::flat_absy::FlatParameter;
|
||||
use crate::flat_absy::FlatVariable;
|
||||
use crate::ir::folder::Folder;
|
||||
use crate::ir::Directive;
|
||||
use crate::ir::ProgIterator;
|
||||
use crate::ir::Statement;
|
||||
use std::collections::HashSet;
|
||||
use zokrates_field::Field;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UnconstrainedVariableDetector {
|
||||
pub(self) variables: HashSet<FlatVariable>,
|
||||
}
|
||||
|
||||
impl UnconstrainedVariableDetector {
|
||||
pub fn new<T: Field, I: IntoIterator<Item = Statement<T>>>(p: &ProgIterator<T, I>) -> Self {
|
||||
UnconstrainedVariableDetector {
|
||||
variables: p
|
||||
.arguments
|
||||
.iter()
|
||||
.filter(|p| p.private)
|
||||
.map(|p| p.id)
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finalize(self) -> Result<(), usize> {
|
||||
if self.variables.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
Err(self.variables.len())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Field> Folder<T> for UnconstrainedVariableDetector {
|
||||
fn fold_argument(&mut self, p: FlatParameter) -> FlatParameter {
|
||||
p
|
||||
}
|
||||
fn fold_variable(&mut self, v: FlatVariable) -> FlatVariable {
|
||||
self.variables.remove(&v);
|
||||
v
|
||||
}
|
||||
fn fold_directive(&mut self, d: Directive<T>) -> Directive<T> {
|
||||
self.variables.extend(d.outputs.iter());
|
||||
d
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue