Skip to main content

snarkvm_synthesizer_process/stack/
authorize.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
16use super::*;
17use snarkvm_synthesizer_error::*;
18
19impl<N: Network> Stack<N> {
20    /// Authorizes a call to the program function for the given inputs.
21    #[inline]
22    pub fn authorize<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(
23        &self,
24        private_key: &PrivateKey<N>,
25        function_name: impl TryInto<Identifier<N>>,
26        inputs: impl ExactSizeIterator<Item = impl TryInto<Value<N>>>,
27        rng: &mut R,
28    ) -> Result<Authorization<N>, StackAuthError> {
29        let timer = timer!("Stack::authorize");
30
31        // Get the program ID.
32        let program_id = *self.program.id();
33        // Prepare the function name.
34        let function_name = function_name.try_into().map_err(|_| anyhow!("Invalid function name"))?;
35        // Retrieve the input types.
36        let input_types = self.get_function(&function_name)?.input_types();
37        lap!(timer, "Retrieve the input types");
38        // Set is_root to true.
39        let is_root = true;
40        // Retrieve the program checksum, if the program has a constructor.
41        let program_checksum = match self.program().contains_constructor() {
42            true => Some(self.program_checksum_as_field()?),
43            false => None,
44        };
45
46        // This is the root request and does not have a caller.
47        let caller = None;
48        // This is the root request and we do not have a root_tvk to pass on.
49        let root_tvk = None;
50        // Compute the request.
51        let request = Request::sign(
52            private_key,
53            program_id,
54            function_name,
55            inputs,
56            &input_types,
57            root_tvk,
58            is_root,
59            program_checksum,
60            false,
61            rng,
62        )?;
63        lap!(timer, "Compute the request");
64        // Initialize the authorization.
65        let authorization = Authorization::new(request.clone());
66        // Construct the call stack.
67        let call_stack = CallStack::Authorize(vec![request], Some(*private_key), authorization.clone());
68        // Construct the authorization from the function.
69        let _response = self.execute_function::<A, R>(call_stack, caller, root_tvk, rng)?;
70        finish!(timer, "Construct the authorization from the function");
71
72        // Return the authorization.
73        Ok(authorization)
74    }
75
76    /// Authorizes a call to the program function for the given inputs.
77    /// Compared to `authorize`, this method does not check for circuit satisfiability of the request.
78    #[inline]
79    pub fn authorize_unchecked<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(
80        &self,
81        private_key: &PrivateKey<N>,
82        function_name: impl TryInto<Identifier<N>>,
83        inputs: impl ExactSizeIterator<Item = impl TryInto<Value<N>>>,
84        rng: &mut R,
85    ) -> Result<Authorization<N>, StackAuthError> {
86        let timer = timer!("Stack::authorize_unchecked");
87
88        // Get the program ID.
89        let program_id = *self.program.id();
90        // Prepare the function name.
91        let function_name = function_name.try_into().map_err(|_| anyhow!("Invalid function name"))?;
92        // Retrieve the input types.
93        let input_types = self.get_function(&function_name)?.input_types();
94        lap!(timer, "Retrieve the input types");
95        // Set is_root to true.
96        let is_root = true;
97
98        // This is the root request and does not have a caller.
99        let caller = None;
100        // This is the root request and we do not have a root_tvk to pass on.
101        let root_tvk = None;
102        // Retrieve the program checksum, if the program has a constructor.
103        let program_checksum = match self.program().contains_constructor() {
104            true => Some(self.program_checksum_as_field()?),
105            false => None,
106        };
107        // Compute the request.
108        let request = Request::sign(
109            private_key,
110            program_id,
111            function_name,
112            inputs,
113            &input_types,
114            root_tvk,
115            is_root,
116            program_checksum,
117            false,
118            rng,
119        )?;
120        lap!(timer, "Compute the request");
121        // Initialize the authorization.
122        let authorization = Authorization::new(request.clone());
123        // Construct the call stack.
124        let call_stack = CallStack::Authorize(vec![request], Some(*private_key), authorization.clone());
125        // Construct the authorization from the function.
126        let _response = self.evaluate_function::<A, R>(call_stack, caller, root_tvk, rng)?;
127        finish!(timer, "Construct the authorization from the function");
128
129        // Return the authorization.
130        Ok(authorization)
131    }
132
133    /// Produces a mocked `Authorization` for a call to the given function on
134    /// the supplied inputs using the provided caller address. The resulting
135    /// `Authorization` has the same size as the one which would be produced
136    /// (and signed) using the private key corresponding to that address and can
137    /// therefore be used to compute the cost of the associated `Execution`, but
138    /// many of its values (such as the input IDs in the `Request`s) may not be
139    /// correct. This method does not check circuit satisfiability or `Request`
140    /// validity.
141    #[inline]
142    pub fn sample_authorization<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(
143        &self,
144        address: Address<A::Network>,
145        program_id: ProgramID<A::Network>,
146        function_name: Identifier<A::Network>,
147        inputs: impl ExactSizeIterator<Item = impl TryInto<Value<A::Network>>>,
148        rng: &mut R,
149    ) -> Result<Authorization<N>, StackAuthError> {
150        let timer = timer!("Stack::sample_authorization");
151
152        if program_id != *self.program.id() {
153            return Err(anyhow!("Program ID mismatch").into());
154        }
155
156        // Get the program ID.
157        let program_id = *self.program.id();
158        // Retrieve the input types.
159        let input_types = self.get_function(&function_name)?.input_types();
160        lap!(timer, "Retrieve the input types");
161
162        // This is the root request and does not have a caller.
163        let caller = None;
164        // This is the root request and we do not have a root_tvk to pass on.
165        let root_tvk = None;
166
167        // Compute the mock request.
168        let mocked_request = Request::sample(address, program_id, function_name, inputs, &input_types, false, rng)?;
169
170        lap!(timer, "Compute the mocked request");
171        // Initialize the authorization.
172        let authorization = Authorization::new(mocked_request.clone());
173        // Construct the call stack.
174        let call_stack = CallStack::AuthorizeMocked(vec![mocked_request], address, authorization.clone());
175        // Construct the authorization from the function.
176        let _response = self.evaluate_function::<A, R>(call_stack, caller, root_tvk, rng)?;
177        finish!(timer, "Construct the mocked authorization from the function");
178
179        // Return the authorization.
180        Ok(authorization)
181    }
182
183    /// Authorizes a call to a public function for the given request.
184    /// Compared to `authorize`, no private key is needed, but this only works for single public requests.
185    #[inline]
186    pub fn authorize_request<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(
187        &self,
188        request: Request<N>,
189        rng: &mut R,
190    ) -> Result<Authorization<N>, StackAuthError> {
191        let timer = timer!("Stack::authorize_request");
192
193        // Initialize the authorization.
194        let authorization = Authorization::new(request.clone());
195        // Construct the call stack.
196        let call_stack = CallStack::Authorize(vec![request], None, authorization.clone());
197        // This is the root request and does not have a caller.
198        let caller = None;
199        // This is the root request and we do not have a root_tvk to pass on.
200        let root_tvk = None;
201        // Construct the authorization from the function.
202        let _response = self.evaluate_function::<A, R>(call_stack, caller, root_tvk, rng)?;
203        finish!(timer, "Construct the authorization from the function");
204
205        // Return the authorization.
206        Ok(authorization)
207    }
208}