execute.rs
1 // Copyright (c) 2025 ADnet Contributors 2 // This file is part of the AlphaVM 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 use super::*; 17 18 impl<N: Network> Process<N> { 19 /// Executes the given authorization. 20 #[inline] 21 pub fn execute<A: circuit::Aleo<Network = N>, R: CryptoRng + Rng>( 22 &self, 23 authorization: Authorization<N>, 24 rng: &mut R, 25 ) -> Result<(Response<N>, Trace<N>)> { 26 let timer = timer!("Process::execute"); 27 28 // Retrieve the main request (without popping it). 29 let request = authorization.peek_next()?; 30 // Construct the locator. 31 let locator = Locator::new(*request.program_id(), *request.function_name()); 32 33 dev_println!("{}", format!(" • Executing '{locator}'...",)); 34 35 // The root request does not have a caller. 36 let caller = None; 37 // The root request does not have to pass on another request's root_tvk. 38 let root_tvk = None; 39 // Initialize the trace. 40 let trace = Arc::new(RwLock::new(Trace::new())); 41 // Initialize the call stack. 42 let call_stack = CallStack::execute(authorization, trace.clone())?; 43 lap!(timer, "Initialize call stack"); 44 45 // Retrieve the stack. 46 let stack = self.get_stack(request.program_id())?; 47 // Execute the circuit. 48 let response = stack.execute_function::<A, R>(call_stack, caller, root_tvk, rng)?; 49 lap!(timer, "Execute the function"); 50 51 // Extract the trace. 52 let trace = Arc::try_unwrap(trace).unwrap().into_inner(); 53 // Ensure the trace is not empty. 54 ensure!(!trace.transitions().is_empty(), "Execution of '{locator}' is empty"); 55 56 finish!(timer); 57 Ok((response, trace)) 58 } 59 } 60 61 #[cfg(test)] 62 mod tests { 63 use super::*; 64 use console::types::Address; 65 66 type CurrentNetwork = console::network::MainnetV0; 67 type CurrentAleo = circuit::AleoV0; 68 69 #[test] 70 fn test_execute_fee_private() { 71 let rng = &mut TestRng::default(); 72 73 // Initialize the process. 74 let process = Process::<CurrentNetwork>::load().unwrap(); 75 76 // Sample a private key. 77 let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 78 let owner = Address::try_from(private_key).unwrap(); 79 80 // Sample a base fee in microcredits. 81 let base_fee_in_microcredits = rng.gen_range(1_000_000..u64::MAX / 2); 82 // Sample a priority fee in microcredits. 83 let priority_fee_in_microcredits = rng.gen_range(0..u64::MAX / 2); 84 // Sample a deployment or execution ID. 85 let deployment_or_execution_id = Field::rand(rng); 86 87 // Sample a credits record. 88 let fee_in_microcredits = base_fee_in_microcredits.saturating_add(priority_fee_in_microcredits); 89 let credits = Record::<CurrentNetwork, Plaintext<_>>::from_str(&format!( 90 "{{ owner: {owner}.private, microcredits: {fee_in_microcredits}u64.private, _nonce: 0group.public, _version: 1u8.public }}" 91 )) 92 .unwrap(); 93 94 // Initialize the authorization. 95 let authorization = process 96 .authorize_fee_private::<CurrentAleo, _>( 97 &private_key, 98 credits, 99 base_fee_in_microcredits, 100 priority_fee_in_microcredits, 101 deployment_or_execution_id, 102 rng, 103 ) 104 .unwrap(); 105 assert!(authorization.is_fee_private(), "Authorization must be for a call to 'credits.alpha/fee_private'"); 106 107 // Execute the authorization. 108 let (response, trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 109 // Ensure the response has 1 output. 110 assert_eq!(response.outputs().len(), 1, "Execution of 'credits.alpha/fee_private' must contain 1 output"); 111 // Ensure the response has 1 output ID. 112 assert_eq!(response.output_ids().len(), 1, "Execution of 'credits.alpha/fee_private' must contain 1 output ID"); 113 // Ensure the trace contains 1 transition. 114 assert_eq!(trace.transitions().len(), 1, "Execution of 'credits.alpha/fee_private' must contain 1 transition"); 115 116 // Retrieve the transition. 117 let transition = trace.transitions()[0].clone(); 118 assert!(transition.is_fee_private(), "Transition must be for 'credits.alpha/fee_private'"); 119 } 120 121 #[test] 122 fn test_execute_fee_public() { 123 let rng = &mut TestRng::default(); 124 125 // Initialize the process. 126 let process = Process::<CurrentNetwork>::load().unwrap(); 127 128 // Sample a private key. 129 let private_key = PrivateKey::new(rng).unwrap(); 130 // Sample a base fee in microcredits. 131 let base_fee_in_microcredits = rng.gen_range(1_000_000..u64::MAX / 2); 132 // Sample a priority fee in microcredits. 133 let priority_fee_in_microcredits = rng.gen_range(0..u64::MAX / 2); 134 // Sample a deployment or execution ID. 135 let deployment_or_execution_id = Field::rand(rng); 136 137 // Compute the authorization. 138 let authorization = process 139 .authorize_fee_public::<CurrentAleo, _>( 140 &private_key, 141 base_fee_in_microcredits, 142 priority_fee_in_microcredits, 143 deployment_or_execution_id, 144 rng, 145 ) 146 .unwrap(); 147 assert!(authorization.is_fee_public(), "Authorization must be for a call to 'credits.alpha/fee_public'"); 148 149 // Execute the authorization. 150 let (response, trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 151 // Ensure the response has 1 outputs. 152 assert_eq!(response.outputs().len(), 1, "Execution of 'credits.alpha/fee_public' must contain 1 output"); 153 // Ensure the response has 1 output IDs. 154 assert_eq!(response.output_ids().len(), 1, "Execution of 'credits.alpha/fee_public' must contain 1 output ID"); 155 // Ensure the trace contains 1 transition. 156 assert_eq!(trace.transitions().len(), 1, "Execution of 'credits.alpha/fee_public' must contain 1 transition"); 157 158 // Retrieve the transition. 159 let transition = trace.transitions()[0].clone(); 160 assert!(transition.is_fee_public(), "Transition must be for 'credits.alpha/fee_public'"); 161 } 162 }