impl bhp, pedersen, poseidon instructions

This commit is contained in:
collin 2022-06-17 15:37:48 -07:00
parent d527a88a3a
commit 26810a15ae
7 changed files with 478 additions and 23 deletions

View File

@ -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
}
}

View File

@ -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<Self> {
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;

View File

@ -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 <https://www.gnu.org/licenses/>.
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
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
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
}
}

View File

@ -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),

View File

@ -15,6 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
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<Self::Output> {
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

View File

@ -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);
}