mirror of
https://github.com/AleoHQ/leo.git
synced 2025-01-05 08:50:21 +03:00
bounds check
This commit is contained in:
parent
dc91b07e5c
commit
e6b7f0fce3
@ -37,6 +37,33 @@ use snarkvm_gadgets::utilities::{
|
|||||||
use snarkvm_r1cs::ConstraintSystem;
|
use snarkvm_r1cs::ConstraintSystem;
|
||||||
|
|
||||||
impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
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)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn enforce_array_access<CS: ConstraintSystem<F>>(
|
pub fn enforce_array_access<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -65,21 +92,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
|||||||
.len()
|
.len()
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|_| ExpressionError::array_length_out_of_bounds(span))?;
|
.map_err(|_| ExpressionError::array_length_out_of_bounds(span))?;
|
||||||
let bounds_check = evaluate_lt::<F, G, CS>(
|
self.array_bounds_check(cs, &&index_resolved, array_len, span)?;
|
||||||
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))?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut current_value = array.pop().unwrap();
|
let mut current_value = array.pop().unwrap();
|
||||||
|
@ -25,7 +25,7 @@ use crate::{
|
|||||||
GroupType,
|
GroupType,
|
||||||
Integer,
|
Integer,
|
||||||
};
|
};
|
||||||
use leo_asg::{ConstInt, Expression};
|
use leo_asg::{ConstInt, Expression, Node};
|
||||||
|
|
||||||
use snarkvm_fields::PrimeField;
|
use snarkvm_fields::PrimeField;
|
||||||
use snarkvm_gadgets::utilities::{eq::EvaluateEqGadget, select::CondSelectGadget};
|
use snarkvm_gadgets::utilities::{eq::EvaluateEqGadget, select::CondSelectGadget};
|
||||||
@ -65,25 +65,34 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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() {
|
for (i, item) in input.iter_mut().enumerate() {
|
||||||
let namespace_string = format!(
|
let namespace_string = format!(
|
||||||
"evaluate dyn array assignment eq {} {}:{}",
|
"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 eq_namespace = cs.ns(|| namespace_string);
|
||||||
|
|
||||||
let index_bounded = i
|
let index_bounded = i
|
||||||
.try_into()
|
.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 const_index = ConstInt::U32(index_bounded).cast_to(&index_resolved.get_type());
|
||||||
let index_comparison = index_resolved
|
let index_comparison = index_resolved
|
||||||
.evaluate_equal(eq_namespace, &Integer::new(&const_index))
|
.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(|| {
|
let unique_namespace = cs.ns(|| {
|
||||||
format!(
|
format!(
|
||||||
"select array dyn assignment {} {}:{}",
|
"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(
|
let value = ConstrainedValue::conditionally_select(
|
||||||
@ -92,7 +101,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
|||||||
&context.target_value,
|
&context.target_value,
|
||||||
&item,
|
&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;
|
*item = value;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
Reference in New Issue
Block a user