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