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}