refactor leo core modules

This commit is contained in:
collin 2020-09-15 22:30:11 -07:00
parent 97f24ae1f1
commit 20fbf96784
11 changed files with 317 additions and 200 deletions

18
core/src/circuits/mod.rs Normal file
View File

@ -0,0 +1,18 @@
// Copyright (C) 2019-2020 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/>.
pub mod unstable;
pub use self::unstable::*;

View File

View File

@ -14,199 +14,29 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
pub mod core_circuit; pub mod circuits;
pub use self::core_circuit::*; pub use self::circuits::*;
pub mod errors; pub mod errors;
pub use self::errors::*; pub use self::errors::*;
pub mod unstable; pub mod types;
pub use self::unstable::*; pub use self::types::*;
use crate::{unstable::blake2s::Blake2sFunction, CoreCircuit};
use leo_gadgets::signed_integer::*;
use leo_typed::{Circuit, Identifier, ImportSymbol, Package, PackageAccess, Span};
use crate::CoreCircuit;
use leo_typed::Span;
use snarkos_models::{ use snarkos_models::{
curves::{Field, PrimeField}, curves::{Field, PrimeField},
gadgets::{ gadgets::r1cs::ConstraintSystem,
r1cs::ConstraintSystem,
utilities::{
boolean::Boolean,
uint::{UInt128, UInt16, UInt32, UInt64, UInt8},
},
},
}; };
static UNSTABLE_CORE_PACKAGE_KEYWORD: &str = "unstable";
/// A core package dependency to be imported into a Leo program
#[derive(Debug, Clone)]
pub struct CorePackage {
name: Identifier,
unstable: bool,
symbols: Vec<ImportSymbol>,
}
impl CorePackage {
pub(crate) fn new(name: Identifier) -> Self {
Self {
name,
unstable: false,
symbols: vec![],
}
}
// Set the `unstable` flag to true if we are importing an unstable core package
pub(crate) fn set_unstable(&mut self) {
self.unstable = true;
}
// Recursively set all symbols we are importing from a core package
pub(crate) fn set_symbols(&mut self, access: PackageAccess) {
match access {
PackageAccess::SubPackage(package) => {
self.set_symbols(package.access);
}
PackageAccess::Star(_) => unimplemented!("cannot import star from core package"),
PackageAccess::Multiple(accesses) => {
for access in accesses {
self.set_symbols(access);
}
}
PackageAccess::Symbol(symbol) => self.symbols.push(symbol),
}
}
// Resolve import symbols into core circuits and store them in the program context
pub(crate) fn append_symbols(&self, symbols: &mut CoreSymbolList) {
for symbol in &self.symbols {
let symbol_name = symbol.symbol.name.as_str();
let span = symbol.span.clone();
// take the alias if it is present
let id = symbol.alias.clone().unwrap_or(symbol.symbol.clone());
let name = id.name.clone();
let circuit = if self.unstable {
// match unstable core circuit
match symbol_name {
CORE_UNSTABLE_BLAKE2S_NAME => Blake2sFunction::ast(symbol.symbol.clone(), span),
_ => unimplemented!("unstable core circuit `{}` not implemented", symbol_name),
}
} else {
// match core circuit
match symbol_name {
_ => unimplemented!("core circuit `{}` not implemented", symbol_name),
}
};
symbols.push(name, circuit)
}
}
}
impl From<Package> for CorePackage {
fn from(package: Package) -> Self {
// Create new core package
let mut core_package = Self::new(package.name);
// Fetch all circuit symbols imported from core package
core_package.set_symbols(package.access);
core_package
}
}
/// A list of core package dependencies
#[derive(Debug)]
pub struct CorePackageList {
packages: Vec<CorePackage>,
}
impl CorePackageList {
pub(crate) fn new() -> Self {
Self { packages: vec![] }
}
pub(crate) fn push(&mut self, package: CorePackage) {
self.packages.push(package);
}
// Return a list of all symbols that need to be stored in the current function
pub fn to_symbols(&self) -> CoreSymbolList {
let mut symbols = CoreSymbolList::new();
for package in &self.packages {
package.append_symbols(&mut symbols);
}
symbols
}
// Parse all dependencies after `core.`
pub fn from_package_access(access: PackageAccess) -> Self {
let mut new = Self::new();
package_access_helper(&mut new, access, false);
new
}
}
fn package_access_helper(list: &mut CorePackageList, access: PackageAccess, is_unstable: bool) {
match access {
PackageAccess::Symbol(_symbol) => unimplemented!("cannot import a symbol directly from Leo core"),
PackageAccess::Multiple(core_functions) => {
for access in core_functions {
package_access_helper(list, access, is_unstable);
}
}
PackageAccess::SubPackage(package) => {
// Set the `unstable` flag to true if we are importing an unstable core package
if package.name.name.eq(UNSTABLE_CORE_PACKAGE_KEYWORD) {
package_access_helper(list, package.access, true);
} else {
let mut core_package = CorePackage::from(*package);
if is_unstable {
core_package.set_unstable()
}
list.push(core_package);
}
}
PackageAccess::Star(_) => unimplemented!("cannot import star from Leo core"),
}
}
/// List of imported core function circuits
pub struct CoreSymbolList {
/// [(circuit_name, circuit_struct)]
symbols: Vec<(String, Circuit)>,
}
impl CoreSymbolList {
pub(crate) fn new() -> Self {
Self { symbols: vec![] }
}
pub(crate) fn push(&mut self, name: String, circuit: Circuit) {
self.symbols.push((name, circuit))
}
pub fn symbols(&self) -> Vec<(String, Circuit)> {
self.symbols.clone()
}
}
/// Calls a core function by it's given name. /// Calls a core function by it's given name.
/// This function should be called by the compiler when enforcing the result of calling a core circuit function. /// This function should be called by the compiler when enforcing the result of calling a core circuit function.
pub fn call_core_function<F: Field + PrimeField, CS: ConstraintSystem<F>>( pub fn call_core_function<F: Field + PrimeField, CS: ConstraintSystem<F>>(
cs: CS, cs: CS,
function_name: String, function_name: String,
arguments: Vec<Value>, arguments: Vec<Value>,
span: Span, // todo: return errors using `leo-typed` span span: Span, // TODO(collinc97): return errors using `leo-typed` span
) -> Vec<Value> { ) -> Vec<Value> {
// Match core function name // Match core function name
match function_name.as_str() { match function_name.as_str() {
@ -214,25 +44,3 @@ pub fn call_core_function<F: Field + PrimeField, CS: ConstraintSystem<F>>(
_ => unimplemented!("core function {} unimplemented", function_name), _ => unimplemented!("core function {} unimplemented", function_name),
} }
} }
/// An intermediate value format that can be converted into a `ConstrainedValue` for the compiler
/// Todo: implement other constrained values
#[derive(Clone)]
pub enum Value {
Boolean(Boolean),
U8(UInt8),
U16(UInt16),
U32(UInt32),
U64(UInt64),
U128(UInt128),
I8(Int8),
I16(Int16),
I32(Int32),
I64(Int64),
I128(Int128),
Array(Vec<Value>),
Tuple(Vec<Value>),
}

View File

@ -0,0 +1,100 @@
// Copyright (C) 2019-2020 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/>.
use crate::{
unstable::blake2s::{Blake2sFunction, CORE_UNSTABLE_BLAKE2S_NAME},
CoreCircuit,
CoreSymbolList,
};
use leo_typed::{Identifier, ImportSymbol, Package, PackageAccess};
/// A core package dependency to be imported into a Leo program
#[derive(Debug, Clone)]
pub struct CorePackage {
name: Identifier,
unstable: bool,
symbols: Vec<ImportSymbol>,
}
impl CorePackage {
pub(crate) fn new(name: Identifier) -> Self {
Self {
name,
unstable: false,
symbols: vec![],
}
}
// Set the `unstable` flag to true if we are importing an unstable core package
pub(crate) fn set_unstable(&mut self) {
self.unstable = true;
}
// Recursively set all symbols we are importing from a core package
pub(crate) fn set_symbols(&mut self, access: PackageAccess) {
match access {
PackageAccess::SubPackage(package) => {
self.set_symbols(package.access);
}
PackageAccess::Star(_) => unimplemented!("cannot import star from core package"),
PackageAccess::Multiple(accesses) => {
for access in accesses {
self.set_symbols(access);
}
}
PackageAccess::Symbol(symbol) => self.symbols.push(symbol),
}
}
// Resolve import symbols into core circuits and store them in the program context
pub(crate) fn append_symbols(&self, symbols: &mut CoreSymbolList) {
for symbol in &self.symbols {
let symbol_name = symbol.symbol.name.as_str();
let span = symbol.span.clone();
// take the alias if it is present
let id = symbol.alias.clone().unwrap_or(symbol.symbol.clone());
let name = id.name.clone();
let circuit = if self.unstable {
// match unstable core circuit
match symbol_name {
CORE_UNSTABLE_BLAKE2S_NAME => Blake2sFunction::ast(symbol.symbol.clone(), span),
_ => unimplemented!("unstable core circuit `{}` not implemented", symbol_name),
}
} else {
// match core circuit
match symbol_name {
_ => unimplemented!("core circuit `{}` not implemented", symbol_name),
}
};
symbols.push(name, circuit)
}
}
}
impl From<Package> for CorePackage {
fn from(package: Package) -> Self {
// Create new core package
let mut core_package = Self::new(package.name);
// Fetch all circuit symbols imported from core package
core_package.set_symbols(package.access);
core_package
}
}

View File

@ -0,0 +1,81 @@
// Copyright (C) 2019-2020 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/>.
use crate::{CorePackage, CoreSymbolList, UNSTABLE_CORE_PACKAGE_KEYWORD};
use leo_typed::PackageAccess;
/// A list of core package dependencies.
/// This struct is created when the compiler parses a core import statement.
#[derive(Debug)]
pub struct CorePackageList {
packages: Vec<CorePackage>,
}
impl CorePackageList {
pub(crate) fn new() -> Self {
Self { packages: vec![] }
}
pub(crate) fn push(&mut self, package: CorePackage) {
self.packages.push(package);
}
// Parse all dependencies after `core.`
pub fn from_package_access(access: PackageAccess) -> Self {
let mut new = Self::new();
package_access_helper(&mut new, access, false);
new
}
// Return a list of all symbols that need to be stored in the current function
pub fn to_symbols(&self) -> CoreSymbolList {
let mut symbols = CoreSymbolList::new();
for package in &self.packages {
package.append_symbols(&mut symbols);
}
symbols
}
}
fn package_access_helper(list: &mut CorePackageList, access: PackageAccess, is_unstable: bool) {
match access {
PackageAccess::Symbol(_symbol) => unimplemented!("cannot import a symbol directly from Leo core"),
PackageAccess::Multiple(core_functions) => {
for access in core_functions {
package_access_helper(list, access, is_unstable);
}
}
PackageAccess::SubPackage(package) => {
// Set the `unstable` flag to true if we are importing an unstable core package
if package.name.name.eq(UNSTABLE_CORE_PACKAGE_KEYWORD) {
package_access_helper(list, package.access, true);
} else {
let mut core_package = CorePackage::from(*package);
if is_unstable {
core_package.set_unstable()
}
list.push(core_package);
}
}
PackageAccess::Star(_) => unimplemented!("cannot import star from Leo core"),
}
}

View File

@ -0,0 +1,38 @@
// Copyright (C) 2019-2020 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/>.
use leo_typed::Circuit;
/// List of imported core function circuits.
/// This struct is created from a `CorePackageList`
pub struct CoreSymbolList {
/// [(circuit_name, circuit_struct)]
symbols: Vec<(String, Circuit)>,
}
impl CoreSymbolList {
pub(crate) fn new() -> Self {
Self { symbols: vec![] }
}
pub(crate) fn push(&mut self, name: String, circuit: Circuit) {
self.symbols.push((name, circuit))
}
pub fn symbols(&self) -> Vec<(String, Circuit)> {
self.symbols.clone()
}
}

32
core/src/types/mod.rs Normal file
View File

@ -0,0 +1,32 @@
// Copyright (C) 2019-2020 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/>.
pub mod core_circuit;
pub use self::core_circuit::*;
pub mod core_package;
pub use self::core_package::*;
pub mod core_package_list;
pub use self::core_package_list::*;
pub mod core_symbol_list;
pub use self::core_symbol_list::*;
pub mod value;
pub use self::value::*;
pub static UNSTABLE_CORE_PACKAGE_KEYWORD: &str = "unstable";

40
core/src/types/value.rs Normal file
View File

@ -0,0 +1,40 @@
// Copyright (C) 2019-2020 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/>.
use leo_gadgets::signed_integer::*;
use snarkos_models::gadgets::utilities::{boolean::Boolean, uint::*};
/// An intermediate value format that can be converted into a `ConstrainedValue` for the compiler
/// TODO(collinc97): implement other constrained values
#[derive(Clone)]
pub enum Value {
Boolean(Boolean),
U8(UInt8),
U16(UInt16),
U32(UInt32),
U64(UInt64),
U128(UInt128),
I8(Int8),
I16(Int16),
I32(Int32),
I64(Int64),
I128(Int128),
Array(Vec<Value>),
Tuple(Vec<Value>),
}