1mod authorization;
17pub use authorization::*;
18
19mod call;
20pub use call::*;
21
22mod finalize_registers;
23pub use finalize_registers::*;
24
25mod finalize_types;
26pub use finalize_types::*;
27
28mod register_types;
29pub use register_types::*;
30
31mod registers;
32pub use registers::*;
33
34mod authorize;
35mod deploy;
36mod evaluate;
37mod execute;
38mod helpers;
39
40use crate::{CallMetrics, Process, Trace};
41use console::{
42 account::{Address, PrivateKey},
43 network::prelude::*,
44 program::{
45 Argument,
46 Entry,
47 EntryType,
48 FinalizeType,
49 Future,
50 Identifier,
51 Literal,
52 Locator,
53 Owner as RecordOwner,
54 Plaintext,
55 PlaintextType,
56 ProgramID,
57 Record,
58 RecordType,
59 RegisterType,
60 Request,
61 Response,
62 U8,
63 U16,
64 Value,
65 ValueType,
66 },
67 types::{Field, Group},
68};
69use snarkvm_ledger_block::{Deployment, Transaction, Transition};
70use snarkvm_synthesizer_program::{
71 CallOperator,
72 Closure,
73 Function,
74 Instruction,
75 Operand,
76 Program,
77 RegistersCircuit,
78 RegistersSigner,
79 RegistersTrait,
80 StackTrait,
81};
82use snarkvm_synthesizer_snark::{Certificate, ProvingKey, UniversalSRS, VerifyingKey};
83
84use aleo_std::prelude::{finish, lap, timer};
85use indexmap::IndexMap;
86#[cfg(feature = "locktick")]
87use locktick::parking_lot::RwLock;
88#[cfg(not(feature = "locktick"))]
89use parking_lot::RwLock;
90use rand::{CryptoRng, Rng};
91use std::sync::{Arc, Weak};
92
93#[cfg(not(feature = "serial"))]
94use rayon::prelude::*;
95
96pub type Assignments<N> = Arc<RwLock<Vec<(circuit::Assignment<<N as Environment>::Field>, CallMetrics<N>)>>>;
97
98#[derive(Clone)]
100pub enum CallStack<N: Network> {
101 Authorize(Vec<Request<N>>, Option<PrivateKey<N>>, Authorization<N>),
103 Synthesize(Vec<Request<N>>, PrivateKey<N>, Authorization<N>),
105 CheckDeployment(Vec<Request<N>>, PrivateKey<N>, Assignments<N>, Option<u64>, Option<u64>),
107 Evaluate(Authorization<N>),
109 Execute(Authorization<N>, Arc<RwLock<Trace<N>>>),
111 PackageRun(Vec<Request<N>>, PrivateKey<N>, Assignments<N>),
113}
114
115impl<N: Network> CallStack<N> {
116 pub fn evaluate(authorization: Authorization<N>) -> Result<Self> {
118 Ok(CallStack::Evaluate(authorization))
119 }
120
121 pub fn execute(authorization: Authorization<N>, trace: Arc<RwLock<Trace<N>>>) -> Result<Self> {
123 Ok(CallStack::Execute(authorization, trace))
124 }
125}
126
127impl<N: Network> CallStack<N> {
128 pub fn replicate(&self) -> Self {
130 match self {
131 CallStack::Authorize(requests, private_key, authorization) => {
132 CallStack::Authorize(requests.clone(), *private_key, authorization.replicate())
133 }
134 CallStack::Synthesize(requests, private_key, authorization) => {
135 CallStack::Synthesize(requests.clone(), *private_key, authorization.replicate())
136 }
137 CallStack::CheckDeployment(requests, private_key, assignments, constraint_limit, variable_limit) => {
138 CallStack::CheckDeployment(
139 requests.clone(),
140 *private_key,
141 Arc::new(RwLock::new(assignments.read().clone())),
142 *constraint_limit,
143 *variable_limit,
144 )
145 }
146 CallStack::Evaluate(authorization) => CallStack::Evaluate(authorization.replicate()),
147 CallStack::Execute(authorization, trace) => {
148 CallStack::Execute(authorization.replicate(), Arc::new(RwLock::new(trace.read().clone())))
149 }
150 CallStack::PackageRun(requests, private_key, assignments) => {
151 CallStack::PackageRun(requests.clone(), *private_key, Arc::new(RwLock::new(assignments.read().clone())))
152 }
153 }
154 }
155
156 pub fn push(&mut self, request: Request<N>) -> Result<()> {
158 match self {
159 CallStack::Authorize(requests, ..)
160 | CallStack::Synthesize(requests, ..)
161 | CallStack::CheckDeployment(requests, ..)
162 | CallStack::PackageRun(requests, ..) => {
163 ensure!(
165 requests.len() < Transaction::<N>::MAX_TRANSITIONS,
166 "The number of requests in the authorization must be less than '{}'.",
167 Transaction::<N>::MAX_TRANSITIONS
168 );
169 requests.push(request)
171 }
172 CallStack::Evaluate(authorization) => authorization.push(request)?,
173 CallStack::Execute(authorization, ..) => authorization.push(request)?,
174 }
175 Ok(())
176 }
177
178 pub fn pop(&mut self) -> Result<Request<N>> {
180 match self {
181 CallStack::Authorize(requests, ..)
182 | CallStack::Synthesize(requests, ..)
183 | CallStack::CheckDeployment(requests, ..)
184 | CallStack::PackageRun(requests, ..) => {
185 requests.pop().ok_or_else(|| anyhow!("No more requests on the stack"))
186 }
187 CallStack::Evaluate(authorization) => authorization.next(),
188 CallStack::Execute(authorization, ..) => authorization.next(),
189 }
190 }
191
192 pub fn peek(&mut self) -> Result<Request<N>> {
194 match self {
195 CallStack::Authorize(requests, ..)
196 | CallStack::Synthesize(requests, ..)
197 | CallStack::CheckDeployment(requests, ..)
198 | CallStack::PackageRun(requests, ..) => {
199 requests.last().cloned().ok_or_else(|| anyhow!("No more requests on the stack"))
200 }
201 CallStack::Evaluate(authorization) => authorization.peek_next(),
202 CallStack::Execute(authorization, ..) => authorization.peek_next(),
203 }
204 }
205}
206
207#[derive(Clone)]
208pub struct Stack<N: Network> {
209 program: Program<N>,
211 stacks: Weak<RwLock<IndexMap<ProgramID<N>, Arc<Stack<N>>>>>,
213 constructor_types: Arc<RwLock<Option<FinalizeTypes<N>>>>,
215 register_types: Arc<RwLock<IndexMap<Identifier<N>, RegisterTypes<N>>>>,
217 finalize_types: Arc<RwLock<IndexMap<Identifier<N>, FinalizeTypes<N>>>>,
219 universal_srs: UniversalSRS<N>,
221 proving_keys: Arc<RwLock<IndexMap<Identifier<N>, ProvingKey<N>>>>,
223 verifying_keys: Arc<RwLock<IndexMap<Identifier<N>, VerifyingKey<N>>>>,
225 program_address: Address<N>,
227 program_checksum: [U8<N>; 32],
229 program_edition: U16<N>,
231 program_owner: Option<Address<N>>,
233}
234
235impl<N: Network> Stack<N> {
236 pub fn new(process: &Process<N>, program: &Program<N>) -> Result<Self> {
238 let program_id = program.id();
240 check_program_is_well_formed(program)?;
242
243 if let Ok(existing_stack) = process.get_stack(program_id) {
245 ensure!(program_id != &ProgramID::from_str("credits.aleo")?, "Cannot re-initialize the 'credits.aleo'.");
247 let existing_program = existing_stack.program();
249 match existing_program.contains_constructor() {
252 false => ensure!(
253 existing_stack.program() == program,
254 "Program '{program_id}' already exists with different contents."
255 ),
256 true => Self::check_upgrade_is_valid(existing_program, program)?,
257 }
258 }
259
260 Stack::initialize(process, program)
262 }
263
264 pub fn new_raw(process: &Process<N>, program: &Program<N>, edition: u16) -> Result<Self> {
267 check_program_is_well_formed(program)?;
269 Stack::create_raw(process, program, edition)
271 }
272
273 pub fn initialize_and_check(&self, process: &Process<N>) -> Result<()> {
275 let mut constructor_types = self.constructor_types.write();
277 let mut register_types = self.register_types.write();
278 let mut finalize_types = self.finalize_types.write();
279
280 constructor_types.take();
282 register_types.clear();
283 finalize_types.clear();
284
285 for import in self.program.imports().keys() {
287 ensure!(import != self.program.id(), "Program cannot import itself");
289 if !process.contains_program(import) {
291 bail!("Cannot add program '{}' because its import '{import}' must be added first", self.program.id())
292 }
293 }
294
295 if let Some(constructor) = self.program.constructor() {
297 let types = FinalizeTypes::from_constructor(self, constructor)?;
299 constructor_types.replace(types);
301 }
302
303 for closure in self.program.closures().values() {
305 let name = closure.name();
307 ensure!(!register_types.contains_key(name), "Closure '{name}' already exists");
309 let types = RegisterTypes::from_closure(self, closure)?;
311 register_types.insert(*name, types);
313 }
314
315 for function in self.program.functions().values() {
317 let name = function.name();
319 ensure!(!register_types.contains_key(name), "Function '{name}' already exists");
321 let types = RegisterTypes::from_function(self, function)?;
323 register_types.insert(*name, types);
325
326 if let Some(finalize) = function.finalize_logic() {
328 let types = FinalizeTypes::from_finalize(self, finalize)?;
330 finalize_types.insert(*name, types);
332 }
333 }
334
335 drop(constructor_types);
337 drop(register_types);
338 drop(finalize_types);
339
340 for function in self.program.functions().values() {
342 self.get_number_of_calls(function.name())?;
345 }
346 Ok(())
347 }
348
349 #[inline]
351 pub fn get_constructor_types(&self) -> Result<FinalizeTypes<N>> {
352 match self.constructor_types.read().as_ref() {
354 Some(constructor_types) => Ok(constructor_types.clone()),
355 None => bail!("Constructor types do not exist"),
356 }
357 }
358
359 #[inline]
361 pub fn get_register_types(&self, name: &Identifier<N>) -> Result<RegisterTypes<N>> {
362 match self.register_types.read().get(name) {
364 Some(register_types) => Ok(register_types.clone()),
365 None => bail!("Register types for '{name}' do not exist"),
366 }
367 }
368
369 #[inline]
371 pub fn get_finalize_types(&self, name: &Identifier<N>) -> Result<FinalizeTypes<N>> {
372 match self.finalize_types.read().get(name) {
374 Some(finalize_types) => Ok(finalize_types.clone()),
375 None => bail!("Finalize types for '{name}' do not exist"),
376 }
377 }
378
379 fn try_insert_credits_function_proving_key(&self, function_name: &Identifier<N>) -> Result<()> {
381 if self.program_id() == &ProgramID::from_str("credits.aleo")?
383 && !self.proving_keys.read().contains_key(function_name)
384 {
385 let proving_key = N::get_credits_proving_key(function_name.to_string())?;
387 self.insert_proving_key(function_name, ProvingKey::new(proving_key.clone()))?;
389 }
390 Ok(())
391 }
392}
393
394impl<N: Network> PartialEq for Stack<N> {
395 fn eq(&self, other: &Self) -> bool {
396 self.program == other.program
397 && *self.register_types.read() == *other.register_types.read()
398 && *self.finalize_types.read() == *other.finalize_types.read()
399 }
400}
401
402impl<N: Network> Eq for Stack<N> {}
403
404#[derive(Clone)]
406pub(crate) enum StackRef<'a, N: Network> {
407 Internal(&'a Stack<N>),
409 External(Arc<Stack<N>>),
411}
412
413impl<N: Network> Deref for StackRef<'_, N> {
414 type Target = Stack<N>;
415
416 fn deref(&self) -> &Self::Target {
417 match self {
418 StackRef::Internal(stack) => stack,
419 StackRef::External(stack) => stack,
420 }
421 }
422}
423
424fn check_program_is_well_formed<N: Network>(program: &Program<N>) -> Result<()> {
426 ensure!(!program.functions().is_empty(), "No functions present in the deployment for program '{}'", program.id());
428
429 let program_bytes = program.to_bytes_le()?;
431 ensure!(program == &Program::from_bytes_le(&program_bytes)?, "Program byte serialization failed");
433
434 let program_string = program.to_string();
436 ensure!(program == &Program::from_str(&program_string)?, "Program string serialization failed");
438
439 Ok(())
440}