1use 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 Register,
33 RegisterType,
34 StructType,
35 Value,
36 ValueType,
37 },
38 types::{Address, Field, U8, U16},
39};
40use rand::{CryptoRng, Rng};
41use snarkvm_synthesizer_snark::{ProvingKey, VerifyingKey};
42
43pub trait StackTrait<N: Network> {
47 fn contains_proving_key(&self, function_name: &Identifier<N>) -> bool;
49
50 fn get_proving_key(&self, function_name: &Identifier<N>) -> Result<ProvingKey<N>>;
52
53 fn insert_proving_key(&self, function_name: &Identifier<N>, proving_key: ProvingKey<N>) -> Result<()>;
55
56 fn remove_proving_key(&self, function_name: &Identifier<N>);
58
59 fn contains_verifying_key(&self, function_name: &Identifier<N>) -> bool;
61
62 fn get_verifying_key(&self, function_name: &Identifier<N>) -> Result<VerifyingKey<N>>;
64
65 fn insert_verifying_key(&self, function_name: &Identifier<N>, verifying_key: VerifyingKey<N>) -> Result<()>;
67
68 fn remove_verifying_key(&self, function_name: &Identifier<N>);
70
71 fn matches_value_type(&self, value: &Value<N>, value_type: &ValueType<N>) -> Result<()>;
73
74 fn matches_register_type(&self, stack_value: &Value<N>, register_type: &RegisterType<N>) -> Result<()>;
76
77 fn matches_external_record(&self, record: &Record<N, Plaintext<N>>, locator: &Locator<N>) -> Result<()>;
79
80 fn matches_record(&self, record: &Record<N, Plaintext<N>>, record_name: &Identifier<N>) -> Result<()>;
82
83 fn matches_plaintext(&self, plaintext: &Plaintext<N>, plaintext_type: &PlaintextType<N>) -> Result<()>;
85
86 fn matches_future(&self, future: &Future<N>, locator: &Locator<N>) -> Result<()>;
88
89 fn program(&self) -> &Program<N>;
91
92 fn program_id(&self) -> &ProgramID<N>;
94
95 fn program_address(&self) -> &Address<N>;
97
98 fn program_checksum(&self) -> &[U8<N>; 32];
100
101 fn program_checksum_as_field(&self) -> Result<Field<N>>;
103
104 fn program_edition(&self) -> U16<N>;
106
107 fn program_owner(&self) -> &Option<Address<N>>;
110
111 fn set_program_owner(&mut self, program_owner: Option<Address<N>>);
113
114 fn get_external_stack(&self, program_id: &ProgramID<N>) -> Result<Arc<Self>>;
116
117 fn get_function(&self, function_name: &Identifier<N>) -> Result<Function<N>>;
119
120 fn get_function_ref(&self, function_name: &Identifier<N>) -> Result<&Function<N>>;
122
123 fn get_number_of_calls(&self, function_name: &Identifier<N>) -> Result<usize>;
125
126 fn sample_value<R: Rng + CryptoRng>(
128 &self,
129 burner_address: &Address<N>,
130 value_type: &RegisterType<N>,
131 rng: &mut R,
132 ) -> Result<Value<N>>;
133
134 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 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 fn register_types_equivalent<N: Network>(
156 stack0: &impl StackTrait<N>,
157 type0: &RegisterType<N>,
158 stack1: &impl StackTrait<N>,
159 type1: &RegisterType<N>,
160) -> Result<bool> {
161 use RegisterType::*;
162 if let (Plaintext(plaintext0), Plaintext(plaintext1)) = (type0, type1) {
163 types_equivalent(stack0, plaintext0, stack1, plaintext1)
164 } else {
165 Ok(type0 == type1)
166 }
167}
168
169pub fn types_equivalent<N: Network>(
192 stack0: &impl StackTrait<N>,
193 type0: &PlaintextType<N>,
194 stack1: &impl StackTrait<N>,
195 type1: &PlaintextType<N>,
196) -> Result<bool> {
197 use PlaintextType::*;
198
199 let struct_compare = |stack0, st0: &StructType<N>, stack1, st1: &StructType<N>| -> Result<bool> {
200 if st0.members().len() != st1.members().len() {
201 return Ok(false);
202 }
203
204 for ((name0, type0), (name1, type1)) in st0.members().iter().zip(st1.members()) {
205 if name0 != name1 || !types_equivalent(stack0, type0, stack1, type1)? {
206 return Ok(false);
207 }
208 }
209
210 Ok(true)
211 };
212
213 match (type0, type1) {
214 (Array(array0), Array(array1)) => Ok(array0.length() == array1.length()
215 && types_equivalent(stack0, array0.next_element_type(), stack1, array1.next_element_type())?),
216 (Literal(lit0), Literal(lit1)) => Ok(lit0 == lit1),
217 (Struct(id0), Struct(id1)) => {
218 if id0 != id1 {
219 return Ok(false);
220 }
221 let struct_type0 = stack0.program().get_struct(id0)?;
222 let struct_type1 = stack1.program().get_struct(id1)?;
223 struct_compare(stack0, struct_type0, stack1, struct_type1)
224 }
225 (ExternalStruct(loc0), ExternalStruct(loc1)) => {
226 if loc0.resource() != loc1.resource() {
227 return Ok(false);
228 }
229 let external_stack0 = stack0.get_external_stack(loc0.program_id())?;
230 let struct_type0 = external_stack0.program().get_struct(loc0.resource())?;
231 let external_stack1 = stack1.get_external_stack(loc1.program_id())?;
232 let struct_type1 = external_stack1.program().get_struct(loc1.resource())?;
233 struct_compare(&*external_stack0, struct_type0, &*external_stack1, struct_type1)
234 }
235 (ExternalStruct(loc), Struct(id)) => {
236 if loc.resource() != id {
237 return Ok(false);
238 }
239 let external_stack = stack0.get_external_stack(loc.program_id())?;
240 let struct_type0 = external_stack.program().get_struct(loc.resource())?;
241 let struct_type1 = stack1.program().get_struct(id)?;
242 struct_compare(&*external_stack, struct_type0, stack1, struct_type1)
243 }
244 (Struct(id), ExternalStruct(loc)) => {
245 if id != loc.resource() {
246 return Ok(false);
247 }
248 let struct_type0 = stack0.program().get_struct(id)?;
249 let external_stack = stack1.get_external_stack(loc.program_id())?;
250 let struct_type1 = external_stack.program().get_struct(loc.resource())?;
251 struct_compare(stack0, struct_type0, &*external_stack, struct_type1)
252 }
253 _ => Ok(false),
254 }
255}
256
257pub trait FinalizeRegistersState<N: Network>: RegistersTrait<N> {
258 fn state(&self) -> &FinalizeGlobalState;
260
261 fn transition_id(&self) -> &N::TransitionID;
263
264 fn function_name(&self) -> &Identifier<N>;
266
267 fn nonce(&self) -> u64;
269}
270
271pub trait RegistersSigner<N: Network>: RegistersTrait<N> {
272 fn signer(&self) -> Result<Address<N>>;
274
275 fn set_signer(&mut self, signer: Address<N>);
277
278 fn root_tvk(&self) -> Result<Field<N>>;
280
281 fn set_root_tvk(&mut self, root_tvk: Field<N>);
283
284 fn caller(&self) -> Result<Address<N>>;
286
287 fn set_caller(&mut self, caller: Address<N>);
289
290 fn tvk(&self) -> Result<Field<N>>;
292
293 fn set_tvk(&mut self, tvk: Field<N>);
295}
296
297pub trait RegistersTrait<N: Network> {
298 fn load(&self, stack: &impl StackTrait<N>, operand: &Operand<N>) -> Result<Value<N>>;
304
305 fn load_literal(&self, stack: &impl StackTrait<N>, operand: &Operand<N>) -> Result<Literal<N>> {
312 match self.load(stack, operand)? {
313 Value::Plaintext(Plaintext::Literal(literal, ..)) => Ok(literal),
314 Value::Plaintext(Plaintext::Struct(..))
315 | Value::Plaintext(Plaintext::Array(..))
316 | Value::Record(..)
317 | Value::Future(..) => {
318 bail!("Operand must be a literal")
319 }
320 }
321 }
322
323 fn load_plaintext(&self, stack: &impl StackTrait<N>, operand: &Operand<N>) -> Result<Plaintext<N>> {
330 match self.load(stack, operand)? {
331 Value::Plaintext(plaintext) => Ok(plaintext),
332 Value::Record(..) | Value::Future(..) => bail!("Operand must be a plaintext"),
333 }
334 }
335
336 fn store(&mut self, stack: &impl StackTrait<N>, register: &Register<N>, stack_value: Value<N>) -> Result<()>;
343
344 fn store_literal(&mut self, stack: &impl StackTrait<N>, register: &Register<N>, literal: Literal<N>) -> Result<()> {
351 self.store(stack, register, Value::Plaintext(Plaintext::from(literal)))
352 }
353}
354
355pub trait RegistersCircuit<N: Network, A: circuit::Aleo<Network = N>> {
359 fn signer_circuit(&self) -> Result<circuit::Address<A>>;
361
362 fn set_signer_circuit(&mut self, signer_circuit: circuit::Address<A>);
364
365 fn root_tvk_circuit(&self) -> Result<circuit::Field<A>>;
367
368 fn set_root_tvk_circuit(&mut self, root_tvk_circuit: circuit::Field<A>);
370
371 fn caller_circuit(&self) -> Result<circuit::Address<A>>;
373
374 fn set_caller_circuit(&mut self, caller_circuit: circuit::Address<A>);
376
377 fn tvk_circuit(&self) -> Result<circuit::Field<A>>;
379
380 fn set_tvk_circuit(&mut self, tvk_circuit: circuit::Field<A>);
382
383 fn load_circuit(&self, stack: &impl StackTrait<N>, operand: &Operand<N>) -> Result<circuit::Value<A>>;
389
390 fn load_literal_circuit(&self, stack: &impl StackTrait<N>, operand: &Operand<N>) -> Result<circuit::Literal<A>> {
397 match self.load_circuit(stack, operand)? {
398 circuit::Value::Plaintext(circuit::Plaintext::Literal(literal, ..)) => Ok(literal),
399 circuit::Value::Plaintext(circuit::Plaintext::Struct(..))
400 | circuit::Value::Plaintext(circuit::Plaintext::Array(..))
401 | circuit::Value::Record(..)
402 | circuit::Value::Future(..) => bail!("Operand must be a literal"),
403 }
404 }
405
406 fn load_plaintext_circuit(
413 &self,
414 stack: &impl StackTrait<N>,
415 operand: &Operand<N>,
416 ) -> Result<circuit::Plaintext<A>> {
417 match self.load_circuit(stack, operand)? {
418 circuit::Value::Plaintext(plaintext) => Ok(plaintext),
419 circuit::Value::Record(..) | circuit::Value::Future(..) => bail!("Operand must be a plaintext"),
420 }
421 }
422
423 fn store_circuit(
430 &mut self,
431 stack: &impl StackTrait<N>,
432 register: &Register<N>,
433 stack_value: circuit::Value<A>,
434 ) -> Result<()>;
435
436 fn store_literal_circuit(
443 &mut self,
444 stack: &impl StackTrait<N>,
445 register: &Register<N>,
446 literal: circuit::Literal<A>,
447 ) -> Result<()> {
448 self.store_circuit(stack, register, circuit::Value::Plaintext(circuit::Plaintext::from(literal)))
449 }
450}