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