snarkvm_synthesizer_process/stack/helpers/
sample.rs1use super::*;
17
18impl<N: Network> Stack<N> {
19 pub fn sample_plaintext<R: Rng + CryptoRng>(
21 &self,
22 plaintext_type: &PlaintextType<N>,
23 rng: &mut R,
24 ) -> Result<Plaintext<N>> {
25 let plaintext = self.sample_plaintext_internal(plaintext_type, 0, rng)?;
27 self.matches_plaintext(&plaintext, plaintext_type)?;
29 Ok(plaintext)
31 }
32
33 pub fn sample_future<R: Rng + CryptoRng>(&self, locator: &Locator<N>, rng: &mut R) -> Result<Future<N>> {
35 let future = self.sample_future_internal(locator, 0, rng)?;
37 self.matches_future(&future, locator)?;
39 Ok(future)
41 }
42
43 pub fn sample_dynamic_future<R: Rng + CryptoRng>(&self, rng: &mut R) -> Result<DynamicFuture<N>> {
45 let program_name = Field::rand(rng);
47 let program_network = Identifier::from_str("aleo").unwrap().to_field()?; let function_name = Field::rand(rng);
51 let argument_root = Field::rand(rng);
53
54 Ok(DynamicFuture::new_unchecked(program_name, program_network, function_name, argument_root, None))
55 }
56
57 pub fn sample_dynamic_record<R: Rng + CryptoRng>(&self, rng: &mut R) -> Result<DynamicRecord<N>> {
59 let owner = Address::rand(rng);
61 let root = Field::rand(rng);
63 let nonce = Group::<N>::rand(rng);
65 let version = U8::<N>::rand(rng);
67
68 Ok(DynamicRecord::new_unchecked(owner, root, nonce, version, None))
69 }
70
71 pub(crate) fn sample_record_internal<R: Rng + CryptoRng>(
73 &self,
74 burner_address: &Address<N>,
75 record_name: &Identifier<N>,
76 nonce: Group<N>,
77 depth: usize,
78 rng: &mut R,
79 ) -> Result<Record<N, Plaintext<N>>> {
80 ensure!(depth <= N::MAX_DATA_DEPTH, "Plaintext exceeded maximum depth of {}", N::MAX_DATA_DEPTH);
82
83 let record_type = self.program.get_record(record_name)?;
85
86 let owner = match record_type.owner().is_public() {
88 true => RecordOwner::Public(*burner_address),
89 false => RecordOwner::Private(Plaintext::Literal(Literal::Address(*burner_address), Default::default())),
90 };
91
92 let data = record_type
94 .entries()
95 .iter()
96 .map(|(entry_name, entry_type)| {
97 let entry = self.sample_entry_internal(entry_type, depth + 1, rng)?;
99 Ok((*entry_name, entry))
101 })
102 .collect::<Result<IndexMap<_, _>>>()?;
103
104 let version = U8::<N>::rand(rng);
106
107 Record::<N, Plaintext<N>>::from_plaintext(owner, data, nonce, version)
109 }
110
111 fn sample_entry_internal<R: Rng + CryptoRng>(
113 &self,
114 entry_type: &EntryType<N>,
115 depth: usize,
116 rng: &mut R,
117 ) -> Result<Entry<N, Plaintext<N>>> {
118 ensure!(depth <= N::MAX_DATA_DEPTH, "Entry exceeded maximum depth of {}", N::MAX_DATA_DEPTH);
120
121 match entry_type {
122 EntryType::Constant(plaintext_type)
123 | EntryType::Public(plaintext_type)
124 | EntryType::Private(plaintext_type) => {
125 let plaintext = self.sample_plaintext_internal(plaintext_type, depth, rng)?;
127 match entry_type {
129 EntryType::Constant(..) => Ok(Entry::Constant(plaintext)),
130 EntryType::Public(..) => Ok(Entry::Public(plaintext)),
131 EntryType::Private(..) => Ok(Entry::Private(plaintext)),
132 }
133 }
134 }
135 }
136
137 fn sample_plaintext_internal<R: Rng + CryptoRng>(
139 &self,
140 plaintext_type: &PlaintextType<N>,
141 depth: usize,
142 rng: &mut R,
143 ) -> Result<Plaintext<N>> {
144 ensure!(depth <= N::MAX_DATA_DEPTH, "Plaintext exceeded maximum depth of {}", N::MAX_DATA_DEPTH);
146
147 let plaintext = match plaintext_type {
149 PlaintextType::Literal(literal_type) => {
151 Plaintext::Literal(Literal::sample(*literal_type, rng), Default::default())
152 }
153 PlaintextType::Struct(struct_name) => {
155 let struct_ = self.program.get_struct(struct_name)?;
157 let members = struct_
159 .members()
160 .iter()
161 .map(|(member_name, member_type)| {
162 let member = self.sample_plaintext_internal(member_type, depth + 1, rng)?;
164 Ok((*member_name, member))
166 })
167 .collect::<Result<IndexMap<_, _>>>()?;
168
169 Plaintext::Struct(members, Default::default())
170 }
171 PlaintextType::ExternalStruct(locator) => {
172 let external_stack = self.get_external_stack(locator.program_id())?;
173 let new_type = PlaintextType::Struct(*locator.resource());
174 return external_stack.sample_plaintext_internal(&new_type, depth, rng);
175 }
176 PlaintextType::Array(array_type) => {
178 let elements = (0..**array_type.length())
180 .map(|_| {
181 self.sample_plaintext_internal(array_type.next_element_type(), depth + 1, rng)
183 })
184 .collect::<Result<Vec<_>>>()?;
185
186 Plaintext::Array(elements, Default::default())
187 }
188 };
189 Ok(plaintext)
191 }
192
193 fn sample_future_internal<R: Rng + CryptoRng>(
195 &self,
196 locator: &Locator<N>,
197 depth: usize,
198 rng: &mut R,
199 ) -> Result<Future<N>> {
200 let external_stack = match locator.program_id() == self.program_id() {
202 true => None,
203 false => Some(self.get_external_stack(locator.program_id())?),
206 };
207 let function = match &external_stack {
209 Some(external_stack) => external_stack.get_function_ref(locator.resource())?,
210 None => self.get_function_ref(locator.resource())?,
211 };
212
213 let inputs = match function.finalize_logic() {
215 Some(finalize_logic) => finalize_logic.inputs(),
216 None => bail!("Function '{locator}' does not have a finalize block"),
217 };
218
219 let arguments = inputs
221 .into_iter()
222 .map(|input| {
223 match input.finalize_type() {
224 FinalizeType::Plaintext(plaintext_type) => {
225 let plaintext = match &external_stack {
227 Some(external_stack) => {
228 external_stack.sample_plaintext_internal(plaintext_type, depth + 1, rng)?
229 }
230 None => self.sample_plaintext_internal(plaintext_type, depth + 1, rng)?,
231 };
232 Ok(Argument::Plaintext(plaintext))
234 }
235 FinalizeType::Future(locator) => {
236 let future = match &external_stack {
238 Some(external_stack) => external_stack.sample_future_internal(locator, depth + 1, rng)?,
239 None => self.sample_future_internal(locator, depth + 1, rng)?,
240 };
241 Ok(Argument::Future(future))
243 }
244 FinalizeType::DynamicFuture => {
245 let dynamic_future = self.sample_dynamic_future(rng)?;
247 Ok(Argument::DynamicFuture(dynamic_future))
249 }
250 }
251 })
252 .collect::<Result<Vec<_>>>()?;
253
254 Ok(Future::new(*locator.program_id(), *locator.resource(), arguments))
255 }
256}