merge lastest master

This commit is contained in:
gluaxspeed 2021-02-04 09:39:02 -05:00
commit ba417a9a73
40 changed files with 185 additions and 192 deletions

47
.github/workflows/leo-setup.yml vendored Normal file
View File

@ -0,0 +1,47 @@
name: leo-setup
on:
pull_request:
push:
branches:
- master
paths-ignore:
- 'docs/**'
- 'documentation/**'
env:
RUST_BACKTRACE: 1
jobs:
add:
name: Add Package ('leo add')
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
override: true
components: rustfmt
- name: Install Leo
uses: actions-rs/cargo@v1
env:
CARGO_NET_GIT_FETCH_WITH_CLI: true
with:
command: install
args: --path .
- name: 'leo setup for examples'
env:
USER: ${{ secrets.ALEO_PM_USERNAME }}
PASS: ${{ secrets.ALEO_PM_PASSWORD }}
run: |
cd examples/pedersen-hash
leo setup
leo setup
leo setup --skip-key-check
leo clean

View File

@ -0,0 +1 @@
v1.2.0

22
Cargo.lock generated
View File

@ -1232,7 +1232,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "leo-asg" name = "leo-asg"
version = "1.0.8" version = "1.2.0"
dependencies = [ dependencies = [
"criterion", "criterion",
"indexmap", "indexmap",
@ -1247,7 +1247,7 @@ dependencies = [
[[package]] [[package]]
name = "leo-ast" name = "leo-ast"
version = "1.0.8" version = "1.2.0"
dependencies = [ dependencies = [
"criterion", "criterion",
"indexmap", "indexmap",
@ -1261,7 +1261,7 @@ dependencies = [
[[package]] [[package]]
name = "leo-compiler" name = "leo-compiler"
version = "1.0.8" version = "1.2.0"
dependencies = [ dependencies = [
"bincode", "bincode",
"hex", "hex",
@ -1295,7 +1295,7 @@ dependencies = [
[[package]] [[package]]
name = "leo-gadgets" name = "leo-gadgets"
version = "1.0.8" version = "1.2.0"
dependencies = [ dependencies = [
"criterion", "criterion",
"rand", "rand",
@ -1308,7 +1308,7 @@ dependencies = [
[[package]] [[package]]
name = "leo-grammar" name = "leo-grammar"
version = "1.0.8" version = "1.2.0"
dependencies = [ dependencies = [
"criterion", "criterion",
"from-pest", "from-pest",
@ -1324,7 +1324,7 @@ dependencies = [
[[package]] [[package]]
name = "leo-imports" name = "leo-imports"
version = "1.0.8" version = "1.2.0"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"leo-asg", "leo-asg",
@ -1336,7 +1336,7 @@ dependencies = [
[[package]] [[package]]
name = "leo-input" name = "leo-input"
version = "1.0.8" version = "1.2.0"
dependencies = [ dependencies = [
"from-pest", "from-pest",
"pest", "pest",
@ -1348,7 +1348,7 @@ dependencies = [
[[package]] [[package]]
name = "leo-lang" name = "leo-lang"
version = "1.0.8" version = "1.2.0"
dependencies = [ dependencies = [
"clap", "clap",
"colored", "colored",
@ -1387,11 +1387,11 @@ dependencies = [
[[package]] [[package]]
name = "leo-linter" name = "leo-linter"
version = "1.0.8" version = "1.2.0"
[[package]] [[package]]
name = "leo-package" name = "leo-package"
version = "1.0.8" version = "1.2.0"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"serde", "serde",
@ -1404,7 +1404,7 @@ dependencies = [
[[package]] [[package]]
name = "leo-state" name = "leo-state"
version = "1.0.8" version = "1.2.0"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"leo-ast", "leo-ast",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "leo-lang" name = "leo-lang"
version = "1.0.8" version = "1.2.0"
authors = [ "The Aleo Team <hello@aleo.org>" ] authors = [ "The Aleo Team <hello@aleo.org>" ]
description = "The Leo programming language" description = "The Leo programming language"
homepage = "https://aleo.org" homepage = "https://aleo.org"
@ -35,36 +35,36 @@ members = [
"linter", "linter",
"package", "package",
"state", "state",
"asg", "asg"
] ]
[dependencies.leo-ast] [dependencies.leo-ast]
path = "./ast" path = "./ast"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-compiler] [dependencies.leo-compiler]
path = "./compiler" path = "./compiler"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-gadgets] [dependencies.leo-gadgets]
path = "./gadgets" path = "./gadgets"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-imports] [dependencies.leo-imports]
path = "./imports" path = "./imports"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-input] [dependencies.leo-input]
path = "./input" path = "./input"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-package] [dependencies.leo-package]
path = "./package" path = "./package"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-state] [dependencies.leo-state]
path = "./state" path = "./state"
version = "1.0.8" version = "1.2.0"
[dependencies.snarkvm-algorithms] [dependencies.snarkvm-algorithms]
version = "0.0.2" version = "0.0.2"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "leo-asg" name = "leo-asg"
version = "1.0.8" version = "1.2.0"
authors = [ "The Aleo Team <hello@aleo.org>" ] authors = [ "The Aleo Team <hello@aleo.org>" ]
description = "ASG of the Leo programming language" description = "ASG of the Leo programming language"
homepage = "https://aleo.org" homepage = "https://aleo.org"
@ -23,9 +23,6 @@ version = "1.0"
[dependencies.serde_json] [dependencies.serde_json]
version = "1.0" version = "1.0"
[dev-dependencies.criterion]
version = "0.3"
[dependencies.indexmap] [dependencies.indexmap]
version = "1.6" version = "1.6"
@ -33,16 +30,19 @@ version = "1.6"
version = "1.0" version = "1.0"
[dependencies.leo-ast] [dependencies.leo-ast]
version = "1.0" version = "1.2.0"
path = "../ast" path = "../ast"
[dependencies.leo-grammar] [dependencies.leo-grammar]
version = "1.0" version = "1.2.0"
path = "../grammar" path = "../grammar"
[dependencies.uuid] [dependencies.uuid]
version = "0.8" version = "0.8"
features = ["v4", "serde"] features = [ "v4", "serde" ]
[dependencies.num-bigint] [dependencies.num-bigint]
version = "0.3" version = "0.3"
[dev-dependencies.criterion]
version = "0.3"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "leo-ast" name = "leo-ast"
version = "1.0.8" version = "1.2.0"
authors = [ "The Aleo Team <hello@aleo.org>" ] authors = [ "The Aleo Team <hello@aleo.org>" ]
description = "Core AST of the Leo programming language" description = "Core AST of the Leo programming language"
homepage = "https://aleo.org" homepage = "https://aleo.org"
@ -28,11 +28,11 @@ harness = false
[dependencies.leo-grammar] [dependencies.leo-grammar]
path = "../grammar" path = "../grammar"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-input] [dependencies.leo-input]
path = "../input" path = "../input"
version = "1.0.8" version = "1.2.0"
[dependencies.indexmap] [dependencies.indexmap]
version = "1.6.1" version = "1.6.1"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "leo-compiler" name = "leo-compiler"
version = "1.0.8" version = "1.2.0"
authors = [ "The Aleo Team <hello@aleo.org>" ] authors = [ "The Aleo Team <hello@aleo.org>" ]
description = "Compiler of the Leo programming language" description = "Compiler of the Leo programming language"
homepage = "https://aleo.org" homepage = "https://aleo.org"
@ -19,35 +19,35 @@ edition = "2018"
[dependencies.leo-ast] [dependencies.leo-ast]
path = "../ast" path = "../ast"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-gadgets] [dependencies.leo-gadgets]
path = "../gadgets" path = "../gadgets"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-grammar] [dependencies.leo-grammar]
path = "../grammar" path = "../grammar"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-imports] [dependencies.leo-imports]
path = "../imports" path = "../imports"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-input] [dependencies.leo-input]
path = "../input" path = "../input"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-package] [dependencies.leo-package]
path = "../package" path = "../package"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-state] [dependencies.leo-state]
path = "../state" path = "../state"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-asg] [dependencies.leo-asg]
path = "../asg" path = "../asg"
version = "1.0.8" version = "1.2.0"
[dependencies.snarkvm-curves] [dependencies.snarkvm-curves]
version = "0.0.2" version = "0.0.2"
@ -110,7 +110,7 @@ version = "0.1"
[dependencies.uuid] [dependencies.uuid]
version = "0.8" version = "0.8"
features = ["v4", "serde"] features = [ "v4", "serde" ]
[dev-dependencies.num-bigint] [dev-dependencies.num-bigint]
version = "0.3" version = "0.3"

View File

@ -22,12 +22,8 @@ use leo_asg::Variable;
use snarkvm_models::curves::{Field, PrimeField}; use snarkvm_models::curves::{Field, PrimeField};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> { impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn store_definition(&mut self, variable: &Variable, mut value: ConstrainedValue<F, G>) { pub fn store_definition(&mut self, variable: &Variable, value: ConstrainedValue<F, G>) {
let variable = variable.borrow(); let variable = variable.borrow();
// Store with given mutability
if variable.mutable {
value = ConstrainedValue::Mutable(Box::new(value));
}
self.store(variable.id, value); self.store(variable.id, value);
} }

View File

@ -34,7 +34,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
index: &Arc<Expression>, index: &Arc<Expression>,
span: &Span, span: &Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<F, G>, ExpressionError> {
let array = match self.enforce_operand(cs, array)? { let array = match self.enforce_expression(cs, array)? {
ConstrainedValue::Array(array) => array, ConstrainedValue::Array(array) => array,
value => return Err(ExpressionError::undefined_array(value.to_string(), span.to_owned())), value => return Err(ExpressionError::undefined_array(value.to_string(), span.to_owned())),
}; };
@ -52,7 +52,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
right: Option<&Arc<Expression>>, right: Option<&Arc<Expression>>,
span: &Span, span: &Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<F, G>, ExpressionError> {
let array = match self.enforce_operand(cs, array)? { let array = match self.enforce_expression(cs, array)? {
ConstrainedValue::Array(array) => array, ConstrainedValue::Array(array) => array,
value => return Err(ExpressionError::undefined_array(value.to_string(), span.to_owned())), value => return Err(ExpressionError::undefined_array(value.to_string(), span.to_owned())),
}; };

View File

@ -32,7 +32,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
index: &Arc<Expression>, index: &Arc<Expression>,
span: &Span, span: &Span,
) -> Result<usize, ExpressionError> { ) -> Result<usize, ExpressionError> {
match self.enforce_operand(cs, index)? { match self.enforce_expression(cs, index)? {
ConstrainedValue::Integer(number) => Ok(number.to_usize(span)?), ConstrainedValue::Integer(number) => Ok(number.to_usize(span)?),
value => Err(ExpressionError::invalid_index(value.to_string(), span)), value => Err(ExpressionError::invalid_index(value.to_string(), span)),
} }

View File

@ -35,8 +35,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
left: &Arc<Expression>, left: &Arc<Expression>,
right: &Arc<Expression>, right: &Arc<Expression>,
) -> Result<ConstrainedValuePair<F, G>, ExpressionError> { ) -> Result<ConstrainedValuePair<F, G>, ExpressionError> {
let resolved_left = self.enforce_operand(cs, left)?; let resolved_left = self.enforce_expression(cs, left)?;
let resolved_right = self.enforce_operand(cs, right)?; let resolved_right = self.enforce_expression(cs, right)?;
Ok((resolved_left, resolved_right)) Ok((resolved_left, resolved_right))
} }

View File

@ -18,6 +18,3 @@
pub mod binary; pub mod binary;
pub use self::binary::*; pub use self::binary::*;
pub mod operand;
pub use self::operand::*;

View File

@ -1,43 +0,0 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
//! Enforces one operand in a binary expression in a compiled Leo program.
use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};
use leo_asg::Expression;
use std::sync::Arc;
use snarkvm_models::{
curves::{Field, PrimeField},
gadgets::r1cs::ConstraintSystem,
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
/// Enforce an operand of a binary expression.
/// We don't care about mutability because we are not changing any variables.
/// We try to resolve unresolved types here if the type is given explicitly.
pub fn enforce_operand<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
expression: &Arc<Expression>,
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
let mut branch = self.enforce_expression(cs, expression)?;
branch.get_inner_mut();
Ok(branch)
}
}

View File

@ -33,7 +33,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<F, G>, ExpressionError> {
if let Some(target) = &expr.target { if let Some(target) = &expr.target {
//todo: we can prob pass values by ref here to avoid copying the entire circuit on access //todo: we can prob pass values by ref here to avoid copying the entire circuit on access
let target_value = self.enforce_operand(cs, target)?; let target_value = self.enforce_expression(cs, target)?;
match target_value { match target_value {
ConstrainedValue::CircuitExpression(def, members) => { ConstrainedValue::CircuitExpression(def, members) => {
assert!(def.circuit == expr.circuit); assert!(def.circuit == expr.circuit);

View File

@ -41,9 +41,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
value => return Err(ExpressionError::conditional_boolean(value.to_string(), span.to_owned())), value => return Err(ExpressionError::conditional_boolean(value.to_string(), span.to_owned())),
}; };
let first_value = self.enforce_operand(cs, first)?; let first_value = self.enforce_expression(cs, first)?;
let second_value = self.enforce_operand(cs, second)?; let second_value = self.enforce_expression(cs, second)?;
let unique_namespace = cs.ns(|| { let unique_namespace = cs.ns(|| {
format!( format!(

View File

@ -92,7 +92,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let resolved_inner = self.enforce_expression(cs, inner)?; let resolved_inner = self.enforce_expression(cs, inner)?;
enforce_negate(cs, resolved_inner, &span) enforce_negate(cs, resolved_inner, &span)
} }
UnaryOperation::Not => Ok(evaluate_not(self.enforce_operand(cs, inner)?, &span)?), UnaryOperation::Not => Ok(evaluate_not(self.enforce_expression(cs, inner)?, &span)?),
}, },
Expression::Ternary(TernaryExpression { Expression::Ternary(TernaryExpression {

View File

@ -35,7 +35,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
span: &Span, span: &Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<F, G>, ExpressionError> {
// Get the tuple values. // Get the tuple values.
let tuple = match self.enforce_operand(cs, tuple)? { let tuple = match self.enforce_expression(cs, tuple)? {
ConstrainedValue::Tuple(tuple) => tuple, ConstrainedValue::Tuple(tuple) => tuple,
value => return Err(ExpressionError::undefined_array(value.to_string(), span.to_owned())), value => return Err(ExpressionError::undefined_array(value.to_string(), span.to_owned())),
}; };

View File

@ -61,13 +61,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
// Store input values as new variables in resolved program // Store input values as new variables in resolved program
for (variable, input_expression) in function.arguments.iter().zip(arguments.iter()) { for (variable, input_expression) in function.arguments.iter().zip(arguments.iter()) {
let mut input_value = self.enforce_expression(cs, input_expression)?; let input_value = self.enforce_expression(cs, input_expression)?;
let variable = variable.borrow(); let variable = variable.borrow();
if variable.mutable {
input_value = ConstrainedValue::Mutable(Box::new(input_value))
}
self.store(variable.id, input_value); self.store(variable.id, input_value);
} }

View File

@ -109,10 +109,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let variable = variable.borrow(); let variable = variable.borrow();
let mut result = vec![match self.get_mut(&variable.id) { let mut result = vec![match self.get_mut(&variable.id) {
Some(value) => match value { Some(value) => value,
ConstrainedValue::Mutable(mutable) => &mut **mutable,
_ => return Err(StatementError::immutable_assign(variable.name.to_string(), span)),
},
None => return Err(StatementError::undefined_variable(variable.name.to_string(), span)), None => return Err(StatementError::undefined_variable(variable.name.to_string(), span)),
}]; }];

View File

@ -48,16 +48,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
// Initialize empty return value. // Initialize empty return value.
let mut return_value = ConstrainedValue::Tuple(vec![]); let mut return_value = ConstrainedValue::Tuple(vec![]);
// Error if the function or one of its branches does not return.
if !expected_return.is_unit()
&& results
.iter()
.find(|(indicator, _res)| get_indicator_value(indicator))
.is_none()
{
return Err(StatementError::no_returns(&expected_return, span.to_owned()));
}
// Find the return value // Find the return value
let mut ignored = vec![]; let mut ignored = vec![];
let mut found_return = false; let mut found_return = false;

View File

@ -31,8 +31,7 @@ use snarkvm_models::{
pub struct Blake2s; pub struct Blake2s;
fn unwrap_argument<F: Field + PrimeField, G: GroupType<F>>(mut arg: ConstrainedValue<F, G>) -> Vec<UInt8> { fn unwrap_argument<F: Field + PrimeField, G: GroupType<F>>(arg: ConstrainedValue<F, G>) -> Vec<UInt8> {
arg.get_inner_mut();
if let ConstrainedValue::Array(args) = arg { if let ConstrainedValue::Array(args) = arg {
assert_eq!(args.len(), 32); // asg enforced assert_eq!(args.len(), 32); // asg enforced
args.into_iter() args.into_iter()

View File

@ -67,10 +67,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let variable = assignee.target_variable.borrow(); let variable = assignee.target_variable.borrow();
let mut result = vec![match self.get_mut(&variable.id) { let mut result = vec![match self.get_mut(&variable.id) {
Some(value) => match value { Some(value) => value,
ConstrainedValue::Mutable(mutable) => &mut **mutable,
_ => return Err(StatementError::immutable_assign(variable.name.to_string(), span)),
},
None => return Err(StatementError::undefined_variable(variable.name.to_string(), span)), None => return Err(StatementError::undefined_variable(variable.name.to_string(), span)),
}]; }];
@ -101,14 +98,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
} }
} }
// discards unnecessary mutable wrappers
fn unwrap_mutable(input: &mut ConstrainedValue<F, G>) -> &mut ConstrainedValue<F, G> {
match input {
ConstrainedValue::Mutable(x) => Self::unwrap_mutable(&mut **x),
x => x,
}
}
// todo: this can prob have most of its error checking removed // todo: this can prob have most of its error checking removed
pub(crate) fn resolve_assignee_access<'a>( pub(crate) fn resolve_assignee_access<'a>(
access: ResolvedAssigneeAccess, access: ResolvedAssigneeAccess,
@ -120,7 +109,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
if value.len() != 1 { if value.len() != 1 {
return Err(StatementError::array_assign_interior_index(span.clone())); return Err(StatementError::array_assign_interior_index(span.clone()));
} }
match Self::unwrap_mutable(value.remove(0)) { match value.remove(0) {
ConstrainedValue::Array(old) => { ConstrainedValue::Array(old) => {
if index > old.len() { if index > old.len() {
Err(StatementError::array_assign_index_bounds( Err(StatementError::array_assign_index_bounds(
@ -140,7 +129,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
if value.len() == 1 { if value.len() == 1 {
// not a range of a range // not a range of a range
match Self::unwrap_mutable(value.remove(0)) { match value.remove(0) {
ConstrainedValue::Array(old) => { ConstrainedValue::Array(old) => {
let stop_index = stop_index.unwrap_or(old.len()); let stop_index = stop_index.unwrap_or(old.len());
Self::check_range_index(start_index, stop_index, old.len(), &span)?; Self::check_range_index(start_index, stop_index, old.len(), &span)?;
@ -154,14 +143,14 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let stop_index = stop_index.unwrap_or(value.len()); let stop_index = stop_index.unwrap_or(value.len());
Self::check_range_index(start_index, stop_index, value.len(), &span)?; Self::check_range_index(start_index, stop_index, value.len(), &span)?;
Ok(value.drain(start_index..stop_index).map(Self::unwrap_mutable).collect()) Ok(value.drain(start_index..stop_index).collect())
} }
} }
ResolvedAssigneeAccess::Tuple(index, span) => { ResolvedAssigneeAccess::Tuple(index, span) => {
if value.len() != 1 { if value.len() != 1 {
return Err(StatementError::array_assign_interior_index(span)); return Err(StatementError::array_assign_interior_index(span));
} }
match Self::unwrap_mutable(value.remove(0)) { match value.remove(0) {
ConstrainedValue::Tuple(old) => { ConstrainedValue::Tuple(old) => {
if index > old.len() { if index > old.len() {
Err(StatementError::tuple_assign_index_bounds(index, old.len(), span)) Err(StatementError::tuple_assign_index_bounds(index, old.len(), span))
@ -176,7 +165,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
if value.len() != 1 { if value.len() != 1 {
return Err(StatementError::array_assign_interior_index(span.clone())); return Err(StatementError::array_assign_interior_index(span.clone()));
} }
match Self::unwrap_mutable(value.remove(0)) { match value.remove(0) {
ConstrainedValue::CircuitExpression(_variable, members) => { ConstrainedValue::CircuitExpression(_variable, members) => {
// Modify the circuit variable in place // Modify the circuit variable in place
let matched_variable = members.iter_mut().find(|member| member.0 == name); let matched_variable = members.iter_mut().find(|member| member.0 == name);

View File

@ -30,7 +30,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
cs: &mut CS, cs: &mut CS,
statement: &ReturnStatement, statement: &ReturnStatement,
) -> Result<ConstrainedValue<F, G>, StatementError> { ) -> Result<ConstrainedValue<F, G>, StatementError> {
let result = self.enforce_operand(cs, &statement.expression)?; let result = self.enforce_expression(cs, &statement.expression)?;
Ok(result) Ok(result)
} }
} }

View File

@ -49,9 +49,6 @@ pub enum ConstrainedValue<F: Field + PrimeField, G: GroupType<F>> {
// Circuits // Circuits
CircuitExpression(Arc<CircuitBody>, Vec<ConstrainedCircuitMember<F, G>>), CircuitExpression(Arc<CircuitBody>, Vec<ConstrainedCircuitMember<F, G>>),
// Modifiers
Mutable(Box<ConstrainedValue<F, G>>),
} }
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> { impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
@ -81,22 +78,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
Type::Tuple(types) Type::Tuple(types)
} }
ConstrainedValue::CircuitExpression(id, _members) => Type::Circuit(id.circuit.clone()), ConstrainedValue::CircuitExpression(id, _members) => Type::Circuit(id.circuit.clone()),
ConstrainedValue::Mutable(value) => return value.to_type(span),
}) })
} }
///
/// Modifies the `self` [ConstrainedValue] so there are no `mut` keywords wrapping the `self` value.
///
pub(crate) fn get_inner_mut(&mut self) {
if let ConstrainedValue::Mutable(inner) = self {
// Recursively remove `mut` keywords.
inner.get_inner_mut();
// Modify the value.
*self = *inner.clone()
}
}
} }
impl<F: Field + PrimeField, G: GroupType<F>> fmt::Display for ConstrainedValue<F, G> { impl<F: Field + PrimeField, G: GroupType<F>> fmt::Display for ConstrainedValue<F, G> {
@ -142,7 +125,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> fmt::Display for ConstrainedValue<F
} }
write!(f, "}}") write!(f, "}}")
} }
ConstrainedValue::Mutable(ref value) => write!(f, "{}", value),
} }
} }
} }
@ -265,8 +247,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> CondSelectGadget<F> for Constrained
ConstrainedValue::CircuitExpression(identifier.clone(), members) ConstrainedValue::CircuitExpression(identifier.clone(), members)
} }
(ConstrainedValue::Mutable(first), _) => Self::conditionally_select(cs, cond, first, second)?,
(_, ConstrainedValue::Mutable(second)) => Self::conditionally_select(cs, cond, first, second)?,
(_, _) => return Err(SynthesisError::Unsatisfiable), (_, _) => return Err(SynthesisError::Unsatisfiable),
}) })
} }

View File

@ -0,0 +1,6 @@
function main () {
let mut x = true;
if x {
let y = 0u8;
}
}

View File

@ -101,6 +101,14 @@ fn test_not_mutable() {
assert_satisfied(program); assert_satisfied(program);
} }
#[test]
fn test_conditional_mut() {
let program_string = include_str!("conditional_mut.leo");
let program = parse_program(program_string).unwrap();
assert_satisfied(program);
}
#[test] #[test]
fn test_not_u32() { fn test_not_u32() {
let program_string = include_str!("not_u32.leo"); let program_string = include_str!("not_u32.leo");

View File

@ -0,0 +1,7 @@
function main(x: u8) -> u8 {
if x == 2u8 {
return 3u8
} else {
return 4u8
}
}

View File

@ -0,0 +1,5 @@
[main]
x: u8 = 1u8;
[registers]
x: u8 = 0;

View File

@ -16,6 +16,19 @@
use crate::{assert_satisfied, expect_asg_error, get_output, parse_program, parse_program_with_input}; use crate::{assert_satisfied, expect_asg_error, get_output, parse_program, parse_program_with_input};
#[test]
fn test_conditional_return() {
let input_string = include_str!("input/conditional_return.in");
let program_string = include_str!("conditional_return.leo");
let program = parse_program_with_input(program_string, input_string).unwrap();
let expected_string = include_str!("output/conditional_return.out");
let actual_bytes = get_output(program);
let actual_string = std::str::from_utf8(actual_bytes.bytes().as_slice()).unwrap();
assert_eq!(expected_string, actual_string);
}
#[test] #[test]
fn test_empty() { fn test_empty() {
let program_string = include_str!("empty.leo"); let program_string = include_str!("empty.leo");

View File

@ -0,0 +1,2 @@
[registers]
x: u8 = 4;

View File

@ -1,6 +1,6 @@
[package] [package]
name = "leo-gadgets" name = "leo-gadgets"
version = "1.0.8" version = "1.2.0"
authors = [ "The Aleo Team <hello@aleo.org>" ] authors = [ "The Aleo Team <hello@aleo.org>" ]
description = "Gadgets of the Leo programming language" description = "Gadgets of the Leo programming language"
homepage = "https://aleo.org" homepage = "https://aleo.org"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "leo-grammar" name = "leo-grammar"
version = "1.0.8" version = "1.2.0"
authors = [ "The Aleo Team <hello@aleo.org>" ] authors = [ "The Aleo Team <hello@aleo.org>" ]
description = "AST generated by pest from the Leo grammar rules" description = "AST generated by pest from the Leo grammar rules"
homepage = "https://aleo.org" homepage = "https://aleo.org"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "leo-imports" name = "leo-imports"
version = "1.0.8" version = "1.2.0"
authors = [ "The Aleo Team <hello@aleo.org>" ] authors = [ "The Aleo Team <hello@aleo.org>" ]
description = "Import parser for Leo program package dependencies" description = "Import parser for Leo program package dependencies"
homepage = "https://aleo.org" homepage = "https://aleo.org"
@ -19,15 +19,15 @@ edition = "2018"
[dependencies.leo-ast] [dependencies.leo-ast]
path = "../ast" path = "../ast"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-grammar] [dependencies.leo-grammar]
path = "../grammar" path = "../grammar"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-asg] [dependencies.leo-asg]
path = "../asg" path = "../asg"
version = "1.0.7" version = "1.2.0"
[dependencies.indexmap] [dependencies.indexmap]
version = "1.6.1" version = "1.6.1"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "leo-input" name = "leo-input"
version = "1.0.8" version = "1.2.0"
authors = [ "The Aleo Team <hello@aleo.org>" ] authors = [ "The Aleo Team <hello@aleo.org>" ]
description = "Input parser of the Leo programming language" description = "Input parser of the Leo programming language"
homepage = "https://aleo.org" homepage = "https://aleo.org"

View File

@ -29,24 +29,24 @@ use std::{convert::TryFrom, env::current_dir, time::Instant};
pub struct ProveCommand; pub struct ProveCommand;
impl CLI for ProveCommand { impl CLI for ProveCommand {
type Options = (); type Options = bool;
type Output = (Proof<Bls12_377>, PreparedVerifyingKey<Bls12_377>); type Output = (Proof<Bls12_377>, PreparedVerifyingKey<Bls12_377>);
const ABOUT: AboutType = "Run the program and produce a proof"; const ABOUT: AboutType = "Run the program and produce a proof";
const ARGUMENTS: &'static [ArgumentType] = &[]; const ARGUMENTS: &'static [ArgumentType] = &[];
const FLAGS: &'static [FlagType] = &[]; const FLAGS: &'static [FlagType] = &[("--skip-key-check")];
const NAME: NameType = "prove"; const NAME: NameType = "prove";
const OPTIONS: &'static [OptionType] = &[]; const OPTIONS: &'static [OptionType] = &[];
const SUBCOMMANDS: &'static [SubCommandType] = &[]; const SUBCOMMANDS: &'static [SubCommandType] = &[];
#[cfg_attr(tarpaulin, skip)] #[cfg_attr(tarpaulin, skip)]
fn parse(_arguments: &ArgMatches) -> Result<Self::Options, CLIError> { fn parse(arguments: &ArgMatches) -> Result<Self::Options, CLIError> {
Ok(()) Ok(!arguments.is_present("skip-key-check"))
} }
#[cfg_attr(tarpaulin, skip)] #[cfg_attr(tarpaulin, skip)]
fn output(options: Self::Options) -> Result<Self::Output, CLIError> { fn output(do_setup_check: Self::Options) -> Result<Self::Output, CLIError> {
let (program, parameters, prepared_verifying_key) = SetupCommand::output(options)?; let (program, parameters, prepared_verifying_key) = SetupCommand::output(do_setup_check)?;
// Begin "Proving" context for console logging // Begin "Proving" context for console logging
let span = tracing::span!(tracing::Level::INFO, "Proving"); let span = tracing::span!(tracing::Level::INFO, "Proving");

View File

@ -28,24 +28,24 @@ use std::time::Instant;
pub struct RunCommand; pub struct RunCommand;
impl CLI for RunCommand { impl CLI for RunCommand {
type Options = (); type Options = bool;
type Output = (); type Output = ();
const ABOUT: AboutType = "Run a program with input variables"; const ABOUT: AboutType = "Run a program with input variables";
const ARGUMENTS: &'static [ArgumentType] = &[]; const ARGUMENTS: &'static [ArgumentType] = &[];
const FLAGS: &'static [FlagType] = &[]; const FLAGS: &'static [FlagType] = &[("--skip-key-check")];
const NAME: NameType = "run"; const NAME: NameType = "run";
const OPTIONS: &'static [OptionType] = &[]; const OPTIONS: &'static [OptionType] = &[];
const SUBCOMMANDS: &'static [SubCommandType] = &[]; const SUBCOMMANDS: &'static [SubCommandType] = &[];
#[cfg_attr(tarpaulin, skip)] #[cfg_attr(tarpaulin, skip)]
fn parse(_arguments: &ArgMatches) -> Result<Self::Options, CLIError> { fn parse(arguments: &ArgMatches) -> Result<Self::Options, CLIError> {
Ok(()) Ok(!arguments.is_present("skip-key-check"))
} }
#[cfg_attr(tarpaulin, skip)] #[cfg_attr(tarpaulin, skip)]
fn output(options: Self::Options) -> Result<(), CLIError> { fn output(do_setup_check: Self::Options) -> Result<(), CLIError> {
let (proof, prepared_verifying_key) = ProveCommand::output(options)?; let (proof, prepared_verifying_key) = ProveCommand::output(do_setup_check)?;
// Begin "Verifying" context for console logging // Begin "Verifying" context for console logging
let span = tracing::span!(tracing::Level::INFO, "Verifying"); let span = tracing::span!(tracing::Level::INFO, "Verifying");

View File

@ -39,7 +39,7 @@ use std::{convert::TryFrom, env::current_dir, time::Instant};
pub struct SetupCommand; pub struct SetupCommand;
impl CLI for SetupCommand { impl CLI for SetupCommand {
type Options = (); type Options = bool;
type Output = ( type Output = (
Compiler<Fr, EdwardsGroupType>, Compiler<Fr, EdwardsGroupType>,
Parameters<Bls12_377>, Parameters<Bls12_377>,
@ -48,23 +48,23 @@ impl CLI for SetupCommand {
const ABOUT: AboutType = "Run a program setup"; const ABOUT: AboutType = "Run a program setup";
const ARGUMENTS: &'static [ArgumentType] = &[]; const ARGUMENTS: &'static [ArgumentType] = &[];
const FLAGS: &'static [FlagType] = &[]; const FLAGS: &'static [FlagType] = &[("--skip-key-check")];
const NAME: NameType = "setup"; const NAME: NameType = "setup";
const OPTIONS: &'static [OptionType] = &[]; const OPTIONS: &'static [OptionType] = &[];
const SUBCOMMANDS: &'static [SubCommandType] = &[]; const SUBCOMMANDS: &'static [SubCommandType] = &[];
#[cfg_attr(tarpaulin, skip)] #[cfg_attr(tarpaulin, skip)]
fn parse(_arguments: &ArgMatches) -> Result<Self::Options, CLIError> { fn parse(arguments: &ArgMatches) -> Result<Self::Options, CLIError> {
Ok(()) Ok(!arguments.is_present("skip-key-check"))
} }
#[cfg_attr(tarpaulin, skip)] #[cfg_attr(tarpaulin, skip)]
fn output(options: Self::Options) -> Result<Self::Output, CLIError> { fn output(do_check: Self::Options) -> Result<Self::Output, CLIError> {
// Get the package name // Get the package name
let path = current_dir()?; let path = current_dir()?;
let package_name = Manifest::try_from(path.as_path())?.get_package_name(); let package_name = Manifest::try_from(path.as_path())?.get_package_name();
match BuildCommand::output(options)? { match BuildCommand::output(())? {
Some((program, checksum_differs)) => { Some((program, checksum_differs)) => {
// Begin "Setup" context for console logging // Begin "Setup" context for console logging
let span = tracing::span!(tracing::Level::INFO, "Setup"); let span = tracing::span!(tracing::Level::INFO, "Setup");
@ -116,8 +116,11 @@ impl CLI for SetupCommand {
// Read the proving key file from the output directory // Read the proving key file from the output directory
tracing::info!("Loading proving key..."); tracing::info!("Loading proving key...");
if !do_check {
tracing::info!("Skipping curve check");
}
let proving_key_bytes = ProvingKeyFile::new(&package_name).read_from(&path)?; let proving_key_bytes = ProvingKeyFile::new(&package_name).read_from(&path)?;
let proving_key = Parameters::<Bls12_377>::read(proving_key_bytes.as_slice(), true)?; let proving_key = Parameters::<Bls12_377>::read(proving_key_bytes.as_slice(), do_check)?;
tracing::info!("Complete"); tracing::info!("Complete");
// Read the verification key file from the output directory // Read the verification key file from the output directory

View File

@ -2,7 +2,7 @@ dependencies = { }
[package] [package]
name = "leo-linter" name = "leo-linter"
version = "1.0.8" version = "1.2.0"
authors = [ "The Aleo Team <hello@aleo.org>" ] authors = [ "The Aleo Team <hello@aleo.org>" ]
description = "Linter of the Leo programming language" description = "Linter of the Leo programming language"
homepage = "https://aleo.org" homepage = "https://aleo.org"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "leo-package" name = "leo-package"
version = "1.0.8" version = "1.2.0"
authors = [ "The Aleo Team <hello@aleo.org>" ] authors = [ "The Aleo Team <hello@aleo.org>" ]
description = "Package parser of the Leo programming language" description = "Package parser of the Leo programming language"
homepage = "https://aleo.org" homepage = "https://aleo.org"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "leo-state" name = "leo-state"
version = "1.0.8" version = "1.2.0"
authors = [ "The Aleo Team <hello@aleo.org>" ] authors = [ "The Aleo Team <hello@aleo.org>" ]
description = "State parser of the Leo programming language" description = "State parser of the Leo programming language"
homepage = "https://aleo.org" homepage = "https://aleo.org"
@ -19,11 +19,11 @@ edition = "2018"
[dependencies.leo-input] [dependencies.leo-input]
path = "../input" path = "../input"
version = "1.0.8" version = "1.2.0"
[dependencies.leo-ast] [dependencies.leo-ast]
path = "../ast" path = "../ast"
version = "1.0.8" version = "1.2.0"
[dependencies.snarkvm-algorithms] [dependencies.snarkvm-algorithms]
version = "0.0.2" version = "0.0.2"