run.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 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> Package<N> { 19 /// Runs a program function with the given inputs. 20 pub fn run<A: crate::circuit::Alpha<Network = N, BaseField = N::Field>, R: Rng + CryptoRng>( 21 &self, 22 private_key: &PrivateKey<N>, 23 function_name: Identifier<N>, 24 inputs: &[Value<N>], 25 rng: &mut R, 26 ) -> Result<(Response<N>, Vec<CallMetrics<N>>)> { 27 // Retrieve the main program. 28 let program = self.program(); 29 // Retrieve the program ID. 30 let program_id = program.id(); 31 // Ensure that the function exists. 32 if !program.contains_function(&function_name) { 33 bail!("Function '{function_name}' does not exist.") 34 } 35 36 // Prepare the locator (even if logging is disabled, to sanity check the locator is well-formed). 37 let _locator = Locator::<N>::from_str(&format!("{program_id}/{function_name}"))?; 38 39 dev_println!("🚀 Running '{}'...\n", _locator.to_string()); 40 41 // Construct the process. 42 let process = self.get_process()?; 43 // Authorize the function call. 44 let authorization = process.authorize::<A, R>(private_key, program_id, function_name, inputs.iter(), rng)?; 45 46 // TODO (howardwu): Retrieve the value directly from the authorize call. 47 // Pop the first request. 48 let request = authorization.next()?; 49 // Retrieve the stack. 50 let stack = process.get_stack(program_id)?; 51 // Initialize the assignments. 52 let assignments = Assignments::<N>::default(); 53 // Initialize the call stack. 54 let call_stack = CallStack::PackageRun(vec![request], *private_key, assignments.clone()); 55 // Synthesize the circuit. 56 let response = stack.execute_function::<A, R>(call_stack, None, None, rng)?; 57 // Retrieve the call metrics. 58 let call_metrics = assignments.read().iter().map(|(_, metrics)| *metrics).collect::<Vec<_>>(); 59 // Return the response and call metrics. 60 Ok((response, call_metrics)) 61 } 62 } 63 64 #[cfg(test)] 65 mod tests { 66 use super::*; 67 use alphavm_utilities::TestRng; 68 69 type CurrentAlpha = alphavm_circuit::network::AlphaV0; 70 71 #[test] 72 fn test_run() { 73 // Samples a new package at a temporary directory. 74 let (directory, package) = crate::package::test_helpers::sample_token_package(); 75 76 // Ensure the build directory does *not* exist. 77 assert!(!package.build_directory().exists()); 78 // Build the package. 79 package.build::<CurrentAlpha>().unwrap(); 80 // Ensure the build directory exists. 81 assert!(package.build_directory().exists()); 82 83 // Initialize an RNG. 84 let rng = &mut TestRng::default(); 85 // Sample the function inputs. 86 let (private_key, function_name, inputs) = 87 crate::package::test_helpers::sample_package_run(package.program_id()); 88 // Run the program function. 89 let (_response, _metrics) = package.run::<CurrentAlpha, _>(&private_key, function_name, &inputs, rng).unwrap(); 90 91 // Proactively remove the temporary directory (to conserve space). 92 std::fs::remove_dir_all(directory).unwrap(); 93 } 94 95 #[test] 96 fn test_run_with_import() { 97 // Samples a new package at a temporary directory. 98 let (directory, package) = crate::package::test_helpers::sample_wallet_package(); 99 100 // Ensure the build directory does *not* exist. 101 assert!(!package.build_directory().exists()); 102 // Build the package. 103 package.build::<CurrentAlpha>().unwrap(); 104 // Ensure the build directory exists. 105 assert!(package.build_directory().exists()); 106 107 // Initialize an RNG. 108 let rng = &mut TestRng::default(); 109 // Sample the function inputs. 110 let (private_key, function_name, inputs) = 111 crate::package::test_helpers::sample_package_run(package.program_id()); 112 // Run the program function. 113 let (_response, _metrics) = package.run::<CurrentAlpha, _>(&private_key, function_name, &inputs, rng).unwrap(); 114 115 // Proactively remove the temporary directory (to conserve space). 116 std::fs::remove_dir_all(directory).unwrap(); 117 } 118 119 #[test] 120 fn test_run_with_nested_imports() { 121 // Samples a new package at a temporary directory. 122 let (directory, package) = crate::package::test_helpers::sample_nested_package(); 123 124 // Ensure the build directory does *not* exist. 125 assert!(!package.build_directory().exists()); 126 // Build the package. 127 package.build::<CurrentAlpha>().unwrap(); 128 // Ensure the build directory exists. 129 assert!(package.build_directory().exists()); 130 131 // Initialize an RNG. 132 let rng = &mut TestRng::default(); 133 // Sample the function inputs. 134 let (private_key, function_name, inputs) = 135 crate::package::test_helpers::sample_package_run(package.program_id()); 136 // Run the program function. 137 let (_response, _metrics) = package.run::<CurrentAlpha, _>(&private_key, function_name, &inputs, rng).unwrap(); 138 139 // Proactively remove the temporary directory (to conserve space). 140 std::fs::remove_dir_all(directory).unwrap(); 141 } 142 143 /// Use `cargo test profiler --features timer` to run this test. 144 #[ignore] 145 #[test] 146 fn test_profiler() -> Result<()> { 147 // Samples a new package at a temporary directory. 148 let (directory, package) = crate::package::test_helpers::sample_token_package(); 149 150 // Ensure the build directory does *not* exist. 151 assert!(!package.build_directory().exists()); 152 // Build the package. 153 package.build::<CurrentAlpha>().unwrap(); 154 // Ensure the build directory exists. 155 assert!(package.build_directory().exists()); 156 157 // Initialize an RNG. 158 let rng = &mut TestRng::default(); 159 // Sample the function inputs. 160 let (private_key, function_name, inputs) = 161 crate::package::test_helpers::sample_package_run(package.program_id()); 162 // Run the program function. 163 let (_response, _metrics) = package.run::<CurrentAlpha, _>(&private_key, function_name, &inputs, rng).unwrap(); 164 165 // Proactively remove the temporary directory (to conserve space). 166 std::fs::remove_dir_all(directory).unwrap(); 167 168 bail!("\n\nRemember to #[ignore] this test!\n\n") 169 } 170 }