From 26810a15ae2c27c5cfd0b45084ff3c6ca141aacf Mon Sep 17 00:00:00 2001 From: collin <16715212+collinc97@users.noreply.github.com> Date: Fri, 17 Jun 2022 15:37:48 -0700 Subject: [PATCH] impl bhp, pedersen, poseidon instructions --- compiler/core/src/algorithms/bhp.rs | 116 ++++++++++++ compiler/core/src/algorithms/mod.rs | 170 ++++++++++++++++-- compiler/core/src/algorithms/pedersen.rs | 84 +++++++++ compiler/core/src/algorithms/poseidon.rs | 114 ++++++++++++ compiler/parser/src/tokenizer/lexer.rs | 2 +- .../src/type_checker/check_expressions.rs | 5 +- examples/hello-world/src/main.leo | 10 +- 7 files changed, 478 insertions(+), 23 deletions(-) create mode 100644 compiler/core/src/algorithms/pedersen.rs create mode 100644 compiler/core/src/algorithms/poseidon.rs diff --git a/compiler/core/src/algorithms/bhp.rs b/compiler/core/src/algorithms/bhp.rs index 732012e3d1..0c40466129 100644 --- a/compiler/core/src/algorithms/bhp.rs +++ b/compiler/core/src/algorithms/bhp.rs @@ -30,3 +30,119 @@ impl CoreFunction for BHP256Hash { Type::Field } } + +pub struct BHP256Commit; + +impl CoreFunction for BHP256Commit { + const NUM_ARGS: usize = 2; + + fn first_arg_types() -> &'static [Type] { + &ALL_TYPES + } + + fn second_arg_types() -> &'static [Type] { + &[Type::Scalar] + } + + fn return_type() -> Type { + Type::Field + } +} + +pub struct BHP512Hash; + +impl CoreFunction for BHP512Hash { + const NUM_ARGS: usize = 1; + + fn first_arg_types() -> &'static [Type] { + &ALL_TYPES + } + + fn return_type() -> Type { + Type::Field + } +} + +pub struct BHP512Commit; + +impl CoreFunction for BHP512Commit { + const NUM_ARGS: usize = 2; + + fn first_arg_types() -> &'static [Type] { + &ALL_TYPES + } + + fn second_arg_types() -> &'static [Type] { + &[Type::Scalar] + } + + fn return_type() -> Type { + Type::Field + } +} + + +pub struct BHP768Hash; + +impl CoreFunction for BHP768Hash { + const NUM_ARGS: usize = 1; + + fn first_arg_types() -> &'static [Type] { + &ALL_TYPES + } + + fn return_type() -> Type { + Type::Field + } +} + +pub struct BHP768Commit; + +impl CoreFunction for BHP768Commit { + const NUM_ARGS: usize = 2; + + fn first_arg_types() -> &'static [Type] { + &ALL_TYPES + } + + fn second_arg_types() -> &'static [Type] { + &[Type::Scalar] + } + + fn return_type() -> Type { + Type::Field + } +} + + +pub struct BHP1024Hash; + +impl CoreFunction for BHP1024Hash { + const NUM_ARGS: usize = 1; + + fn first_arg_types() -> &'static [Type] { + &ALL_TYPES + } + + fn return_type() -> Type { + Type::Field + } +} + +pub struct BHP1024Commit; + +impl CoreFunction for BHP1024Commit { + const NUM_ARGS: usize = 2; + + fn first_arg_types() -> &'static [Type] { + &ALL_TYPES + } + + fn second_arg_types() -> &'static [Type] { + &[Type::Scalar] + } + + fn return_type() -> Type { + Type::Field + } +} diff --git a/compiler/core/src/algorithms/mod.rs b/compiler/core/src/algorithms/mod.rs index ee754433f2..912f56e5d4 100644 --- a/compiler/core/src/algorithms/mod.rs +++ b/compiler/core/src/algorithms/mod.rs @@ -16,59 +16,188 @@ mod bhp; pub use bhp::*; +mod pedersen; +pub use pedersen::*; + +mod poseidon; +pub use poseidon::*; + use crate::Types; use leo_span::{sym, Symbol}; +use leo_ast::{IntegerType, Type}; use indexmap::IndexSet; -use leo_ast::{IntegerType, Type}; + +/// Returns `true` if the given symbol matches the name of a core circuit. +pub fn is_core_circuit(circuit: Symbol) -> bool { + match circuit { + sym::bhp256 + | sym::bhp512 + | sym::bhp768 + | sym::bhp1024 + | sym::ped64 + | sym::ped128 + | sym::psd2 + | sym::psd4 + | sym::psd8 => true, + _ => false, + } +} /// A core instruction that maps directly to an AVM bytecode instruction. #[derive(Clone, PartialEq, Eq)] pub enum CoreInstruction { + BHP256Commit, BHP256Hash, - BHP512, - BHP768, - BHP1024, - Pedersen64, - Pedersen128, - Poseidon2, - Poseidon4, - Poseidon8, + BHP512Commit, + BHP512Hash, + BHP768Commit, + BHP768Hash, + BHP1024Commit, + BHP1024Hash, + + Pedersen64Commit, + Pedersen64Hash, + Pedersen128Commit, + Pedersen128Hash, + + Poseidon2Hash, + Poseidon2PRF, + Poseidon4Hash, + Poseidon4PRF, + Poseidon8Hash, + Poseidon8PRF, } impl CoreInstruction { /// Returns a `CoreInstruction` from the given circuit and method symbols. pub fn from_symbols(circuit: Symbol, function: Symbol) -> Option { Some(match (circuit, function) { + (sym::bhp256, sym::commit) => Self::BHP256Commit, (sym::bhp256, sym::hash) => Self::BHP256Hash, + (sym::bhp512, sym::commit) => Self::BHP512Commit, + (sym::bhp512, sym::hash) => Self::BHP512Hash, + (sym::bhp768, sym::commit) => Self::BHP768Commit, + (sym::bhp768, sym::hash) => Self::BHP768Hash, + (sym::bhp1024, sym::commit) => Self::BHP1024Commit, + (sym::bhp1024, sym::hash) => Self::BHP1024Hash, + + (sym::ped64, sym::commit) => Self::Pedersen64Commit, + (sym::ped64, sym::hash) => Self::Pedersen64Hash, + (sym::ped128, sym::commit) => Self::Pedersen128Commit, + (sym::ped128, sym::hash) => Self::Pedersen128Hash, + + (sym::psd2, sym::hash) => Self::Poseidon2Hash, + (sym::psd2, sym::prf) => Self::Poseidon2PRF, + (sym::psd4, sym::hash) => Self::Poseidon4Hash, + (sym::psd4, sym::prf) => Self::Poseidon4PRF, + (sym::psd8, sym::hash) => Self::Poseidon8Hash, + (sym::psd8, sym::prf) => Self::Poseidon8PRF, _ => return None, }) } + /// Returns the number of arguments required by the instruction. pub fn num_args(&self) -> usize { match self { + CoreInstruction::BHP256Commit => BHP256Commit::NUM_ARGS, CoreInstruction::BHP256Hash => BHP256Hash::NUM_ARGS, - _ => unimplemented!(), + CoreInstruction::BHP512Commit => BHP512Commit::NUM_ARGS, + CoreInstruction::BHP512Hash => BHP512Hash::NUM_ARGS, + CoreInstruction::BHP768Commit => BHP768Commit::NUM_ARGS, + CoreInstruction::BHP768Hash => BHP768Hash::NUM_ARGS, + CoreInstruction::BHP1024Commit => BHP1024Commit::NUM_ARGS, + CoreInstruction::BHP1024Hash => BHP1024Hash::NUM_ARGS, + + CoreInstruction::Pedersen64Commit => Pedersen64Commit::NUM_ARGS, + CoreInstruction::Pedersen64Hash => Pedersen64Hash::NUM_ARGS, + CoreInstruction::Pedersen128Commit => Pedersen128Commit::NUM_ARGS, + CoreInstruction::Pedersen128Hash => Pedersen128Hash::NUM_ARGS, + + CoreInstruction::Poseidon2Hash => Poseidon2Hash::NUM_ARGS, + CoreInstruction::Poseidon2PRF => Poseidon2PRF::NUM_ARGS, + CoreInstruction::Poseidon4Hash => Poseidon4Hash::NUM_ARGS, + CoreInstruction::Poseidon4PRF => Poseidon4PRF::NUM_ARGS, + CoreInstruction::Poseidon8Hash => Poseidon8Hash::NUM_ARGS, + CoreInstruction::Poseidon8PRF => Poseidon8PRF::NUM_ARGS, } } + /// The allowed types for the first argument of the instruction. pub fn first_arg_types(&self) -> &'static [Type] { match self { + CoreInstruction::BHP256Commit => BHP256Commit::first_arg_types(), CoreInstruction::BHP256Hash => BHP256Hash::first_arg_types(), - _ => unimplemented!(), + CoreInstruction::BHP512Commit => BHP512Commit::first_arg_types(), + CoreInstruction::BHP512Hash => BHP512Hash::first_arg_types(), + CoreInstruction::BHP768Commit => BHP768Commit::first_arg_types(), + CoreInstruction::BHP768Hash => BHP768Hash::first_arg_types(), + CoreInstruction::BHP1024Commit => BHP1024Commit::first_arg_types(), + CoreInstruction::BHP1024Hash => BHP1024Hash::first_arg_types(), + + CoreInstruction::Pedersen64Commit => Pedersen64Commit::first_arg_types(), + CoreInstruction::Pedersen64Hash => Pedersen64Hash::first_arg_types(), + CoreInstruction::Pedersen128Commit => Pedersen128Commit::first_arg_types(), + CoreInstruction::Pedersen128Hash => Pedersen128Hash::first_arg_types(), + + CoreInstruction::Poseidon2Hash => Poseidon2Hash::first_arg_types(), + CoreInstruction::Poseidon2PRF => Poseidon2PRF::first_arg_types(), + CoreInstruction::Poseidon4Hash => Poseidon4Hash::first_arg_types(), + CoreInstruction::Poseidon4PRF => Poseidon4PRF::first_arg_types(), + CoreInstruction::Poseidon8Hash => Poseidon8Hash::first_arg_types(), + CoreInstruction::Poseidon8PRF => Poseidon8PRF::first_arg_types(), } } + /// The allowed types for the second argument of the instruction. pub fn second_arg_types(&self) -> &'static [Type] { match self { - _ => unimplemented!(), + CoreInstruction::BHP256Commit => BHP256Commit::second_arg_types(), + CoreInstruction::BHP256Hash => BHP256Hash::second_arg_types(), + CoreInstruction::BHP512Commit => BHP512Commit::second_arg_types(), + CoreInstruction::BHP512Hash => BHP512Hash::second_arg_types(), + CoreInstruction::BHP768Commit => BHP768Commit::second_arg_types(), + CoreInstruction::BHP768Hash => BHP768Hash::second_arg_types(), + CoreInstruction::BHP1024Commit => BHP1024Commit::second_arg_types(), + CoreInstruction::BHP1024Hash => BHP1024Hash::second_arg_types(), + + CoreInstruction::Pedersen64Commit => Pedersen64Commit::second_arg_types(), + CoreInstruction::Pedersen64Hash => Pedersen64Hash::second_arg_types(), + CoreInstruction::Pedersen128Commit => Pedersen128Commit::second_arg_types(), + CoreInstruction::Pedersen128Hash => Pedersen128Hash::second_arg_types(), + + CoreInstruction::Poseidon2Hash => Poseidon2Hash::second_arg_types(), + CoreInstruction::Poseidon2PRF => Poseidon2PRF::second_arg_types(), + CoreInstruction::Poseidon4Hash => Poseidon4Hash::second_arg_types(), + CoreInstruction::Poseidon4PRF => Poseidon4PRF::second_arg_types(), + CoreInstruction::Poseidon8Hash => Poseidon8Hash::second_arg_types(), + CoreInstruction::Poseidon8PRF => Poseidon8PRF::second_arg_types(), } } + /// The type of the instruction output. pub fn return_type(&self) -> Type { match self { + CoreInstruction::BHP256Commit => BHP256Commit::return_type(), CoreInstruction::BHP256Hash => BHP256Hash::return_type(), - _ => unimplemented!(), + CoreInstruction::BHP512Commit => BHP512Commit::return_type(), + CoreInstruction::BHP512Hash => BHP512Hash::return_type(), + CoreInstruction::BHP768Commit => BHP768Commit::return_type(), + CoreInstruction::BHP768Hash => BHP768Hash::return_type(), + CoreInstruction::BHP1024Commit => BHP1024Commit::return_type(), + CoreInstruction::BHP1024Hash => BHP1024Hash::return_type(), + + CoreInstruction::Pedersen64Commit => Pedersen64Commit::return_type(), + CoreInstruction::Pedersen64Hash => Pedersen64Hash::return_type(), + CoreInstruction::Pedersen128Commit => Pedersen128Commit::return_type(), + CoreInstruction::Pedersen128Hash => Pedersen128Hash::return_type(), + + CoreInstruction::Poseidon2Hash => Poseidon2Hash::return_type(), + CoreInstruction::Poseidon2PRF => Poseidon2PRF::return_type(), + CoreInstruction::Poseidon4Hash => Poseidon4Hash::return_type(), + CoreInstruction::Poseidon4PRF => Poseidon4PRF::return_type(), + CoreInstruction::Poseidon8Hash => Poseidon8Hash::return_type(), + CoreInstruction::Poseidon8PRF => Poseidon8PRF::return_type(), } } } @@ -110,6 +239,21 @@ const ALL_TYPES: [Type; 16] = [ Type::String, ]; +const BOOL_INT_STRING_TYPES: [Type; 12] = [ + Type::Boolean, + Type::IntegerType(IntegerType::I8), + Type::IntegerType(IntegerType::I16), + Type::IntegerType(IntegerType::I32), + Type::IntegerType(IntegerType::I64), + Type::IntegerType(IntegerType::I128), + Type::IntegerType(IntegerType::U8), + Type::IntegerType(IntegerType::U16), + Type::IntegerType(IntegerType::U32), + Type::IntegerType(IntegerType::U64), + Type::IntegerType(IntegerType::U128), + Type::String, +]; + // todo (collin): deprecate this code pub struct Algorithms; diff --git a/compiler/core/src/algorithms/pedersen.rs b/compiler/core/src/algorithms/pedersen.rs new file mode 100644 index 0000000000..105bb0c421 --- /dev/null +++ b/compiler/core/src/algorithms/pedersen.rs @@ -0,0 +1,84 @@ +// 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 . + +use crate::algorithms::{CoreFunction, BOOL_INT_STRING_TYPES}; +use leo_ast::Type; + +pub struct Pedersen64Hash; + +impl CoreFunction for Pedersen64Hash { + const NUM_ARGS: usize = 1; + + fn first_arg_types() -> &'static [Type] { + &BOOL_INT_STRING_TYPES + } + + fn return_type() -> Type { + Type::Group + } +} + +pub struct Pedersen64Commit; + +impl CoreFunction for Pedersen64Commit { + const NUM_ARGS: usize = 2; + + fn first_arg_types() -> &'static [Type] { + &BOOL_INT_STRING_TYPES + } + + fn second_arg_types() -> &'static [Type] { + &[Type::Scalar] + } + + fn return_type() -> Type { + Type::Group + } +} + + +pub struct Pedersen128Hash; + +impl CoreFunction for Pedersen128Hash { + const NUM_ARGS: usize = 1; + + fn first_arg_types() -> &'static [Type] { + &BOOL_INT_STRING_TYPES + } + + fn return_type() -> Type { + Type::Group + } +} + +pub struct Pedersen128Commit; + +impl CoreFunction for Pedersen128Commit { + const NUM_ARGS: usize = 2; + + fn first_arg_types() -> &'static [Type] { + &BOOL_INT_STRING_TYPES + } + + fn second_arg_types() -> &'static [Type] { + &[Type::Scalar] + } + + fn return_type() -> Type { + Type::Group + } +} + diff --git a/compiler/core/src/algorithms/poseidon.rs b/compiler/core/src/algorithms/poseidon.rs new file mode 100644 index 0000000000..2143daa825 --- /dev/null +++ b/compiler/core/src/algorithms/poseidon.rs @@ -0,0 +1,114 @@ +// 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 . + +use crate::algorithms::{CoreFunction, ALL_TYPES}; +use leo_ast::Type; + +pub struct Poseidon2Hash; + +impl CoreFunction for Poseidon2Hash { + const NUM_ARGS: usize = 1; + + fn first_arg_types() -> &'static [Type] { + &ALL_TYPES + } + + fn return_type() -> Type { + Type::Field + } +} + +pub struct Poseidon2PRF; + +impl CoreFunction for Poseidon2PRF { + const NUM_ARGS: usize = 2; + + fn first_arg_types() -> &'static [Type] { + &[Type::Field] + } + + fn second_arg_types() -> &'static [Type] { + &ALL_TYPES + } + + fn return_type() -> Type { + Type::Field + } +} + +pub struct Poseidon4Hash; + +impl CoreFunction for Poseidon4Hash { + const NUM_ARGS: usize = 1; + + fn first_arg_types() -> &'static [Type] { + &ALL_TYPES + } + + fn return_type() -> Type { + Type::Field + } +} + +pub struct Poseidon4PRF; + +impl CoreFunction for Poseidon4PRF { + const NUM_ARGS: usize = 2; + + fn first_arg_types() -> &'static [Type] { + &[Type::Field] + } + + fn second_arg_types() -> &'static [Type] { + &ALL_TYPES + } + + fn return_type() -> Type { + Type::Field + } +} + +pub struct Poseidon8Hash; + +impl CoreFunction for Poseidon8Hash { + const NUM_ARGS: usize = 1; + + fn first_arg_types() -> &'static [Type] { + &ALL_TYPES + } + + fn return_type() -> Type { + Type::Field + } +} + +pub struct Poseidon8PRF; + +impl CoreFunction for Poseidon8PRF { + const NUM_ARGS: usize = 2; + + fn first_arg_types() -> &'static [Type] { + &[Type::Field] + } + + fn second_arg_types() -> &'static [Type] { + &ALL_TYPES + } + + fn return_type() -> Type { + Type::Field + } +} diff --git a/compiler/parser/src/tokenizer/lexer.rs b/compiler/parser/src/tokenizer/lexer.rs index b76950c060..21b1e389f8 100644 --- a/compiler/parser/src/tokenizer/lexer.rs +++ b/compiler/parser/src/tokenizer/lexer.rs @@ -290,7 +290,7 @@ impl Token { } return Ok((1, Token::Div)); } - ':' => return single(&mut input, Token::Colon), + ':' => return followed_by(&mut input, ':', Token::DoubleColon, Token::Colon), ';' => return single(&mut input, Token::Semicolon), '<' => return three_cases(&mut input, '=', Token::LtEq, '<', Token::Shl, Token::Lt), '>' => return three_cases(&mut input, '=', Token::GtEq, '>', Token::Shr, Token::Gt), diff --git a/compiler/passes/src/type_checker/check_expressions.rs b/compiler/passes/src/type_checker/check_expressions.rs index a5846e0345..fe23210f3c 100644 --- a/compiler/passes/src/type_checker/check_expressions.rs +++ b/compiler/passes/src/type_checker/check_expressions.rs @@ -15,6 +15,7 @@ // along with the Leo library. If not, see . use leo_ast::*; +use leo_core::is_core_circuit; use leo_errors::TypeCheckerError; use crate::TypeChecker; @@ -65,7 +66,9 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> { fn visit_identifier(&mut self, input: &'a Identifier, expected: &Self::AdditionalInput) -> Option { if let VisitResult::VisitChildren = self.visitor.visit_identifier(input) { - return if let Some(var) = self.visitor.symbol_table.clone().lookup_variable(&input.name) { + return if is_core_circuit(input.name) { + Some(Type::Identifier(*input)) + } else if let Some(var) = self.visitor.symbol_table.clone().lookup_variable(&input.name) { Some(self.visitor.assert_expected_option(*var.type_, expected, var.span)) } else { self.visitor diff --git a/examples/hello-world/src/main.leo b/examples/hello-world/src/main.leo index e6ddfdeb44..619a062417 100644 --- a/examples/hello-world/src/main.leo +++ b/examples/hello-world/src/main.leo @@ -1,9 +1,3 @@ -circuit BHP256 { - function commit() -> bool { - return true; - } -} - -function main(a: u8) -> u8 { - return a >> 1u32; +function main(a: u8) -> field { + return BHP257::hash(a); } \ No newline at end of file