Skip to main content

snarkvm_synthesizer_process/
lib.rs

1// Copyright (c) 2019-2026 Provable Inc.
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
16#![forbid(unsafe_code)]
17#![allow(clippy::too_many_arguments)]
18// #![warn(clippy::cast_possible_truncation)]
19// TODO (howardwu): Update the return type on `execute` after stabilizing the interface.
20#![allow(clippy::type_complexity)]
21
22extern crate snarkvm_circuit as circuit;
23extern crate snarkvm_console as console;
24
25mod cost;
26pub use cost::*;
27
28mod stack;
29pub use stack::*;
30
31mod trace;
32pub use trace::*;
33
34mod authorize;
35mod deploy;
36mod evaluate;
37mod execute;
38mod finalize;
39mod view;
40#[cfg(feature = "history")]
41pub use view::evaluate_view_at_height;
42mod verify_deployment;
43mod verify_execution;
44mod verify_fee;
45
46#[cfg(test)]
47mod tests;
48
49use console::{
50    account::PrivateKey,
51    network::prelude::*,
52    program::{
53        DynamicFuture,
54        Identifier,
55        Literal,
56        Locator,
57        OutputID,
58        Plaintext,
59        PlaintextType,
60        ProgramID,
61        Record,
62        Request,
63        Response,
64        Value,
65        ValueType,
66        compute_function_id,
67    },
68    types::{Field, U16, U64},
69};
70use snarkvm_algorithms::snark::varuna::VarunaVersion;
71use snarkvm_ledger_block::{Deployment, DeploymentVersion, Execution, Fee, Input, Output, Transaction, Transition};
72use snarkvm_ledger_store::{FinalizeStorage, FinalizeStore, atomic_batch_scope};
73use snarkvm_synthesizer_program::{
74    Branch,
75    CastType,
76    Command,
77    FinalizeGlobalState,
78    FinalizeOperation,
79    Function,
80    Instruction,
81    Operand,
82    Program,
83    StackTrait,
84};
85use snarkvm_synthesizer_snark::{ProvingKey, UniversalSRS, VerifyingKey};
86use snarkvm_utilities::{defer, dev_println};
87
88use aleo_std::prelude::{finish, lap, timer};
89use indexmap::{IndexMap, IndexSet};
90
91#[cfg(feature = "locktick")]
92use locktick::{
93    LockGuard,
94    parking_lot::{Mutex, RwLock},
95};
96use parking_lot::MutexGuard;
97#[cfg(not(feature = "locktick"))]
98use parking_lot::{Mutex, RwLock};
99use std::{
100    collections::{HashMap, HashSet},
101    sync::Arc,
102};
103
104// Note: a `Process` and all of its fields are meant to be completely stateless. They have no
105// notion of block height or consensus version.
106pub struct Process<N: Network> {
107    /// The universal SRS.
108    universal_srs: UniversalSRS<N>,
109    /// The mapping of program IDs to stacks.
110    stacks: Arc<RwLock<IndexMap<ProgramID<N>, Arc<Stack<N>>>>>,
111    /// The mapping of program IDs to old stacks.
112    old_stacks: RwLock<IndexMap<ProgramID<N>, Option<Arc<Stack<N>>>>>,
113    /// A lock used to create instances of `ProcessExclusiveGuard`, which ensures that only
114    /// one of them may ever exist at a time.
115    lock: Mutex<()>,
116}
117
118/// A wrapper ensuring exclusive access to the Process for the purposes of methods which
119/// affect the state of the stacks.
120pub struct ProcessExclusiveGuard<'a, N: Network> {
121    process: &'a Process<N>,
122    #[cfg(not(feature = "locktick"))]
123    _guard: MutexGuard<'a, ()>,
124    #[cfg(feature = "locktick")]
125    _guard: LockGuard<MutexGuard<'a, ()>>,
126}
127
128impl<'a, N: Network> std::ops::Deref for ProcessExclusiveGuard<'a, N> {
129    type Target = Process<N>;
130
131    fn deref(&self) -> &Self::Target {
132        self.process
133    }
134}
135
136impl<'a, N: Network> ProcessExclusiveGuard<'a, N> {
137    /// Panics, since this guard already holds the process lock.
138    #[inline]
139    pub fn lock(&self) -> ! {
140        panic!("Attempted to lock `Process` from `ProcessExclusiveGuard`; this would deadlock")
141    }
142
143    /// Adds a new stack to the process.
144    /// If the program already exists, then the existing stack is replaced and the original stack is returned.
145    /// Note. This method assumes that the provided stack is valid.
146    #[inline]
147    pub fn add_stack(&self, stack: Stack<N>) -> Option<Arc<Stack<N>>> {
148        // Get the program ID.
149        let program_id = *stack.program_id();
150        // Arc the stack first to limit the scope of the write lock.
151        let stack = Arc::new(stack);
152        // Insert the stack into the process, replacing the existing stack if it exists.
153        self.process.stacks.write().insert(program_id, stack)
154    }
155
156    /// Stages a stack to be added to the process.
157    /// The new stack is active, while the old stack is retained in `old_stacks`.
158    /// The `commit_stacks` method must be called to finalize the addition of the new stack.
159    /// The `revert_stacks` method can be called to revert the staged stacks.
160    #[inline]
161    pub fn stage_stack(&self, stack: Stack<N>) {
162        // Get the program ID.
163        let program_id = *stack.program_id();
164        // Arc the stack first to limit the scope of the write lock.
165        let stack = Arc::new(stack);
166        // If no entry in `old_stacks` exists for `program_id`, store the old stack.
167        // Note: If `old_stack` is `None`, it means that we are adding a new program to the process.
168        let old_stack = self.process.stacks.write().insert(program_id, stack);
169        let mut old_stacks = self.process.old_stacks.write();
170        if !old_stacks.contains_key(&program_id) {
171            old_stacks.insert(program_id, old_stack);
172        }
173    }
174
175    /// Commits the staged stacks to the process.
176    /// This finalizes the addition of the new stacks and clears the old stacks.
177    #[inline]
178    pub fn commit_stacks(&self) {
179        // Clear the old stacks.
180        self.process.old_stacks.write().clear();
181    }
182
183    /// Reverts the staged stacks, restoring the previous state of the process.
184    /// This will remove the new stacks and restore the old stacks.
185    #[inline]
186    pub fn revert_stacks(&self) {
187        // Restore the old stacks.
188        let mut stacks = self.process.stacks.write();
189        for (program_id, stack) in self.process.old_stacks.write().drain(..) {
190            // If the stack is `None`, remove the program from the process.
191            // Otherwise, insert the old stack back into the process.
192            if let Some(stack) = stack {
193                stacks.insert(program_id, stack);
194            } else {
195                stacks.shift_remove(&program_id);
196            }
197        }
198    }
199
200    /// Adds a new program to the process, verifying that it is a valid addition.
201    /// If the program exists, then the existing stack is replaced and discarded.
202    /// Note. This method should **NOT** be used by the on-chain VM to add new program, use `finalize_deployment` or `load_deployment` instead instead.
203    #[inline]
204    pub fn add_program(&self, program: &Program<N>) -> Result<()> {
205        // Initialize the 'credits.aleo' program ID.
206        let credits_program_id = ProgramID::<N>::from_str("credits.aleo")?;
207        // If the program is not 'credits.aleo', compute the program stack, and add it to the process.
208        if program.id() != &credits_program_id {
209            self.add_stack(Stack::new(self.process, program)?);
210        }
211        Ok(())
212    }
213
214    /// Adds a new program with the given edition to the process, verifying that it is a valid addition.
215    /// If the program exists, then the existing stack is replaced and discarded.
216    /// Note. This method should **NOT** be used by the on-chain VM to add new program, use `finalize_deployment` or `load_deployment` instead instead.
217    #[inline]
218    pub fn add_program_with_edition(&self, program: &Program<N>, edition: u16) -> Result<()> {
219        // Initialize the 'credits.aleo' program ID.
220        let credits_program_id = ProgramID::<N>::from_str("credits.aleo")?;
221        // If the program is not 'credits.aleo', compute the program stack, and add it to the process.
222        if program.id() != &credits_program_id {
223            let stack = Stack::new_raw(self.process, program, edition)?;
224            stack.initialize_and_check(self.process)?;
225            self.add_stack(stack);
226        }
227        Ok(())
228    }
229
230    /// Adds a set of programs and editions, in topological order, to the process, deferring validation of the programs until all programs are added.
231    /// If a program exists, then the existing stack is replaced and discarded.
232    /// Either all programs are added or none are.
233    /// Note. This method should **NOT** be used by the on-chain VM to add new program, use `finalize_deployment` or `load_deployment` instead instead.
234    #[inline]
235    pub fn add_programs_with_editions(&self, programs: &[(Program<N>, u16)]) -> Result<()> {
236        // Initialize the 'credits.aleo' program ID.
237        let credits_program_id = ProgramID::<N>::from_str("credits.aleo")?;
238        // Defer cleanup of the uncommitted stacks.
239        defer! {
240            self.revert_stacks()
241        }
242        // Initialize raw stacks for each of the programs, skipping `credits.aleo`.
243        for (program, edition) in programs {
244            if program.id() != &credits_program_id {
245                self.stage_stack(Stack::new_raw(self.process, program, *edition)?)
246            }
247        }
248        // For each stack, check and initialize it before adding it to the process.
249        for (program, _) in programs {
250            // Retrieve the stack.
251            let stack = self.process.get_stack(program.id())?;
252            // Initialize and check the stack for well-formedness.
253            stack.initialize_and_check(self.process)?;
254        }
255        // Commit the staged stacks.
256        self.commit_stacks();
257        Ok(())
258    }
259
260    /// Update the `credits.aleo` program in the VM with the latest verifying keys.
261    pub fn update_credits_verifying_keys(&self) -> Result<()> {
262        // Initialize the store for 'credits.aleo'.
263        let credits = Program::<N>::credits()?;
264
265        // Synthesize the 'credits.aleo' verifying keys.
266        for function_name in credits.functions().keys() {
267            // Remove the proving key.
268            self.process.remove_proving_key(credits.id(), function_name)?;
269            // Load the verifying key.
270            let verifying_key = N::get_credits_verifying_key(function_name.to_string())?;
271            // Retrieve the number of public and private variables.
272            // Note: This number does *NOT* include the number of constants. This is safe because
273            // this program is never deployed, as it is a first-class citizen of the protocol.
274            let num_variables = verifying_key.circuit_info.num_public_and_private_variables as u64;
275            // Insert the verifying key.
276            self.process.insert_verifying_key(
277                credits.id(),
278                function_name,
279                VerifyingKey::new(verifying_key.clone(), num_variables),
280            )?;
281        }
282
283        Ok(())
284    }
285}
286
287impl<N: Network> Process<N> {
288    /// Initializes a new process.
289    #[inline]
290    pub fn setup<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(rng: &mut R) -> Result<Self> {
291        let timer = timer!("Process:setup");
292
293        // Initialize the process.
294        let process = Self {
295            universal_srs: UniversalSRS::load()?,
296            stacks: Default::default(),
297            old_stacks: Default::default(),
298            lock: Default::default(),
299        };
300        lap!(timer, "Initialize process");
301
302        // Initialize the 'credits.aleo' program.
303        let program = Program::credits()?;
304        lap!(timer, "Load credits program");
305
306        // Compute the 'credits.aleo' program stack.
307        let stack = Stack::new(&process, &program)?;
308        lap!(timer, "Initialize stack");
309
310        // Synthesize the 'credits.aleo' circuit keys.
311        for function_name in program.functions().keys() {
312            stack.synthesize_key::<A, _>(function_name, rng)?;
313            lap!(timer, "Synthesize circuit keys for {function_name}");
314        }
315        let rng = &mut rand::rng();
316        let credits_record_name = Identifier::<N>::from_str("credits").unwrap(); // Safe: "credits" is always a valid identifier.
317        stack.synthesize_translation_key::<A, _>(&credits_record_name, rng)?;
318        lap!(timer, "Synthesize credits program keys");
319
320        // Add the 'credits.aleo' stack to the process.
321        process.lock().add_stack(stack);
322
323        finish!(timer);
324        // Return the process.
325        Ok(process)
326    }
327
328    /// Guard the Process against any concurrent reads or writes.
329    pub fn lock(&self) -> ProcessExclusiveGuard<'_, N> {
330        ProcessExclusiveGuard { process: self, _guard: self.lock.lock() }
331    }
332
333    /// Ensure that the types referred to in this program's mappings exist.
334    pub fn mapping_types_exist(&self, program: &Program<N>) -> Result<()> {
335        for mapping in program.mappings().values() {
336            self.plaintext_exists(mapping.key().plaintext_type(), program)?;
337            self.plaintext_exists(mapping.value().plaintext_type(), program)?;
338        }
339        Ok(())
340    }
341
342    // If `type_` is a struct or an array containing a struct, ensure the struct type exists.
343    fn plaintext_exists(&self, type_: &PlaintextType<N>, program: &Program<N>) -> Result<()> {
344        match type_ {
345            PlaintextType::Literal(..) => Ok(()),
346            PlaintextType::Struct(struct_name) => {
347                // Retrieve the struct from the program.
348                ensure!(
349                    program.get_struct(struct_name).is_ok(),
350                    "Struct '{struct_name}' in '{}' is not defined.",
351                    program.id()
352                );
353                Ok(())
354            }
355            PlaintextType::ExternalStruct(locator) => {
356                let stack = self.get_stack(locator.program_id())?;
357                ensure!(
358                    stack.program().get_struct(locator.resource()).is_ok(),
359                    "Struct '{}' in '{}' is not defined.",
360                    locator.resource(),
361                    stack.program().id(),
362                );
363                Ok(())
364            }
365            PlaintextType::Array(array_type) => self.plaintext_exists(array_type.base_element_type(), program),
366        }
367    }
368}
369
370impl<N: Network> Process<N> {
371    /// Initializes a new process.
372    #[inline]
373    pub fn load() -> Result<Self> {
374        let timer = timer!("Process::load");
375
376        // Initialize the process.
377        let process = Self {
378            universal_srs: UniversalSRS::load()?,
379            stacks: Default::default(),
380            old_stacks: Default::default(),
381            lock: Default::default(),
382        };
383        lap!(timer, "Initialize process");
384
385        // Initialize the 'credits.aleo' program.
386        let program = Program::credits()?;
387        lap!(timer, "Load credits program");
388
389        // Compute the 'credits.aleo' program stack.
390        let stack = Stack::new(&process, &program)?;
391        lap!(timer, "Initialize stack");
392
393        // Synthesize the 'credits.aleo' verifying keys.
394        for function_name in program.functions().keys() {
395            // Load the verifying key.
396            let verifying_key = N::get_credits_verifying_key(function_name.to_string())?;
397            // Retrieve the number of public and private variables.
398            // Note: This number does *NOT* include the number of constants. This is safe because
399            // this program is never deployed, as it is a first-class citizen of the protocol.
400            let num_variables = verifying_key.circuit_info.num_public_and_private_variables as u64;
401            // Insert the verifying key.
402            stack.insert_verifying_key(function_name, VerifyingKey::new(verifying_key.clone(), num_variables))?;
403            lap!(timer, "Load verifying key for {function_name}");
404        }
405        lap!(timer, "Load circuit keys");
406
407        // Add the stack to the process.
408        process.lock().add_stack(stack);
409
410        finish!(timer, "Process::load");
411        // Return the process.
412        Ok(process)
413    }
414
415    /// Initializes a new process with the V0 credits.aleo verifiying keys.
416    #[inline]
417    pub fn load_v0() -> Result<Self> {
418        let timer = timer!("Process::load_v0");
419
420        // Initialize the process.
421        let process = Self {
422            universal_srs: UniversalSRS::load()?,
423            stacks: Default::default(),
424            old_stacks: Default::default(),
425            lock: Default::default(),
426        };
427        lap!(timer, "Initialize process");
428
429        // Initialize the 'credits.aleo' program.
430        let program = Program::credits()?;
431        lap!(timer, "Load credits program");
432
433        // Compute the 'credits.aleo' program stack.
434        let stack = Stack::new(&process, &program)?;
435        lap!(timer, "Initialize stack");
436
437        // Synthesize the 'credits.aleo' verifying keys.
438        for function_name in program.functions().keys() {
439            // Load the verifying key.
440            let verifying_key = N::get_credits_v0_verifying_key(function_name.to_string())?;
441            // Retrieve the number of public and private variables.
442            // Note: This number does *NOT* include the number of constants. This is safe because
443            // this program is never deployed, as it is a first-class citizen of the protocol.
444            let num_variables = verifying_key.circuit_info.num_public_and_private_variables as u64;
445            // Insert the verifying key.
446            stack.insert_verifying_key(function_name, VerifyingKey::new(verifying_key.clone(), num_variables))?;
447            lap!(timer, "Load verifying key for {function_name}");
448        }
449        lap!(timer, "Load circuit keys");
450
451        // Add the stack to the process.
452        process.lock().add_stack(stack);
453
454        finish!(timer, "Process::load_v0");
455        // Return the process.
456        Ok(process)
457    }
458
459    /// Initializes a new process without downloading the 'credits.aleo' circuit keys (for web contexts).
460    #[inline]
461    #[cfg(feature = "wasm")]
462    pub fn load_web() -> Result<Self> {
463        // Initialize the process.
464        let process = Self {
465            universal_srs: UniversalSRS::load()?,
466            stacks: Default::default(),
467            old_stacks: Default::default(),
468            lock: Default::default(),
469        };
470
471        // Initialize the 'credits.aleo' program.
472        let program = Program::credits()?;
473
474        // Compute the 'credits.aleo' program stack.
475        let stack = Stack::new(&process, &program)?;
476
477        // Add the stack to the process.
478        process.lock().add_stack(stack);
479
480        // Return the process.
481        Ok(process)
482    }
483
484    /// Returns the universal SRS.
485    #[inline]
486    pub const fn universal_srs(&self) -> &UniversalSRS<N> {
487        &self.universal_srs
488    }
489
490    /// Returns `true` if the process contains the program with the given ID.
491    #[inline]
492    pub fn contains_program(&self, program_id: &ProgramID<N>) -> bool {
493        self.stacks.read().contains_key(program_id)
494    }
495
496    /// Returns the program IDs of all programs in the process.
497    #[inline]
498    pub fn program_ids(&self) -> Vec<ProgramID<N>> {
499        self.stacks.read().keys().copied().collect()
500    }
501
502    /// Returns the stack for the given program ID.
503    #[inline]
504    pub fn get_stack(&self, program_id: impl TryInto<ProgramID<N>>) -> Result<Arc<Stack<N>>> {
505        // Prepare the program ID.
506        let program_id = program_id.try_into().map_err(|_| anyhow!("Invalid program ID"))?;
507        // Retrieve the stack.
508        let stack = self
509            .stacks
510            .read()
511            .get(&program_id)
512            .ok_or_else(|| anyhow!("Program '{program_id}' does not exist"))?
513            .clone();
514        // Ensure the program ID matches.
515        ensure!(stack.program_id() == &program_id, "Expected program '{}', found '{program_id}'", stack.program_id());
516        // Return the stack.
517        Ok(stack)
518    }
519
520    /// Returns the latest deployed edition for the given program ID, defaulting to 0 if unknown.
521    #[inline]
522    pub fn get_latest_edition_for_program(&self, program_id: &ProgramID<N>) -> u16 {
523        self.get_stack(program_id).ok().map(|s| *s.program_edition()).unwrap_or(0u16)
524    }
525
526    /// Returns the proving key for the given program ID and function name.
527    #[inline]
528    pub fn get_proving_key(
529        &self,
530        program_id: impl TryInto<ProgramID<N>>,
531        function_name: impl TryInto<Identifier<N>>,
532    ) -> Result<ProvingKey<N>> {
533        // Prepare the function name.
534        let function_name = function_name.try_into().map_err(|_| anyhow!("Invalid function name"))?;
535        // Return the proving key.
536        self.get_stack(program_id)?.get_proving_key(&function_name)
537    }
538
539    /// Returns the verifying key for the given program ID and function name.
540    #[inline]
541    pub fn get_verifying_key(
542        &self,
543        program_id: impl TryInto<ProgramID<N>>,
544        function_name: impl TryInto<Identifier<N>>,
545    ) -> Result<VerifyingKey<N>> {
546        // Prepare the function name.
547        let function_name = function_name.try_into().map_err(|_| anyhow!("Invalid function name"))?;
548        // Return the verifying key.
549        self.get_stack(program_id)?.get_verifying_key(&function_name)
550    }
551
552    /// Inserts the given proving key, for the given program ID and function name.
553    #[inline]
554    pub fn insert_proving_key(
555        &self,
556        program_id: &ProgramID<N>,
557        function_name: &Identifier<N>,
558        proving_key: ProvingKey<N>,
559    ) -> Result<()> {
560        self.get_stack(program_id)?.insert_proving_key(function_name, proving_key)
561    }
562
563    /// Removes the given proving key, for the given program ID and function name.
564    #[inline]
565    pub fn remove_proving_key(&self, program_id: &ProgramID<N>, function_name: &Identifier<N>) -> Result<()> {
566        self.get_stack(program_id)?.remove_proving_key(function_name);
567        Ok(())
568    }
569
570    /// Inserts the given verifying key, for the given program ID and function name.
571    #[inline]
572    pub fn insert_verifying_key(
573        &self,
574        program_id: &ProgramID<N>,
575        function_name: &Identifier<N>,
576        verifying_key: VerifyingKey<N>,
577    ) -> Result<()> {
578        self.get_stack(program_id)?.insert_verifying_key(function_name, verifying_key)
579    }
580
581    /// Removes the given verifying key, for the given program ID and function name.
582    #[inline]
583    pub fn remove_verifying_key(&self, program_id: &ProgramID<N>, function_name: &Identifier<N>) -> Result<()> {
584        self.get_stack(program_id)?.remove_verifying_key(function_name);
585        Ok(())
586    }
587
588    /// Synthesizes the proving and verifying key for the given program ID and function name.
589    #[inline]
590    pub fn synthesize_key<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(
591        &self,
592        program_id: &ProgramID<N>,
593        function_name: &Identifier<N>,
594        rng: &mut R,
595    ) -> Result<()> {
596        // Synthesize the proving and verifying key.
597        self.get_stack(program_id)?.synthesize_key::<A, R>(function_name, rng)
598    }
599
600    /// Synthesizes the translation key for the given record name.
601    #[inline]
602    pub fn synthesize_translation_key<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(
603        &self,
604        program_id: &ProgramID<N>,
605        record_name: &Identifier<N>,
606        rng: &mut R,
607    ) -> Result<()> {
608        self.get_stack(program_id)?.synthesize_translation_key::<A, R>(record_name, rng)
609    }
610}
611
612#[cfg(test)]
613pub mod test_helpers {
614    use super::*;
615    use console::{account::PrivateKey, network::MainnetV0, program::Identifier};
616    use snarkvm_ledger_block::Transition;
617    use snarkvm_ledger_query::Query;
618    use snarkvm_ledger_store::{BlockStore, helpers::memory::BlockMemory};
619    use snarkvm_synthesizer_program::Program;
620
621    use aleo_std::StorageMode;
622    use std::sync::OnceLock;
623
624    type CurrentNetwork = MainnetV0;
625    type CurrentAleo = circuit::network::AleoV0;
626
627    /// Returns an execution for the given program and function name.
628    pub fn get_execution(
629        process: &mut Process<CurrentNetwork>,
630        program: &Program<CurrentNetwork>,
631        function_name: &Identifier<CurrentNetwork>,
632        inputs: impl ExactSizeIterator<Item = impl TryInto<Value<CurrentNetwork>>>,
633    ) -> Execution<CurrentNetwork> {
634        // Initialize a new rng.
635        let rng = &mut TestRng::default();
636
637        // Initialize a private key.
638        let private_key = PrivateKey::new(rng).unwrap();
639
640        // Add the program to the process if doesn't yet exist.
641        if !process.contains_program(program.id()) {
642            process.lock().add_program(program).unwrap();
643        }
644
645        // Compute the authorization.
646        let authorization =
647            process.authorize::<CurrentAleo, _>(&private_key, program.id(), function_name, inputs, rng).unwrap();
648
649        // Execute the program.
650        let (_, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
651
652        // Initialize a new block store.
653        let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap();
654
655        // Prepare the assignments from the block store.
656        trace.prepare(&snarkvm_ledger_query::Query::from(block_store)).unwrap();
657
658        // Get the locator.
659        let locator = format!("{:?}:{function_name:?}", program.id());
660
661        // Return the execution object.
662        trace.prove_execution::<CurrentAleo, _>(&locator, VarunaVersion::V1, rng).unwrap()
663    }
664
665    pub fn sample_key() -> (Identifier<CurrentNetwork>, ProvingKey<CurrentNetwork>, VerifyingKey<CurrentNetwork>) {
666        static INSTANCE: OnceLock<(
667            Identifier<CurrentNetwork>,
668            ProvingKey<CurrentNetwork>,
669            VerifyingKey<CurrentNetwork>,
670        )> = OnceLock::new();
671        INSTANCE
672            .get_or_init(|| {
673                // Initialize a new program.
674                let (string, program) = Program::<CurrentNetwork>::parse(
675                    r"
676program testing.aleo;
677
678function compute:
679    input r0 as u32.private;
680    input r1 as u32.public;
681    add r0 r1 into r2;
682    output r2 as u32.public;",
683                )
684                .unwrap();
685                assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
686
687                // Declare the function name.
688                let function_name = Identifier::from_str("compute").unwrap();
689
690                // Initialize the RNG.
691                let rng = &mut TestRng::default();
692
693                // Construct the process.
694                let process = sample_process(&program);
695
696                // Synthesize a proving and verifying key.
697                process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, rng).unwrap();
698
699                // Get the proving and verifying key.
700                let proving_key = process.get_proving_key(program.id(), function_name).unwrap();
701                let verifying_key = process.get_verifying_key(program.id(), function_name).unwrap();
702
703                (function_name, proving_key, verifying_key)
704            })
705            .clone()
706    }
707
708    pub(crate) fn sample_execution() -> Execution<CurrentNetwork> {
709        static INSTANCE: OnceLock<Execution<CurrentNetwork>> = OnceLock::new();
710        INSTANCE
711            .get_or_init(|| {
712                // Initialize a new program.
713                let (string, program) = Program::<CurrentNetwork>::parse(
714                    r"
715program testing.aleo;
716
717function compute:
718    input r0 as u32.private;
719    input r1 as u32.public;
720    add r0 r1 into r2;
721    output r2 as u32.public;",
722                )
723                .unwrap();
724                assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
725
726                // Declare the function name.
727                let function_name = Identifier::from_str("compute").unwrap();
728
729                // Initialize the RNG.
730                let rng = &mut TestRng::default();
731                // Initialize a new caller account.
732                let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
733
734                // Initialize a new block store.
735                let block_store =
736                    BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap();
737
738                // Construct the process.
739                let process = sample_process(&program);
740                // Authorize the function call.
741                let authorization = process
742                    .authorize::<CurrentAleo, _>(
743                        &caller_private_key,
744                        program.id(),
745                        function_name,
746                        ["5u32", "10u32"].into_iter(),
747                        rng,
748                    )
749                    .unwrap();
750                assert_eq!(authorization.len(), 1);
751                // Execute the request.
752                let (_response, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
753                assert_eq!(trace.transitions().len(), 1);
754
755                // Prepare the trace.
756                trace.prepare(&Query::from(block_store)).unwrap();
757                // Compute the execution.
758                trace.prove_execution::<CurrentAleo, _>("testing", VarunaVersion::V1, rng).unwrap()
759            })
760            .clone()
761    }
762
763    pub fn sample_transition() -> Transition<CurrentNetwork> {
764        // Retrieve the execution.
765        let mut execution = sample_execution();
766        // Ensure the execution is not empty.
767        assert!(!execution.is_empty());
768        // Return the transition.
769        execution.pop().unwrap()
770    }
771
772    /// Initializes a new process with the given program.
773    pub(crate) fn sample_process(program: &Program<CurrentNetwork>) -> Process<CurrentNetwork> {
774        // Construct a new process.
775        let process = Process::load().unwrap();
776        // Add the program to the process.
777        process.lock().add_program(program).unwrap();
778        // Return the process.
779        process
780    }
781}