snarkvm_synthesizer_process/stack/
deploy.rs1use super::*;
17
18use rand::{SeedableRng, rngs::StdRng};
19
20impl<N: Network> Stack<N> {
21 #[inline]
23 pub fn deploy<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(&self, rng: &mut R) -> Result<Deployment<N>> {
24 let timer = timer!("Stack::deploy");
25
26 ensure!(!self.program.functions().is_empty(), "Program '{}' has no functions", self.program.id());
28
29 let mut verifying_keys = Vec::with_capacity(self.program.functions().len());
31
32 for function_name in self.program.functions().keys() {
33 self.synthesize_key::<A, R>(function_name, rng)?;
35 lap!(timer, "Synthesize key for {function_name}");
36
37 let proving_key = self.get_proving_key(function_name)?;
39 let verifying_key = self.get_verifying_key(function_name)?;
41 lap!(timer, "Retrieve the keys for {function_name}");
42
43 let certificate = Certificate::certify(&function_name.to_string(), &proving_key, &verifying_key)?;
45 lap!(timer, "Certify the circuit");
46
47 verifying_keys.push((*function_name, (verifying_key, certificate)));
49 }
50
51 finish!(timer);
52
53 Deployment::new(N::EDITION, self.program.clone(), verifying_keys)
55 }
56
57 #[inline]
59 pub fn verify_deployment<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(
60 &self,
61 deployment: &Deployment<N>,
62 rng: &mut R,
63 ) -> Result<()> {
64 let timer = timer!("Stack::verify_deployment");
65
66 deployment.check_is_ordered()?;
70 ensure!(&self.program == deployment.program(), "The stack program does not match the deployment program");
72
73 let program_id = self.program.id();
76
77 ensure!(deployment.num_combined_variables()? <= N::MAX_DEPLOYMENT_VARIABLES);
79 ensure!(deployment.num_combined_constraints()? <= N::MAX_DEPLOYMENT_CONSTRAINTS);
81
82 let mut call_stacks = Vec::with_capacity(deployment.verifying_keys().len());
84
85 let root_tvk = None;
87
88 let caller = None;
90
91 ensure!(
93 deployment.program().functions().len() == deployment.verifying_keys().len(),
94 "The number of functions in the program does not match the number of verifying keys"
95 );
96
97 let seed = u64::from_bytes_le(&deployment.to_deployment_id()?.to_bytes_le()?[0..8])?;
101 let mut seeded_rng = rand_chacha::ChaChaRng::seed_from_u64(seed);
102
103 for (function, (_, (verifying_key, _))) in
105 deployment.program().functions().values().zip_eq(deployment.verifying_keys())
106 {
107 let burner_private_key = PrivateKey::new(rng)?;
109 let burner_address = Address::try_from(&burner_private_key)?;
111 let input_types = function.input_types();
113 let inputs = input_types
115 .iter()
116 .map(|input_type| match input_type {
117 ValueType::ExternalRecord(locator) => {
118 let stack = self.get_external_stack(locator.program_id())?;
120 stack.sample_value(&burner_address, &ValueType::Record(*locator.resource()), &mut seeded_rng)
122 }
123 _ => self.sample_value(&burner_address, input_type, &mut seeded_rng),
124 })
125 .collect::<Result<Vec<_>>>()?;
126 lap!(timer, "Sample the inputs");
127 let is_root = true;
129
130 let request = Request::sign(
132 &burner_private_key,
133 *program_id,
134 *function.name(),
135 inputs.into_iter(),
136 &input_types,
137 root_tvk,
138 is_root,
139 rng,
140 )?;
141 lap!(timer, "Compute the request for {}", function.name());
142 let assignments = Assignments::<N>::default();
144 let Some(constraint_limit) = verifying_key.circuit_info.num_constraints.checked_sub(1) else {
146 bail!("The constraint limit of 0 for function '{}' is invalid", function.name());
148 };
149 let variable_limit = verifying_key.num_variables();
151 let call_stack = CallStack::CheckDeployment(
153 vec![request],
154 burner_private_key,
155 assignments.clone(),
156 Some(constraint_limit as u64),
157 Some(variable_limit),
158 );
159 call_stacks.push((function.name(), call_stack, assignments));
161 }
162
163 let rngs = (0..call_stacks.len()).map(|_| StdRng::from_seed(seeded_rng.gen())).collect::<Vec<_>>();
165 cfg_into_iter!(call_stacks).zip_eq(deployment.verifying_keys()).zip_eq(rngs).try_for_each(
166 |(((function_name, call_stack, assignments), (_, (verifying_key, certificate))), mut rng)| {
167 if let Err(err) = self.execute_function::<A, _>(call_stack, caller, root_tvk, &mut rng) {
169 bail!("Failed to synthesize the circuit for '{function_name}': {err}")
170 }
171 match assignments.read().last() {
173 None => bail!("The assignment for function '{function_name}' is missing in '{program_id}'"),
174 Some((assignment, _metrics)) => {
175 if !certificate.verify(&function_name.to_string(), assignment, verifying_key) {
177 bail!("The certificate for function '{function_name}' is invalid in '{program_id}'")
178 }
179 }
180 };
181 Ok(())
182 },
183 )?;
184
185 finish!(timer);
186
187 Ok(())
188 }
189}