snarkvm_synthesizer_program/traits/
stack_and_registers.rs

1// Copyright 2024 Aleo Network Foundation
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use std::sync::Arc;
17
18use crate::{FinalizeGlobalState, Function, Operand, Program};
19use console::{
20    account::Group,
21    network::Network,
22    prelude::{Result, bail},
23    program::{
24        Future,
25        Identifier,
26        Literal,
27        Locator,
28        Plaintext,
29        PlaintextType,
30        ProgramID,
31        Record,
32        RecordType,
33        Register,
34        RegisterType,
35        Value,
36        ValueType,
37    },
38    types::{Address, Field},
39};
40use rand::{CryptoRng, Rng};
41use synthesizer_snark::{ProvingKey, VerifyingKey};
42
43pub trait StackKeys<N: Network> {
44    /// Returns `true` if the proving key for the given function name exists.
45    fn contains_proving_key(&self, function_name: &Identifier<N>) -> bool;
46
47    /// Returns the proving key for the given function name.
48    fn get_proving_key(&self, function_name: &Identifier<N>) -> Result<ProvingKey<N>>;
49
50    /// Inserts the proving key for the given function name.
51    fn insert_proving_key(&self, function_name: &Identifier<N>, proving_key: ProvingKey<N>) -> Result<()>;
52
53    /// Removes the proving key for the given function name.
54    fn remove_proving_key(&self, function_name: &Identifier<N>);
55
56    /// Returns `true` if the verifying key for the given function name exists.
57    fn contains_verifying_key(&self, function_name: &Identifier<N>) -> bool;
58
59    /// Returns the verifying key for the given function name.
60    fn get_verifying_key(&self, function_name: &Identifier<N>) -> Result<VerifyingKey<N>>;
61
62    /// Inserts the verifying key for the given function name.
63    fn insert_verifying_key(&self, function_name: &Identifier<N>, verifying_key: VerifyingKey<N>) -> Result<()>;
64
65    /// Removes the verifying key for the given function name.
66    fn remove_verifying_key(&self, function_name: &Identifier<N>);
67}
68
69pub trait StackMatches<N: Network> {
70    /// Checks that the given value matches the layout of the value type.
71    fn matches_value_type(&self, value: &Value<N>, value_type: &ValueType<N>) -> Result<()>;
72
73    /// Checks that the given stack value matches the layout of the register type.
74    fn matches_register_type(&self, stack_value: &Value<N>, register_type: &RegisterType<N>) -> Result<()>;
75
76    /// Checks that the given record matches the layout of the external record type.
77    fn matches_external_record(&self, record: &Record<N, Plaintext<N>>, locator: &Locator<N>) -> Result<()>;
78
79    /// Checks that the given record matches the layout of the record type.
80    fn matches_record(&self, record: &Record<N, Plaintext<N>>, record_name: &Identifier<N>) -> Result<()>;
81
82    /// Checks that the given plaintext matches the layout of the plaintext type.
83    fn matches_plaintext(&self, plaintext: &Plaintext<N>, plaintext_type: &PlaintextType<N>) -> Result<()>;
84
85    /// Checks that the given future matches the layout of the future type.
86    fn matches_future(&self, future: &Future<N>, locator: &Locator<N>) -> Result<()>;
87}
88
89pub trait StackProgram<N: Network> {
90    /// Returns the program.
91    fn program(&self) -> &Program<N>;
92
93    /// Returns the program ID.
94    fn program_id(&self) -> &ProgramID<N>;
95
96    /// Returns the program depth.
97    fn program_depth(&self) -> usize;
98
99    /// Returns the program address.
100    fn program_address(&self) -> &Address<N>;
101
102    /// Returns `true` if the stack contains the external record.
103    fn contains_external_record(&self, locator: &Locator<N>) -> bool;
104
105    /// Returns the external stack for the given program ID.
106    fn get_external_stack(&self, program_id: &ProgramID<N>) -> Result<&Arc<Self>>;
107
108    /// Returns the external program for the given program ID.
109    fn get_external_program(&self, program_id: &ProgramID<N>) -> Result<&Program<N>>;
110
111    /// Returns `true` if the stack contains the external record.
112    fn get_external_record(&self, locator: &Locator<N>) -> Result<&RecordType<N>>;
113
114    /// Returns the expected finalize cost for the given function name.
115    fn get_finalize_cost(&self, function_name: &Identifier<N>) -> Result<u64>;
116
117    /// Returns the function with the given function name.
118    fn get_function(&self, function_name: &Identifier<N>) -> Result<Function<N>>;
119
120    /// Returns a reference to the function with the given function name.
121    fn get_function_ref(&self, function_name: &Identifier<N>) -> Result<&Function<N>>;
122
123    /// Returns the expected number of calls for the given function name.
124    fn get_number_of_calls(&self, function_name: &Identifier<N>) -> Result<usize>;
125
126    /// Samples a value for the given value_type.
127    fn sample_value<R: Rng + CryptoRng>(
128        &self,
129        burner_address: &Address<N>,
130        value_type: &ValueType<N>,
131        rng: &mut R,
132    ) -> Result<Value<N>>;
133
134    /// Returns a record for the given record name, with the given burner address and nonce.
135    fn sample_record<R: Rng + CryptoRng>(
136        &self,
137        burner_address: &Address<N>,
138        record_name: &Identifier<N>,
139        record_nonce: Group<N>,
140        rng: &mut R,
141    ) -> Result<Record<N, Plaintext<N>>>;
142
143    /// Returns a record for the given record name, deriving the nonce from tvk and index.
144    fn sample_record_using_tvk<R: Rng + CryptoRng>(
145        &self,
146        burner_address: &Address<N>,
147        record_name: &Identifier<N>,
148        tvk: Field<N>,
149        index: Field<N>,
150        rng: &mut R,
151    ) -> Result<Record<N, Plaintext<N>>>;
152}
153
154pub trait FinalizeRegistersState<N: Network> {
155    /// Returns the global state for the finalize scope.
156    fn state(&self) -> &FinalizeGlobalState;
157
158    /// Returns the transition ID for the finalize scope.
159    fn transition_id(&self) -> &N::TransitionID;
160
161    /// Returns the function name for the finalize scope.
162    fn function_name(&self) -> &Identifier<N>;
163
164    /// Returns the nonce for the finalize registers.
165    fn nonce(&self) -> u64;
166}
167
168pub trait RegistersSigner<N: Network> {
169    /// Returns the transition signer.
170    fn signer(&self) -> Result<Address<N>>;
171
172    /// Sets the transition signer.
173    fn set_signer(&mut self, signer: Address<N>);
174
175    /// Returns the root transition view key.
176    fn root_tvk(&self) -> Result<Field<N>>;
177
178    /// Sets the root transition view key.
179    fn set_root_tvk(&mut self, root_tvk: Field<N>);
180
181    /// Returns the transition caller.
182    fn caller(&self) -> Result<Address<N>>;
183
184    /// Sets the transition caller.
185    fn set_caller(&mut self, caller: Address<N>);
186
187    /// Returns the transition view key.
188    fn tvk(&self) -> Result<Field<N>>;
189
190    /// Sets the transition view key.
191    fn set_tvk(&mut self, tvk: Field<N>);
192}
193
194pub trait RegistersSignerCircuit<N: Network, A: circuit::Aleo<Network = N>> {
195    /// Returns the transition signer, as a circuit.
196    fn signer_circuit(&self) -> Result<circuit::Address<A>>;
197
198    /// Sets the transition signer, as a circuit.
199    fn set_signer_circuit(&mut self, signer_circuit: circuit::Address<A>);
200
201    /// Returns the root transition view key, as a circuit.
202    fn root_tvk_circuit(&self) -> Result<circuit::Field<A>>;
203
204    /// Sets the root transition view key, as a circuit.
205    fn set_root_tvk_circuit(&mut self, root_tvk_circuit: circuit::Field<A>);
206
207    /// Returns the transition caller, as a circuit.
208    fn caller_circuit(&self) -> Result<circuit::Address<A>>;
209
210    /// Sets the transition caller, as a circuit.
211    fn set_caller_circuit(&mut self, caller_circuit: circuit::Address<A>);
212
213    /// Returns the transition view key, as a circuit.
214    fn tvk_circuit(&self) -> Result<circuit::Field<A>>;
215
216    /// Sets the transition view key, as a circuit.
217    fn set_tvk_circuit(&mut self, tvk_circuit: circuit::Field<A>);
218}
219
220pub trait RegistersLoad<N: Network> {
221    /// Loads the value of a given operand.
222    ///
223    /// # Errors
224    /// This method should halt if the register locator is not found.
225    /// In the case of register members, this method should halt if the member is not found.
226    fn load(&self, stack: &(impl StackMatches<N> + StackProgram<N>), operand: &Operand<N>) -> Result<Value<N>>;
227
228    /// Loads the literal of a given operand.
229    ///
230    /// # Errors
231    /// This method should halt if the given operand is not a literal.
232    /// This method should halt if the register locator is not found.
233    /// In the case of register members, this method should halt if the member is not found.
234    #[inline]
235    fn load_literal(
236        &self,
237        stack: &(impl StackMatches<N> + StackProgram<N>),
238        operand: &Operand<N>,
239    ) -> Result<Literal<N>> {
240        match self.load(stack, operand)? {
241            Value::Plaintext(Plaintext::Literal(literal, ..)) => Ok(literal),
242            Value::Plaintext(Plaintext::Struct(..))
243            | Value::Plaintext(Plaintext::Array(..))
244            | Value::Record(..)
245            | Value::Future(..) => {
246                bail!("Operand must be a literal")
247            }
248        }
249    }
250
251    /// Loads the plaintext of a given operand.
252    ///
253    /// # Errors
254    /// This method should halt if the given operand is not a plaintext.
255    /// This method should halt if the register locator is not found.
256    /// In the case of register members, this method should halt if the member is not found.
257    #[inline]
258    fn load_plaintext(
259        &self,
260        stack: &(impl StackMatches<N> + StackProgram<N>),
261        operand: &Operand<N>,
262    ) -> Result<Plaintext<N>> {
263        match self.load(stack, operand)? {
264            Value::Plaintext(plaintext) => Ok(plaintext),
265            Value::Record(..) | Value::Future(..) => bail!("Operand must be a plaintext"),
266        }
267    }
268}
269
270pub trait RegistersLoadCircuit<N: Network, A: circuit::Aleo<Network = N>> {
271    /// Loads the value of a given operand.
272    ///
273    /// # Errors
274    /// This method should halt if the register locator is not found.
275    /// In the case of register members, this method should halt if the member is not found.
276    fn load_circuit(
277        &self,
278        stack: &(impl StackMatches<N> + StackProgram<N>),
279        operand: &Operand<N>,
280    ) -> Result<circuit::Value<A>>;
281
282    /// Loads the literal of a given operand.
283    ///
284    /// # Errors
285    /// This method should halt if the given operand is not a literal.
286    /// This method should halt if the register locator is not found.
287    /// In the case of register members, this method should halt if the member is not found.
288    #[inline]
289    fn load_literal_circuit(
290        &self,
291        stack: &(impl StackMatches<N> + StackProgram<N>),
292        operand: &Operand<N>,
293    ) -> Result<circuit::Literal<A>> {
294        match self.load_circuit(stack, operand)? {
295            circuit::Value::Plaintext(circuit::Plaintext::Literal(literal, ..)) => Ok(literal),
296            circuit::Value::Plaintext(circuit::Plaintext::Struct(..))
297            | circuit::Value::Plaintext(circuit::Plaintext::Array(..))
298            | circuit::Value::Record(..)
299            | circuit::Value::Future(..) => bail!("Operand must be a literal"),
300        }
301    }
302
303    /// Loads the plaintext of a given operand.
304    ///
305    /// # Errors
306    /// This method should halt if the given operand is not a plaintext.
307    /// This method should halt if the register locator is not found.
308    /// In the case of register members, this method should halt if the member is not found.
309    #[inline]
310    fn load_plaintext_circuit(
311        &self,
312        stack: &(impl StackMatches<N> + StackProgram<N>),
313        operand: &Operand<N>,
314    ) -> Result<circuit::Plaintext<A>> {
315        match self.load_circuit(stack, operand)? {
316            circuit::Value::Plaintext(plaintext) => Ok(plaintext),
317            circuit::Value::Record(..) | circuit::Value::Future(..) => bail!("Operand must be a plaintext"),
318        }
319    }
320}
321
322pub trait RegistersStore<N: Network> {
323    /// Assigns the given value to the given register, assuming the register is not already assigned.
324    ///
325    /// # Errors
326    /// This method should halt if the given register is a register member.
327    /// This method should halt if the given register is an input register.
328    /// This method should halt if the register is already used.
329    fn store(
330        &mut self,
331        stack: &(impl StackMatches<N> + StackProgram<N>),
332        register: &Register<N>,
333        stack_value: Value<N>,
334    ) -> Result<()>;
335
336    /// Assigns the given literal to the given register, assuming the register is not already assigned.
337    ///
338    /// # Errors
339    /// This method should halt if the given register is a register member.
340    /// This method should halt if the given register is an input register.
341    /// This method should halt if the register is already used.
342    #[inline]
343    fn store_literal(
344        &mut self,
345        stack: &(impl StackMatches<N> + StackProgram<N>),
346        register: &Register<N>,
347        literal: Literal<N>,
348    ) -> Result<()> {
349        self.store(stack, register, Value::Plaintext(Plaintext::from(literal)))
350    }
351}
352
353pub trait RegistersStoreCircuit<N: Network, A: circuit::Aleo<Network = N>> {
354    /// Assigns the given value to the given register, assuming the register is not already assigned.
355    ///
356    /// # Errors
357    /// This method should halt if the given register is a register member.
358    /// This method should halt if the given register is an input register.
359    /// This method should halt if the register is already used.
360    fn store_circuit(
361        &mut self,
362        stack: &(impl StackMatches<N> + StackProgram<N>),
363        register: &Register<N>,
364        stack_value: circuit::Value<A>,
365    ) -> Result<()>;
366
367    /// Assigns the given literal to the given register, assuming the register is not already assigned.
368    ///
369    /// # Errors
370    /// This method should halt if the given register is a register member.
371    /// This method should halt if the given register is an input register.
372    /// This method should halt if the register is already used.
373    #[inline]
374    fn store_literal_circuit(
375        &mut self,
376        stack: &(impl StackMatches<N> + StackProgram<N>),
377        register: &Register<N>,
378        literal: circuit::Literal<A>,
379    ) -> Result<()> {
380        self.store_circuit(stack, register, circuit::Value::Plaintext(circuit::Plaintext::from(literal)))
381    }
382}