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(crate) fn sample_record_internal<R: Rng + CryptoRng>(
45 &self,
46 burner_address: &Address<N>,
47 record_name: &Identifier<N>,
48 nonce: Group<N>,
49 depth: usize,
50 rng: &mut R,
51 ) -> Result<Record<N, Plaintext<N>>> {
52 ensure!(depth <= N::MAX_DATA_DEPTH, "Plaintext exceeded maximum depth of {}", N::MAX_DATA_DEPTH);
54
55 let record_type = self.program.get_record(record_name)?;
57
58 let owner = match record_type.owner().is_public() {
60 true => RecordOwner::Public(*burner_address),
61 false => RecordOwner::Private(Plaintext::Literal(Literal::Address(*burner_address), Default::default())),
62 };
63
64 let data = record_type
66 .entries()
67 .iter()
68 .map(|(entry_name, entry_type)| {
69 let entry = self.sample_entry_internal(entry_type, depth + 1, rng)?;
71 Ok((*entry_name, entry))
73 })
74 .collect::<Result<IndexMap<_, _>>>()?;
75
76 let version = U8::<N>::rand(rng);
78
79 Record::<N, Plaintext<N>>::from_plaintext(owner, data, nonce, version)
81 }
82
83 fn sample_entry_internal<R: Rng + CryptoRng>(
85 &self,
86 entry_type: &EntryType<N>,
87 depth: usize,
88 rng: &mut R,
89 ) -> Result<Entry<N, Plaintext<N>>> {
90 ensure!(depth <= N::MAX_DATA_DEPTH, "Entry exceeded maximum depth of {}", N::MAX_DATA_DEPTH);
92
93 match entry_type {
94 EntryType::Constant(plaintext_type)
95 | EntryType::Public(plaintext_type)
96 | EntryType::Private(plaintext_type) => {
97 let plaintext = self.sample_plaintext_internal(plaintext_type, depth, rng)?;
99 match entry_type {
101 EntryType::Constant(..) => Ok(Entry::Constant(plaintext)),
102 EntryType::Public(..) => Ok(Entry::Public(plaintext)),
103 EntryType::Private(..) => Ok(Entry::Private(plaintext)),
104 }
105 }
106 }
107 }
108
109 fn sample_plaintext_internal<R: Rng + CryptoRng>(
111 &self,
112 plaintext_type: &PlaintextType<N>,
113 depth: usize,
114 rng: &mut R,
115 ) -> Result<Plaintext<N>> {
116 ensure!(depth <= N::MAX_DATA_DEPTH, "Plaintext exceeded maximum depth of {}", N::MAX_DATA_DEPTH);
118
119 let plaintext = match plaintext_type {
121 PlaintextType::Literal(literal_type) => {
123 Plaintext::Literal(Literal::sample(*literal_type, rng), Default::default())
124 }
125 PlaintextType::Struct(struct_name) => {
127 let struct_ = self.program.get_struct(struct_name)?;
129 let members = struct_
131 .members()
132 .iter()
133 .map(|(member_name, member_type)| {
134 let member = self.sample_plaintext_internal(member_type, depth + 1, rng)?;
136 Ok((*member_name, member))
138 })
139 .collect::<Result<IndexMap<_, _>>>()?;
140
141 Plaintext::Struct(members, Default::default())
142 }
143 PlaintextType::Array(array_type) => {
145 let elements = (0..**array_type.length())
147 .map(|_| {
148 self.sample_plaintext_internal(array_type.next_element_type(), depth + 1, rng)
150 })
151 .collect::<Result<Vec<_>>>()?;
152
153 Plaintext::Array(elements, Default::default())
154 }
155 };
156 Ok(plaintext)
158 }
159
160 fn sample_future_internal<R: Rng + CryptoRng>(
162 &self,
163 locator: &Locator<N>,
164 depth: usize,
165 rng: &mut R,
166 ) -> Result<Future<N>> {
167 let external_stack = match locator.program_id() == self.program_id() {
169 true => None,
170 false => Some(self.get_external_stack(locator.program_id())?),
173 };
174 let function = match &external_stack {
176 Some(external_stack) => external_stack.get_function_ref(locator.resource())?,
177 None => self.get_function_ref(locator.resource())?,
178 };
179
180 let inputs = match function.finalize_logic() {
182 Some(finalize_logic) => finalize_logic.inputs(),
183 None => bail!("Function '{locator}' does not have a finalize block"),
184 };
185
186 let arguments = inputs
187 .into_iter()
188 .map(|input| {
189 match input.finalize_type() {
190 FinalizeType::Plaintext(plaintext_type) => {
191 let plaintext = self.sample_plaintext_internal(plaintext_type, depth + 1, rng)?;
193 Ok(Argument::Plaintext(plaintext))
195 }
196 FinalizeType::Future(locator) => {
197 let future = self.sample_future_internal(locator, depth + 1, rng)?;
199 Ok(Argument::Future(future))
201 }
202 }
203 })
204 .collect::<Result<Vec<_>>>()?;
205
206 Ok(Future::new(*locator.program_id(), *locator.resource(), arguments))
207 }
208}