1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

Merge pull request #1120 from Zokrates/detect-unconstrained-variables

Detect unconstrained variables gracefully
This commit is contained in:
Darko Macesic 2022-04-08 15:10:52 +02:00 committed by GitHub
commit c598a66039
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 3 deletions

View file

@ -0,0 +1 @@
Handle unconstrained variables gracefully

View file

@ -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())
}
}

View file

@ -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)]

View 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
}
}