snarkvm_synthesizer_process/
execute.rs1use super::*;
17use snarkvm_synthesizer_error::*;
18
19impl<N: Network> Process<N> {
20 #[inline]
22 pub fn execute<A: circuit::Aleo<Network = N>, R: CryptoRng + Rng>(
23 &self,
24 authorization: Authorization<N>,
25 rng: &mut R,
26 ) -> Result<(Response<N>, Trace<N>), ProcessExecError> {
27 let timer = timer!("Process::execute");
28
29 let request = authorization.peek_next()?;
31 let locator = Locator::new(*request.program_id(), *request.function_name());
33
34 dev_println!("{}", format!(" • Executing '{locator}'...",));
35
36 let caller = None;
38 let root_tvk = None;
40 let trace = Arc::new(RwLock::new(Trace::new()));
42 let translations = Arc::new(RwLock::new(Vec::new()));
44 let call_stack = CallStack::execute(authorization, trace.clone(), translations)?;
46 lap!(timer, "Initialize call stack");
47
48 let stack = self.get_stack(request.program_id())?;
50 let response = stack.execute_function::<A, R>(call_stack, caller, root_tvk, rng)?;
52 lap!(timer, "Execute the function");
53
54 let mut trace = Arc::try_unwrap(trace).unwrap().into_inner();
56 if trace.transitions().is_empty() {
58 return Err(anyhow!("Execution of '{locator}' is empty").into());
59 }
60 trace.construct_call_graph(self)?;
62
63 finish!(timer);
64 Ok((response, trace))
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71 use console::types::Address;
72
73 type CurrentNetwork = console::network::MainnetV0;
74 type CurrentAleo = circuit::AleoV0;
75
76 #[test]
77 fn test_execute_fee_private() {
78 let rng = &mut TestRng::default();
79
80 let process = Process::<CurrentNetwork>::load().unwrap();
82
83 let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
85 let owner = Address::try_from(private_key).unwrap();
86
87 let base_fee_in_microcredits = rng.gen_range(1_000_000..u64::MAX / 2);
89 let priority_fee_in_microcredits = rng.gen_range(0..u64::MAX / 2);
91 let deployment_or_execution_id = Field::rand(rng);
93
94 let fee_in_microcredits = base_fee_in_microcredits.saturating_add(priority_fee_in_microcredits);
96 let credits = Record::<CurrentNetwork, Plaintext<_>>::from_str(&format!(
97 "{{ owner: {owner}.private, microcredits: {fee_in_microcredits}u64.private, _nonce: 0group.public, _version: 1u8.public }}"
98 ))
99 .unwrap();
100
101 let authorization = process
103 .authorize_fee_private::<CurrentAleo, _>(
104 &private_key,
105 credits,
106 base_fee_in_microcredits,
107 priority_fee_in_microcredits,
108 deployment_or_execution_id,
109 rng,
110 )
111 .unwrap();
112 assert!(authorization.is_fee_private(), "Authorization must be for a call to 'credits.aleo/fee_private'");
113
114 let (response, trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
116 assert_eq!(response.outputs().len(), 1, "Execution of 'credits.aleo/fee_private' must contain 1 output");
118 assert_eq!(response.output_ids().len(), 1, "Execution of 'credits.aleo/fee_private' must contain 1 output ID");
120 assert_eq!(trace.transitions().len(), 1, "Execution of 'credits.aleo/fee_private' must contain 1 transition");
122
123 let transition = trace.transitions()[0].clone();
125 assert!(transition.is_fee_private(), "Transition must be for 'credits.aleo/fee_private'");
126 }
127
128 #[test]
129 fn test_execute_fee_public() {
130 let rng = &mut TestRng::default();
131
132 let process = Process::<CurrentNetwork>::load().unwrap();
134
135 let private_key = PrivateKey::new(rng).unwrap();
137 let base_fee_in_microcredits = rng.gen_range(1_000_000..u64::MAX / 2);
139 let priority_fee_in_microcredits = rng.gen_range(0..u64::MAX / 2);
141 let deployment_or_execution_id = Field::rand(rng);
143
144 let authorization = process
146 .authorize_fee_public::<CurrentAleo, _>(
147 &private_key,
148 base_fee_in_microcredits,
149 priority_fee_in_microcredits,
150 deployment_or_execution_id,
151 rng,
152 )
153 .unwrap();
154 assert!(authorization.is_fee_public(), "Authorization must be for a call to 'credits.aleo/fee_public'");
155
156 let (response, trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
158 assert_eq!(response.outputs().len(), 1, "Execution of 'credits.aleo/fee_public' must contain 1 output");
160 assert_eq!(response.output_ids().len(), 1, "Execution of 'credits.aleo/fee_public' must contain 1 output ID");
162 assert_eq!(trace.transitions().len(), 1, "Execution of 'credits.aleo/fee_public' must contain 1 transition");
164
165 let transition = trace.transitions()[0].clone();
167 assert!(transition.is_fee_public(), "Transition must be for 'credits.aleo/fee_public'");
168 }
169}