Merge branch 'master' into type_tweaks

This commit is contained in:
Collin Chin 2020-10-20 22:29:23 -07:00 committed by GitHub
commit d2dcf65b68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
149 changed files with 588 additions and 697 deletions

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::{errors::ParserError, files::File, LeoAst};
use leo_ast::LeoAst;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use std::path::{Path, PathBuf};

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
#![allow(clippy::module_inception)]
pub mod access;
pub use access::*;

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
#![allow(clippy::module_inception)]
pub mod annotations;
pub use annotations::*;

View File

@ -39,20 +39,17 @@ pub enum ParserError {
impl ParserError {
pub fn set_path(&mut self, path: PathBuf) {
match self {
ParserError::SyntaxError(error) => {
let new_error: Error<Rule> = match error {
SyntaxError::Error(error) => {
let new_error = error.clone();
new_error.with_path(path.to_str().unwrap())
}
};
if let ParserError::SyntaxError(error) = self {
let new_error: Error<Rule> = match error {
SyntaxError::Error(error) => {
let new_error = error.clone();
new_error.with_path(path.to_str().unwrap())
}
};
tracing::error!("{}", new_error);
tracing::error!("{}", new_error);
*error = SyntaxError::Error(new_error);
}
_ => {}
*error = SyntaxError::Error(new_error);
}
}
}

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
#![allow(clippy::module_inception)]
pub mod function_input;
pub use function_input::*;

View File

@ -39,11 +39,11 @@ pub struct ConditionalStatement<'ast> {
impl<'ast> fmt::Display for ConditionalStatement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "if ({}) {{\n", self.condition)?;
write!(f, "\t{:#?}\n", self.statements)?;
writeln!(f, "if ({}) {{", self.condition)?;
writeln!(f, "\t{:#?}", self.statements)?;
self.next
.as_ref()
.map(|n_or_e| write!(f, "}} {}", n_or_e))
.unwrap_or(write!(f, "}}"))
.unwrap_or_else(|| write!(f, "}}"))
}
}

View File

@ -135,6 +135,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
}
/// Parses the Leo program file, constructs a syntax tree, and generates a program.
#[allow(deprecated)]
pub(crate) fn parse_program(&mut self) -> Result<(), CompilerError> {
// Use the parser to construct the abstract syntax tree.
let program_string = LeoAst::load_file(&self.main_file_path)?;

View File

@ -53,9 +53,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
// Unwrap assertion value and handle errors
let result_option = match assert_expression {
ConstrainedValue::Boolean(boolean) => boolean.get_value(),
_ => return Err(ConsoleError::assertion_must_be_boolean(expression_string, span.clone())),
_ => return Err(ConsoleError::assertion_must_be_boolean(expression_string, span)),
};
let result_bool = result_option.ok_or(ConsoleError::assertion_depends_on_input(span.clone()))?;
let result_bool = result_option.ok_or_else(|| ConsoleError::assertion_depends_on_input(span.clone()))?;
if !result_bool {
return Err(ConsoleError::assertion_failed(expression_string, span));

View File

@ -37,16 +37,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
return Err(ConsoleError::length(
formatted.containers.len(),
formatted.parameters.len(),
formatted.span.clone(),
formatted.span,
));
}
// Trim starting double quote `"`
let mut string = formatted.string.as_str();
string = string.trim_start_matches("\"");
string = string.trim_start_matches('\"');
// Trim everything after the ending double quote `"`
let parts: Vec<&str> = string.split("\"").collect();
let parts: Vec<&str> = string.split('\"').collect();
string = parts[0];
// Insert the parameter for each container `{}`

View File

@ -32,7 +32,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
mutable: bool,
identifier: Identifier,
mut value: ConstrainedValue<F, G>,
) -> () {
) {
// Store with given mutability
if mutable {
value = ConstrainedValue::Mutable(Box::new(value));

View File

@ -50,7 +50,8 @@ impl ConsoleError {
}
pub fn assertion_depends_on_input(span: Span) -> Self {
let message = format!("console.assert() failed to evaluate. This error is caused by empty input file values");
let message =
"console.assert() failed to evaluate. This error is caused by empty input file values".to_string();
Self::new_from_span(message, span)
}

View File

@ -146,7 +146,7 @@ impl ExpressionError {
}
pub fn self_keyword(span: Span) -> Self {
let message = format!("cannot call keyword `Self` outside of a circuit function");
let message = "cannot call keyword `Self` outside of a circuit function".to_string();
Self::new_from_span(message, span)
}

View File

@ -48,7 +48,7 @@ impl ImportError {
}
pub fn convert_os_string(span: Span) -> Self {
let message = format!("failed to convert file string name, maybe an illegal character?");
let message = "failed to convert file string name, maybe an illegal character?".to_string();
Self::new_from_span(message, span)
}

View File

@ -36,7 +36,7 @@ impl OutputBytesError {
}
pub fn not_enough_registers(span: Span) -> Self {
let message = format!("number of input registers must be greater than or equal to output registers");
let message = "number of input registers must be greater than or equal to output registers".to_string();
Self::new_from_span(message, span)
}

View File

@ -67,13 +67,13 @@ impl StatementError {
}
pub fn array_assign_index(span: Span) -> Self {
let message = format!("Cannot assign single index to array of values");
let message = "Cannot assign single index to array of values".to_string();
Self::new_from_span(message, span)
}
pub fn array_assign_range(span: Span) -> Self {
let message = format!("Cannot assign range of array values to single value");
let message = "Cannot assign range of array values to single value".to_string();
Self::new_from_span(message, span)
}
@ -145,7 +145,7 @@ impl StatementError {
}
pub fn tuple_assign_index(span: Span) -> Self {
let message = format!("Cannot assign single index to tuple of values");
let message = "Cannot assign single index to tuple of values".to_string();
Self::new_from_span(message, span)
}

View File

@ -64,7 +64,7 @@ impl AddressError {
}
pub fn missing_address(span: Span) -> Self {
let message = format!("expected address input not found");
let message = "expected address input not found".to_string();
Self::new_from_span(message, span)
}

View File

@ -88,13 +88,13 @@ impl GroupError {
}
pub fn x_recover(span: Span) -> Self {
let message = format!("could not recover group element from x coordinate");
let message = "could not recover group element from x coordinate".to_string();
Self::new_from_span(message, span)
}
pub fn y_recover(span: Span) -> Self {
let message = format!("could not recover group element from y coordinate");
let message = "could not recover group element from y coordinate".to_string();
Self::new_from_span(message, span)
}

View File

@ -68,7 +68,7 @@ impl IntegerError {
}
pub fn negate_operation(span: Span) -> Self {
let message = format!("integer negation can only be enforced on signed integers");
let message = "integer negation can only be enforced on signed integers".to_string();
Self::new_from_span(message, span)
}
@ -83,9 +83,9 @@ impl IntegerError {
}
pub fn invalid_index(span: Span) -> Self {
let message = format!(
let message =
"index must be a constant value unsigned integer. allocated indices produce a circuit of unknown size"
);
.to_string();
Self::new_from_span(message, span)
}

View File

@ -63,7 +63,7 @@ impl ValueError {
}
pub fn implicit_group(span: Span) -> Self {
let message = format!("group coordinates should be in (x, y)group format");
let message = "group coordinates should be in (x, y)group format".to_string();
Self::new_from_span(message, span)
}

View File

@ -45,11 +45,9 @@ pub fn enforce_div<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
enforce_div(cs, val_1, val_2, span)
}
(val_1, val_2) => {
return Err(ExpressionError::incompatible_types(
format!("{} / {}", val_1, val_2,),
span,
));
}
(val_1, val_2) => Err(ExpressionError::incompatible_types(
format!("{} / {}", val_1, val_2,),
span,
)),
}
}

View File

@ -45,11 +45,9 @@ pub fn enforce_mul<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
enforce_mul(cs, val_1, val_2, span)
}
(val_1, val_2) => {
return Err(ExpressionError::incompatible_types(
format!("{} * {}", val_1, val_2),
span,
));
}
(val_1, val_2) => Err(ExpressionError::incompatible_types(
format!("{} * {}", val_1, val_2),
span,
)),
}
}

View File

@ -25,6 +25,7 @@ use snarkos_models::{
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
#[allow(clippy::too_many_arguments)]
pub fn enforce_array_access<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
@ -56,9 +57,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
None => 0usize, // Array slice starts at index 0
};
let to_resolved = match to {
Some(to_index) => {
self.enforce_index(cs, file_scope.clone(), function_scope.clone(), to_index, span.clone())?
}
Some(to_index) => self.enforce_index(cs, file_scope, function_scope, to_index, span)?,
None => array.len(), // Array slice ends at array length
};
Ok(ConstrainedValue::Array(array[from_resolved..to_resolved].to_owned()))

View File

@ -37,7 +37,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
file_scope: String,
function_scope: String,
mut expected_type: Option<Type>,
array: Vec<Box<SpreadOrExpression>>,
array: Vec<SpreadOrExpression>,
span: Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
// Check explicit array type dimension if given
@ -47,12 +47,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
match type_ {
Type::Array(ref type_, ref dimensions) => {
let number = match dimensions.first() {
Some(number) => number.clone(),
Some(number) => *number,
None => return Err(ExpressionError::unexpected_array(type_.to_string(), span)),
};
expected_dimensions.push(number);
expected_type = Some(type_.outer_dimension(dimensions).clone());
expected_type = Some(type_.outer_dimension(dimensions));
}
ref type_ => {
return Err(ExpressionError::unexpected_array(type_.to_string(), span));
@ -62,7 +62,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let mut result = vec![];
for element in array.into_iter() {
match *element {
match element {
SpreadOrExpression::Spread(spread) => match spread {
Expression::Identifier(identifier) => {
let array_name = new_scope(function_scope.clone(), identifier.to_string());
@ -89,14 +89,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
}
// Check expected_dimensions if given
if !expected_dimensions.is_empty() {
if expected_dimensions[expected_dimensions.len() - 1] != result.len() {
return Err(ExpressionError::invalid_length(
expected_dimensions[expected_dimensions.len() - 1],
result.len(),
span,
));
}
if !expected_dimensions.is_empty() && expected_dimensions[expected_dimensions.len() - 1] != result.len() {
return Err(ExpressionError::invalid_length(
expected_dimensions[expected_dimensions.len() - 1],
result.len(),
span,
));
}
Ok(ConstrainedValue::Array(result))

View File

@ -34,15 +34,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
span: Span,
) -> Result<usize, ExpressionError> {
let expected_type = Some(Type::IntegerType(IntegerType::U32));
match self.enforce_operand(
cs,
file_scope.clone(),
function_scope.clone(),
expected_type,
index,
span.clone(),
)? {
ConstrainedValue::Integer(number) => Ok(number.to_usize(span.clone())?),
match self.enforce_operand(cs, file_scope, function_scope, expected_type, index, span.clone())? {
ConstrainedValue::Integer(number) => Ok(number.to_usize(span)?),
value => Err(ExpressionError::invalid_index(value.to_string(), span)),
}
}

View File

@ -24,7 +24,10 @@ use snarkos_models::{
gadgets::r1cs::ConstraintSystem,
};
type ConstrainedValuePair<T, U> = (ConstrainedValue<T, U>, ConstrainedValue<T, U>);
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
#[allow(clippy::too_many_arguments)]
pub fn enforce_binary_expression<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
@ -34,7 +37,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
left: Expression,
right: Expression,
span: Span,
) -> Result<(ConstrainedValue<F, G>, ConstrainedValue<F, G>), ExpressionError> {
) -> Result<ConstrainedValuePair<F, G>, ExpressionError> {
let mut resolved_left = self.enforce_operand(
cs,
file_scope.clone(),
@ -45,8 +48,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
)?;
let mut resolved_right = self.enforce_operand(
cs,
file_scope.clone(),
function_scope.clone(),
file_scope,
function_scope,
expected_type.clone(),
right,
span.clone(),

View File

@ -29,9 +29,10 @@ use snarkos_models::{
gadgets::r1cs::ConstraintSystem,
};
static SELF_KEYWORD: &'static str = "self";
static SELF_KEYWORD: &str = "self";
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
#[allow(clippy::too_many_arguments)]
pub fn enforce_circuit_access<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
@ -45,11 +46,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
// access a circuit member using the `self` keyword
if let Expression::Identifier(ref identifier) = *circuit_identifier {
if identifier.is_self() {
let self_file_scope = new_scope(file_scope.clone(), identifier.name.to_string());
let self_file_scope = new_scope(file_scope, identifier.name.to_string());
let self_function_scope = new_scope(self_file_scope.clone(), identifier.name.to_string());
let member_value =
self.evaluate_identifier(self_file_scope, self_function_scope, None, circuit_member.clone())?;
self.evaluate_identifier(self_file_scope, self_function_scope, None, circuit_member)?;
return Ok(member_value);
}
@ -58,9 +59,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let (circuit_name, members) = match self.enforce_operand(
cs,
file_scope.clone(),
function_scope.clone(),
function_scope,
expected_type,
*circuit_identifier.clone(),
*circuit_identifier,
span.clone(),
)? {
ConstrainedValue::CircuitExpression(name, members) => (name, members),

View File

@ -40,7 +40,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
span: Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
// Circuit definitions are located at the minimum file scope
let scopes: Vec<&str> = file_scope.split("_").collect();
let scopes: Vec<&str> = file_scope.split('_').collect();
let mut program_identifier = new_scope(scopes[0].to_string(), identifier.to_string());
if identifier.is_self() {
@ -53,9 +53,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
};
let circuit_identifier = circuit.circuit_name.clone();
let mut resolved_members = vec![];
let mut resolved_members = Vec::with_capacity(circuit.members.len());
for member in circuit.members.clone().into_iter() {
for member in circuit.members.into_iter() {
match member {
CircuitMember::CircuitVariable(is_mutable, identifier, type_) => {
let matched_variable = members
@ -98,7 +98,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
}
Ok(ConstrainedValue::CircuitExpression(
circuit_identifier.clone(),
circuit_identifier,
resolved_members,
))
}

View File

@ -25,6 +25,7 @@ use snarkos_models::{
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
#[allow(clippy::too_many_arguments)]
pub fn enforce_circuit_static_access<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
@ -36,26 +37,20 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
span: Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
// Get defined circuit
let circuit = match *circuit_identifier.clone() {
let circuit = match *circuit_identifier {
Expression::Identifier(identifier) => {
// Use the "Self" keyword to access a static circuit function
if identifier.is_self() {
let circuit = self
.get(&file_scope)
.ok_or(ExpressionError::self_keyword(identifier.span.clone()))?;
.ok_or_else(|| ExpressionError::self_keyword(identifier.span))?;
circuit.to_owned()
} else {
self.evaluate_identifier(file_scope.clone(), function_scope.clone(), expected_type, identifier)?
self.evaluate_identifier(file_scope, function_scope, expected_type, identifier)?
}
}
expression => self.enforce_expression(
cs,
file_scope.clone(),
function_scope.clone(),
expected_type,
expression,
)?,
expression => self.enforce_expression(cs, file_scope, function_scope, expected_type, expression)?,
}
.extract_circuit(span.clone())?;

View File

@ -26,6 +26,7 @@ use snarkos_models::{
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
/// Enforce ternary conditional expression
#[allow(clippy::too_many_arguments)]
pub fn enforce_conditional_expression<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
@ -57,14 +58,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
span.clone(),
)?;
let second_value = self.enforce_operand(
cs,
file_scope.clone(),
function_scope.clone(),
expected_type,
second,
span.clone(),
)?;
let second_value = self.enforce_operand(cs, file_scope, function_scope, expected_type, second, span.clone())?;
let unique_namespace = cs.ns(|| {
format!(
@ -74,6 +68,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
});
ConstrainedValue::conditionally_select(unique_namespace, &conditional_value, &first_value, &second_value)
.map_err(|e| ExpressionError::cannot_enforce(format!("conditional select"), e, span))
.map_err(|e| ExpressionError::cannot_enforce("conditional select".to_string(), e, span))
}
}

View File

@ -70,8 +70,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Expression::Add(left, right, span) => {
let (resolved_left, resolved_right) = self.enforce_binary_expression(
cs,
file_scope.clone(),
function_scope.clone(),
file_scope,
function_scope,
expected_type,
*left,
*right,
@ -83,8 +83,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Expression::Sub(left, right, span) => {
let (resolved_left, resolved_right) = self.enforce_binary_expression(
cs,
file_scope.clone(),
function_scope.clone(),
file_scope,
function_scope,
expected_type,
*left,
*right,
@ -96,8 +96,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Expression::Mul(left, right, span) => {
let (resolved_left, resolved_right) = self.enforce_binary_expression(
cs,
file_scope.clone(),
function_scope.clone(),
file_scope,
function_scope,
expected_type,
*left,
*right,
@ -109,8 +109,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Expression::Div(left, right, span) => {
let (resolved_left, resolved_right) = self.enforce_binary_expression(
cs,
file_scope.clone(),
function_scope.clone(),
file_scope,
function_scope,
expected_type,
*left,
*right,
@ -122,8 +122,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Expression::Pow(left, right, span) => {
let (resolved_left, resolved_right) = self.enforce_binary_expression(
cs,
file_scope.clone(),
function_scope.clone(),
file_scope,
function_scope,
expected_type,
*left,
*right,
@ -141,8 +141,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Expression::Or(left, right, span) => {
let (resolved_left, resolved_right) = self.enforce_binary_expression(
cs,
file_scope.clone(),
function_scope.clone(),
file_scope,
function_scope,
expected_type,
*left,
*right,
@ -154,8 +154,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Expression::And(left, right, span) => {
let (resolved_left, resolved_right) = self.enforce_binary_expression(
cs,
file_scope.clone(),
function_scope.clone(),
file_scope,
function_scope,
expected_type,
*left,
*right,
@ -165,67 +165,32 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Ok(enforce_and(cs, resolved_left, resolved_right, span)?)
}
Expression::Eq(left, right, span) => {
let (resolved_left, resolved_right) = self.enforce_binary_expression(
cs,
file_scope.clone(),
function_scope.clone(),
None,
*left,
*right,
span.clone(),
)?;
let (resolved_left, resolved_right) =
self.enforce_binary_expression(cs, file_scope, function_scope, None, *left, *right, span.clone())?;
Ok(evaluate_eq(cs, resolved_left, resolved_right, span)?)
}
Expression::Ge(left, right, span) => {
let (resolved_left, resolved_right) = self.enforce_binary_expression(
cs,
file_scope.clone(),
function_scope.clone(),
None,
*left,
*right,
span.clone(),
)?;
let (resolved_left, resolved_right) =
self.enforce_binary_expression(cs, file_scope, function_scope, None, *left, *right, span.clone())?;
Ok(evaluate_ge(cs, resolved_left, resolved_right, span)?)
}
Expression::Gt(left, right, span) => {
let (resolved_left, resolved_right) = self.enforce_binary_expression(
cs,
file_scope.clone(),
function_scope.clone(),
None,
*left,
*right,
span.clone(),
)?;
let (resolved_left, resolved_right) =
self.enforce_binary_expression(cs, file_scope, function_scope, None, *left, *right, span.clone())?;
Ok(evaluate_gt(cs, resolved_left, resolved_right, span)?)
}
Expression::Le(left, right, span) => {
let (resolved_left, resolved_right) = self.enforce_binary_expression(
cs,
file_scope.clone(),
function_scope.clone(),
None,
*left,
*right,
span.clone(),
)?;
let (resolved_left, resolved_right) =
self.enforce_binary_expression(cs, file_scope, function_scope, None, *left, *right, span.clone())?;
Ok(evaluate_le(cs, resolved_left, resolved_right, span)?)
}
Expression::Lt(left, right, span) => {
let (resolved_left, resolved_right) = self.enforce_binary_expression(
cs,
file_scope.clone(),
function_scope.clone(),
None,
*left,
*right,
span.clone(),
)?;
let (resolved_left, resolved_right) =
self.enforce_binary_expression(cs, file_scope, function_scope, None, *left, *right, span.clone())?;
Ok(evaluate_lt(cs, resolved_left, resolved_right, span)?)
}

View File

@ -25,6 +25,7 @@ use snarkos_models::{
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
/// Call a default core circuit function with arguments
#[allow(clippy::too_many_arguments)]
pub fn enforce_core_circuit_call_expression<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
@ -36,7 +37,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
span: Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
// Get the value of each core function argument
let mut argument_values = vec![];
let mut argument_values = Vec::with_capacity(arguments.len());
for argument in arguments.into_iter() {
let argument_value =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), None, argument)?;
@ -49,10 +50,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let res = call_core_circuit(cs, core_circuit, argument_values, span.clone())?;
// Convert the core function returns into constrained values
let returns = res
.into_iter()
.map(|value| ConstrainedValue::from(value))
.collect::<Vec<_>>();
let returns = res.into_iter().map(ConstrainedValue::from).collect::<Vec<_>>();
let return_value = if returns.len() == 1 {
// The function has a single return
@ -72,6 +70,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
}
}
return Ok(return_value);
Ok(return_value)
}
}

View File

@ -25,6 +25,7 @@ use snarkos_models::{
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
#[allow(clippy::too_many_arguments)]
pub fn enforce_function_call_expression<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
@ -35,7 +36,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
arguments: Vec<Expression>,
span: Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
let (declared_circuit_reference, function_value) = match *function.clone() {
let (declared_circuit_reference, function_value) = match *function {
Expression::CircuitMemberAccess(circuit_identifier, circuit_member, span) => {
// Call a circuit function that can mutate self.
@ -62,7 +63,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
),
};
let (outer_scope, function_call) = function_value.extract_function(file_scope.clone(), span.clone())?;
let (outer_scope, function_call) = function_value.extract_function(file_scope, span.clone())?;
let name_unique = format!(
"function call {} {}:{}",

View File

@ -37,7 +37,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
unresolved_identifier: Identifier,
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
// Evaluate the identifier name in the current function scope
let variable_name = new_scope(function_scope.clone(), unresolved_identifier.to_string());
let variable_name = new_scope(function_scope, unresolved_identifier.to_string());
let identifier_name = new_scope(file_scope, unresolved_identifier.to_string());
let mut result_value = if let Some(value) = self.get(&variable_name) {
@ -58,7 +58,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
return Err(ExpressionError::undefined_identifier(unresolved_identifier));
};
result_value.resolve_type(expected_type, unresolved_identifier.span.clone())?;
result_value.resolve_type(expected_type, unresolved_identifier.span)?;
Ok(result_value)
}

View File

@ -35,7 +35,7 @@ pub fn enforce_and<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
if let (ConstrainedValue::Boolean(left_bool), ConstrainedValue::Boolean(right_bool)) = (left, right) {
let name_unique = format!("{} {}:{}", name, span.line, span.start);
let result = Boolean::and(cs.ns(|| name_unique), &left_bool, &right_bool)
.map_err(|e| BooleanError::cannot_enforce(format!("&&"), e, span))?;
.map_err(|e| BooleanError::cannot_enforce("&&".to_string(), e, span))?;
return Ok(ConstrainedValue::Boolean(result));
}

View File

@ -35,7 +35,7 @@ pub fn enforce_or<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F
if let (ConstrainedValue::Boolean(left_bool), ConstrainedValue::Boolean(right_bool)) = (left, right) {
let name_unique = format!("{} {}:{}", name, span.line, span.start);
let result = Boolean::or(cs.ns(|| name_unique), &left_bool, &right_bool)
.map_err(|e| BooleanError::cannot_enforce(format!("||"), e, span))?;
.map_err(|e| BooleanError::cannot_enforce("||".to_string(), e, span))?;
return Ok(ConstrainedValue::Boolean(result));
}

View File

@ -102,7 +102,7 @@ pub fn evaluate_eq<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
}
};
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(format!("=="), span))?;
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate("==".to_string(), span))?;
Ok(ConstrainedValue::Boolean(boolean))
}

View File

@ -52,7 +52,7 @@ pub fn evaluate_ge<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
}
};
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(format!(">="), span))?;
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(">=".to_string(), span))?;
Ok(ConstrainedValue::Boolean(boolean))
}

View File

@ -52,7 +52,7 @@ pub fn evaluate_gt<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
}
};
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(format!(">"), span))?;
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(">".to_string(), span))?;
Ok(ConstrainedValue::Boolean(boolean))
}

View File

@ -52,7 +52,7 @@ pub fn evaluate_le<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
}
};
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(format!("<="), span))?;
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate("<=".to_string(), span))?;
Ok(ConstrainedValue::Boolean(boolean))
}

View File

@ -52,7 +52,7 @@ pub fn evaluate_lt<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
}
};
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(format!("<"), span))?;
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate("<".to_string(), span))?;
Ok(ConstrainedValue::Boolean(boolean))
}

View File

@ -25,6 +25,7 @@ use snarkos_models::{
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
#[allow(clippy::too_many_arguments)]
pub fn enforce_tuple_access<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
@ -35,16 +36,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
index: usize,
span: Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
let tuple = match self.enforce_operand(
cs,
file_scope.clone(),
function_scope.clone(),
expected_type,
*tuple,
span.clone(),
)? {
let tuple = match self.enforce_operand(cs, file_scope, function_scope, expected_type, *tuple, span.clone())? {
ConstrainedValue::Tuple(tuple) => tuple,
value => return Err(ExpressionError::undefined_array(value.to_string(), span.clone())),
value => return Err(ExpressionError::undefined_array(value.to_string(), span)),
};
if index > tuple.len() - 1 {

View File

@ -38,22 +38,21 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
// Check explicit tuple type dimension if given
let mut expected_types = vec![];
if expected_type.is_some() {
match expected_type.unwrap() {
Type::Tuple(ref types) => {
expected_types = types.clone();
}
ref type_ => {
return Err(ExpressionError::unexpected_tuple(
type_.to_string(),
format!("{:?}", tuple),
span,
));
}
match expected_type {
Some(Type::Tuple(ref types)) => {
expected_types = types.clone();
}
Some(ref type_) => {
return Err(ExpressionError::unexpected_tuple(
type_.to_string(),
format!("{:?}", tuple),
span,
));
}
None => {}
}
let mut result = vec![];
let mut result = Vec::with_capacity(tuple.len());
for (i, expression) in tuple.into_iter().enumerate() {
let type_ = if expected_types.is_empty() {
None

View File

@ -55,7 +55,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
check_arguments_length(function.input.len(), input.len(), function.span.clone())?;
// Store input values as new variables in resolved program
for (input_model, input_expression) in function.input.clone().iter().zip(input.into_iter()) {
for (input_model, input_expression) in function.input.iter().zip(input.into_iter()) {
let (name, value) = match input_model {
InputVariable::InputKeyword(identifier) => {
let input_value = self.enforce_function_input(

View File

@ -62,14 +62,14 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
// Allocate each input variable as a circuit expression
let mut sections = vec![];
let mut sections = Vec::with_capacity(4);
sections.push((registers_name, registers_values));
sections.push((record_name, record_values));
sections.push((state_name, state_values));
sections.push((state_leaf_name, state_leaf_values));
let mut members = vec![];
let mut members = Vec::with_capacity(sections.len());
for (name, values) in sections {
let member_name = name.clone();

View File

@ -30,7 +30,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
identifier: Identifier,
section: HashMap<Parameter, Option<InputValue>>,
) -> Result<ConstrainedValue<F, G>, FunctionError> {
let mut members = vec![];
let mut members = Vec::with_capacity(section.len());
// Allocate each section definition as a circuit member value

View File

@ -42,7 +42,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let registers = input.get_registers();
// Iterate over main function input variables and allocate new values
let mut input_variables = vec![];
let mut input_variables = Vec::with_capacity(function.input.len());
for input_model in function.input.clone().into_iter() {
let (identifier, value) = match input_model {
InputVariable::InputKeyword(identifier) => {
@ -54,7 +54,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let name = input_model.identifier.name.clone();
let input_option = input
.get(&name)
.ok_or(FunctionError::input_not_found(name.clone(), function.span.clone()))?;
.ok_or_else(|| FunctionError::input_not_found(name.clone(), function.span.clone()))?;
let input_value = self.allocate_main_function_input(
cs,
input_model.type_,

View File

@ -37,14 +37,14 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
span: Span,
) -> Result<(), StatementError> {
// if there are no results, continue
if results.len() == 0 {
if results.is_empty() {
return Ok(());
}
// If all indicators are none, then there are no branch conditions in the function.
// We simply return the last result.
if let None = results.iter().find(|(indicator, _res)| indicator.is_some()) {
if results.iter().all(|(indicator, _res)| indicator.is_none()) {
let result = &results[results.len() - 1].1;
*return_value = result.clone();

View File

@ -21,7 +21,7 @@ use std::{collections::HashMap, env::current_dir};
/// Parses all relevant import files for a program.
/// Stores compiled program structs.
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct ImportParser {
imports: HashMap<String, Program>,
core_packages: Vec<Package>,
@ -29,10 +29,7 @@ pub struct ImportParser {
impl ImportParser {
pub fn new() -> Self {
Self {
imports: HashMap::new(),
core_packages: vec![],
}
Self::default()
}
pub(crate) fn insert_import(&mut self, file_name: String, program: Program) {
@ -44,7 +41,7 @@ impl ImportParser {
let _res = self.core_packages.push(package.clone());
}
pub fn get_import(&self, file_name: &String) -> Option<&Program> {
pub fn get_import(&self, file_name: &str) -> Option<&Program> {
self.imports.get(file_name)
}
@ -56,7 +53,7 @@ impl ImportParser {
let mut imports = Self::new();
// Find all imports relative to current directory
let path = current_dir().map_err(|error| ImportError::current_directory_error(error))?;
let path = current_dir().map_err(ImportError::current_directory_error)?;
// Parse each imported file
program

View File

@ -70,14 +70,12 @@ impl ImportParser {
let entries = fs::read_dir(path)
.map_err(|error| ImportError::directory_error(error, package_name.span.clone(), error_path.clone()))?
.into_iter()
.collect::<Result<Vec<_>, std::io::Error>>()
.map_err(|error| ImportError::directory_error(error, package_name.span.clone(), error_path.clone()))?;
let matched_source_entry = entries.into_iter().find(|entry| {
entry
.file_name()
.to_os_string()
.into_string()
.unwrap()
.trim_end_matches(SOURCE_FILE_EXTENSION)
@ -90,7 +88,6 @@ impl ImportParser {
} else if imports_directory.exists() {
let entries = fs::read_dir(imports_directory)
.map_err(|error| ImportError::directory_error(error, package_name.span.clone(), error_path.clone()))?
.into_iter()
.collect::<Result<Vec<_>, std::io::Error>>()
.map_err(|error| ImportError::directory_error(error, package_name.span.clone(), error_path.clone()))?;

View File

@ -30,11 +30,10 @@ fn parse_import_file(entry: &DirEntry, span: &Span) -> Result<Program, ImportErr
.map_err(|error| ImportError::directory_error(error, span.clone(), entry.path()))?;
let file_name = entry
.file_name()
.to_os_string()
.into_string()
.map_err(|_| ImportError::convert_os_string(span.clone()))?;
let mut file_path = entry.path().to_path_buf();
let mut file_path = entry.path();
if file_type.is_dir() {
file_path.push(LIBRARY_FILE);
@ -62,7 +61,7 @@ impl ImportParser {
.extension()
.map_or(false, |ext| ext.eq(&OsString::from(FILE_EXTENSION)));
let mut package_path = path.to_path_buf();
let mut package_path = path;
package_path.push(LIBRARY_FILE);
let is_package = is_dir && package_path.exists();
@ -93,7 +92,7 @@ impl ImportParser {
Ok(())
} else {
// importing * from a directory or non-leo file in `package/src/` is illegal
Err(ImportError::star(entry.path().to_path_buf(), span.clone()))
Err(ImportError::star(entry.path(), span.clone()))
}
}

View File

@ -33,7 +33,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
.find(|package| import.package.eq(package));
if let Some(package) = core_dependency {
self.store_core_package(scope.clone(), package.clone())?;
self.store_core_package(scope, package.clone())?;
return Ok(());
}
@ -45,7 +45,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
// Find imported program
let program = imported_programs
.get_import(&package)
.ok_or(ImportError::unknown_package(import.package.name.clone()))?;
.ok_or_else(|| ImportError::unknown_package(import.package.name.clone()))?;
// Parse imported program
self.store_definitions(program.clone(), imported_programs)?;

View File

@ -59,7 +59,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let value = match matched_circuit {
Some((_circuit_name, circuit)) => ConstrainedValue::Import(
program_name.clone(),
program_name,
Box::new(ConstrainedValue::CircuitDefinition(circuit.clone())),
),
None => {
@ -71,7 +71,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
match matched_function {
Some((_function_name, function)) => ConstrainedValue::Import(
program_name.clone(),
program_name,
Box::new(ConstrainedValue::Function(None, function.clone())),
),
None => return Err(ImportError::unknown_symbol(symbol.to_owned(), program_name)),
@ -80,7 +80,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
};
// take the alias if it is present
let id = symbol.alias.clone().unwrap_or(symbol.symbol.clone());
let id = symbol.alias.clone().unwrap_or_else(|| symbol.symbol.clone());
let name = new_scope(scope, id.to_string());
// store imported circuit under imported name

View File

@ -16,6 +16,8 @@
//! Module containing structs and types that make up a Leo program.
#![allow(clippy::module_inception)]
#[macro_use]
extern crate thiserror;

View File

@ -71,8 +71,7 @@ impl OutputBytes {
string.push_str(&format);
}
let mut bytes: Vec<u8> = vec![];
bytes.extend_from_slice(string.as_bytes());
let bytes = string.into_bytes();
Ok(Self(bytes))
}

View File

@ -27,30 +27,36 @@ pub struct ConstrainedProgram<F: Field + PrimeField, G: GroupType<F>> {
pub identifiers: HashMap<String, ConstrainedValue<F, G>>,
}
impl<F: Field + PrimeField, G: GroupType<F>> Default for ConstrainedProgram<F, G> {
fn default() -> Self {
Self {
identifiers: HashMap::new(),
}
}
}
pub fn new_scope(outer: String, inner: String) -> String {
format!("{}_{}", outer, inner)
}
pub fn is_in_scope(current_scope: &String, desired_scope: &String) -> bool {
pub fn is_in_scope(current_scope: &str, desired_scope: &str) -> bool {
current_scope.ends_with(desired_scope)
}
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn new() -> Self {
Self {
identifiers: HashMap::new(),
}
Self::default()
}
pub(crate) fn store(&mut self, name: String, value: ConstrainedValue<F, G>) {
self.identifiers.insert(name, value);
}
pub(crate) fn get(&self, name: &String) -> Option<&ConstrainedValue<F, G>> {
pub(crate) fn get(&self, name: &str) -> Option<&ConstrainedValue<F, G>> {
self.identifiers.get(name)
}
pub(crate) fn get_mut(&mut self, name: &String) -> Option<&mut ConstrainedValue<F, G>> {
pub(crate) fn get_mut(&mut self, name: &str) -> Option<&mut ConstrainedValue<F, G>> {
self.identifiers.get_mut(name)
}
}

View File

@ -28,6 +28,7 @@ use snarkos_models::{
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
#[allow(clippy::too_many_arguments)]
pub fn assign_array<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
@ -44,7 +45,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
// Resolve index so we know if we are assigning to a single value or a range of values
match range_or_expression {
RangeOrExpression::Expression(index) => {
let index = self.enforce_index(cs, file_scope.clone(), function_scope.clone(), index, span.clone())?;
let index = self.enforce_index(cs, file_scope, function_scope, index, span.clone())?;
// Modify the single value of the array in place
match self.get_mutable_assignee(name, span.clone())? {
@ -75,13 +76,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
None => 0usize,
};
let to_index_option = match to {
Some(integer) => Some(self.enforce_index(
cs,
file_scope.clone(),
function_scope.clone(),
integer,
span.clone(),
)?),
Some(integer) => Some(self.enforce_index(cs, file_scope, function_scope, integer, span.clone())?),
None => None,
};

View File

@ -35,6 +35,7 @@ use snarkos_models::{
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
#[allow(clippy::too_many_arguments)]
pub fn enforce_assign_statement<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
@ -57,7 +58,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
match assignee {
Assignee::Identifier(_identifier) => {
let condition = indicator.unwrap_or(Boolean::Constant(true));
let old_value = self.get_mutable_assignee(variable_name.clone(), span.clone())?;
let old_value = self.get_mutable_assignee(variable_name, span.clone())?;
new_value.resolve_type(Some(old_value.to_type(span.clone())?), span.clone())?;
@ -76,7 +77,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
function_scope,
indicator,
variable_name,
range_or_expression,
*range_or_expression,
new_value,
span,
),

View File

@ -43,7 +43,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
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(|member| member.0 == variable_name);
let matched_variable = members.iter_mut().find(|member| member.0 == variable_name);
match matched_variable {
Some(member) => match &member.1 {
@ -81,7 +81,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
member.1 = selected_value.to_owned();
Ok(selected_value.to_owned())
Ok(selected_value)
}
_ => {
// Throw an error if we try to mutate an immutable circuit variable

View File

@ -16,7 +16,7 @@
//! Enforces a branch of a conditional or iteration statement in a compiled Leo program.
use crate::{errors::StatementError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};
use crate::{program::ConstrainedProgram, GroupType, IndicatorAndConstrainedValue, StatementResult};
use leo_typed::{Statement, Type};
use snarkos_models::{
@ -33,16 +33,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
indicator: Option<Boolean>,
statements: Vec<Statement>,
return_type: Option<Type>,
) -> Result<Vec<(Option<Boolean>, ConstrainedValue<F, G>)>, StatementError> {
let mut results = vec![];
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
let mut results = Vec::with_capacity(statements.len());
// Evaluate statements. Only allow a single return argument to be returned.
for statement in statements.iter() {
for statement in statements.into_iter() {
let mut value = self.enforce_statement(
cs,
file_scope.clone(),
function_scope.clone(),
indicator.clone(),
statement.clone(),
indicator,
statement,
return_type.clone(),
"".to_owned(),
)?;

View File

@ -16,7 +16,14 @@
//! Methods to enforce constraints on statements in a compiled Leo program.
use crate::{errors::StatementError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};
use crate::{
errors::StatementError,
program::ConstrainedProgram,
value::ConstrainedValue,
GroupType,
IndicatorAndConstrainedValue,
StatementResult,
};
use leo_typed::{ConditionalNestedOrEndStatement, ConditionalStatement, Span, Type};
use snarkos_models::{
@ -28,7 +35,7 @@ fn indicator_to_string(indicator: &Boolean) -> String {
indicator
.get_value()
.map(|b| b.to_string())
.unwrap_or(format!("[input]"))
.unwrap_or_else(|| "[input]".to_string())
}
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
@ -36,6 +43,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
/// Due to R1CS constraints, we must evaluate every branch to properly construct the circuit.
/// At program execution, we will pass an `indicator` bit down to all child statements within each branch.
/// The `indicator` bit will select that branch while keeping the constraint system satisfied.
#[allow(clippy::too_many_arguments)]
pub fn enforce_conditional_statement<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
@ -45,7 +53,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
statement: ConditionalStatement,
return_type: Option<Type>,
span: Span,
) -> Result<Vec<(Option<Boolean>, ConstrainedValue<F, G>)>, StatementError> {
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
let statement_string = statement.to_string();
// Inherit the indicator from a previous conditional statement or assume that we are the outer parent

View File

@ -56,20 +56,20 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
) -> Result<Vec<ConstrainedValue<F, G>>, StatementError> {
let types = match type_ {
Some(Type::Tuple(types)) => types,
Some(type_) => return Err(StatementError::tuple_type(type_.to_string(), span.clone())),
Some(type_) => return Err(StatementError::tuple_type(type_.to_string(), span)),
None => vec![],
};
let implicit_types = types.is_empty();
let mut expected_types = vec![];
let mut expected_types = Vec::with_capacity(expressions.len());
for i in 0..expressions.len() {
let expected_type = if implicit_types { None } else { Some(types[i].clone()) };
for ty in types.iter().take(expressions.len()) {
let expected_type = if implicit_types { None } else { Some(ty.clone()) };
expected_types.push(expected_type);
}
let mut values = vec![];
let mut values = Vec::with_capacity(expressions.len());
for (expression, expected_type) in expressions.into_iter().zip(expected_types.into_iter()) {
let value = self.enforce_expression(
@ -86,6 +86,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Ok(values)
}
#[allow(clippy::too_many_arguments)]
fn enforce_tuple_definition<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
@ -135,6 +136,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub fn enforce_definition_statement<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
@ -157,7 +159,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let variable = variables.names[0].clone();
let expression = self.enforce_expression(
cs,
file_scope.clone(),
file_scope,
function_scope.clone(),
variables.type_,
expressions[0].clone(),
@ -181,14 +183,14 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let values = match self.enforce_expression(
cs,
file_scope.clone(),
file_scope,
function_scope.clone(),
variables.type_.clone(),
expressions[0].clone(),
)? {
// ConstrainedValue::Return(values) => values,
ConstrainedValue::Tuple(values) => values,
value => return Err(StatementError::multiple_definition(value.to_string(), span.clone())),
value => return Err(StatementError::multiple_definition(value.to_string(), span)),
};
self.enforce_multiple_definition(cs, function_scope, is_constant, variables, values, span)

View File

@ -17,12 +17,13 @@
//! Enforces an iteration statement in a compiled Leo program.
use crate::{
errors::StatementError,
new_scope,
program::ConstrainedProgram,
value::ConstrainedValue,
GroupType,
IndicatorAndConstrainedValue,
Integer,
StatementResult,
};
use leo_typed::{Expression, Identifier, Span, Statement, Type};
@ -35,6 +36,7 @@ use snarkos_models::{
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
#[allow(clippy::too_many_arguments)]
pub fn enforce_iteration_statement<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
@ -47,7 +49,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
statements: Vec<Statement>,
return_type: Option<Type>,
span: Span,
) -> Result<Vec<(Option<Boolean>, ConstrainedValue<F, G>)>, StatementError> {
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
let mut results = vec![];
let from = self.enforce_index(cs, file_scope.clone(), function_scope.clone(), start, span.clone())?;

View File

@ -28,9 +28,7 @@ fn check_return_type(expected: Option<Type>, actual: Type, span: Span) -> Result
match expected {
Some(expected) => {
if expected.ne(&actual) {
if expected.is_self() && actual.is_circuit() {
return Ok(());
} else if expected.match_array_types(&actual) {
if (expected.is_self() && actual.is_circuit()) || expected.match_array_types(&actual) {
return Ok(());
} else {
return Err(StatementError::arguments_type(&expected, &actual, span));
@ -56,8 +54,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let result = self.enforce_operand(
cs,
file_scope.clone(),
function_scope.clone(),
file_scope,
function_scope,
return_type.clone(),
expression,
span.clone(),

View File

@ -24,12 +24,16 @@ use snarkos_models::{
gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean},
};
pub type StatementResult<T> = Result<T, StatementError>;
pub type IndicatorAndConstrainedValue<T, U> = (Option<Boolean>, ConstrainedValue<T, U>);
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
/// Enforce a program statement.
/// Returns a Vector of (indicator, value) tuples.
/// Each evaluated statement may execute of one or more statements that may return early.
/// To indicate which of these return values to take we conditionally select the value according
/// to the `indicator` bit that evaluates to true.
#[allow(clippy::too_many_arguments)]
pub fn enforce_statement<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
@ -39,7 +43,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
statement: Statement,
return_type: Option<Type>,
declared_circuit_reference: String,
) -> Result<Vec<(Option<Boolean>, ConstrainedValue<F, G>)>, StatementError> {
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
let mut results = vec![];
match statement {
@ -70,7 +74,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
declared_circuit_reference,
indicator,
variable,
expression,
*expression,
span,
)?;
}
@ -94,8 +98,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
function_scope,
indicator,
index,
start,
stop,
*start,
*stop,
statements,
return_type,
span,

View File

@ -153,7 +153,7 @@ impl<F: Field + PrimeField> AllocGadget<String, F> for Address {
impl<F: Field + PrimeField> EvaluateEqGadget<F> for Address {
fn evaluate_equal<CS: ConstraintSystem<F>>(&self, mut cs: CS, other: &Self) -> Result<Boolean, SynthesisError> {
if self.is_constant() && other.is_constant() {
return Ok(Boolean::Constant(self.eq(other)));
Ok(Boolean::Constant(self.eq(other)))
} else {
let mut result = Boolean::constant(true);

View File

@ -79,7 +79,7 @@ impl<F: Field + PrimeField> FieldType<F> {
(FieldType::Allocated(self_value), FieldType::Allocated(other_value)) => {
let result = self_value
.add(cs, other_value)
.map_err(|e| FieldError::binary_operation(format!("+"), e, span))?;
.map_err(|e| FieldError::binary_operation("+".to_string(), e, span))?;
Ok(FieldType::Allocated(result))
}
@ -88,7 +88,7 @@ impl<F: Field + PrimeField> FieldType<F> {
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => Ok(FieldType::Allocated(
allocated_value
.add_constant(cs, constant_value)
.map_err(|e| FieldError::binary_operation(format!("+"), e, span))?,
.map_err(|e| FieldError::binary_operation("+".to_string(), e, span))?,
)),
}
}
@ -102,7 +102,7 @@ impl<F: Field + PrimeField> FieldType<F> {
(FieldType::Allocated(self_value), FieldType::Allocated(other_value)) => {
let result = self_value
.sub(cs, other_value)
.map_err(|e| FieldError::binary_operation(format!("-"), e, span))?;
.map_err(|e| FieldError::binary_operation("-".to_string(), e, span))?;
Ok(FieldType::Allocated(result))
}
@ -111,7 +111,7 @@ impl<F: Field + PrimeField> FieldType<F> {
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => Ok(FieldType::Allocated(
allocated_value
.sub_constant(cs, constant_value)
.map_err(|e| FieldError::binary_operation(format!("+"), e, span))?,
.map_err(|e| FieldError::binary_operation("+".to_string(), e, span))?,
)),
}
}
@ -125,7 +125,7 @@ impl<F: Field + PrimeField> FieldType<F> {
(FieldType::Allocated(self_value), FieldType::Allocated(other_value)) => {
let result = self_value
.mul(cs, other_value)
.map_err(|e| FieldError::binary_operation(format!("*"), e, span))?;
.map_err(|e| FieldError::binary_operation("*".to_string(), e, span))?;
Ok(FieldType::Allocated(result))
}
@ -134,7 +134,7 @@ impl<F: Field + PrimeField> FieldType<F> {
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => Ok(FieldType::Allocated(
allocated_value
.mul_by_constant(cs, constant_value)
.map_err(|e| FieldError::binary_operation(format!("*"), e, span))?,
.map_err(|e| FieldError::binary_operation("*".to_string(), e, span))?,
)),
}
}
@ -144,14 +144,14 @@ impl<F: Field + PrimeField> FieldType<F> {
FieldType::Constant(constant) => {
let constant_inverse = constant
.inverse()
.ok_or(FieldError::no_inverse(constant.to_string(), span.clone()))?;
.ok_or_else(|| FieldError::no_inverse(constant.to_string(), span.clone()))?;
FieldType::Constant(constant_inverse)
}
FieldType::Allocated(allocated) => {
let allocated_inverse = allocated
.inverse(&mut cs)
.map_err(|e| FieldError::binary_operation(format!("+"), e, span.clone()))?;
.map_err(|e| FieldError::binary_operation("+".to_string(), e, span.clone()))?;
FieldType::Allocated(allocated_inverse)
}

View File

@ -48,7 +48,7 @@ use std::{
#[derive(Clone, Debug)]
pub enum EdwardsGroupType {
Constant(EdwardsAffine),
Allocated(EdwardsBlsGadget),
Allocated(Box<EdwardsBlsGadget>),
}
impl GroupType<Fq> for EdwardsGroupType {
@ -60,7 +60,7 @@ impl GroupType<Fq> for EdwardsGroupType {
fn to_allocated<CS: ConstraintSystem<Fq>>(&self, mut cs: CS, span: Span) -> Result<Self, GroupError> {
self.allocated(cs.ns(|| format!("allocate affine point {}:{}", span.line, span.start)))
.map(|result| EdwardsGroupType::Allocated(result))
.map(|ebg| EdwardsGroupType::Allocated(Box::new(ebg)))
.map_err(|error| GroupError::synthesis_error(error, span))
}
@ -71,7 +71,7 @@ impl GroupType<Fq> for EdwardsGroupType {
let result = <EdwardsBlsGadget as GroupGadget<GroupAffine<EdwardsParameters>, Fq>>::negate(group, cs)
.map_err(|e| GroupError::negate_operation(e, span))?;
Ok(EdwardsGroupType::Allocated(result))
Ok(EdwardsGroupType::Allocated(Box::new(result)))
}
}
}
@ -88,18 +88,18 @@ impl GroupType<Fq> for EdwardsGroupType {
cs,
other_value,
)
.map_err(|e| GroupError::binary_operation(format!("+"), e, span))?;
.map_err(|e| GroupError::binary_operation("+".to_string(), e, span))?;
Ok(EdwardsGroupType::Allocated(result))
Ok(EdwardsGroupType::Allocated(Box::new(result)))
}
(EdwardsGroupType::Constant(constant_value), EdwardsGroupType::Allocated(allocated_value))
| (EdwardsGroupType::Allocated(allocated_value), EdwardsGroupType::Constant(constant_value)) => {
Ok(EdwardsGroupType::Allocated(
Ok(EdwardsGroupType::Allocated(Box::new(
allocated_value
.add_constant(cs, constant_value)
.map_err(|e| GroupError::binary_operation(format!("+"), e, span))?,
))
.map_err(|e| GroupError::binary_operation("+".to_string(), e, span))?,
)))
}
}
}
@ -116,18 +116,18 @@ impl GroupType<Fq> for EdwardsGroupType {
cs,
other_value,
)
.map_err(|e| GroupError::binary_operation(format!("-"), e, span))?;
.map_err(|e| GroupError::binary_operation("-".to_string(), e, span))?;
Ok(EdwardsGroupType::Allocated(result))
Ok(EdwardsGroupType::Allocated(Box::new(result)))
}
(EdwardsGroupType::Constant(constant_value), EdwardsGroupType::Allocated(allocated_value))
| (EdwardsGroupType::Allocated(allocated_value), EdwardsGroupType::Constant(constant_value)) => {
Ok(EdwardsGroupType::Allocated(
Ok(EdwardsGroupType::Allocated(Box::new(
allocated_value
.sub_constant(cs, constant_value)
.map_err(|e| GroupError::binary_operation(format!("-"), e, span))?,
))
.map_err(|e| GroupError::binary_operation("-".to_string(), e, span))?,
)))
}
}
}
@ -143,13 +143,13 @@ impl EdwardsGroupType {
pub fn edwards_affine_from_single(number: String, span: Span) -> Result<EdwardsAffine, GroupError> {
if number.eq("0") {
return Ok(EdwardsAffine::zero());
Ok(EdwardsAffine::zero())
} else {
let one = edwards_affine_one();
let number_value = Fp256::from_str(&number).map_err(|_| GroupError::n_group(number, span))?;
let result: EdwardsAffine = one.mul(&number_value);
return Ok(result);
Ok(result)
}
}
@ -201,11 +201,13 @@ impl EdwardsGroupType {
let x = Fq::from_str(&x_string).map_err(|_| GroupError::x_invalid(x_string, x_span))?;
match greatest {
// Sign provided
Some(greatest) => EdwardsAffine::from_x_coordinate(x, greatest).ok_or(GroupError::x_recover(element_span)),
Some(greatest) => {
EdwardsAffine::from_x_coordinate(x, greatest).ok_or_else(|| GroupError::x_recover(element_span))
}
// Sign inferred
None => {
// Attempt to recover with a sign_low bit.
if let Some(element) = EdwardsAffine::from_x_coordinate(x.clone(), false) {
if let Some(element) = EdwardsAffine::from_x_coordinate(x, false) {
return Ok(element);
}
@ -230,11 +232,13 @@ impl EdwardsGroupType {
match greatest {
// Sign provided
Some(greatest) => EdwardsAffine::from_y_coordinate(y, greatest).ok_or(GroupError::y_recover(element_span)),
Some(greatest) => {
EdwardsAffine::from_y_coordinate(y, greatest).ok_or_else(|| GroupError::y_recover(element_span))
}
// Sign inferred
None => {
// Attempt to recover with a sign_low bit.
if let Some(element) = EdwardsAffine::from_y_coordinate(y.clone(), false) {
if let Some(element) = EdwardsAffine::from_y_coordinate(y, false) {
return Ok(element);
}
@ -294,12 +298,8 @@ impl EdwardsGroupType {
let x_value = allocated.x.get_value();
let y_value = allocated.y.get_value();
let x_allocated = FpGadget::alloc(cs.ns(|| format!("x")), || {
x_value.ok_or(SynthesisError::AssignmentMissing)
})?;
let y_allocated = FpGadget::alloc(cs.ns(|| format!("y")), || {
y_value.ok_or(SynthesisError::AssignmentMissing)
})?;
let x_allocated = FpGadget::alloc(cs.ns(|| "x"), || x_value.ok_or(SynthesisError::AssignmentMissing))?;
let y_allocated = FpGadget::alloc(cs.ns(|| "y"), || y_value.ok_or(SynthesisError::AssignmentMissing))?;
Ok(EdwardsBlsGadget::new(x_allocated, y_allocated))
}
@ -316,7 +316,7 @@ impl AllocGadget<GroupValue, Fq> for EdwardsGroupType {
Self::alloc_helper(value_gen)
})?;
Ok(EdwardsGroupType::Allocated(value))
Ok(EdwardsGroupType::Allocated(Box::new(value)))
}
fn alloc_input<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<GroupValue>, CS: ConstraintSystem<Fq>>(
@ -327,7 +327,7 @@ impl AllocGadget<GroupValue, Fq> for EdwardsGroupType {
Self::alloc_helper(value_gen)
})?;
Ok(EdwardsGroupType::Allocated(value))
Ok(EdwardsGroupType::Allocated(Box::new(value)))
}
}
@ -454,7 +454,7 @@ impl CondSelectGadget<Fq> for EdwardsGroupType {
let second_gadget = second.allocated(cs.ns(|| "second"))?;
let result = EdwardsBlsGadget::conditionally_select(cs, cond, &first_gadget, &second_gadget)?;
Ok(EdwardsGroupType::Allocated(result))
Ok(EdwardsGroupType::Allocated(Box::new(result)))
}
}

View File

@ -157,7 +157,7 @@ impl Integer {
let unsigned_integer = self;
let value_option: Option<String> = match_unsigned_integer!(unsigned_integer => unsigned_integer.get_value());
let value = value_option.ok_or(IntegerError::invalid_index(span.clone()))?;
let value = value_option.ok_or_else(|| IntegerError::invalid_index(span.clone()))?;
let value_usize = value
.parse::<usize>()
.map_err(|_| IntegerError::invalid_integer(value, span))?;
@ -378,7 +378,7 @@ impl Integer {
let result = match_signed_integer!(a, s => a.neg(cs.ns(|| unique_namespace)));
result.ok_or(IntegerError::negate_operation(span))
result.ok_or_else(|| IntegerError::negate_operation(span))
}
pub fn add<F: Field + PrimeField, CS: ConstraintSystem<F>>(
@ -395,7 +395,7 @@ impl Integer {
let result = match_integers_span!((a, b), s => a.add(cs.ns(|| unique_namespace), &b));
result.ok_or(IntegerError::binary_operation(format!("+"), span))
result.ok_or_else(|| IntegerError::binary_operation("+".to_string(), span))
}
pub fn sub<F: Field + PrimeField, CS: ConstraintSystem<F>>(
@ -412,7 +412,7 @@ impl Integer {
let result = match_integers_span!((a, b), s => a.sub(cs.ns(|| unique_namespace), &b));
result.ok_or(IntegerError::binary_operation(format!("-"), span))
result.ok_or_else(|| IntegerError::binary_operation("-".to_string(), span))
}
pub fn mul<F: Field + PrimeField, CS: ConstraintSystem<F>>(
@ -429,7 +429,7 @@ impl Integer {
let result = match_integers_span!((a, b), s => a.mul(cs.ns(|| unique_namespace), &b));
result.ok_or(IntegerError::binary_operation(format!("*"), span))
result.ok_or_else(|| IntegerError::binary_operation("*".to_string(), span))
}
pub fn div<F: Field + PrimeField, CS: ConstraintSystem<F>>(
@ -446,7 +446,7 @@ impl Integer {
let result = match_integers_span!((a, b), s => a.div(cs.ns(|| unique_namespace), &b));
result.ok_or(IntegerError::binary_operation(format!("÷"), span))
result.ok_or_else(|| IntegerError::binary_operation("÷".to_string(), span))
}
pub fn pow<F: Field + PrimeField, CS: ConstraintSystem<F>>(
@ -463,7 +463,7 @@ impl Integer {
let result = match_integers_span!((a, b), s => a.pow(cs.ns(|| unique_namespace), &b));
result.ok_or(IntegerError::binary_operation(format!("**"), span))
result.ok_or_else(|| IntegerError::binary_operation("**".to_string(), span))
}
}

View File

@ -110,7 +110,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
// Data type wrappers
ConstrainedValue::Array(array) => {
let array_type = array[0].to_type(span.clone())?;
let array_type = array[0].to_type(span)?;
let mut dimensions = vec![array.len()];
// Nested array type
@ -122,7 +122,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
Type::Array(Box::new(array_type), dimensions)
}
ConstrainedValue::Tuple(tuple) => {
let mut types = vec![];
let mut types = Vec::with_capacity(tuple.len());
for value in tuple {
let type_ = value.to_type(span.clone())?;
@ -205,15 +205,15 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
// If this is a circuit function, evaluate inside the circuit scope
if let Some(identifier) = circuit_identifier {
// avoid creating recursive scope
if !is_in_scope(&scope, &identifier.name.to_string()) {
outer_scope = new_scope(scope, identifier.name.to_string());
if !is_in_scope(&scope, &identifier.name) {
outer_scope = new_scope(scope, identifier.name);
}
}
Ok((outer_scope, function.clone()))
Ok((outer_scope, function))
}
ConstrainedValue::Import(import_scope, function) => function.extract_function(import_scope, span),
value => return Err(ExpressionError::undefined_function(value.to_string(), span)),
value => Err(ExpressionError::undefined_function(value.to_string(), span)),
}
}
@ -221,7 +221,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
match self {
ConstrainedValue::CircuitDefinition(circuit) => Ok(circuit),
ConstrainedValue::Import(_import_scope, circuit) => circuit.extract_circuit(span),
value => return Err(ExpressionError::undefined_circuit(value.to_string(), span)),
value => Err(ExpressionError::undefined_circuit(value.to_string(), span)),
}
}
@ -239,7 +239,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
}
ConstrainedValue::Boolean(boolean) => {
let option = boolean.get_value();
let name = option.map(|b| b.to_string()).unwrap_or(format!("[allocated]"));
let name = option
.map(|b| b.to_string())
.unwrap_or_else(|| "[allocated]".to_string());
*boolean = allocate_bool(&mut cs, name, option, span)?;
}
@ -256,7 +258,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
ConstrainedValue::Integer(integer) => {
let integer_type = integer.get_type();
let option = integer.get_value();
let name = option.clone().unwrap_or(format!("[allocated]"));
let name = option.clone().unwrap_or_else(|| "[allocated]".to_string());
*integer = Integer::allocate_type(&mut cs, integer_type, name, option, span)?;
}
@ -328,7 +330,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> fmt::Display for ConstrainedValue<F
value
.get_value()
.map(|v| v.to_string())
.unwrap_or(format!("[allocated]"))
.unwrap_or_else(|| "[allocated]".to_string())
),
ConstrainedValue::Field(ref value) => write!(f, "{:?}", value),
ConstrainedValue::Group(ref value) => write!(f, "{:?}", value),
@ -402,18 +404,18 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConditionalEqGadget<F> for Constrai
num_1.conditional_enforce_equal(cs, num_2, condition)
}
(ConstrainedValue::Array(arr_1), ConstrainedValue::Array(arr_2)) => {
for (i, (left, right)) in arr_1.into_iter().zip(arr_2.into_iter()).enumerate() {
for (i, (left, right)) in arr_1.iter().zip(arr_2.iter()).enumerate() {
left.conditional_enforce_equal(cs.ns(|| format!("array[{}]", i)), right, condition)?;
}
Ok(())
}
(ConstrainedValue::Tuple(tuple_1), ConstrainedValue::Tuple(tuple_2)) => {
for (i, (left, right)) in tuple_1.into_iter().zip(tuple_2.into_iter()).enumerate() {
for (i, (left, right)) in tuple_1.iter().zip(tuple_2.iter()).enumerate() {
left.conditional_enforce_equal(cs.ns(|| format!("tuple index {}", i)), right, condition)?;
}
Ok(())
}
(_, _) => return Err(SynthesisError::Unsatisfiable),
(_, _) => Err(SynthesisError::Unsatisfiable),
}
}
@ -446,9 +448,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> CondSelectGadget<F> for Constrained
ConstrainedValue::Integer(Integer::conditionally_select(cs, cond, num_1, num_2)?)
}
(ConstrainedValue::Array(arr_1), ConstrainedValue::Array(arr_2)) => {
let mut array = vec![];
let mut array = Vec::with_capacity(arr_1.len());
for (i, (first, second)) in arr_1.into_iter().zip(arr_2.into_iter()).enumerate() {
for (i, (first, second)) in arr_1.iter().zip(arr_2.iter()).enumerate() {
array.push(Self::conditionally_select(
cs.ns(|| format!("array[{}]", i)),
cond,
@ -460,9 +462,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> CondSelectGadget<F> for Constrained
ConstrainedValue::Array(array)
}
(ConstrainedValue::Tuple(tuple_1), ConstrainedValue::Array(tuple_2)) => {
let mut array = vec![];
let mut array = Vec::with_capacity(tuple_1.len());
for (i, (first, second)) in tuple_1.into_iter().zip(tuple_2.into_iter()).enumerate() {
for (i, (first, second)) in tuple_1.iter().zip(tuple_2.iter()).enumerate() {
array.push(Self::conditionally_select(
cs.ns(|| format!("tuple index {}", i)),
cond,
@ -482,9 +484,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> CondSelectGadget<F> for Constrained
ConstrainedValue::CircuitExpression(identifier, members_1),
ConstrainedValue::CircuitExpression(_identifier, members_2),
) => {
let mut members = vec![];
let mut members = Vec::with_capacity(members_1.len());
for (i, (first, second)) in members_1.into_iter().zip(members_2.into_iter()).enumerate() {
for (i, (first, second)) in members_1.iter().zip(members_2.iter()).enumerate() {
members.push(ConstrainedCircuitMember::conditionally_select(
cs.ns(|| format!("circuit member[{}]", i)),
cond,
@ -545,18 +547,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> From<Value> for ConstrainedValue<F,
Value::I64(i64) => ConstrainedValue::Integer(Integer::I64(i64)),
Value::I128(i128) => ConstrainedValue::Integer(Integer::I128(i128)),
Value::Array(array) => ConstrainedValue::Array(
array
.into_iter()
.map(|element| ConstrainedValue::from(element))
.collect(),
),
Value::Tuple(tuple) => ConstrainedValue::Tuple(
tuple
.into_iter()
.map(|element| ConstrainedValue::from(element))
.collect(),
),
Value::Array(array) => ConstrainedValue::Array(array.into_iter().map(ConstrainedValue::from).collect()),
Value::Tuple(tuple) => ConstrainedValue::Tuple(tuple.into_iter().map(ConstrainedValue::from).collect()),
}
}
}

View File

@ -17,8 +17,8 @@
use crate::{assert_satisfied, expect_compiler_error, generate_main_input, parse_program};
use leo_typed::InputValue;
static TEST_ADDRESS_1: &'static str = "aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8";
static TEST_ADDRESS_2: &'static str = "aleo18qgam03qe483tdrcc3fkqwpp38ehff4a2xma6lu7hams6lfpgcpq3dq05r";
static TEST_ADDRESS_1: &str = "aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8";
static TEST_ADDRESS_2: &str = "aleo18qgam03qe483tdrcc3fkqwpp38ehff4a2xma6lu7hams6lfpgcpq3dq05r";
#[test]
fn test_valid() {

View File

@ -43,7 +43,7 @@ fn fail_boolean_statement(program: EdwardsTestCompiler) {
CompilerError::FunctionError(FunctionError::StatementError(StatementError::ExpressionError(
ExpressionError::BooleanError(BooleanError::Error(_)),
))) => {}
_ => panic!("Expected boolean error, got {}"),
e => panic!("Expected boolean error, got {}", e),
}
}

View File

@ -14,6 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
// allow the use of EdwardsTestCompiler::parse_program_from_string for tests
#![allow(deprecated)]
pub mod address;
pub mod array;
pub mod boolean;

View File

@ -35,7 +35,7 @@ impl CorePackageError {
}
pub fn core_package_star(span: Span) -> Self {
let message = format!("Cannot import star from leo-core");
let message = "Cannot import star from leo-core".to_string();
Self::new_from_span(message, span)
}

View File

@ -48,7 +48,7 @@ impl CorePackageListError {
}
pub fn core_package_star(span: Span) -> Self {
let message = format!("Cannot import star from leo-core");
let message = "Cannot import star from leo-core".to_string();
Self::new_from_span(message, span)
}

View File

@ -104,7 +104,7 @@ impl CoreCircuit for Blake2sCircuit {
),
span.clone(),
)],
span: span.clone(),
span,
},
)],
}
@ -141,7 +141,7 @@ impl CoreCircuit for Blake2sCircuit {
.to_bytes(cs)
.map_err(|e| CoreCircuitError::cannot_enforce("Vec<UInt8> ToBytes".to_owned(), e, span.clone()))?;
let return_value = bytes.into_iter().map(|byte| Value::U8(byte)).collect();
let return_value = bytes.into_iter().map(Value::U8).collect();
// Return one array digest value
Ok(vec![Value::Array(return_value)])
@ -158,7 +158,7 @@ fn check_array_bytes(value: Value, size: usize, span: Span) -> Result<Vec<UInt8>
return Err(CoreCircuitError::array_length(size, array_value.len(), span));
}
let mut array_bytes = vec![];
let mut array_bytes = Vec::with_capacity(array_value.len());
for value in array_value {
let byte = match value {

View File

@ -71,7 +71,7 @@ impl CorePackage {
let span = circuit.span.clone();
// take the alias if it is present
let id = circuit.alias.clone().unwrap_or(circuit.symbol.clone());
let id = circuit.alias.clone().unwrap_or_else(|| circuit.symbol.clone());
let name = id.name.clone();
let circuit = if self.unstable {
@ -87,9 +87,7 @@ impl CorePackage {
}
} else {
// match core circuit
match circuit_name {
name => return Err(CorePackageError::undefined_core_circuit(name.to_string(), span)),
}
return Err(CorePackageError::undefined_core_circuit(circuit_name.to_string(), span));
};
circuit_structs.push(name, circuit)

View File

@ -71,7 +71,7 @@ impl fmt::Display for Value {
}
};
let string = string_option.unwrap_or("[input]".to_owned());
let string = string_option.unwrap_or_else(|| "[input]".to_owned());
write!(f, "{}", string)
}

View File

@ -30,7 +30,6 @@ where
{
type ErrorType;
#[must_use]
fn add<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self) -> Result<Self, Self::ErrorType>;
}

View File

@ -23,6 +23,5 @@ where
{
type ErrorType;
#[must_use]
fn div<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self) -> Result<Self, Self::ErrorType>;
}

View File

@ -23,6 +23,5 @@ where
{
type ErrorType;
#[must_use]
fn mul<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self) -> Result<Self, Self::ErrorType>;
}

View File

@ -29,7 +29,6 @@ where
{
type ErrorType;
#[must_use]
fn neg<CS: ConstraintSystem<F>>(&self, cs: CS) -> Result<Self, Self::ErrorType>;
}
@ -44,7 +43,7 @@ impl<F: Field> Neg<F> for Vec<Boolean> {
let mut one = vec![Boolean::constant(true)];
one.append(&mut vec![Boolean::Constant(false); self.len() - 1]);
let mut bits = flipped.add_bits(cs.ns(|| format!("add one")), &one)?;
let mut bits = flipped.add_bits(cs.ns(|| "add one"), &one)?;
let _carry = bits.pop(); // we already accounted for overflow above
Ok(bits)

View File

@ -23,6 +23,5 @@ where
{
type ErrorType;
#[must_use]
fn pow<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self) -> Result<Self, Self::ErrorType>;
}

View File

@ -23,6 +23,5 @@ where
{
type ErrorType;
#[must_use]
fn sub<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self) -> Result<Self, Self::ErrorType>;
}

View File

@ -44,12 +44,12 @@ impl<'a, F: Field> FullAdder<'a, F> for Boolean {
b: &'a Self,
carry: &'a Self,
) -> Result<(Self, Self), SynthesisError> {
let a_x_b = Boolean::xor(cs.ns(|| format!("a XOR b")), a, b)?;
let sum = Boolean::xor(cs.ns(|| format!("adder sum")), &a_x_b, carry)?;
let a_x_b = Boolean::xor(cs.ns(|| "a XOR b"), a, b)?;
let sum = Boolean::xor(cs.ns(|| "adder sum"), &a_x_b, carry)?;
let c1 = Boolean::and(cs.ns(|| format!("a AND b")), a, b)?;
let c2 = Boolean::and(cs.ns(|| format!("carry AND (a XOR b)")), carry, &a_x_b)?;
let carry = Boolean::or(cs.ns(|| format!("c1 OR c2")), &c1, &c2)?;
let c1 = Boolean::and(cs.ns(|| "a AND b"), a, b)?;
let c2 = Boolean::and(cs.ns(|| "carry AND (a XOR b)"), carry, &a_x_b)?;
let carry = Boolean::or(cs.ns(|| "c1 OR c2"), &c1, &c2)?;
Ok((sum, carry))
}

View File

@ -27,14 +27,13 @@ pub trait RippleCarryAdder<F: Field, Rhs = Self>
where
Self: std::marker::Sized,
{
#[must_use]
fn add_bits<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self) -> Result<Vec<Boolean>, SynthesisError>;
}
// Generic impl
impl<F: Field> RippleCarryAdder<F> for Vec<Boolean> {
fn add_bits<CS: ConstraintSystem<F>>(&self, mut cs: CS, other: &Self) -> Result<Vec<Boolean>, SynthesisError> {
let mut result = vec![];
let mut result = Vec::with_capacity(self.len() + 1);
let mut carry = Boolean::constant(false);
for (i, (a, b)) in self.iter().zip(other.iter()).enumerate() {
let (sum, next) = Boolean::add(cs.ns(|| format!("rpc {}", i)), a, b, &carry)?;

View File

@ -30,7 +30,7 @@ impl SignExtend for Boolean {
fn sign_extend(bits: &[Boolean], length: usize) -> Vec<Boolean> {
let msb = bits.last().expect("empty bit list");
let bits_needed = length - bits.len();
let mut extension = vec![msb.clone(); bits_needed];
let mut extension = vec![*msb; bits_needed];
let mut result = Vec::from(bits);
result.append(&mut extension);

View File

@ -87,7 +87,7 @@ macro_rules! add_int_impl {
all_constants = false;
// Add the coeff * bit_gadget
lc = lc + (coeff, bit.get_variable());
lc += (coeff, bit.get_variable());
}
Boolean::Not(ref bit) => {
all_constants = false;
@ -97,7 +97,7 @@ macro_rules! add_int_impl {
}
Boolean::Constant(bit) => {
if bit {
lc = lc + (coeff, CS::one());
lc += (coeff, CS::one());
}
}
}
@ -117,7 +117,7 @@ macro_rules! add_int_impl {
}
// Storage area for the resulting bits
let mut result_bits = vec![];
let mut result_bits = Vec::with_capacity(max_bits);
// Allocate each bit_gadget of the result
let mut coeff = F::one();

View File

@ -206,13 +206,13 @@ macro_rules! div_int_impl {
&r
)?;
index = index - 1;
index -= 1;
let mut q_new = q.clone();
q_new.bits[index] = true_bit.clone();
q_new.value = Some(q_new.value.unwrap() + bit_value);
bit_value = (bit_value >> 1);
bit_value >>= 1;
q = Self::conditionally_select(
&mut cs.ns(|| format!("set_bit_or_same_{}", i)),

View File

@ -84,7 +84,7 @@ macro_rules! mul_int_impl {
a_shifted.truncate(size);
// conditionally add
let mut to_add = vec![];
let mut to_add = Vec::with_capacity(a_shifted.len());
for (j, a_bit) in a_shifted.iter().enumerate() {
let selected_bit = Boolean::conditionally_select(
&mut cs.ns(|| format!("select product bit {} {}", i, j)),
@ -146,7 +146,7 @@ macro_rules! mul_int_impl {
all_constants = false;
// Add the coeff * bit_gadget
lc = lc + (coeff, bit.get_variable());
lc += (coeff, bit.get_variable());
}
Boolean::Not(ref bit) => {
all_constants = false;
@ -156,7 +156,7 @@ macro_rules! mul_int_impl {
}
Boolean::Constant(bit) => {
if bit {
lc = lc + (coeff, CS::one());
lc += (coeff, CS::one());
}
}
}
@ -175,7 +175,7 @@ macro_rules! mul_int_impl {
}
// Storage area for the resulting bits
let mut result_bits = vec![];
let mut result_bits = Vec::with_capacity(max_bits);
// Allocate each bit_gadget of the result
let mut coeff = F::one();

View File

@ -34,10 +34,10 @@ fn check_all_constant_bits(expected: i128, actual: Int128) {
let mask = 1 << i as i128;
let result = expected & mask;
match b {
&Boolean::Is(_) => panic!(),
&Boolean::Not(_) => panic!(),
&Boolean::Constant(b) => {
match *b {
Boolean::Is(_) => panic!(),
Boolean::Not(_) => panic!(),
Boolean::Constant(b) => {
let bit = result == mask;
assert_eq!(b, bit);
}
@ -51,16 +51,16 @@ fn check_all_allocated_bits(expected: i128, actual: Int128) {
let mask = 1 << i as i128;
let result = expected & mask;
match b {
&Boolean::Is(ref b) => {
match *b {
Boolean::Is(ref b) => {
let bit = result == mask;
assert_eq!(b.get_value().unwrap(), bit);
}
&Boolean::Not(ref b) => {
Boolean::Not(ref b) => {
let bit = result == mask;
assert_eq!(!b.get_value().unwrap(), bit);
}
&Boolean::Constant(_) => unreachable!(),
Boolean::Constant(_) => unreachable!(),
}
}
}

View File

@ -34,10 +34,10 @@ fn check_all_constant_bits(expected: i16, actual: Int16) {
let mask = 1 << i as i16;
let result = expected & mask;
match b {
&Boolean::Is(_) => panic!(),
&Boolean::Not(_) => panic!(),
&Boolean::Constant(b) => {
match *b {
Boolean::Is(_) => panic!(),
Boolean::Not(_) => panic!(),
Boolean::Constant(b) => {
let bit = result == mask;
assert_eq!(b, bit);
}
@ -51,16 +51,16 @@ fn check_all_allocated_bits(expected: i16, actual: Int16) {
let mask = 1 << i as i16;
let result = expected & mask;
match b {
&Boolean::Is(ref b) => {
match *b {
Boolean::Is(ref b) => {
let bit = result == mask;
assert_eq!(b.get_value().unwrap(), bit);
}
&Boolean::Not(ref b) => {
Boolean::Not(ref b) => {
let bit = result == mask;
assert_eq!(!b.get_value().unwrap(), bit);
}
&Boolean::Constant(_) => unreachable!(),
Boolean::Constant(_) => unreachable!(),
}
}
}

View File

@ -34,10 +34,10 @@ fn check_all_constant_bits(expected: i32, actual: Int32) {
let mask = 1 << i as i32;
let result = expected & mask;
match b {
&Boolean::Is(_) => panic!(),
&Boolean::Not(_) => panic!(),
&Boolean::Constant(b) => {
match *b {
Boolean::Is(_) => panic!(),
Boolean::Not(_) => panic!(),
Boolean::Constant(b) => {
let bit = result == mask;
assert_eq!(b, bit);
}
@ -51,16 +51,16 @@ fn check_all_allocated_bits(expected: i32, actual: Int32) {
let mask = 1 << i as i32;
let result = expected & mask;
match b {
&Boolean::Is(ref b) => {
match *b {
Boolean::Is(ref b) => {
let bit = result == mask;
assert_eq!(b.get_value().unwrap(), bit);
}
&Boolean::Not(ref b) => {
Boolean::Not(ref b) => {
let bit = result == mask;
assert_eq!(!b.get_value().unwrap(), bit);
}
&Boolean::Constant(_) => unreachable!(),
Boolean::Constant(_) => unreachable!(),
}
}
}

View File

@ -34,10 +34,10 @@ fn check_all_constant_bits(expected: i64, actual: Int64) {
let mask = 1 << i as i64;
let result = expected & mask;
match b {
&Boolean::Is(_) => panic!(),
&Boolean::Not(_) => panic!(),
&Boolean::Constant(b) => {
match *b {
Boolean::Is(_) => panic!(),
Boolean::Not(_) => panic!(),
Boolean::Constant(b) => {
let bit = result == mask;
assert_eq!(b, bit);
}
@ -51,16 +51,16 @@ fn check_all_allocated_bits(expected: i64, actual: Int64) {
let mask = 1 << i as i64;
let result = expected & mask;
match b {
&Boolean::Is(ref b) => {
match *b {
Boolean::Is(ref b) => {
let bit = result == mask;
assert_eq!(b.get_value().unwrap(), bit);
}
&Boolean::Not(ref b) => {
Boolean::Not(ref b) => {
let bit = result == mask;
assert_eq!(!b.get_value().unwrap(), bit);
}
&Boolean::Constant(_) => unreachable!(),
Boolean::Constant(_) => unreachable!(),
}
}
}

View File

@ -34,10 +34,10 @@ fn check_all_constant_bits(expected: i8, actual: Int8) {
let mask = 1 << i as i8;
let result = expected & mask;
match b {
&Boolean::Is(_) => panic!(),
&Boolean::Not(_) => panic!(),
&Boolean::Constant(b) => {
match *b {
Boolean::Is(_) => panic!(),
Boolean::Not(_) => panic!(),
Boolean::Constant(b) => {
let bit = result == mask;
assert_eq!(b, bit);
}
@ -51,16 +51,16 @@ fn check_all_allocated_bits(expected: i8, actual: Int8) {
let mask = 1 << i as i8;
let result = expected & mask;
match b {
&Boolean::Is(ref b) => {
match *b {
Boolean::Is(ref b) => {
let bit = result == mask;
assert_eq!(b.get_value().unwrap(), bit);
}
&Boolean::Not(ref b) => {
Boolean::Not(ref b) => {
let bit = result == mask;
assert_eq!(!b.get_value().unwrap(), bit);
}
&Boolean::Constant(_) => unreachable!(),
Boolean::Constant(_) => unreachable!(),
}
}
}

View File

@ -53,20 +53,17 @@ pub enum InputParserError {
impl InputParserError {
pub fn set_path(&mut self, path: PathBuf) {
match self {
InputParserError::SyntaxError(error) => {
let new_error: Error<Rule> = match error {
InputSyntaxError::Error(error) => {
let new_error = error.clone();
new_error.with_path(path.to_str().unwrap())
}
};
if let InputParserError::SyntaxError(error) = self {
let new_error: Error<Rule> = match error {
InputSyntaxError::Error(error) => {
let new_error = error.clone();
new_error.with_path(path.to_str().unwrap())
}
};
tracing::error!("{}", new_error);
tracing::error!("{}", new_error);
*error = InputSyntaxError::Error(new_error);
}
_ => {}
*error = InputSyntaxError::Error(new_error);
}
}

View File

@ -35,7 +35,7 @@ pub trait CLI {
.iter()
.map(|a| {
let mut args = Arg::with_name(a.0).help(a.1).required(a.3).index(a.4);
if a.2.len() > 0 {
if !a.2.is_empty() {
args = args.possible_values(a.2);
}
args
@ -47,7 +47,7 @@ pub trait CLI {
.collect::<Vec<Arg<'static, 'static>>>();
let options = &Self::OPTIONS
.iter()
.map(|a| match a.2.len() > 0 {
.map(|a| match !a.2.is_empty() {
true => Arg::from_usage(a.0)
.conflicts_with_all(a.1)
.possible_values(a.2)
@ -64,7 +64,7 @@ pub trait CLI {
&s.2.iter()
.map(|a| {
let mut args = Arg::with_name(a.0).help(a.1).required(a.3).index(a.4);
if a.2.len() > 0 {
if !a.2.is_empty() {
args = args.possible_values(a.2);
}
args
@ -78,7 +78,7 @@ pub trait CLI {
)
.args(
&s.4.iter()
.map(|a| match a.2.len() > 0 {
.map(|a| match !a.2.is_empty() {
true => Arg::from_usage(a.0)
.conflicts_with_all(a.1)
.possible_values(a.2)

View File

@ -167,7 +167,7 @@ impl CLI for AddCommand {
let mut file_path = path.clone();
file_path.push(file_name);
if file_name.ends_with("/") {
if file_name.ends_with('/') {
create_dir_all(file_path)?;
} else {
if let Some(parent_directory) = path.parent() {

View File

@ -93,7 +93,7 @@ impl CLI for BuildCommand {
// Compile the library file but do not output
let _program = Compiler::<Fq, EdwardsGroupType>::parse_program_without_input(
package_name.clone(),
lib_file_path.clone(),
lib_file_path,
output_directory.clone(),
)?;
tracing::info!("Complete");
@ -121,7 +121,7 @@ impl CLI for BuildCommand {
// Load the program at `main_file_path`
let program = Compiler::<Fq, EdwardsGroupType>::parse_program_with_input(
package_name.clone(),
main_file_path.clone(),
main_file_path,
output_directory,
&input_string,
input_path,

View File

@ -65,7 +65,7 @@ impl CLI for DeployCommand {
Ok(())
}
None => {
let mut main_file_path = path.clone();
let mut main_file_path = path;
main_file_path.push(SOURCE_DIRECTORY_NAME);
main_file_path.push(MAIN_FILENAME);

View File

@ -65,7 +65,7 @@ impl CLI for LintCommand {
Ok(())
}
None => {
let mut main_file_path = path.clone();
let mut main_file_path = path;
main_file_path.push(SOURCE_DIRECTORY_NAME);
main_file_path.push(MAIN_FILENAME);

Some files were not shown because too many files have changed in this diff Show More