bounds check

This commit is contained in:
Protryon 2021-06-04 07:35:50 -07:00
parent dc91b07e5c
commit e6b7f0fce3
2 changed files with 43 additions and 21 deletions

View File

@ -37,6 +37,33 @@ use snarkvm_gadgets::utilities::{
use snarkvm_r1cs::ConstraintSystem;
impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
pub fn array_bounds_check<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
index_resolved: &Integer,
array_len: u32,
span: &Span,
) -> Result<(), ExpressionError> {
let bounds_check = evaluate_lt::<F, G, CS>(
cs,
ConstrainedValue::Integer(index_resolved.clone()),
ConstrainedValue::Integer(Integer::new(
&ConstInt::U32(array_len).cast_to(&index_resolved.get_type()),
)),
span,
)?;
let bounds_check = match bounds_check {
ConstrainedValue::Boolean(b) => b,
_ => unimplemented!("illegal non-Integer returned from lt"),
};
let namespace_string = format!("evaluate array access bounds {}:{}", span.line_start, span.col_start);
let mut unique_namespace = cs.ns(|| namespace_string);
bounds_check
.enforce_equal(&mut unique_namespace, &Boolean::Constant(true))
.map_err(|e| ExpressionError::cannot_enforce("array bounds check".to_string(), e, span))?;
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub fn enforce_array_access<CS: ConstraintSystem<F>>(
&mut self,
@ -65,21 +92,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
.len()
.try_into()
.map_err(|_| ExpressionError::array_length_out_of_bounds(span))?;
let bounds_check = evaluate_lt::<F, G, CS>(
cs,
ConstrainedValue::Integer(index_resolved.clone()),
ConstrainedValue::Integer(Integer::new(&ConstInt::U32(array_len))),
span,
)?;
let bounds_check = match bounds_check {
ConstrainedValue::Boolean(b) => b,
_ => unimplemented!("illegal non-Integer returned from lt"),
};
let namespace_string = format!("evaluate array access bounds {}:{}", span.line_start, span.col_start);
let mut unique_namespace = cs.ns(|| namespace_string);
bounds_check
.enforce_equal(&mut unique_namespace, &Boolean::Constant(true))
.map_err(|e| ExpressionError::cannot_enforce("array bounds check".to_string(), e, span))?;
self.array_bounds_check(cs, &&index_resolved, array_len, span)?;
}
let mut current_value = array.pop().unwrap();

View File

@ -25,7 +25,7 @@ use crate::{
GroupType,
Integer,
};
use leo_asg::{ConstInt, Expression};
use leo_asg::{ConstInt, Expression, Node};
use snarkvm_fields::PrimeField;
use snarkvm_gadgets::utilities::{eq::EvaluateEqGadget, select::CondSelectGadget};
@ -65,25 +65,34 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
}
}
} else {
let span = index.span().cloned().unwrap_or_default();
{
let array_len: u32 = input
.len()
.try_into()
.map_err(|_| ExpressionError::array_length_out_of_bounds(&span))?;
self.array_bounds_check(cs, &&index_resolved, array_len, &span)?;
}
for (i, item) in input.iter_mut().enumerate() {
let namespace_string = format!(
"evaluate dyn array assignment eq {} {}:{}",
i, context.span.line_start, context.span.col_start
i, span.line_start, span.col_start
);
let eq_namespace = cs.ns(|| namespace_string);
let index_bounded = i
.try_into()
.map_err(|_| ExpressionError::array_index_out_of_legal_bounds(&context.span))?;
.map_err(|_| ExpressionError::array_index_out_of_legal_bounds(&span))?;
let const_index = ConstInt::U32(index_bounded).cast_to(&index_resolved.get_type());
let index_comparison = index_resolved
.evaluate_equal(eq_namespace, &Integer::new(&const_index))
.map_err(|_| ExpressionError::cannot_evaluate("==".to_string(), &context.span))?;
.map_err(|_| ExpressionError::cannot_evaluate("==".to_string(), &span))?;
let unique_namespace = cs.ns(|| {
format!(
"select array dyn assignment {} {}:{}",
i, context.span.line_start, context.span.col_start
i, span.line_start, span.col_start
)
});
let value = ConstrainedValue::conditionally_select(
@ -92,7 +101,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
&context.target_value,
&item,
)
.map_err(|e| ExpressionError::cannot_enforce("conditional select".to_string(), e, &context.span))?;
.map_err(|e| ExpressionError::cannot_enforce("conditional select".to_string(), e, &span))?;
*item = value;
}
Ok(())