snarkvm_synthesizer_process/stack/helpers/synthesize.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 /// Synthesizes the proving key and verifying key for the given function name.
20 #[inline]
21 pub fn synthesize_key<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(
22 &self,
23 function_name: &Identifier<N>,
24 rng: &mut R,
25 ) -> Result<()> {
26 // If the proving and verifying key already exist, skip the synthesis for this function.
27 if self.contains_proving_key(function_name) && self.contains_verifying_key(function_name) {
28 return Ok(());
29 }
30
31 // Retrieve the program ID.
32 let program_id = self.program_id();
33 // Retrieve the function input types.
34 let input_types = self.get_function(function_name)?.input_types();
35
36 // Initialize a burner private key.
37 let burner_private_key = PrivateKey::new(rng)?;
38 // Compute the burner address.
39 let burner_address = Address::try_from(&burner_private_key)?;
40 // Sample the inputs.
41 let inputs = input_types
42 .iter()
43 .map(|input_type| match input_type {
44 ValueType::ExternalRecord(locator) => {
45 // Retrieve the external stack.
46 let stack = self.get_external_stack(locator.program_id())?;
47 // Sample the input.
48 stack.sample_value(&burner_address, &ValueType::Record(*locator.resource()), rng)
49 }
50 _ => self.sample_value(&burner_address, input_type, rng),
51 })
52 .collect::<Result<Vec<_>>>()?;
53 // Sample 'is_root'.
54 let is_root = true;
55
56 // The `root_tvk` is `None` when deploying an individual circuit.
57 let root_tvk = None;
58
59 // The caller is `None` when deploying an individual circuit.
60 let caller = None;
61
62 // Compute the request, with a burner private key.
63 let request = Request::sign(
64 &burner_private_key,
65 *program_id,
66 *function_name,
67 inputs.into_iter(),
68 &input_types,
69 root_tvk,
70 is_root,
71 rng,
72 )?;
73 // Initialize the authorization.
74 let authorization = Authorization::new(request.clone());
75 // Initialize the call stack.
76 let call_stack = CallStack::Synthesize(vec![request], burner_private_key, authorization);
77 // Synthesize the circuit.
78 let _response = self.execute_function::<A, R>(call_stack, caller, root_tvk, rng)?;
79
80 // Ensure the proving key exists.
81 ensure!(self.contains_proving_key(function_name), "Function '{function_name}' is missing a proving key.");
82 // Ensure the verifying key exists.
83 ensure!(self.contains_verifying_key(function_name), "Function '{function_name}' is missing a verifying key.");
84 Ok(())
85 }
86
87 /// Synthesizes and stores the `(proving_key, verifying_key)` for the given function name and assignment.
88 #[inline]
89 pub fn synthesize_from_assignment(
90 &self,
91 function_name: &Identifier<N>,
92 assignment: &circuit::Assignment<N::Field>,
93 ) -> Result<()> {
94 // If the proving and verifying key already exist, skip the synthesis for this function.
95 if self.contains_proving_key(function_name) && self.contains_verifying_key(function_name) {
96 return Ok(());
97 }
98
99 // Synthesize the proving and verifying key.
100 let (proving_key, verifying_key) = self.universal_srs.to_circuit_key(&function_name.to_string(), assignment)?;
101 // Insert the proving key.
102 self.insert_proving_key(function_name, proving_key)?;
103 // Insert the verifying key.
104 self.insert_verifying_key(function_name, verifying_key)
105 }
106}