snarkvm_synthesizer_process/stack/
authorize.rs

1// Copyright (c) 2019-2025 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
16use super::*;
17
18impl<N: Network> Stack<N> {
19    /// Authorizes a call to the program function for the given inputs.
20    #[inline]
21    pub fn authorize<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(
22        &self,
23        private_key: &PrivateKey<N>,
24        function_name: impl TryInto<Identifier<N>>,
25        inputs: impl ExactSizeIterator<Item = impl TryInto<Value<N>>>,
26        rng: &mut R,
27    ) -> Result<Authorization<N>> {
28        let timer = timer!("Stack::authorize");
29
30        // Get the program ID.
31        let program_id = *self.program.id();
32        // Prepare the function name.
33        let function_name = function_name.try_into().map_err(|_| anyhow!("Invalid function name"))?;
34        // Retrieve the input types.
35        let input_types = self.get_function(&function_name)?.input_types();
36        lap!(timer, "Retrieve the input types");
37        // Set is_root to true.
38        let is_root = true;
39        // Retrieve the program checksum, if the program has a constructor.
40        let program_checksum = match self.program().contains_constructor() {
41            true => Some(self.program_checksum_as_field()?),
42            false => None,
43        };
44
45        // This is the root request and does not have a caller.
46        let caller = None;
47        // This is the root request and we do not have a root_tvk to pass on.
48        let root_tvk = None;
49        // Compute the request.
50        let request = Request::sign(
51            private_key,
52            program_id,
53            function_name,
54            inputs,
55            &input_types,
56            root_tvk,
57            is_root,
58            program_checksum,
59            rng,
60        )?;
61        lap!(timer, "Compute the request");
62        // Initialize the authorization.
63        let authorization = Authorization::new(request.clone());
64        // Construct the call stack.
65        let call_stack = CallStack::Authorize(vec![request], Some(*private_key), authorization.clone());
66        // Construct the authorization from the function.
67        let _response = self.execute_function::<A, R>(call_stack, caller, root_tvk, rng)?;
68        finish!(timer, "Construct the authorization from the function");
69
70        // Return the authorization.
71        Ok(authorization)
72    }
73
74    /// Authorizes a call to the program function for the given inputs.
75    /// Compared to `authorize`, this method does not check for circuit satisfiability of the request.
76    #[inline]
77    pub fn authorize_unchecked<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(
78        &self,
79        private_key: &PrivateKey<N>,
80        function_name: impl TryInto<Identifier<N>>,
81        inputs: impl ExactSizeIterator<Item = impl TryInto<Value<N>>>,
82        rng: &mut R,
83    ) -> Result<Authorization<N>> {
84        let timer = timer!("Stack::authorize_unchecked");
85
86        // Get the program ID.
87        let program_id = *self.program.id();
88        // Prepare the function name.
89        let function_name = function_name.try_into().map_err(|_| anyhow!("Invalid function name"))?;
90        // Retrieve the input types.
91        let input_types = self.get_function(&function_name)?.input_types();
92        lap!(timer, "Retrieve the input types");
93        // Set is_root to true.
94        let is_root = true;
95
96        // This is the root request and does not have a caller.
97        let caller = None;
98        // This is the root request and we do not have a root_tvk to pass on.
99        let root_tvk = None;
100        // Retrieve the program checksum, if the program has a constructor.
101        let program_checksum = match self.program().contains_constructor() {
102            true => Some(self.program_checksum_as_field()?),
103            false => None,
104        };
105        // Compute the request.
106        let request = Request::sign(
107            private_key,
108            program_id,
109            function_name,
110            inputs,
111            &input_types,
112            root_tvk,
113            is_root,
114            program_checksum,
115            rng,
116        )?;
117        lap!(timer, "Compute the request");
118        // Initialize the authorization.
119        let authorization = Authorization::new(request.clone());
120        // Construct the call stack.
121        let call_stack = CallStack::Authorize(vec![request], Some(*private_key), authorization.clone());
122        // Construct the authorization from the function.
123        let _response = self.evaluate_function::<A, R>(call_stack, caller, root_tvk, rng)?;
124        finish!(timer, "Construct the authorization from the function");
125
126        // Return the authorization.
127        Ok(authorization)
128    }
129
130    /// Authorizes a call to a public function for the given request.
131    /// Compared to `authorize`, no private key is needed, but this only works for single public requests.
132    #[inline]
133    pub fn authorize_request<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(
134        &self,
135        request: Request<N>,
136        rng: &mut R,
137    ) -> Result<Authorization<N>> {
138        let timer = timer!("Stack::authorize_request");
139
140        // Get the program ID.
141        let program_id = *self.program.id();
142        // Ensure the program ID is credits.aleo.
143        ensure!(program_id.to_string() == "credits.aleo", "Program ID must be credits.aleo");
144        // Initialize the authorization.
145        let authorization = Authorization::new(request.clone());
146        // Construct the call stack.
147        let call_stack = CallStack::Authorize(vec![request], None, authorization.clone());
148        // This is the root request and does not have a caller.
149        let caller = None;
150        // This is the root request and we do not have a root_tvk to pass on.
151        let root_tvk = None;
152        // Construct the authorization from the function.
153        let _response = self.evaluate_function::<A, R>(call_stack, caller, root_tvk, rng)?;
154        finish!(timer, "Construct the authorization from the function");
155
156        // Return the authorization.
157        Ok(authorization)
158    }
159}