leo_core/algorithms/
mod.rs

1// Copyright (C) 2019-2023 Aleo Systems Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16mod bhp;
17pub use bhp::*;
18
19mod pedersen;
20pub use pedersen::*;
21
22mod poseidon;
23pub use poseidon::*;
24
25use leo_ast::Type;
26use leo_span::{sym, Symbol};
27
28/// A core instruction that maps directly to an AVM bytecode instruction.
29#[derive(Clone, PartialEq, Eq)]
30pub enum CoreInstruction {
31    BHP256Commit,
32    BHP256Hash,
33    BHP512Commit,
34    BHP512Hash,
35    BHP768Commit,
36    BHP768Hash,
37    BHP1024Commit,
38    BHP1024Hash,
39
40    Pedersen64Commit,
41    Pedersen64Hash,
42    Pedersen128Commit,
43    Pedersen128Hash,
44
45    Poseidon2Hash,
46    Poseidon4Hash,
47    Poseidon8Hash,
48}
49
50impl CoreInstruction {
51    /// Returns a `CoreInstruction` from the given module and method symbols.
52    pub fn from_symbols(module: Symbol, function: Symbol) -> Option<Self> {
53        Some(match (module, function) {
54            (sym::BHP256, sym::commit) => Self::BHP256Commit,
55            (sym::BHP256, sym::hash) => Self::BHP256Hash,
56            (sym::BHP512, sym::commit) => Self::BHP512Commit,
57            (sym::BHP512, sym::hash) => Self::BHP512Hash,
58            (sym::BHP768, sym::commit) => Self::BHP768Commit,
59            (sym::BHP768, sym::hash) => Self::BHP768Hash,
60            (sym::BHP1024, sym::commit) => Self::BHP1024Commit,
61            (sym::BHP1024, sym::hash) => Self::BHP1024Hash,
62
63            (sym::Pedersen64, sym::commit) => Self::Pedersen64Commit,
64            (sym::Pedersen64, sym::hash) => Self::Pedersen64Hash,
65            (sym::Pedersen128, sym::commit) => Self::Pedersen128Commit,
66            (sym::Pedersen128, sym::hash) => Self::Pedersen128Hash,
67
68            (sym::Poseidon2, sym::hash) => Self::Poseidon2Hash,
69            (sym::Poseidon4, sym::hash) => Self::Poseidon4Hash,
70            (sym::Poseidon8, sym::hash) => Self::Poseidon8Hash,
71            _ => return None,
72        })
73    }
74
75    /// Returns the number of arguments required by the instruction.
76    pub fn num_args(&self) -> usize {
77        match self {
78            Self::BHP256Commit => BHP256Commit::NUM_ARGS,
79            Self::BHP256Hash => BHP256Hash::NUM_ARGS,
80            Self::BHP512Commit => BHP512Commit::NUM_ARGS,
81            Self::BHP512Hash => BHP512Hash::NUM_ARGS,
82            Self::BHP768Commit => BHP768Commit::NUM_ARGS,
83            Self::BHP768Hash => BHP768Hash::NUM_ARGS,
84            Self::BHP1024Commit => BHP1024Commit::NUM_ARGS,
85            Self::BHP1024Hash => BHP1024Hash::NUM_ARGS,
86
87            Self::Pedersen64Commit => Pedersen64Commit::NUM_ARGS,
88            Self::Pedersen64Hash => Pedersen64Hash::NUM_ARGS,
89            Self::Pedersen128Commit => Pedersen128Commit::NUM_ARGS,
90            Self::Pedersen128Hash => Pedersen128Hash::NUM_ARGS,
91
92            Self::Poseidon2Hash => Poseidon2Hash::NUM_ARGS,
93            Self::Poseidon4Hash => Poseidon4Hash::NUM_ARGS,
94            Self::Poseidon8Hash => Poseidon8Hash::NUM_ARGS,
95        }
96    }
97
98    /// Returns whether or not the first argument is an allowed type.
99    pub fn first_arg_is_allowed_type(&self, type_: &Type) -> bool {
100        match self {
101            CoreInstruction::BHP256Commit => BHP256Commit::first_arg_is_allowed_type(type_),
102            CoreInstruction::BHP256Hash => BHP256Hash::first_arg_is_allowed_type(type_),
103            CoreInstruction::BHP512Commit => BHP512Commit::first_arg_is_allowed_type(type_),
104            CoreInstruction::BHP512Hash => BHP512Hash::first_arg_is_allowed_type(type_),
105            CoreInstruction::BHP768Commit => BHP768Commit::first_arg_is_allowed_type(type_),
106            CoreInstruction::BHP768Hash => BHP768Hash::first_arg_is_allowed_type(type_),
107            CoreInstruction::BHP1024Commit => BHP1024Commit::first_arg_is_allowed_type(type_),
108            CoreInstruction::BHP1024Hash => BHP1024Hash::first_arg_is_allowed_type(type_),
109            CoreInstruction::Pedersen64Commit => Pedersen64Commit::first_arg_is_allowed_type(type_),
110            CoreInstruction::Pedersen64Hash => Pedersen64Hash::first_arg_is_allowed_type(type_),
111            CoreInstruction::Pedersen128Commit => Pedersen128Commit::first_arg_is_allowed_type(type_),
112            CoreInstruction::Pedersen128Hash => Pedersen128Hash::first_arg_is_allowed_type(type_),
113            CoreInstruction::Poseidon2Hash => Poseidon2Hash::first_arg_is_allowed_type(type_),
114            CoreInstruction::Poseidon4Hash => Poseidon4Hash::first_arg_is_allowed_type(type_),
115            CoreInstruction::Poseidon8Hash => Poseidon8Hash::first_arg_is_allowed_type(type_),
116        }
117    }
118
119    /// Returns whether or not the second argument is an allowed type.
120    pub fn second_arg_is_allowed_type(&self, type_: &Type) -> bool {
121        match self {
122            CoreInstruction::BHP256Commit => BHP256Commit::second_arg_is_allowed_type(type_),
123            CoreInstruction::BHP256Hash => BHP256Hash::second_arg_is_allowed_type(type_),
124            CoreInstruction::BHP512Commit => BHP512Commit::second_arg_is_allowed_type(type_),
125            CoreInstruction::BHP512Hash => BHP512Hash::second_arg_is_allowed_type(type_),
126            CoreInstruction::BHP768Commit => BHP768Commit::second_arg_is_allowed_type(type_),
127            CoreInstruction::BHP768Hash => BHP768Hash::second_arg_is_allowed_type(type_),
128            CoreInstruction::BHP1024Commit => BHP1024Commit::second_arg_is_allowed_type(type_),
129            CoreInstruction::BHP1024Hash => BHP1024Hash::second_arg_is_allowed_type(type_),
130            CoreInstruction::Pedersen64Commit => Pedersen64Commit::second_arg_is_allowed_type(type_),
131            CoreInstruction::Pedersen64Hash => Pedersen64Hash::second_arg_is_allowed_type(type_),
132            CoreInstruction::Pedersen128Commit => Pedersen128Commit::second_arg_is_allowed_type(type_),
133            CoreInstruction::Pedersen128Hash => Pedersen128Hash::second_arg_is_allowed_type(type_),
134            CoreInstruction::Poseidon2Hash => Poseidon2Hash::second_arg_is_allowed_type(type_),
135            CoreInstruction::Poseidon4Hash => Poseidon4Hash::second_arg_is_allowed_type(type_),
136            CoreInstruction::Poseidon8Hash => Poseidon8Hash::second_arg_is_allowed_type(type_),
137        }
138    }
139
140    /// The type of the instruction output.
141    pub fn return_type(&self) -> Type {
142        match self {
143            Self::BHP256Commit => BHP256Commit::return_type(),
144            Self::BHP256Hash => BHP256Hash::return_type(),
145            Self::BHP512Commit => BHP512Commit::return_type(),
146            Self::BHP512Hash => BHP512Hash::return_type(),
147            Self::BHP768Commit => BHP768Commit::return_type(),
148            Self::BHP768Hash => BHP768Hash::return_type(),
149            Self::BHP1024Commit => BHP1024Commit::return_type(),
150            Self::BHP1024Hash => BHP1024Hash::return_type(),
151
152            Self::Pedersen64Commit => Pedersen64Commit::return_type(),
153            Self::Pedersen64Hash => Pedersen64Hash::return_type(),
154            Self::Pedersen128Commit => Pedersen128Commit::return_type(),
155            Self::Pedersen128Hash => Pedersen128Hash::return_type(),
156
157            Self::Poseidon2Hash => Poseidon2Hash::return_type(),
158            Self::Poseidon4Hash => Poseidon4Hash::return_type(),
159            Self::Poseidon8Hash => Poseidon8Hash::return_type(),
160        }
161    }
162}
163
164/// A core function of a core struct, e.g. `hash` or `commit`
165/// Provides required type information to the type checker.
166trait CoreFunction {
167    const NUM_ARGS: usize;
168
169    /// Returns whether or not the first argument is an allowed type.
170    fn first_arg_is_allowed_type(_: &Type) -> bool {
171        false
172    }
173
174    /// Returns whether or not the second argument is an allowed type.
175    fn second_arg_is_allowed_type(_: &Type) -> bool {
176        false
177    }
178
179    /// The return type of the core function.
180    fn return_type() -> Type;
181}