throw an error when assigning to an immutable circuit variable

This commit is contained in:
collin 2020-09-02 17:52:17 -07:00
parent df9fb58677
commit 87781fed03
4 changed files with 30 additions and 14 deletions

View File

@ -96,6 +96,12 @@ impl StatementError {
Self::new_from_span(message, span)
}
pub fn immutable_circuit_variable(name: String, span: Span) -> Self {
let message = format!("Circuit member variable `{}` is immutable", name);
Self::new_from_span(message, span)
}
pub fn indicator_calculation(name: String, span: Span) -> Self {
let message = format!(
"Constraint system failed to evaluate branch selection indicator `{}`",
@ -168,8 +174,8 @@ impl StatementError {
Self::new_from_span(message, span)
}
pub fn undefined_circuit_object(name: String, span: Span) -> Self {
let message = format!("Attempted to assign to unknown circuit object `{}`", name);
pub fn undefined_circuit_variable(name: String, span: Span) -> Self {
let message = format!("Attempted to assign to unknown circuit member variable `{}`", name);
Self::new_from_span(message, span)
}

View File

@ -77,9 +77,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
for stored_member in members {
let circuit_scope = new_scope(file_scope.clone(), circuit_name.to_string());
let self_keyword = new_scope(circuit_scope, SELF_KEYWORD.to_string());
let field = new_scope(self_keyword, stored_member.0.to_string());
let variable = new_scope(self_keyword, stored_member.0.to_string());
self.store(field, stored_member.1.clone());
self.store(variable, stored_member.1.clone());
}
}
ConstrainedValue::Static(value) => {

View File

@ -33,19 +33,20 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
cs: &mut CS,
indicator: Option<Boolean>,
circuit_name: String,
object_name: Identifier,
variable_name: Identifier,
mut new_value: ConstrainedValue<F, G>,
span: Span,
) -> Result<(), StatementError> {
let condition = indicator.unwrap_or(Boolean::Constant(true));
// Get the mutable circuit by name
match self.get_mutable_assignee(circuit_name, span.clone())? {
ConstrainedValue::CircuitExpression(_variable, members) => {
// Modify the circuit variable in place
let matched_variable = members.into_iter().find(|object| object.0 == object_name);
let matched_variable = members.into_iter().find(|member| member.0 == variable_name);
match matched_variable {
Some(object) => match &object.1 {
Some(member) => match &member.1 {
ConstrainedValue::Function(_circuit_identifier, function) => {
return Err(StatementError::immutable_circuit_function(
function.identifier.to_string(),
@ -55,27 +56,35 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
ConstrainedValue::Static(_value) => {
return Err(StatementError::immutable_circuit_function("static".into(), span));
}
_ => {
new_value.resolve_type(Some(object.1.to_type(span.clone())?), span.clone())?;
ConstrainedValue::Mutable(value) => {
new_value.resolve_type(Some(value.to_type(span.clone())?), span.clone())?;
let name_unique = format!("select {} {}:{}", new_value, span.line, span.start);
let selected_value = ConstrainedValue::conditionally_select(
cs.ns(|| name_unique),
&condition,
&new_value,
&object.1,
&member.1,
)
.map_err(|_| {
StatementError::select_fail(new_value.to_string(), object.1.to_string(), span)
StatementError::select_fail(new_value.to_string(), member.1.to_string(), span)
})?;
object.1 = selected_value.to_owned();
member.1 = selected_value.to_owned();
}
_ => {
return Err(StatementError::immutable_circuit_variable(variable_name.name, span));
}
},
None => return Err(StatementError::undefined_circuit_object(object_name.to_string(), span)),
None => {
return Err(StatementError::undefined_circuit_variable(
variable_name.to_string(),
span,
));
}
}
}
_ => return Err(StatementError::undefined_circuit(object_name.to_string(), span)),
_ => return Err(StatementError::undefined_circuit(variable_name.to_string(), span)),
}
Ok(())

View File

@ -132,6 +132,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
Type::Tuple(types)
}
ConstrainedValue::CircuitExpression(id, _members) => Type::Circuit(id.clone()),
ConstrainedValue::Mutable(value) => return value.to_type(span),
value => return Err(ValueError::implicit(value.to_string(), span)),
})
}